cql-rb 1.0.0.pre7 → 1.0.0.pre8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/cql/byte_buffer.rb +22 -0
- data/lib/cql/client.rb +79 -310
- data/lib/cql/client/asynchronous_client.rb +254 -0
- data/lib/cql/client/asynchronous_prepared_statement.rb +19 -0
- data/lib/cql/client/column_metadata.rb +22 -0
- data/lib/cql/client/query_result.rb +34 -0
- data/lib/cql/client/result_metadata.rb +31 -0
- data/lib/cql/client/synchronous_client.rb +47 -0
- data/lib/cql/client/synchronous_prepared_statement.rb +47 -0
- data/lib/cql/future.rb +7 -3
- data/lib/cql/io.rb +1 -0
- data/lib/cql/io/io_reactor.rb +9 -3
- data/lib/cql/io/node_connection.rb +2 -2
- data/lib/cql/protocol.rb +5 -4
- data/lib/cql/protocol/request.rb +23 -0
- data/lib/cql/protocol/requests/credentials_request.rb +1 -1
- data/lib/cql/protocol/requests/execute_request.rb +13 -84
- data/lib/cql/protocol/requests/options_request.rb +1 -1
- data/lib/cql/protocol/requests/prepare_request.rb +2 -1
- data/lib/cql/protocol/requests/query_request.rb +3 -1
- data/lib/cql/protocol/requests/register_request.rb +1 -1
- data/lib/cql/protocol/requests/startup_request.rb +1 -2
- data/lib/cql/protocol/{response_body.rb → response.rb} +1 -1
- data/lib/cql/protocol/responses/authenticate_response.rb +1 -1
- data/lib/cql/protocol/responses/error_response.rb +1 -1
- data/lib/cql/protocol/responses/ready_response.rb +1 -1
- data/lib/cql/protocol/responses/result_response.rb +1 -1
- data/lib/cql/protocol/responses/rows_result_response.rb +1 -1
- data/lib/cql/protocol/responses/supported_response.rb +1 -1
- data/lib/cql/protocol/type_converter.rb +226 -46
- data/lib/cql/version.rb +1 -1
- data/spec/cql/byte_buffer_spec.rb +38 -0
- data/spec/cql/client/asynchronous_client_spec.rb +472 -0
- data/spec/cql/client/client_shared.rb +27 -0
- data/spec/cql/client/synchronous_client_spec.rb +104 -0
- data/spec/cql/client/synchronous_prepared_statement_spec.rb +65 -0
- data/spec/cql/future_spec.rb +4 -0
- data/spec/cql/io/io_reactor_spec.rb +39 -20
- data/spec/cql/protocol/request_spec.rb +17 -0
- data/spec/cql/protocol/requests/credentials_request_spec.rb +82 -0
- data/spec/cql/protocol/requests/execute_request_spec.rb +174 -0
- data/spec/cql/protocol/requests/options_request_spec.rb +24 -0
- data/spec/cql/protocol/requests/prepare_request_spec.rb +70 -0
- data/spec/cql/protocol/requests/query_request_spec.rb +95 -0
- data/spec/cql/protocol/requests/register_request_spec.rb +24 -0
- data/spec/cql/protocol/requests/startup_request_spec.rb +29 -0
- data/spec/integration/client_spec.rb +26 -19
- data/spec/integration/protocol_spec.rb +2 -2
- data/spec/integration/regression_spec.rb +1 -1
- metadata +35 -9
- data/lib/cql/protocol/request_body.rb +0 -15
- data/lib/cql/protocol/request_frame.rb +0 -20
- data/spec/cql/client_spec.rb +0 -454
- data/spec/cql/protocol/request_frame_spec.rb +0 -456
@@ -0,0 +1,27 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
shared_context 'client setup' do
|
4
|
+
let :connection_options do
|
5
|
+
{:host => 'example.com', :port => 12321, :io_reactor => io_reactor}
|
6
|
+
end
|
7
|
+
|
8
|
+
let :io_reactor do
|
9
|
+
FakeIoReactor.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def connections
|
13
|
+
io_reactor.connections
|
14
|
+
end
|
15
|
+
|
16
|
+
def connection
|
17
|
+
connections.first
|
18
|
+
end
|
19
|
+
|
20
|
+
def requests
|
21
|
+
connection[:requests]
|
22
|
+
end
|
23
|
+
|
24
|
+
def last_request
|
25
|
+
requests.last
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'cql/client/client_shared'
|
5
|
+
|
6
|
+
|
7
|
+
module Cql
|
8
|
+
module Client
|
9
|
+
describe SynchronousClient do
|
10
|
+
let :client do
|
11
|
+
described_class.new(async_client)
|
12
|
+
end
|
13
|
+
|
14
|
+
let :async_client do
|
15
|
+
stub(:async_client)
|
16
|
+
end
|
17
|
+
|
18
|
+
let :future do
|
19
|
+
stub(:future, get: nil)
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#connect' do
|
23
|
+
it 'calls #connect on the async client and waits for the result' do
|
24
|
+
async_client.should_receive(:connect).and_return(future)
|
25
|
+
future.should_receive(:get)
|
26
|
+
client.connect
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'returns self' do
|
30
|
+
async_client.stub(:connect).and_return(future)
|
31
|
+
client.connect.should equal(client)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#close' do
|
36
|
+
it 'calls #close on the async client and waits for the result' do
|
37
|
+
async_client.should_receive(:close).and_return(future)
|
38
|
+
future.should_receive(:get)
|
39
|
+
client.close
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'returns self' do
|
43
|
+
async_client.stub(:close).and_return(future)
|
44
|
+
client.close.should equal(client)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe '#connected?' do
|
49
|
+
it 'delegates to the async client' do
|
50
|
+
async_client.stub(:connected?).and_return(true)
|
51
|
+
client.connected?.should be_true
|
52
|
+
async_client.stub(:connected?).and_return(false)
|
53
|
+
client.connected?.should be_false
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe '#keyspace' do
|
58
|
+
it 'delegates to the async client' do
|
59
|
+
async_client.stub(:keyspace).and_return('foo')
|
60
|
+
client.keyspace.should == 'foo'
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe '#use' do
|
65
|
+
it 'calls #use on the async client and waits for the result' do
|
66
|
+
async_client.should_receive(:use).with('foo').and_return(future)
|
67
|
+
future.should_receive(:get)
|
68
|
+
client.use('foo')
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe '#execute' do
|
73
|
+
it 'calls #execute on the async client and waits for, and returns the result' do
|
74
|
+
result = stub(:result)
|
75
|
+
async_client.stub(:execute).with('SELECT * FROM something', :one).and_return(future)
|
76
|
+
future.stub(:get).and_return(result)
|
77
|
+
client.execute('SELECT * FROM something', :one).should equal(result)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe '#prepare' do
|
82
|
+
it 'calls #prepare on the async client, waits for the result and returns a SynchronousFuture' do
|
83
|
+
result = stub(:result)
|
84
|
+
metadata = stub(:metadata)
|
85
|
+
async_statement = stub(:async_statement, metadata: metadata)
|
86
|
+
another_future = stub(:another_future)
|
87
|
+
async_client.stub(:prepare).with('SELECT * FROM something').and_return(future)
|
88
|
+
future.stub(:get).and_return(async_statement)
|
89
|
+
statement = client.prepare('SELECT * FROM something')
|
90
|
+
async_statement.should_receive(:execute).and_return(another_future)
|
91
|
+
another_future.stub(:get).and_return(result)
|
92
|
+
statement.execute.should equal(result)
|
93
|
+
statement.metadata.should equal(metadata)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe '#async' do
|
98
|
+
it 'returns an asynchronous client' do
|
99
|
+
client.async.should equal(async_client)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
|
6
|
+
module Cql
|
7
|
+
module Client
|
8
|
+
describe SynchronousPreparedStatement do
|
9
|
+
let :statement do
|
10
|
+
described_class.new(async_statement)
|
11
|
+
end
|
12
|
+
|
13
|
+
let :async_statement do
|
14
|
+
stub(:async_statement, metadata: metadata)
|
15
|
+
end
|
16
|
+
|
17
|
+
let :metadata do
|
18
|
+
stub(:metadata)
|
19
|
+
end
|
20
|
+
|
21
|
+
let :future do
|
22
|
+
Future.new
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#metadata' do
|
26
|
+
it 'returns the async statement\'s metadata' do
|
27
|
+
statement.metadata.should equal(async_statement.metadata)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#execute' do
|
32
|
+
it 'it calls #execute on the async statement and waits for the result' do
|
33
|
+
result = stub(:result)
|
34
|
+
async_statement.should_receive(:execute).with('one', 'two', :three).and_return(future)
|
35
|
+
future.complete!(result)
|
36
|
+
statement.execute('one', 'two', :three).should equal(result)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '#pipeline' do
|
41
|
+
it 'executes the statement multiple times and waits for all the results' do
|
42
|
+
result1 = stub(:result1)
|
43
|
+
result2 = stub(:result2)
|
44
|
+
async_statement.stub(:execute).with('one', 'two', :three).and_return(Future.completed(result1))
|
45
|
+
async_statement.stub(:execute).with('four', 'file', :all).and_return(Future.completed(result2))
|
46
|
+
results = statement.pipeline do |p|
|
47
|
+
p.execute('one', 'two', :three)
|
48
|
+
p.execute('four', 'file', :all)
|
49
|
+
end
|
50
|
+
results.should eql([result1, result2])
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'does nothing when statements are executed' do
|
54
|
+
statement.pipeline { |p| }.should == []
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe '#async' do
|
59
|
+
it 'returns an asynchronous statement' do
|
60
|
+
statement.async.should equal(async_statement)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/spec/cql/future_spec.rb
CHANGED
@@ -190,6 +190,10 @@ module Cql
|
|
190
190
|
f = Future.combine(Future.new, Future.new)
|
191
191
|
expect { f.fail!(StandardError.new('Blurgh')) }.to raise_error(FutureError)
|
192
192
|
end
|
193
|
+
|
194
|
+
it 'completes with an empty list when no futures are given' do
|
195
|
+
Future.combine.get.should == []
|
196
|
+
end
|
193
197
|
end
|
194
198
|
end
|
195
199
|
|
@@ -213,37 +213,56 @@ module Cql
|
|
213
213
|
expect { f.get }.to raise_error(ConnectionNotFoundError)
|
214
214
|
end
|
215
215
|
|
216
|
-
it '
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
216
|
+
it 'queues requests when the connection is busy' do
|
217
|
+
request = Cql::Protocol::QueryRequest.new('UPDATE x SET y = 1 WHERE z = 2', :one)
|
218
|
+
|
219
|
+
io_reactor.start
|
220
|
+
connection_id = io_reactor.add_connection(host, port).get
|
221
|
+
|
222
|
+
futures = 200.times.map do
|
223
|
+
io_reactor.queue_request(request, connection_id)
|
224
|
+
end
|
225
|
+
|
226
|
+
128.times do |i|
|
227
|
+
server.broadcast!("\x81\x00#{[i].pack('c')}\b\x00\x00\x00\x04\x00\x00\x00\x01")
|
228
|
+
end
|
229
|
+
|
230
|
+
Future.combine(*futures.shift(128)).get
|
231
|
+
|
232
|
+
128.times do |i|
|
233
|
+
server.broadcast!("\x81\x00#{[i].pack('c')}\b\x00\x00\x00\x04\x00\x00\x00\x01")
|
226
234
|
end
|
227
|
-
|
235
|
+
|
236
|
+
Future.combine(*futures).get
|
228
237
|
end
|
229
238
|
|
230
|
-
it 'fails
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
239
|
+
it 'fails queued requests when the connection closes' do
|
240
|
+
request = Cql::Protocol::QueryRequest.new('UPDATE x SET y = 1 WHERE z = 2', :one)
|
241
|
+
|
242
|
+
io_reactor.start
|
243
|
+
connection_id = io_reactor.add_connection(host, port).get
|
244
|
+
|
245
|
+
failures = 0
|
246
|
+
|
247
|
+
200.times do
|
248
|
+
f = io_reactor.queue_request(request, connection_id)
|
249
|
+
f.on_failure do
|
250
|
+
failures += 1
|
237
251
|
end
|
238
252
|
end
|
239
|
-
|
253
|
+
|
254
|
+
server.broadcast!("\x01\x00\x00\x02\x00\x00\x00\x16")
|
255
|
+
|
256
|
+
await { failures == 200 }
|
240
257
|
end
|
241
258
|
end
|
242
259
|
|
243
260
|
it 'fails if there is an error when encoding the request' do
|
261
|
+
request = stub(:request)
|
262
|
+
request.stub(:encode_frame).and_raise(Cql::ProtocolError.new('Boork!'))
|
244
263
|
io_reactor.start
|
245
264
|
io_reactor.add_connection(host, port).get
|
246
|
-
f = io_reactor.queue_request(
|
265
|
+
f = io_reactor.queue_request(request)
|
247
266
|
expect { f.get }.to raise_error(Cql::ProtocolError)
|
248
267
|
end
|
249
268
|
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
|
6
|
+
module Cql
|
7
|
+
module Protocol
|
8
|
+
describe Request do
|
9
|
+
describe '#encode_frame' do
|
10
|
+
it 'returns a rendered request frame for the specified channel' do
|
11
|
+
frame = PrepareRequest.new('SELECT * FROM things').encode_frame(3)
|
12
|
+
frame.to_s.should == "\x01\x00\x03\x09\x00\x00\x00\x18\x00\x00\x00\x14SELECT * FROM things"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
|
6
|
+
module Cql
|
7
|
+
module Protocol
|
8
|
+
describe CredentialsRequest do
|
9
|
+
describe '#encode_frame' do
|
10
|
+
it 'encodes a CREDENTIALS request frame' do
|
11
|
+
bytes = CredentialsRequest.new('username' => 'cassandra', 'password' => 'ardnassac').encode_frame(3)
|
12
|
+
bytes.should == (
|
13
|
+
"\x01\x00\x03\04" +
|
14
|
+
"\x00\x00\x00\x2c" +
|
15
|
+
"\x00\x02" +
|
16
|
+
"\x00\x08username" +
|
17
|
+
"\x00\x09cassandra" +
|
18
|
+
"\x00\x08password" +
|
19
|
+
"\x00\x09ardnassac"
|
20
|
+
)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#to_s' do
|
25
|
+
it 'returns a pretty string' do
|
26
|
+
request = CredentialsRequest.new('foo' => 'bar', 'hello' => 'world')
|
27
|
+
request.to_s.should == 'CREDENTIALS {"foo"=>"bar", "hello"=>"world"}'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#eql?' do
|
32
|
+
it 'returns when the credentials are the same' do
|
33
|
+
c1 = CredentialsRequest.new('username' => 'foo', 'password' => 'bar')
|
34
|
+
c2 = CredentialsRequest.new('username' => 'foo', 'password' => 'bar')
|
35
|
+
c2.should eql(c2)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'returns when the credentials are equivalent' do
|
39
|
+
pending 'this would be nice, but is hardly necessary' do
|
40
|
+
c1 = CredentialsRequest.new(:username => 'foo', :password => 'bar')
|
41
|
+
c2 = CredentialsRequest.new('username' => 'foo', 'password' => 'bar')
|
42
|
+
c1.should eql(c2)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'returns false when the credentials are different' do
|
47
|
+
c1 = CredentialsRequest.new('username' => 'foo', 'password' => 'world')
|
48
|
+
c2 = CredentialsRequest.new('username' => 'foo', 'hello' => 'world')
|
49
|
+
c1.should_not eql(c2)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'is aliased as ==' do
|
53
|
+
c1 = CredentialsRequest.new('username' => 'foo', 'password' => 'bar')
|
54
|
+
c2 = CredentialsRequest.new('username' => 'foo', 'password' => 'bar')
|
55
|
+
c1.should == c2
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe '#hash' do
|
60
|
+
it 'has the same hash code as another identical object' do
|
61
|
+
c1 = CredentialsRequest.new('username' => 'foo', 'password' => 'bar')
|
62
|
+
c2 = CredentialsRequest.new('username' => 'foo', 'password' => 'bar')
|
63
|
+
c1.hash.should == c2.hash
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'has the same hash code as another object with equivalent credentials' do
|
67
|
+
pending 'this would be nice, but is hardly necessary' do
|
68
|
+
c1 = CredentialsRequest.new(:username => 'foo', :password => 'bar')
|
69
|
+
c2 = CredentialsRequest.new('username' => 'foo', 'password' => 'bar')
|
70
|
+
c1.hash.should == c2.hash
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'does not have the same hash code when the credentials are different' do
|
75
|
+
c1 = CredentialsRequest.new('username' => 'foo', 'password' => 'world')
|
76
|
+
c2 = CredentialsRequest.new('username' => 'foo', 'hello' => 'world')
|
77
|
+
c1.hash.should_not == c2.hash
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
|
6
|
+
module Cql
|
7
|
+
module Protocol
|
8
|
+
describe ExecuteRequest do
|
9
|
+
let :id do
|
10
|
+
"\xCAH\x7F\x1Ez\x82\xD2<N\x8A\xF35Qq\xA5/"
|
11
|
+
end
|
12
|
+
|
13
|
+
let :column_metadata do
|
14
|
+
[
|
15
|
+
['ks', 'tbl', 'col1', :varchar],
|
16
|
+
['ks', 'tbl', 'col2', :int],
|
17
|
+
['ks', 'tbl', 'col3', :varchar]
|
18
|
+
]
|
19
|
+
end
|
20
|
+
|
21
|
+
let :values do
|
22
|
+
['hello', 42, 'foo']
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#initialize' do
|
26
|
+
it 'raises an error when the metadata and values don\'t have the same size' do
|
27
|
+
expect { ExecuteRequest.new(id, column_metadata, ['hello', 42], :each_quorum) }.to raise_error(ArgumentError)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'raises an error for unsupported column types' do
|
31
|
+
column_metadata[2][3] = :imaginary
|
32
|
+
expect { ExecuteRequest.new(id, column_metadata, ['hello', 42, 'foo'], :each_quorum) }.to raise_error(UnsupportedColumnTypeError)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'raises an error for unsupported column collection types' do
|
36
|
+
column_metadata[2][3] = [:imaginary, :varchar]
|
37
|
+
expect { ExecuteRequest.new(id, column_metadata, ['hello', 42, ['foo']], :each_quorum) }.to raise_error(UnsupportedColumnTypeError)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'raises an error when collection values are not enumerable' do
|
41
|
+
column_metadata[2][3] = [:set, :varchar]
|
42
|
+
expect { ExecuteRequest.new(id, column_metadata, ['hello', 42, 'foo'], :each_quorum) }.to raise_error(InvalidValueError)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'raises an error when it cannot encode the argument' do
|
46
|
+
expect { ExecuteRequest.new(id, column_metadata, ['hello', 'not an int', 'foo'], :each_quorum) }.to raise_error(TypeError, /cannot be encoded as INT/)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe '#encode_frame' do
|
51
|
+
it 'encodes an EXECUTE request frame' do
|
52
|
+
bytes = ExecuteRequest.new(id, column_metadata, ['hello', 42, 'foo'], :each_quorum).encode_frame(3)
|
53
|
+
bytes.should == "\x01\x00\x03\x0a\x00\x00\x00\x2e\x00\x10\xCAH\x7F\x1Ez\x82\xD2<N\x8A\xF35Qq\xA5/\x00\x03\x00\x00\x00\x05hello\x00\x00\x00\x04\x00\x00\x00\x2a\x00\x00\x00\x03foo\x00\x07"
|
54
|
+
end
|
55
|
+
|
56
|
+
specs = [
|
57
|
+
[:ascii, 'test', "test"],
|
58
|
+
[:bigint, 1012312312414123, "\x00\x03\x98\xB1S\xC8\x7F\xAB"],
|
59
|
+
[:blob, "\xab\xcd", "\xab\xcd"],
|
60
|
+
[:boolean, false, "\x00"],
|
61
|
+
[:boolean, true, "\x01"],
|
62
|
+
[:decimal, BigDecimal.new('1042342234234.123423435647768234'), "\x00\x00\x00\x12\r'\xFDI\xAD\x80f\x11g\xDCfV\xAA"],
|
63
|
+
[:double, 10000.123123123, "@\xC3\x88\x0F\xC2\x7F\x9DU"],
|
64
|
+
[:float, 12.13, "AB\x14{"],
|
65
|
+
[:inet, IPAddr.new('8.8.8.8'), "\x08\x08\x08\x08"],
|
66
|
+
[:inet, IPAddr.new('::1'), "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"],
|
67
|
+
[:int, 12348098, "\x00\xBCj\xC2"],
|
68
|
+
[:text, 'FOOBAR', 'FOOBAR'],
|
69
|
+
[:timestamp, Time.at(1358013521.123), "\x00\x00\x01</\xE9\xDC\xE3"],
|
70
|
+
[:timeuuid, Uuid.new('a4a70900-24e1-11df-8924-001ff3591711'), "\xA4\xA7\t\x00$\xE1\x11\xDF\x89$\x00\x1F\xF3Y\x17\x11"],
|
71
|
+
[:uuid, Uuid.new('cfd66ccc-d857-4e90-b1e5-df98a3d40cd6'), "\xCF\xD6l\xCC\xD8WN\x90\xB1\xE5\xDF\x98\xA3\xD4\f\xD6"],
|
72
|
+
[:varchar, 'hello', 'hello'],
|
73
|
+
[:varint, 1231312312331283012830129382342342412123, "\x03\x9EV \x15\f\x03\x9DK\x18\xCDI\\$?\a["],
|
74
|
+
[:varint, -234234234234, "\xC9v\x8D:\x86"],
|
75
|
+
[[:list, :timestamp], [Time.at(1358013521.123)], "\x00\x01" + "\x00\x08\x00\x00\x01</\xE9\xDC\xE3"],
|
76
|
+
[[:list, :boolean], [true, false, true, true], "\x00\x04" + "\x00\x01\x01" + "\x00\x01\x00" + "\x00\x01\x01" + "\x00\x01\x01"],
|
77
|
+
[[:map, :uuid, :int], {Uuid.new('cfd66ccc-d857-4e90-b1e5-df98a3d40cd6') => 45345, Uuid.new('a4a70900-24e1-11df-8924-001ff3591711') => 98765}, "\x00\x02" + "\x00\x10\xCF\xD6l\xCC\xD8WN\x90\xB1\xE5\xDF\x98\xA3\xD4\f\xD6" + "\x00\x04\x00\x00\xb1\x21" + "\x00\x10\xA4\xA7\t\x00$\xE1\x11\xDF\x89$\x00\x1F\xF3Y\x17\x11" + "\x00\x04\x00\x01\x81\xcd"],
|
78
|
+
[[:map, :ascii, :blob], {'hello' => 'world', 'one' => "\x01", 'two' => "\x02"}, "\x00\x03" + "\x00\x05hello" + "\x00\x05world" + "\x00\x03one" + "\x00\x01\x01" + "\x00\x03two" + "\x00\x01\x02"],
|
79
|
+
[[:set, :int], Set.new([13, 3453, 456456, 123, 768678]), "\x00\x05" + "\x00\x04\x00\x00\x00\x0d" + "\x00\x04\x00\x00\x0d\x7d" + "\x00\x04\x00\x06\xf7\x08" + "\x00\x04\x00\x00\x00\x7b" + "\x00\x04\x00\x0b\xba\xa6"],
|
80
|
+
[[:set, :varchar], Set.new(['foo', 'bar', 'baz']), "\x00\x03" + "\x00\x03foo" + "\x00\x03bar" + "\x00\x03baz"],
|
81
|
+
[[:set, :int], [13, 3453, 456456, 123, 768678], "\x00\x05" + "\x00\x04\x00\x00\x00\x0d" + "\x00\x04\x00\x00\x0d\x7d" + "\x00\x04\x00\x06\xf7\x08" + "\x00\x04\x00\x00\x00\x7b" + "\x00\x04\x00\x0b\xba\xa6"],
|
82
|
+
[[:set, :varchar], ['foo', 'bar', 'baz'], "\x00\x03" + "\x00\x03foo" + "\x00\x03bar" + "\x00\x03baz"]
|
83
|
+
]
|
84
|
+
specs.each do |type, value, expected_bytes|
|
85
|
+
it "encodes #{type} values" do
|
86
|
+
metadata = [['ks', 'tbl', 'id_column', type]]
|
87
|
+
buffer = ExecuteRequest.new(id, metadata, [value], :one).encode_frame(3)
|
88
|
+
buffer.discard(8 + 2 + 16 + 2)
|
89
|
+
length = buffer.read_int
|
90
|
+
result_bytes = buffer.read(length)
|
91
|
+
result_bytes.should eql_bytes(expected_bytes)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe '#to_s' do
|
97
|
+
it 'returns a pretty string' do
|
98
|
+
request = ExecuteRequest.new(id, column_metadata, values, :each_quorum)
|
99
|
+
request.to_s.should == 'EXECUTE ca487f1e7a82d23c4e8af3355171a52f ["hello", 42, "foo"] EACH_QUORUM'
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe '#eql?' do
|
104
|
+
it 'returns true when the ID, metadata, values and consistency are the same' do
|
105
|
+
e1 = ExecuteRequest.new(id, column_metadata, values, :one)
|
106
|
+
e2 = ExecuteRequest.new(id, column_metadata, values, :one)
|
107
|
+
e1.should eql(e2)
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'returns false when the ID is different' do
|
111
|
+
e1 = ExecuteRequest.new(id, column_metadata, values, :one)
|
112
|
+
e2 = ExecuteRequest.new(id.reverse, column_metadata, values, :one)
|
113
|
+
e1.should_not eql(e2)
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'returns false when the metadata is different' do
|
117
|
+
e1 = ExecuteRequest.new(id, column_metadata, values, :one)
|
118
|
+
e2 = ExecuteRequest.new(id, column_metadata.reverse, values, :one)
|
119
|
+
e1.should_not eql(e2)
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'returns false when the values are different' do
|
123
|
+
e1 = ExecuteRequest.new(id, column_metadata, values, :one)
|
124
|
+
e2 = ExecuteRequest.new(id, column_metadata, values.reverse, :one)
|
125
|
+
e1.should_not eql(e2)
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'returns false when the consistency is different' do
|
129
|
+
e1 = ExecuteRequest.new(id, column_metadata, values, :one)
|
130
|
+
e2 = ExecuteRequest.new(id, column_metadata, values, :two)
|
131
|
+
e1.should_not eql(e2)
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'is aliased as ==' do
|
135
|
+
e1 = ExecuteRequest.new(id, column_metadata, values, :one)
|
136
|
+
e2 = ExecuteRequest.new(id, column_metadata, values, :one)
|
137
|
+
e1.should == e2
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
describe '#hash' do
|
142
|
+
it 'has the same hash code as another identical object' do
|
143
|
+
e1 = ExecuteRequest.new(id, column_metadata, values, :one)
|
144
|
+
e2 = ExecuteRequest.new(id, column_metadata, values, :one)
|
145
|
+
e1.hash.should == e2.hash
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'does not have the same hash code when the ID is different' do
|
149
|
+
e1 = ExecuteRequest.new(id, column_metadata, values, :one)
|
150
|
+
e2 = ExecuteRequest.new(id.reverse, column_metadata, values, :one)
|
151
|
+
e1.hash.should_not == e2.hash
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'does not have the same hash code when the metadata is different' do
|
155
|
+
e1 = ExecuteRequest.new(id, column_metadata, values, :one)
|
156
|
+
e2 = ExecuteRequest.new(id, column_metadata.reverse, values, :one)
|
157
|
+
e1.hash.should_not == e2.hash
|
158
|
+
end
|
159
|
+
|
160
|
+
it 'does not have the same hash code when the values are different' do
|
161
|
+
e1 = ExecuteRequest.new(id, column_metadata, values, :one)
|
162
|
+
e2 = ExecuteRequest.new(id, column_metadata, values.reverse, :one)
|
163
|
+
e1.hash.should_not == e2.hash
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'does not have the same hash code when the consistency is different' do
|
167
|
+
e1 = ExecuteRequest.new(id, column_metadata, values, :one)
|
168
|
+
e2 = ExecuteRequest.new(id, column_metadata, values, :two)
|
169
|
+
e1.hash.should_not == e2.hash
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|