cql-rb 1.0.0.pre0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +13 -0
- data/bin/cqlexec +135 -0
- data/lib/cql.rb +11 -0
- data/lib/cql/client.rb +196 -0
- data/lib/cql/future.rb +176 -0
- data/lib/cql/io.rb +13 -0
- data/lib/cql/io/io_reactor.rb +351 -0
- data/lib/cql/protocol.rb +39 -0
- data/lib/cql/protocol/decoding.rb +156 -0
- data/lib/cql/protocol/encoding.rb +109 -0
- data/lib/cql/protocol/request_frame.rb +228 -0
- data/lib/cql/protocol/response_frame.rb +551 -0
- data/lib/cql/uuid.rb +46 -0
- data/lib/cql/version.rb +5 -0
- data/spec/cql/client_spec.rb +368 -0
- data/spec/cql/future_spec.rb +297 -0
- data/spec/cql/io/io_reactor_spec.rb +290 -0
- data/spec/cql/protocol/decoding_spec.rb +464 -0
- data/spec/cql/protocol/encoding_spec.rb +338 -0
- data/spec/cql/protocol/request_frame_spec.rb +359 -0
- data/spec/cql/protocol/response_frame_spec.rb +746 -0
- data/spec/cql/uuid_spec.rb +40 -0
- data/spec/integration/client_spec.rb +101 -0
- data/spec/integration/protocol_spec.rb +326 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/support/fake_io_reactor.rb +55 -0
- data/spec/support/fake_server.rb +95 -0
- metadata +87 -0
@@ -0,0 +1,338 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
|
6
|
+
module Cql
|
7
|
+
module Protocol
|
8
|
+
describe Encoding do
|
9
|
+
let :buffer do
|
10
|
+
''
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#write_int' do
|
14
|
+
it 'encodes an int' do
|
15
|
+
Encoding.write_int(buffer, 2323234234)
|
16
|
+
buffer.should == "\x8a\x79\xbd\xba"
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'appends to the buffer' do
|
20
|
+
buffer << "\xab"
|
21
|
+
Encoding.write_int(buffer, 10)
|
22
|
+
buffer.should == "\xab\x00\x00\x00\x0a"
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'returns the buffer' do
|
26
|
+
result = Encoding.write_int(buffer, 2323234234)
|
27
|
+
result.should equal(buffer)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#write_short' do
|
32
|
+
it 'encodes a short' do
|
33
|
+
Encoding.write_short(buffer, 0xabcd)
|
34
|
+
buffer.should == "\xab\xcd"
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'appends to the buffer' do
|
38
|
+
buffer << "\xab"
|
39
|
+
Encoding.write_short(buffer, 10)
|
40
|
+
buffer.should == "\xab\x00\x0a"
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'returns the buffer' do
|
44
|
+
result = Encoding.write_short(buffer, 42)
|
45
|
+
result.should equal(buffer)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe '#write_string' do
|
50
|
+
it 'encodes a string' do
|
51
|
+
Encoding.write_string(buffer, 'hello')
|
52
|
+
buffer.should == "\x00\x05hello"
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'encodes an empty string' do
|
56
|
+
Encoding.write_string(buffer, '')
|
57
|
+
buffer.should == "\x00\x00"
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'appends to the buffer' do
|
61
|
+
buffer << "\xab"
|
62
|
+
Encoding.write_string(buffer, 'foo')
|
63
|
+
buffer.should == "\xab\x00\x03foo"
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'returns the buffer' do
|
67
|
+
result = Encoding.write_string(buffer, 'hello')
|
68
|
+
result.should equal(buffer)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe '#write_long_string' do
|
73
|
+
it 'encodes a string' do
|
74
|
+
Encoding.write_long_string(buffer, 'hello world ' * 100_000)
|
75
|
+
buffer.should start_with("\x00\x12\x4f\x80hello world hello world hello world hello")
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'encodes an empty string' do
|
79
|
+
Encoding.write_long_string(buffer, '')
|
80
|
+
buffer.should == "\x00\x00\x00\x00"
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'appends to the buffer' do
|
84
|
+
buffer << "\xab"
|
85
|
+
Encoding.write_long_string(buffer, 'foo')
|
86
|
+
buffer.should == "\xab\x00\x00\x00\x03foo"
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'returns the buffer' do
|
90
|
+
result = Encoding.write_long_string(buffer, 'hello')
|
91
|
+
result.should equal(buffer)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe '#write_uuid' do
|
96
|
+
let :uuid do
|
97
|
+
Uuid.new('a4a70900-24e1-11df-8924-001ff3591711')
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'encodes an UUID' do
|
101
|
+
Encoding.write_uuid(buffer, uuid)
|
102
|
+
buffer.should == "\xA4\xA7\t\x00$\xE1\x11\xDF\x89$\x00\x1F\xF3Y\x17\x11"
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'appends to the buffer' do
|
106
|
+
buffer << 'FOO'
|
107
|
+
Encoding.write_uuid(buffer, uuid)
|
108
|
+
buffer.should start_with('FOO')
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'returns the buffer' do
|
112
|
+
result = Encoding.write_uuid(buffer, uuid)
|
113
|
+
result.should equal(buffer)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe '#write_string_list' do
|
118
|
+
it 'encodes a string list' do
|
119
|
+
Encoding.write_string_list(buffer, %w[foo bar hello world])
|
120
|
+
buffer.should == "\x00\x04\x00\x03foo\x00\x03bar\x00\x05hello\x00\x05world"
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'encodes an empty string list' do
|
124
|
+
Encoding.write_string_list(buffer, [])
|
125
|
+
buffer.should == "\x00\x00"
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'appends to the buffer' do
|
129
|
+
buffer << "\xab"
|
130
|
+
Encoding.write_string_list(buffer, %w[foo bar])
|
131
|
+
buffer.should == "\xab\x00\x02\x00\x03foo\x00\x03bar"
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'returns the buffer' do
|
135
|
+
result = Encoding.write_string_list(buffer, %w[foo])
|
136
|
+
result.should equal(buffer)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
describe '#write_bytes' do
|
141
|
+
it 'encodes a byte array' do
|
142
|
+
Encoding.write_bytes(buffer, "\xaa" * 2000)
|
143
|
+
buffer.should == ("\x00\x00\x07\xd0" << ("\xaa" * 2000))
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'encodes nil' do
|
147
|
+
Encoding.write_bytes(buffer, nil)
|
148
|
+
buffer.should == "\xff\xff\xff\xff"
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'appends to the buffer' do
|
152
|
+
buffer << "\xab"
|
153
|
+
Encoding.write_bytes(buffer, "\xf0\x0b\xbar")
|
154
|
+
buffer.should == "\xab\x00\x00\x00\x04\xf0\x0b\xbar"
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'returns the buffer' do
|
158
|
+
result = Encoding.write_bytes(buffer, "\xab")
|
159
|
+
result.should equal(buffer)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
describe '#write_short_bytes' do
|
164
|
+
it 'encodes a byte array' do
|
165
|
+
Encoding.write_short_bytes(buffer, "\xaa\xbb\xcc")
|
166
|
+
buffer.should == "\x00\x03\xaa\xbb\xcc"
|
167
|
+
end
|
168
|
+
|
169
|
+
it 'encodes nil' do
|
170
|
+
Encoding.write_short_bytes(buffer, nil)
|
171
|
+
buffer.should == "\xff\xff"
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'appends to the buffer' do
|
175
|
+
buffer << "\xab"
|
176
|
+
Encoding.write_short_bytes(buffer, "\xf0\x0b\xbar")
|
177
|
+
buffer.should == "\xab\x00\x04\xf0\x0b\xbar"
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'returns the buffer' do
|
181
|
+
result = Encoding.write_short_bytes(buffer, "\xab")
|
182
|
+
result.should equal(buffer)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
describe '#write_consistency' do
|
187
|
+
{
|
188
|
+
:any => "\x00\x00",
|
189
|
+
:one => "\x00\x01",
|
190
|
+
:two => "\x00\x02",
|
191
|
+
:three => "\x00\x03",
|
192
|
+
:quorum => "\x00\x04",
|
193
|
+
:all => "\x00\x05",
|
194
|
+
:local_quorum => "\x00\x06",
|
195
|
+
:each_quorum => "\x00\x07"
|
196
|
+
}.each do |consistency, expected_encoding|
|
197
|
+
it "encodes #{consistency}" do
|
198
|
+
Encoding.write_consistency(buffer, consistency)
|
199
|
+
buffer.should == expected_encoding
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
it 'raises an exception for an unknown consistency' do
|
204
|
+
expect { Encoding.write_consistency(buffer, :foo) }.to raise_error(EncodingError)
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'appends to the buffer' do
|
208
|
+
buffer << "\xab"
|
209
|
+
Encoding.write_consistency(buffer, :one)
|
210
|
+
buffer.should == "\xab\x00\x01"
|
211
|
+
end
|
212
|
+
|
213
|
+
it 'returns the buffer' do
|
214
|
+
result = Encoding.write_consistency(buffer, :quorum)
|
215
|
+
result.should equal(buffer)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
describe '#write_string_map' do
|
220
|
+
it 'encodes a string map' do
|
221
|
+
Encoding.write_string_map(buffer, 'HELLO' => 'world', 'foo' => 'bar')
|
222
|
+
buffer.should == "\x00\x02\x00\x05HELLO\x00\x05world\x00\x03foo\x00\x03bar"
|
223
|
+
end
|
224
|
+
|
225
|
+
it 'encodes an empty map' do
|
226
|
+
Encoding.write_string_map(buffer, {})
|
227
|
+
buffer.should == "\x00\x00"
|
228
|
+
end
|
229
|
+
|
230
|
+
it 'appends to the buffer' do
|
231
|
+
buffer << "\xab"
|
232
|
+
Encoding.write_string_map(buffer, 'foo' => 'bar')
|
233
|
+
buffer.should == "\xab\x00\x01\x00\x03foo\x00\x03bar"
|
234
|
+
end
|
235
|
+
|
236
|
+
it 'returns the buffer' do
|
237
|
+
result = Encoding.write_string_map(buffer, 'HELLO' => 'world')
|
238
|
+
result.should equal(buffer)
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
describe '#write_long' do
|
243
|
+
it 'encodes a long' do
|
244
|
+
Encoding.write_long(buffer, 0x0123456789)
|
245
|
+
buffer.should == "\x00\x00\x00\x01\x23\x45\x67\x89"
|
246
|
+
end
|
247
|
+
|
248
|
+
it 'appends to the buffer' do
|
249
|
+
buffer << "\x99"
|
250
|
+
Encoding.write_long(buffer, 0x0123456789)
|
251
|
+
buffer.should == "\x99\x00\x00\x00\x01\x23\x45\x67\x89"
|
252
|
+
end
|
253
|
+
|
254
|
+
it 'returns the buffer' do
|
255
|
+
result = Encoding.write_long(buffer, 1)
|
256
|
+
result.should equal(buffer)
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
describe '#write_varint' do
|
261
|
+
it 'encodes a variable length integer' do
|
262
|
+
Encoding.write_varint(buffer, 1231312312331283012830129382342342412123)
|
263
|
+
buffer.should == "\x03\x9EV \x15\f\x03\x9DK\x18\xCDI\\$?\a["
|
264
|
+
end
|
265
|
+
|
266
|
+
it 'encodes a negative variable length integer' do
|
267
|
+
Encoding.write_varint(buffer, -234234234234)
|
268
|
+
buffer.should == "\xC9v\x8D:\x86"
|
269
|
+
end
|
270
|
+
|
271
|
+
it 'appends to the buffer' do
|
272
|
+
buffer << "\x99"
|
273
|
+
Encoding.write_varint(buffer, -234234234234)
|
274
|
+
buffer.should == "\x99\xC9v\x8D:\x86"
|
275
|
+
end
|
276
|
+
|
277
|
+
it 'returns the buffer' do
|
278
|
+
result = Encoding.write_varint(buffer, -234234234234)
|
279
|
+
result.should equal(buffer)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
describe '#write_decimal' do
|
284
|
+
it 'encodes a BigDecimal as a decimal' do
|
285
|
+
Encoding.write_decimal(buffer, BigDecimal.new('1042342234234.123423435647768234'))
|
286
|
+
buffer.should == "\x00\x00\x00\x12\r'\xFDI\xAD\x80f\x11g\xDCfV\xAA"
|
287
|
+
end
|
288
|
+
|
289
|
+
it 'appends to the buffer' do
|
290
|
+
buffer << "\x99"
|
291
|
+
Encoding.write_decimal(buffer, BigDecimal.new('1042342234234.123423435647768234'))
|
292
|
+
buffer.should start_with("\x99")
|
293
|
+
end
|
294
|
+
|
295
|
+
it 'returns the buffer' do
|
296
|
+
result = Encoding.write_decimal(buffer, BigDecimal.new('3.14'))
|
297
|
+
result.should equal(buffer)
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
describe '#write_double' do
|
302
|
+
it 'encodes a double' do
|
303
|
+
Encoding.write_double(buffer, 10000.123123123)
|
304
|
+
buffer.should == "@\xC3\x88\x0F\xC2\x7F\x9DU"
|
305
|
+
end
|
306
|
+
|
307
|
+
it 'appends to the buffer' do
|
308
|
+
buffer << 'BEFORE'
|
309
|
+
Encoding.write_double(buffer, 10000.123123123)
|
310
|
+
buffer.should start_with('BEFORE')
|
311
|
+
end
|
312
|
+
|
313
|
+
it 'returns the buffer' do
|
314
|
+
result = Encoding.write_double(buffer, 10000.123123123)
|
315
|
+
result.should equal(buffer)
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
describe '#write_float' do
|
320
|
+
it 'encodes a float' do
|
321
|
+
Encoding.write_float(buffer, 12.13)
|
322
|
+
buffer.should == "AB\x14{"
|
323
|
+
end
|
324
|
+
|
325
|
+
it 'appends to the buffer' do
|
326
|
+
buffer << 'BEFORE'
|
327
|
+
Encoding.write_float(buffer, 12.13)
|
328
|
+
buffer.should start_with('BEFORE')
|
329
|
+
end
|
330
|
+
|
331
|
+
it 'returns the buffer' do
|
332
|
+
result = Encoding.write_float(buffer, 12.13)
|
333
|
+
result.should equal(buffer)
|
334
|
+
end
|
335
|
+
end
|
336
|
+
end
|
337
|
+
end
|
338
|
+
end
|
@@ -0,0 +1,359 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
|
6
|
+
module Cql
|
7
|
+
module Protocol
|
8
|
+
describe RequestFrame do
|
9
|
+
context 'with OPTIONS requests' do
|
10
|
+
it 'encodes an OPTIONS request' do
|
11
|
+
bytes = RequestFrame.new(OptionsRequest.new).write('')
|
12
|
+
bytes.should == "\x01\x00\x00\x05\x00\x00\x00\x00"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'with STARTUP requests' do
|
17
|
+
it 'encodes the request' do
|
18
|
+
bytes = RequestFrame.new(StartupRequest.new('3.0.0', 'snappy')).write('')
|
19
|
+
bytes.should == "\x01\x00\x00\x01\x00\x00\x00\x2b\x00\x02\x00\x0bCQL_VERSION\x00\x053.0.0\x00\x0bCOMPRESSION\x00\x06snappy"
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'defaults to CQL 3.0.0 and no compression' do
|
23
|
+
bytes = RequestFrame.new(StartupRequest.new).write('')
|
24
|
+
bytes.should == "\x01\x00\x00\x01\x00\x00\x00\x16\x00\x01\x00\x0bCQL_VERSION\x00\x053.0.0"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'with REGISTER requests' do
|
29
|
+
it 'encodes the request' do
|
30
|
+
bytes = RequestFrame.new(RegisterRequest.new('TOPOLOGY_CHANGE', 'STATUS_CHANGE')).write('')
|
31
|
+
bytes.should == "\x01\x00\x00\x0b\x00\x00\x00\x22\x00\x02\x00\x0fTOPOLOGY_CHANGE\x00\x0dSTATUS_CHANGE"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'with QUERY requests' do
|
36
|
+
it 'encodes the request' do
|
37
|
+
bytes = RequestFrame.new(QueryRequest.new('USE system', :all)).write('')
|
38
|
+
bytes.should == "\x01\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x0aUSE system\x00\x05"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'with PREPARE requests' do
|
43
|
+
it 'encodes the request' do
|
44
|
+
bytes = RequestFrame.new(PrepareRequest.new('UPDATE users SET email = ? WHERE user_name = ?')).write('')
|
45
|
+
bytes.should == "\x01\x00\x00\x09\x00\x00\x00\x32\x00\x00\x00\x2eUPDATE users SET email = ? WHERE user_name = ?"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'with EXECUTE requests' do
|
50
|
+
let :id do
|
51
|
+
"\xCAH\x7F\x1Ez\x82\xD2<N\x8A\xF35Qq\xA5/"
|
52
|
+
end
|
53
|
+
|
54
|
+
let :column_metadata do
|
55
|
+
[['ks', 'tbl', 'col1', :varchar], ['ks', 'tbl', 'col2', :int], ['ks', 'tbl', 'col3', :varchar]]
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'encodes the request' do
|
59
|
+
bytes = RequestFrame.new(ExecuteRequest.new(id, column_metadata, ['hello', 42, 'foo'], :each_quorum)).write('')
|
60
|
+
bytes.should == "\x01\x00\x00\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"
|
61
|
+
end
|
62
|
+
|
63
|
+
specs = [
|
64
|
+
[:ascii, 'test', "test"],
|
65
|
+
[:bigint, 1012312312414123, "\x00\x03\x98\xB1S\xC8\x7F\xAB"],
|
66
|
+
[:blob, "\xab\xcd", "\xab\xcd"],
|
67
|
+
[:boolean, false, "\x00"],
|
68
|
+
[:boolean, true, "\x01"],
|
69
|
+
[:decimal, BigDecimal.new('1042342234234.123423435647768234'), "\x00\x00\x00\x12\r'\xFDI\xAD\x80f\x11g\xDCfV\xAA"],
|
70
|
+
[:double, 10000.123123123, "@\xC3\x88\x0F\xC2\x7F\x9DU"],
|
71
|
+
[:float, 12.13, "AB\x14{"],
|
72
|
+
[:inet, IPAddr.new('8.8.8.8'), "\x08\x08\x08\x08"],
|
73
|
+
[:inet, IPAddr.new('::1'), "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"],
|
74
|
+
[:int, 12348098, "\x00\xBCj\xC2"],
|
75
|
+
[:text, 'FOOBAR', 'FOOBAR'],
|
76
|
+
[:timestamp, Time.at(1358013521.123), "\x00\x00\x01</\xE9\xDC\xE3"],
|
77
|
+
[:timeuuid, Uuid.new('a4a70900-24e1-11df-8924-001ff3591711'), "\xA4\xA7\t\x00$\xE1\x11\xDF\x89$\x00\x1F\xF3Y\x17\x11"],
|
78
|
+
[:uuid, Uuid.new('cfd66ccc-d857-4e90-b1e5-df98a3d40cd6'), "\xCF\xD6l\xCC\xD8WN\x90\xB1\xE5\xDF\x98\xA3\xD4\f\xD6"],
|
79
|
+
[:varchar, 'hello', 'hello'],
|
80
|
+
[:varint, 1231312312331283012830129382342342412123, "\x03\x9EV \x15\f\x03\x9DK\x18\xCDI\\$?\a["],
|
81
|
+
[:varint, -234234234234, "\xC9v\x8D:\x86"]
|
82
|
+
]
|
83
|
+
specs.each do |type, value, expected_bytes|
|
84
|
+
it "encodes #{type} values" do
|
85
|
+
metadata = [['ks', 'tbl', 'id_column', type]]
|
86
|
+
bytes = RequestFrame.new(ExecuteRequest.new(id, metadata, [value], :one)).write('')
|
87
|
+
bytes.slice!(0, 8 + 2 + 16 + 2)
|
88
|
+
length = bytes.slice!(0, 4).unpack('N').first
|
89
|
+
result_bytes = bytes[0, length]
|
90
|
+
result_bytes.should == expected_bytes
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'raises an error when the metadata and values don\'t have the same size' do
|
95
|
+
expect { ExecuteRequest.new(id, column_metadata, ['hello', 42], :each_quorum) }.to raise_error(ArgumentError)
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'raises an error for unsupported column types' do
|
99
|
+
column_metadata[2][3] = :imaginary
|
100
|
+
expect { RequestFrame.new(ExecuteRequest.new(id, column_metadata, ['hello', 42, 'foo'], :each_quorum)).write('') }.to raise_error(UnsupportedColumnTypeError)
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'raises an error when it cannot encode the argument' do
|
104
|
+
expect { ExecuteRequest.new(id, column_metadata, ['hello', 'not an int', 'foo'], :each_quorum).write('') }.to raise_error(TypeError, /cannot be encoded as INT/)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context 'with a stream ID' do
|
109
|
+
it 'encodes the stream ID in the header' do
|
110
|
+
bytes = RequestFrame.new(QueryRequest.new('USE system', :all), 42).write('')
|
111
|
+
bytes[2].should == "\x2a"
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'defaults to zero' do
|
115
|
+
bytes = RequestFrame.new(QueryRequest.new('USE system', :all)).write('')
|
116
|
+
bytes[2].should == "\x00"
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'raises an exception if the stream ID is outside of 0..127' do
|
120
|
+
expect { RequestFrame.new(QueryRequest.new('USE system', :all), -1) }.to raise_error(InvalidStreamIdError)
|
121
|
+
expect { RequestFrame.new(QueryRequest.new('USE system', :all), 128) }.to raise_error(InvalidStreamIdError)
|
122
|
+
expect { RequestFrame.new(QueryRequest.new('USE system', :all), 99999999) }.to raise_error(InvalidStreamIdError)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
describe StartupRequest do
|
127
|
+
describe '#to_s' do
|
128
|
+
it 'returns a pretty string' do
|
129
|
+
request = StartupRequest.new
|
130
|
+
request.to_s.should == 'STARTUP {"CQL_VERSION"=>"3.0.0"}'
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
describe OptionsRequest do
|
136
|
+
describe '#to_s' do
|
137
|
+
it 'returns a pretty string' do
|
138
|
+
request = OptionsRequest.new
|
139
|
+
request.to_s.should == 'OPTIONS'
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
describe RegisterRequest do
|
145
|
+
describe '#to_s' do
|
146
|
+
it 'returns a pretty string' do
|
147
|
+
request = RegisterRequest.new('TOPOLOGY_CHANGE', 'STATUS_CHANGE')
|
148
|
+
request.to_s.should == 'REGISTER ["TOPOLOGY_CHANGE", "STATUS_CHANGE"]'
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
describe QueryRequest do
|
154
|
+
describe '#to_s' do
|
155
|
+
it 'returns a pretty string' do
|
156
|
+
request = QueryRequest.new('SELECT * FROM system.peers', :local_quorum)
|
157
|
+
request.to_s.should == 'QUERY "SELECT * FROM system.peers" LOCAL_QUORUM'
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
describe '#eql?' do
|
162
|
+
it 'returns true when the CQL and consistency are the same' do
|
163
|
+
q1 = QueryRequest.new('SELECT * FROM system.peers', :two)
|
164
|
+
q2 = QueryRequest.new('SELECT * FROM system.peers', :two)
|
165
|
+
q2.should eql(q2)
|
166
|
+
end
|
167
|
+
|
168
|
+
it 'returns false when the consistency is different' do
|
169
|
+
q1 = QueryRequest.new('SELECT * FROM system.peers', :two)
|
170
|
+
q2 = QueryRequest.new('SELECT * FROM system.peers', :three)
|
171
|
+
q1.should_not eql(q2)
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'returns false when the CQL is different' do
|
175
|
+
q1 = QueryRequest.new('SELECT * FROM system.peers', :two)
|
176
|
+
q2 = QueryRequest.new('SELECT * FROM peers', :two)
|
177
|
+
q1.should_not eql(q2)
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'does not know about CQL syntax' do
|
181
|
+
q1 = QueryRequest.new('SELECT * FROM system.peers', :two)
|
182
|
+
q2 = QueryRequest.new('SELECT * FROM system.peers', :two)
|
183
|
+
q1.should_not eql(q2)
|
184
|
+
end
|
185
|
+
|
186
|
+
it 'is aliased as ==' do
|
187
|
+
q1 = QueryRequest.new('SELECT * FROM system.peers', :two)
|
188
|
+
q2 = QueryRequest.new('SELECT * FROM system.peers', :two)
|
189
|
+
q1.should == q2
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe '#hash' do
|
194
|
+
it 'has the same hash code as another identical object' do
|
195
|
+
q1 = QueryRequest.new('SELECT * FROM system.peers', :two)
|
196
|
+
q2 = QueryRequest.new('SELECT * FROM system.peers', :two)
|
197
|
+
q1.hash.should == q2.hash
|
198
|
+
end
|
199
|
+
|
200
|
+
it 'does not have the same hash code when the consistency is different' do
|
201
|
+
q1 = QueryRequest.new('SELECT * FROM system.peers', :two)
|
202
|
+
q2 = QueryRequest.new('SELECT * FROM system.peers', :three)
|
203
|
+
q1.hash.should_not == q2.hash
|
204
|
+
end
|
205
|
+
|
206
|
+
it 'does not have the same hash code when the CQL is different' do
|
207
|
+
q1 = QueryRequest.new('SELECT * FROM system.peers', :two)
|
208
|
+
q2 = QueryRequest.new('SELECT * FROM peers', :two)
|
209
|
+
q1.hash.should_not == q2.hash
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
describe PrepareRequest do
|
215
|
+
describe '#to_s' do
|
216
|
+
it 'returns a pretty string' do
|
217
|
+
request = PrepareRequest.new('UPDATE users SET email = ? WHERE user_name = ?')
|
218
|
+
request.to_s.should == 'PREPARE "UPDATE users SET email = ? WHERE user_name = ?"'
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
describe '#eql?' do
|
223
|
+
it 'returns true when the CQL is the same' do
|
224
|
+
p1 = PrepareRequest.new('SELECT * FROM system.peers')
|
225
|
+
p2 = PrepareRequest.new('SELECT * FROM system.peers')
|
226
|
+
p1.should eql(p2)
|
227
|
+
end
|
228
|
+
|
229
|
+
it 'returns false when the CQL is different' do
|
230
|
+
p1 = PrepareRequest.new('SELECT * FROM system.peers')
|
231
|
+
p2 = PrepareRequest.new('SELECT * FROM peers')
|
232
|
+
p1.should_not eql(p2)
|
233
|
+
end
|
234
|
+
|
235
|
+
it 'does not know about CQL syntax' do
|
236
|
+
p1 = PrepareRequest.new('SELECT * FROM system.peers')
|
237
|
+
p2 = PrepareRequest.new('SELECT * FROM system.peers')
|
238
|
+
p1.should_not eql(p2)
|
239
|
+
end
|
240
|
+
|
241
|
+
it 'is aliased as ==' do
|
242
|
+
p1 = PrepareRequest.new('SELECT * FROM system.peers')
|
243
|
+
p2 = PrepareRequest.new('SELECT * FROM system.peers')
|
244
|
+
p1.should == p2
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
describe '#hash' do
|
249
|
+
it 'has the same hash code as another identical object' do
|
250
|
+
p1 = PrepareRequest.new('SELECT * FROM system.peers')
|
251
|
+
p2 = PrepareRequest.new('SELECT * FROM system.peers')
|
252
|
+
p1.hash.should == p2.hash
|
253
|
+
end
|
254
|
+
|
255
|
+
it 'does not have the same hash code when the CQL is different' do
|
256
|
+
p1 = PrepareRequest.new('SELECT * FROM system.peers')
|
257
|
+
p2 = PrepareRequest.new('SELECT * FROM peers')
|
258
|
+
p1.hash.should_not == p2.hash
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
describe ExecuteRequest do
|
264
|
+
let :id do
|
265
|
+
"\xCAH\x7F\x1Ez\x82\xD2<N\x8A\xF35Qq\xA5/"
|
266
|
+
end
|
267
|
+
|
268
|
+
let :metadata do
|
269
|
+
[
|
270
|
+
['ks', 'tbl', 'col1', :varchar],
|
271
|
+
['ks', 'tbl', 'col2', :int],
|
272
|
+
['ks', 'tbl', 'col3', :varchar]
|
273
|
+
]
|
274
|
+
end
|
275
|
+
|
276
|
+
let :values do
|
277
|
+
['hello', 42, 'foo']
|
278
|
+
end
|
279
|
+
|
280
|
+
describe '#to_s' do
|
281
|
+
it 'returns a pretty string' do
|
282
|
+
request = ExecuteRequest.new(id, metadata, values, :each_quorum)
|
283
|
+
request.to_s.should == 'EXECUTE ca487f1e7a82d23c4e8af3355171a52f ["hello", 42, "foo"] EACH_QUORUM'
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
describe '#eql?' do
|
288
|
+
it 'returns true when the ID, metadata, values and consistency are the same' do
|
289
|
+
e1 = ExecuteRequest.new(id, metadata, values, :one)
|
290
|
+
e2 = ExecuteRequest.new(id, metadata, values, :one)
|
291
|
+
e1.should eql(e2)
|
292
|
+
end
|
293
|
+
|
294
|
+
it 'returns false when the ID is different' do
|
295
|
+
e1 = ExecuteRequest.new(id, metadata, values, :one)
|
296
|
+
e2 = ExecuteRequest.new(id.reverse, metadata, values, :one)
|
297
|
+
e1.should_not eql(e2)
|
298
|
+
end
|
299
|
+
|
300
|
+
it 'returns false when the metadata is different' do
|
301
|
+
e1 = ExecuteRequest.new(id, metadata, values, :one)
|
302
|
+
e2 = ExecuteRequest.new(id, metadata.reverse, values, :one)
|
303
|
+
e1.should_not eql(e2)
|
304
|
+
end
|
305
|
+
|
306
|
+
it 'returns false when the values are different' do
|
307
|
+
e1 = ExecuteRequest.new(id, metadata, values, :one)
|
308
|
+
e2 = ExecuteRequest.new(id, metadata, values.reverse, :one)
|
309
|
+
e1.should_not eql(e2)
|
310
|
+
end
|
311
|
+
|
312
|
+
it 'returns false when the consistency is different' do
|
313
|
+
e1 = ExecuteRequest.new(id, metadata, values, :one)
|
314
|
+
e2 = ExecuteRequest.new(id, metadata, values, :two)
|
315
|
+
e1.should_not eql(e2)
|
316
|
+
end
|
317
|
+
|
318
|
+
it 'is aliased as ==' do
|
319
|
+
e1 = ExecuteRequest.new(id, metadata, values, :one)
|
320
|
+
e2 = ExecuteRequest.new(id, metadata, values, :one)
|
321
|
+
e1.should == e2
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
describe '#hash' do
|
326
|
+
it 'has the same hash code as another identical object' do
|
327
|
+
e1 = ExecuteRequest.new(id, metadata, values, :one)
|
328
|
+
e2 = ExecuteRequest.new(id, metadata, values, :one)
|
329
|
+
e1.hash.should == e2.hash
|
330
|
+
end
|
331
|
+
|
332
|
+
it 'does not have the same hash code when the ID is different' do
|
333
|
+
e1 = ExecuteRequest.new(id, metadata, values, :one)
|
334
|
+
e2 = ExecuteRequest.new(id.reverse, metadata, values, :one)
|
335
|
+
e1.hash.should_not == e2.hash
|
336
|
+
end
|
337
|
+
|
338
|
+
it 'does not have the same hash code when the metadata is different' do
|
339
|
+
e1 = ExecuteRequest.new(id, metadata, values, :one)
|
340
|
+
e2 = ExecuteRequest.new(id, metadata.reverse, values, :one)
|
341
|
+
e1.hash.should_not == e2.hash
|
342
|
+
end
|
343
|
+
|
344
|
+
it 'does not have the same hash code when the values are different' do
|
345
|
+
e1 = ExecuteRequest.new(id, metadata, values, :one)
|
346
|
+
e2 = ExecuteRequest.new(id, metadata, values.reverse, :one)
|
347
|
+
e1.hash.should_not == e2.hash
|
348
|
+
end
|
349
|
+
|
350
|
+
it 'does not have the same hash code when the consistency is different' do
|
351
|
+
e1 = ExecuteRequest.new(id, metadata, values, :one)
|
352
|
+
e2 = ExecuteRequest.new(id, metadata, values, :two)
|
353
|
+
e1.hash.should_not == e2.hash
|
354
|
+
end
|
355
|
+
end
|
356
|
+
end
|
357
|
+
end
|
358
|
+
end
|
359
|
+
end
|