cql-rb 1.1.3 → 1.2.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.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +19 -11
  3. data/lib/cql.rb +1 -0
  4. data/lib/cql/client.rb +41 -9
  5. data/lib/cql/client/asynchronous_client.rb +9 -4
  6. data/lib/cql/client/asynchronous_prepared_statement.rb +2 -2
  7. data/lib/cql/client/connection_helper.rb +43 -20
  8. data/lib/cql/client/execute_options_decoder.rb +4 -1
  9. data/lib/cql/client/query_result.rb +7 -3
  10. data/lib/cql/client/query_trace.rb +46 -0
  11. data/lib/cql/client/request_runner.rb +7 -2
  12. data/lib/cql/client/void_result.rb +42 -0
  13. data/lib/cql/compression.rb +53 -0
  14. data/lib/cql/compression/snappy_compressor.rb +42 -0
  15. data/lib/cql/io/io_reactor.rb +9 -4
  16. data/lib/cql/protocol.rb +5 -3
  17. data/lib/cql/protocol/cql_protocol_handler.rb +14 -9
  18. data/lib/cql/protocol/frame_decoder.rb +106 -0
  19. data/lib/cql/protocol/frame_encoder.rb +31 -0
  20. data/lib/cql/protocol/request.rb +7 -11
  21. data/lib/cql/protocol/requests/execute_request.rb +2 -2
  22. data/lib/cql/protocol/requests/options_request.rb +4 -0
  23. data/lib/cql/protocol/requests/prepare_request.rb +2 -2
  24. data/lib/cql/protocol/requests/query_request.rb +2 -2
  25. data/lib/cql/protocol/requests/startup_request.rb +12 -5
  26. data/lib/cql/protocol/response.rb +13 -2
  27. data/lib/cql/protocol/responses/authenticate_response.rb +5 -1
  28. data/lib/cql/protocol/responses/detailed_error_response.rb +2 -2
  29. data/lib/cql/protocol/responses/error_response.rb +7 -2
  30. data/lib/cql/protocol/responses/event_response.rb +4 -2
  31. data/lib/cql/protocol/responses/prepared_result_response.rb +20 -4
  32. data/lib/cql/protocol/responses/ready_response.rb +5 -1
  33. data/lib/cql/protocol/responses/result_response.rb +10 -2
  34. data/lib/cql/protocol/responses/rows_result_response.rb +5 -4
  35. data/lib/cql/protocol/responses/schema_change_event_response.rb +1 -1
  36. data/lib/cql/protocol/responses/schema_change_result_response.rb +5 -4
  37. data/lib/cql/protocol/responses/set_keyspace_result_response.rb +4 -3
  38. data/lib/cql/protocol/responses/{status_change_event_result_response.rb → status_change_event_response.rb} +1 -1
  39. data/lib/cql/protocol/responses/supported_response.rb +5 -1
  40. data/lib/cql/protocol/responses/{topology_change_event_result_response.rb → topology_change_event_response.rb} +0 -0
  41. data/lib/cql/protocol/responses/void_result_response.rb +2 -2
  42. data/lib/cql/version.rb +1 -1
  43. data/spec/cql/client/asynchronous_client_spec.rb +52 -31
  44. data/spec/cql/client/asynchronous_prepared_statement_spec.rb +16 -2
  45. data/spec/cql/client/connection_helper_spec.rb +90 -12
  46. data/spec/cql/client/query_trace_spec.rb +138 -0
  47. data/spec/cql/client/request_runner_spec.rb +44 -7
  48. data/spec/cql/client/void_result_spec.rb +43 -0
  49. data/spec/cql/compression/compression_common.rb +59 -0
  50. data/spec/cql/compression/snappy_compressor_spec.rb +23 -0
  51. data/spec/cql/io/io_reactor_spec.rb +8 -1
  52. data/spec/cql/protocol/cql_protocol_handler_spec.rb +40 -0
  53. data/spec/cql/protocol/frame_decoder_spec.rb +132 -0
  54. data/spec/cql/protocol/frame_encoder_spec.rb +105 -0
  55. data/spec/cql/protocol/requests/credentials_request_spec.rb +2 -4
  56. data/spec/cql/protocol/requests/execute_request_spec.rb +5 -5
  57. data/spec/cql/protocol/requests/options_request_spec.rb +10 -4
  58. data/spec/cql/protocol/requests/prepare_request_spec.rb +3 -3
  59. data/spec/cql/protocol/requests/query_request_spec.rb +10 -5
  60. data/spec/cql/protocol/requests/register_request_spec.rb +3 -3
  61. data/spec/cql/protocol/requests/startup_request_spec.rb +11 -5
  62. data/spec/cql/protocol/responses/authenticate_response_spec.rb +27 -0
  63. data/spec/cql/protocol/responses/detailed_error_response_spec.rb +78 -0
  64. data/spec/cql/protocol/responses/error_response_spec.rb +36 -0
  65. data/spec/cql/protocol/responses/event_response_spec.rb +40 -0
  66. data/spec/cql/protocol/responses/prepared_result_response_spec.rb +108 -0
  67. data/spec/cql/protocol/responses/ready_response_spec.rb +39 -0
  68. data/spec/cql/protocol/responses/result_response_spec.rb +57 -0
  69. data/spec/cql/protocol/responses/rows_result_response_spec.rb +273 -0
  70. data/spec/cql/protocol/responses/schema_change_event_response_spec.rb +93 -0
  71. data/spec/cql/protocol/responses/schema_change_result_response_spec.rb +51 -19
  72. data/spec/cql/protocol/responses/set_keyspace_result_response_spec.rb +34 -0
  73. data/spec/cql/protocol/responses/status_change_event_response_spec.rb +35 -0
  74. data/spec/cql/protocol/responses/supported_response_spec.rb +27 -0
  75. data/spec/cql/protocol/responses/topology_change_event_response_spec.rb +35 -0
  76. data/spec/cql/protocol/responses/void_result_response_spec.rb +29 -0
  77. data/spec/integration/client_spec.rb +45 -0
  78. data/spec/integration/protocol_spec.rb +46 -0
  79. data/spec/spec_helper.rb +2 -1
  80. data/spec/support/fake_io_reactor.rb +1 -1
  81. metadata +51 -10
  82. data/lib/cql/protocol/response_frame.rb +0 -129
  83. data/spec/cql/protocol/request_spec.rb +0 -45
  84. data/spec/cql/protocol/response_frame_spec.rb +0 -811
