cql-rb 1.0.0.pre0
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/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
|