@@ -46,9 +46,9 @@ module Cql
46
46
  when Protocol::PrepareRequest
47
47
  statement_id = [rand(2**31)].pack('c*')
48
48
  connection[:last_prepared_statement_id] = statement_id
49
- Protocol::PreparedResultResponse.new(statement_id, raw_metadata)
49
+ Protocol::PreparedResultResponse.new(statement_id, raw_metadata, nil)
50
50
  when Protocol::ExecuteRequest
51
- Protocol::RowsResultResponse.new(rows, raw_metadata)
51
+ Protocol::RowsResultResponse.new(rows, raw_metadata, nil)
52
52
  else
53
53
  raise %(Unexpected request: #{request})
54
54
  end
@@ -190,6 +190,20 @@ module Cql
190
190
  expect { f1.value }.to raise_error(NoMethodError)
191
191
  expect { f2.value }.to raise_error(ArgumentError)
192
192
  end
193
+
194
+ it 'sets the trace flag' do
195
+ tracing = false
196
+ connections.each do |c|
197
+ c.handle_request do |r, t|
198
+ if r.is_a?(Protocol::ExecuteRequest)
199
+ tracing = r.trace
200
+ end
201
+ handle_request(c, r, t)
202
+ end
203
+ end
204
+ statement.execute(11, 'hello', trace: true).value
205
+ tracing.should be_true
206
+ end
193
207
  end
194
208
  end
195
209
  end
@@ -7,7 +7,7 @@ module Cql
7
7
  module Client
8
8
  describe ConnectionHelper do
9
9
  let :connection_helper do
10
- described_class.new(io_reactor, 9876, nil, 1, 7, logger)
10
+ described_class.new(io_reactor, 9876, nil, 1, 7, compressor, logger)
11
11
  end
12
12
 
13
13
  let :io_reactor do
@@ -18,6 +18,10 @@ module Cql
18
18
  NullLogger.new
19
19
  end
20
20
 
21
+ let :compressor do
22
+ nil
23
+ end
24
+
21
25
  describe '#connect' do
22
26
  let :hosts do
23
27
  %w[host0 host1]
@@ -92,10 +96,26 @@ module Cql
92
96
  io_reactor.stub(:connect).with('host1', 9876, 7).and_return(Future.resolved(connection1))
93
97
  connection_helper.connect(hosts, 'some_keyspace')
94
98
  [connection0, connection1].each do |c|
95
- c.requests[0].should be_a(Protocol::StartupRequest)
96
- c.requests[1].cql.should match(/SELECT .* FROM system.local/)
97
- c.requests[2].cql.should == 'USE some_keyspace'
99
+ c.requests[0].should be_a(Protocol::OptionsRequest)
100
+ c.requests[1].should be_a(Protocol::StartupRequest)
101
+ c.requests[2].cql.should match(/SELECT .* FROM system.local/)
102
+ c.requests[3].cql.should == 'USE some_keyspace'
103
+ end
104
+ end
105
+
106
+ it 'saves the supported CQL version and compression algorithms on the connection' do
107
+ connection = FakeConnection.new('host0', 9876, 7)
108
+ connection.handle_request do |request, timeout|
109
+ if request.is_a?(Protocol::OptionsRequest)
110
+ Protocol::SupportedResponse.new('CQL_VERSION' => %w[3.1.1], 'COMPRESSION' => %w[lz4 snappy])
111
+ else
112
+ connection.default_request_handler(request, timeout)
113
+ end
98
114
  end
115
+ io_reactor.stub(:connect).with('host0', 9876, 7).and_return(Future.resolved(connection))
116
+ connection_helper.connect(hosts.take(1), 'some_keyspace')
117
+ connection[:cql_version].should == %w[3.1.1]
118
+ connection[:compression].should == %w[lz4 snappy]
99
119
  end
100
120
 
101
121
  it 'fails if authentication is required and no credentials were specified' do
@@ -114,7 +134,7 @@ module Cql
114
134
 
115
135
  it 'authenticates when authentication is required and credentials were specified' do
116
136
  credentials = {'username' => 'foo', 'password' => 'bar'}
117
- connection_helper = described_class.new(io_reactor, 9876, credentials, 1, 7, logger)
137
+ connection_helper = described_class.new(io_reactor, 9876, credentials, 1, 7, nil, logger)
118
138
  connection = FakeConnection.new('host0', 9876, 7)
119
139
  authentication_sent = false
120
140
  connection.handle_request do |request|
@@ -138,7 +158,7 @@ module Cql
138
158
  connection.handle_request do |request|
139
159
  if request.is_a?(Protocol::QueryRequest) && request.cql =~ /SELECT .* FROM system\.local/
140
160
  row = {'data_center' => 'dc1', 'host_id' => Uuid.new('eac69196-1e28-11e3-8e2b-191b6d153d0c')}
141
- Protocol::RowsResultResponse.new([row], local_metadata)
161
+ Protocol::RowsResultResponse.new([row], local_metadata, nil)
142
162
  else
143
163
  connection.default_request_handler(request)
144
164
  end
@@ -180,11 +200,68 @@ module Cql
180
200
  end
181
201
 
182
202
  it 'connects to each node a configurable number of times' do
183
- connection_helper = described_class.new(io_reactor, 9876, nil, connections_per_node = 3, 7, logger)
203
+ connection_helper = described_class.new(io_reactor, 9876, nil, connections_per_node = 3, 7, nil, logger)
184
204
  connection_helper.connect(hosts, nil)
185
205
  io_reactor.should have_received(:connect).with('host0', 9876, 7).exactly(3).times
186
206
  io_reactor.should have_received(:connect).with('host1', 9876, 7).exactly(3).times
187
207
  end
208
+
209
+ context 'when a compressor is specified' do
210
+ let :compressor do
211
+ double(:compressor, algorithm: 'snappy')
212
+ end
213
+
214
+ let :connection do
215
+ FakeConnection.new('host0', 9876, 7)
216
+ end
217
+
218
+ it 'enables compression by sending the algorithm with the STARTUP request' do
219
+ connection.handle_request do |request, timeout|
220
+ if request.is_a?(Protocol::OptionsRequest)
221
+ Protocol::SupportedResponse.new('CQL_VERSION' => %w[3.1.1], 'COMPRESSION' => %w[lz4 snappy])
222
+ else
223
+ connection.default_request_handler(request, timeout)
224
+ end
225
+ end
226
+ io_reactor.stub(:connect).with('host0', 9876, 7).and_return(Future.resolved(connection))
227
+ connection_helper.connect(hosts.take(1), 'some_keyspace')
228
+ connection.requests[1].options['COMPRESSION'].should == 'snappy'
229
+ end
230
+
231
+ it 'does not enable compression when the algorithm is not supported' do
232
+ connection.handle_request do |request, timeout|
233
+ if request.is_a?(Protocol::OptionsRequest)
234
+ Protocol::SupportedResponse.new('CQL_VERSION' => %w[3.1.1], 'COMPRESSION' => %w[lz4])
235
+ else
236
+ connection.default_request_handler(request, timeout)
237
+ end
238
+ end
239
+ io_reactor.stub(:connect).with('host0', 9876, 7).and_return(Future.resolved(connection))
240
+ connection_helper.connect(hosts.take(1), 'some_keyspace')
241
+ connection.requests[1].options.should_not have_key('COMPRESSION')
242
+ end
243
+
244
+ it 'logs a warning when compression was disabled because the algorithm was not supported' do
245
+ logger.stub(:warn)
246
+ connection.handle_request do |request, timeout|
247
+ if request.is_a?(Protocol::OptionsRequest)
248
+ Protocol::SupportedResponse.new('CQL_VERSION' => %w[3.1.1], 'COMPRESSION' => %w[lz4])
249
+ else
250
+ connection.default_request_handler(request, timeout)
251
+ end
252
+ end
253
+ io_reactor.stub(:connect).with('host0', 9876, 7).and_return(Future.resolved(connection))
254
+ connection_helper.connect(hosts.take(1), 'some_keyspace')
255
+ logger.should have_received(:warn).with(/not supported/)
256
+ end
257
+
258
+ it 'logs the name of the compression algorithm when connecting' do
259
+ logger.stub(:debug)
260
+ io_reactor.stub(:connect).with('host0', 9876, 7).and_return(Future.resolved(connection))
261
+ connection_helper.connect(hosts.take(1), 'some_keyspace')
262
+ logger.should have_received(:debug).with(/using "snappy" compression/)
263
+ end
264
+ end
188
265
  end
189
266
 
190
267
  describe '#discover_peers' do
@@ -232,7 +309,7 @@ module Cql
232
309
  seed_connections.each do |c|
233
310
  c.handle_request do |request|
234
311
  if request.cql =~ /SELECT .* FROM system\.peers/
235
- Protocol::RowsResultResponse.new(yield, peer_metadata)
312
+ Protocol::RowsResultResponse.new(yield, peer_metadata, nil)
236
313
  end
237
314
  end
238
315
  end
@@ -308,9 +385,10 @@ module Cql
308
385
  peer_request_response { seed_connection_rows + extra_connection_rows.take(1) }
309
386
  f = connection_helper.discover_peers(seed_connections, 'some_keyspace')
310
387
  f.value
311
- connection.requests[0].should be_a(Protocol::StartupRequest)
312
- connection.requests[1].cql.should match(/SELECT .* FROM system.local/)
313
- connection.requests[2].cql.should == 'USE some_keyspace'
388
+ connection.requests[0].should be_a(Protocol::OptionsRequest)
389
+ connection.requests[1].should be_a(Protocol::StartupRequest)
390
+ connection.requests[2].cql.should match(/SELECT .* FROM system.local/)
391
+ connection.requests[3].cql.should == 'USE some_keyspace'
314
392
  end
315
393
 
316
394
  it 'connects only to node in the same data centers as the seed nodes' do
@@ -338,7 +416,7 @@ module Cql
338
416
  end
339
417
 
340
418
  it 'connects to each node a configurable number of times' do
341
- connection_helper = described_class.new(io_reactor, 9876, nil, connections_per_node = 3, 7, logger)
419
+ connection_helper = described_class.new(io_reactor, 9876, nil, connections_per_node = 3, 7, nil, logger)
342
420
  connection = FakeConnection.new('host3', 9876, 7)
343
421
  io_reactor.stub(:connect).with('1.0.0.3', 9876, 7).and_return(Future.resolved(connection))
344
422
  peer_request_response { seed_connection_rows + extra_connection_rows.take(1) }
@@ -0,0 +1,138 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+
6
+ module Cql
7
+ module Client
8
+ describe QueryTrace do
9
+ let :trace do
10
+ described_class.new(session_row, event_rows)
11
+ end
12
+
13
+ let :started_at do
14
+ Time.now
15
+ end
16
+
17
+ let :session_row do
18
+ {
19
+ 'session_id' => Uuid.new('a1028490-3f05-11e3-9531-fb72eff05fbb'),
20
+ 'coordinator' => IPAddr.new('127.0.0.1'),
21
+ 'duration' => 1263,
22
+ 'parameters' => {
23
+ 'query' => 'SELECT * FROM something'
24
+ },
25
+ 'request' => 'Execute CQL3 query',
26
+ 'started_at' => started_at
27
+ }
28
+ end
29
+
30
+ let :event_rows do
31
+ [
32
+ {
33
+ 'session_id' => Uuid.new('a1028490-3f05-11e3-9531-fb72eff05fbb'),
34
+ 'event_id' => TimeUuid.new('a1028491-3f05-11e3-9531-fb72eff05fbb'),
35
+ 'activity' => 'Parsing statement',
36
+ 'source' => IPAddr.new('127.0.0.1'),
37
+ 'source_elapsed' => 52,
38
+ 'thread' => 'Native-Transport-Requests:126'
39
+ },
40
+ {
41
+ 'session_id' => Uuid.new('a1028490-3f05-11e3-9531-fb72eff05fbb'),
42
+ 'event_id' => TimeUuid.new('a1028492-3f05-11e3-9531-fb72eff05fbb'),
43
+ 'activity' => 'Peparing statement',
44
+ 'source' => IPAddr.new('127.0.0.1'),
45
+ 'source_elapsed' => 54,
46
+ 'thread' => 'Native-Transport-Requests:126'
47
+ },
48
+ ]
49
+ end
50
+
51
+ context 'when the session is nil' do
52
+ it 'returns nil from all methods' do
53
+ trace = described_class.new(nil, nil)
54
+ trace.coordinator.should be_nil
55
+ trace.cql.should be_nil
56
+ trace.started_at.should be_nil
57
+ trace.events.should be_empty
58
+ end
59
+ end
60
+
61
+ context 'when the duration field of the session is nil' do
62
+ it 'raises an IncompleteTraceError' do
63
+ session_row['duration'] = nil
64
+ expect { described_class.new(session_row, event_rows) }.to raise_error(IncompleteTraceError)
65
+ end
66
+ end
67
+
68
+ describe '#coordinator' do
69
+ it 'returns the IP address of the coordinator node' do
70
+ trace.coordinator.should == IPAddr.new('127.0.0.1')
71
+ end
72
+ end
73
+
74
+ describe '#cql' do
75
+ it 'returns the query' do
76
+ trace.cql.should == 'SELECT * FROM something'
77
+ end
78
+ end
79
+
80
+ describe '#started_at' do
81
+ it 'returns the time the request started' do
82
+ trace.started_at.should eql(started_at)
83
+ end
84
+ end
85
+
86
+ describe '#duration' do
87
+ it 'returns the duration in seconds' do
88
+ trace.duration.should == 0.001263
89
+ end
90
+ end
91
+
92
+ describe '#events' do
93
+ it 'returns a list of TraceEvents' do
94
+ trace.events.should have(2).items
95
+ trace.events.first.should be_a(TraceEvent)
96
+ end
97
+
98
+ it 'returns an unmodifiable list' do
99
+ expect { trace.events << :foo }.to raise_error
100
+ end
101
+
102
+ context 'returns a list of trace events whose' do
103
+ let :events do
104
+ trace.events
105
+ end
106
+
107
+ let :event do
108
+ events.first
109
+ end
110
+
111
+ describe '#activity' do
112
+ it 'returns the event activity' do
113
+ event.activity.should == 'Parsing statement'
114
+ end
115
+ end
116
+
117
+ describe '#source' do
118
+ it 'returns the event source' do
119
+ event.source.should == IPAddr.new('127.0.0.1')
120
+ end
121
+ end
122
+
123
+ describe '#source_elapsed' do
124
+ it 'returns the elapsed time at the source' do
125
+ event.source_elapsed.should == 0.000052
126
+ end
127
+ end
128
+
129
+ describe '#time' do
130
+ it 'returns the time component from the event ID' do
131
+ event.time.to_i.should == TimeUuid.new('a1028492-3f05-11e3-9531-fb72eff05fbb').to_time.to_i
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
@@ -35,27 +35,31 @@ module Cql
35
35
 
36
36
  describe '#execute' do
37
37
  let :rows_response do
38
- Protocol::RowsResultResponse.new(rows, metadata)
38
+ Protocol::RowsResultResponse.new(rows, metadata, nil)
39
39
  end
40
40
 
41
41
  let :void_response do
42
- Protocol::VoidResultResponse.new
42
+ Protocol::VoidResultResponse.new(nil)
43
43
  end
44
44
 
45
45
  let :prepared_response do
46
- Protocol::PreparedResultResponse.new("\x2a", metadata)
46
+ Protocol::PreparedResultResponse.new("\x2a", metadata, nil)
47
47
  end
48
48
 
49
49
  let :error_response do
50
50
  Protocol::ErrorResponse.new(0xbad, 'Bork')
51
51
  end
52
52
 
53
+ let :detailed_error_response do
54
+ Protocol::DetailedErrorResponse.new(0xbad, 'Bork', {:cl => :quorum, :received => 1, :blockfor => 1, :write_type => 'SINGLE'})
55
+ end
56
+
53
57
  let :authenticate_response do
54
58
  Protocol::AuthenticateResponse.new('TheAuthenticator')
55
59
  end
56
60
 
57
61
  let :set_keyspace_response do
58
- Protocol::SetKeyspaceResultResponse.new('some_keyspace')
62
+ Protocol::SetKeyspaceResultResponse.new('some_keyspace', nil)
59
63
  end
60
64
 
61
65
  def run(response, rq=request)
@@ -75,14 +79,14 @@ module Cql
75
79
  connection.should have_received(:send_request).with(request, 7)
76
80
  end
77
81
 
78
- it 'transforms a RowsResultResponse to a query result' do
82
+ it 'transforms a RowsResultResponse to a QueryResult' do
79
83
  result = run(rows_response)
80
84
  result.should have(3).items
81
85
  end
82
86
 
83
- it 'transforms a VoidResultResponse to nil' do
87
+ it 'transforms a VoidResultResponse to a VoidResult' do
84
88
  result = run(void_response)
85
- result.should be_nil
89
+ result.should be_a(VoidResult)
86
90
  end
87
91
 
88
92
  it 'transforms a AuthenticateResponse to an authentication required object' do
@@ -111,6 +115,21 @@ module Cql
111
115
  end
112
116
  end
113
117
 
118
+ it 'sets the #details field of QueryError when the response has details' do
119
+ begin
120
+ run(detailed_error_response)
121
+ rescue QueryError => e
122
+ e.details.should == detailed_error_response.details
123
+ else
124
+ fail('No error was raised')
125
+ end
126
+ end
127
+
128
+ it 'transforms a SupportedResponse into its hash of supported options' do
129
+ result = run(Protocol::SupportedResponse.new('CQL_VERSION' => %w[9.9.9], 'COMPRESSION' => %w[fractal quantum]))
130
+ result.should eql('CQL_VERSION' => %w[9.9.9], 'COMPRESSION' => %w[fractal quantum])
131
+ end
132
+
114
133
  it 'transforms all other responses to nil' do
115
134
  result = run('hibbly hobbly')
116
135
  result.should be_nil
@@ -121,6 +140,24 @@ module Cql
121
140
  result = runner.execute(connection, request) { |response| response.reverse }.value
122
141
  result.should == 'hibbly hobbly'.reverse
123
142
  end
143
+
144
+ context 'when the response has a trace ID' do
145
+ let :trace_id do
146
+ Uuid.new('63a26b40-3f02-11e3-9531-fb72eff05fbb')
147
+ end
148
+
149
+ it 'returns a QueryResult that knows its trace ID' do
150
+ connection.stub(:send_request).with(request, anything).and_return(Future.resolved(Protocol::RowsResultResponse.new(rows, metadata, trace_id)))
151
+ response = runner.execute(connection, request).value
152
+ response.trace_id.should == trace_id
153
+ end
154
+
155
+ it 'returns a VoidResult that knows its trace ID' do
156
+ connection.stub(:send_request).with(request, anything).and_return(Future.resolved(Protocol::VoidResultResponse.new(trace_id)))
157
+ response = runner.execute(connection, request).value
158
+ response.trace_id.should == trace_id
159
+ end
160
+ end
124
161
  end
125
162
  end
126
163
  end
@@ -0,0 +1,43 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+
6
+ module Cql
7
+ module Client
8
+ describe VoidResult do
9
+ describe '#empty?' do
10
+ it 'is true' do
11
+ described_class.new.should be_empty
12
+ end
13
+ end
14
+
15
+ describe '#trace_id' do
16
+ it 'is nil' do
17
+ described_class.new.trace_id.should be_nil
18
+ end
19
+
20
+ it 'is set through the constructor' do
21
+ uuid = Uuid.new('63a26b40-3f02-11e3-9531-fb72eff05fbb')
22
+ described_class.new(uuid).trace_id.should == uuid
23
+ end
24
+ end
25
+
26
+ describe '#metadata' do
27
+ it 'is empty' do
28
+ described_class.new.metadata.each.to_a.should be_empty
29
+ end
30
+ end
31
+
32
+ describe '#each' do
33
+ it 'returns an enumerable' do
34
+ described_class.new.each.should be_a(Enumerable)
35
+ end
36
+
37
+ it 'enumerates nothing' do
38
+ described_class.new.each.to_a.should be_empty
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end