mongo 2.5.0.beta → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (172) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/lib/mongo/address.rb +1 -1
  5. data/lib/mongo/address/unix.rb +1 -1
  6. data/lib/mongo/auth/user.rb +0 -5
  7. data/lib/mongo/auth/user/view.rb +4 -4
  8. data/lib/mongo/bulk_write.rb +60 -32
  9. data/lib/mongo/client.rb +44 -8
  10. data/lib/mongo/cluster.rb +14 -12
  11. data/lib/mongo/cluster/periodic_executor.rb +106 -0
  12. data/lib/mongo/cluster/{cursor_reaper.rb → reapers/cursor_reaper.rb} +5 -37
  13. data/lib/mongo/cluster/reapers/socket_reaper.rb +59 -0
  14. data/lib/mongo/collection.rb +9 -6
  15. data/lib/mongo/collection/view.rb +2 -2
  16. data/lib/mongo/collection/view/builder/aggregation.rb +2 -1
  17. data/lib/mongo/collection/view/builder/find_command.rb +1 -1
  18. data/lib/mongo/collection/view/change_stream.rb +14 -1
  19. data/lib/mongo/collection/view/map_reduce.rb +30 -13
  20. data/lib/mongo/collection/view/readable.rb +5 -5
  21. data/lib/mongo/collection/view/writable.rb +98 -51
  22. data/lib/mongo/error.rb +3 -0
  23. data/lib/mongo/error/invalid_txt_record.rb +27 -0
  24. data/lib/mongo/error/invalid_uri.rb +7 -6
  25. data/lib/mongo/error/mismatched_domain.rb +27 -0
  26. data/lib/mongo/error/no_srv_records.rb +26 -0
  27. data/lib/mongo/error/unsupported_features.rb +0 -18
  28. data/lib/mongo/index/view.rb +2 -2
  29. data/lib/mongo/operation.rb +1 -0
  30. data/lib/mongo/operation/causally_consistent.rb +33 -0
  31. data/lib/mongo/operation/commands.rb +2 -1
  32. data/lib/mongo/operation/commands/aggregate.rb +2 -7
  33. data/lib/mongo/operation/commands/count.rb +27 -0
  34. data/lib/mongo/operation/commands/distinct.rb +27 -0
  35. data/lib/mongo/operation/commands/find.rb +3 -1
  36. data/lib/mongo/operation/commands/map_reduce.rb +1 -0
  37. data/lib/mongo/operation/commands/parallel_scan.rb +1 -0
  38. data/lib/mongo/operation/specifiable.rb +12 -0
  39. data/lib/mongo/operation/uses_command_op_msg.rb +36 -5
  40. data/lib/mongo/operation/write.rb +0 -5
  41. data/lib/mongo/operation/write/bulk/bulkable.rb +4 -8
  42. data/lib/mongo/operation/write/bulk/mergable.rb +2 -0
  43. data/lib/mongo/operation/write/command/create_index.rb +19 -0
  44. data/lib/mongo/operation/write/command/create_user.rb +19 -0
  45. data/lib/mongo/operation/write/command/delete.rb +1 -2
  46. data/lib/mongo/operation/write/command/drop_index.rb +19 -0
  47. data/lib/mongo/operation/write/command/insert.rb +1 -2
  48. data/lib/mongo/operation/write/command/remove_user.rb +19 -0
  49. data/lib/mongo/operation/write/command/update.rb +1 -2
  50. data/lib/mongo/operation/write/command/update_user.rb +19 -0
  51. data/lib/mongo/operation/write/write_command_enabled.rb +1 -3
  52. data/lib/mongo/protocol/compressed.rb +2 -1
  53. data/lib/mongo/protocol/serializers.rb +6 -6
  54. data/lib/mongo/retryable.rb +48 -5
  55. data/lib/mongo/server.rb +15 -0
  56. data/lib/mongo/server/connection.rb +21 -1
  57. data/lib/mongo/server/connection_pool.rb +3 -0
  58. data/lib/mongo/server/connection_pool/queue.rb +50 -5
  59. data/lib/mongo/server/description.rb +11 -3
  60. data/lib/mongo/server/description/features.rb +26 -7
  61. data/lib/mongo/session.rb +133 -6
  62. data/lib/mongo/session/server_session.rb +30 -0
  63. data/lib/mongo/session/session_pool.rb +20 -20
  64. data/lib/mongo/uri.rb +88 -44
  65. data/lib/mongo/uri/srv_protocol.rb +158 -0
  66. data/lib/mongo/version.rb +1 -1
  67. data/lib/mongo/write_concern/normalizable.rb +12 -0
  68. data/mongo.gemspec +1 -2
  69. data/spec/mongo/address_spec.rb +12 -0
  70. data/spec/mongo/auth/user/view_spec.rb +1 -5
  71. data/spec/mongo/bulk_write_spec.rb +232 -401
  72. data/spec/mongo/change_stream_examples_spec.rb +150 -0
  73. data/spec/mongo/client_spec.rb +142 -2
  74. data/spec/mongo/cluster/cursor_reaper_spec.rb +0 -70
  75. data/spec/mongo/cluster/socket_reaper_spec.rb +32 -0
  76. data/spec/mongo/cluster_spec.rb +11 -7
  77. data/spec/mongo/collection/view/aggregation_spec.rb +46 -1
  78. data/spec/mongo/collection/view/builder/find_command_spec.rb +15 -0
  79. data/spec/mongo/collection/view/change_stream_spec.rb +79 -12
  80. data/spec/mongo/collection/view/map_reduce_spec.rb +120 -4
  81. data/spec/mongo/collection/view/readable_spec.rb +23 -5
  82. data/spec/mongo/collection_spec.rb +292 -102
  83. data/spec/mongo/command_monitoring_spec.rb +26 -32
  84. data/spec/mongo/crud_spec.rb +1 -1
  85. data/spec/mongo/cursor_spec.rb +2 -3
  86. data/spec/mongo/database_spec.rb +30 -14
  87. data/spec/mongo/dns_seedlist_discovery_spec.rb +94 -0
  88. data/spec/mongo/grid/fs_bucket_spec.rb +1 -1
  89. data/spec/mongo/grid/stream/write_spec.rb +1 -1
  90. data/spec/mongo/index/view_spec.rb +8 -46
  91. data/spec/mongo/operation/write/bulk/delete_spec.rb +2 -2
  92. data/spec/mongo/operation/write/bulk/insert_spec.rb +2 -10
  93. data/spec/mongo/operation/write/{create_index_spec.rb → command/create_index_spec.rb} +2 -6
  94. data/spec/mongo/operation/write/command/delete_spec.rb +35 -7
  95. data/spec/mongo/operation/write/{drop_index_spec.rb → command/drop_index_spec.rb} +1 -1
  96. data/spec/mongo/operation/write/command/insert_spec.rb +37 -6
  97. data/spec/mongo/operation/write/{remove_user_spec.rb → command/remove_user_spec.rb} +2 -6
  98. data/spec/mongo/operation/write/command/update_spec.rb +34 -7
  99. data/spec/mongo/operation/write/{update_user_spec.rb → command/update_user_spec.rb} +1 -1
  100. data/spec/mongo/operation/write/create_user_spec.rb +1 -1
  101. data/spec/mongo/operation/write/delete_spec.rb +1 -1
  102. data/spec/mongo/operation/write/insert_spec.rb +2 -10
  103. data/spec/mongo/operation/write/update_spec.rb +3 -15
  104. data/spec/mongo/retryable_spec.rb +1 -1
  105. data/spec/mongo/retryable_writes_spec.rb +815 -0
  106. data/spec/mongo/server/connection_pool/queue_spec.rb +35 -2
  107. data/spec/mongo/server/connection_pool_spec.rb +234 -1
  108. data/spec/mongo/server/connection_spec.rb +10 -6
  109. data/spec/mongo/server/description/features_spec.rb +51 -37
  110. data/spec/mongo/server/description_spec.rb +6 -3
  111. data/spec/mongo/server_spec.rb +87 -0
  112. data/spec/mongo/session/server_session_spec.rb +43 -0
  113. data/spec/mongo/session/session_pool_spec.rb +63 -27
  114. data/spec/mongo/session_spec.rb +247 -0
  115. data/spec/mongo/shell_examples_spec.rb +2 -2
  116. data/spec/mongo/uri/srv_protocol_spec.rb +933 -0
  117. data/spec/mongo/uri_spec.rb +42 -3
  118. data/spec/mongo/write_concern/acknowledged_spec.rb +11 -0
  119. data/spec/mongo/write_concern/unacknowledged_spec.rb +11 -0
  120. data/spec/spec_helper.rb +11 -25
  121. data/spec/support/authorization.rb +2 -1
  122. data/spec/support/connection_string.rb +8 -4
  123. data/spec/support/crud.rb +38 -24
  124. data/spec/support/crud/write.rb +30 -3
  125. data/spec/support/crud_tests/read/aggregate-out.yml +21 -0
  126. data/spec/support/crud_tests/write/bulkWrite-arrayFilters.yml +44 -0
  127. data/spec/support/crud_tests/write/findOneAndUpdate-arrayFilters.yml +1 -1
  128. data/spec/support/crud_tests/write/insertMany.yml +1 -3
  129. data/spec/support/crud_tests/write/replaceOne.yml +1 -1
  130. data/spec/support/crud_tests/write/updateMany-arrayFilters.yml +1 -1
  131. data/spec/support/crud_tests/write/updateOne-arrayFilters.yml +1 -1
  132. data/spec/support/dns_seedlist_discovery_tests/longer-parent-in-return.yml +11 -0
  133. data/spec/support/dns_seedlist_discovery_tests/misformatted-option.yml +5 -0
  134. data/spec/support/dns_seedlist_discovery_tests/no-results.yml +5 -0
  135. data/spec/support/dns_seedlist_discovery_tests/not-enough-parts.yml +5 -0
  136. data/spec/support/dns_seedlist_discovery_tests/one-result-default-port.yml +10 -0
  137. data/spec/support/dns_seedlist_discovery_tests/one-txt-record-multiple-strings.yml +10 -0
  138. data/spec/support/dns_seedlist_discovery_tests/one-txt-record.yml +11 -0
  139. data/spec/support/dns_seedlist_discovery_tests/parent-part-mismatch1.yml +5 -0
  140. data/spec/support/dns_seedlist_discovery_tests/parent-part-mismatch2.yml +5 -0
  141. data/spec/support/dns_seedlist_discovery_tests/parent-part-mismatch3.yml +5 -0
  142. data/spec/support/dns_seedlist_discovery_tests/parent-part-mismatch4.yml +5 -0
  143. data/spec/support/dns_seedlist_discovery_tests/parent-part-mismatch5.yml +5 -0
  144. data/spec/support/dns_seedlist_discovery_tests/returned-parent-too-short.yml +5 -0
  145. data/spec/support/dns_seedlist_discovery_tests/returned-parent-wrong.yml +5 -0
  146. data/spec/support/dns_seedlist_discovery_tests/two-results-default-port.yml +11 -0
  147. data/spec/support/dns_seedlist_discovery_tests/two-results-nonstandard-port.yml +11 -0
  148. data/spec/support/dns_seedlist_discovery_tests/two-txt-records.yml +5 -0
  149. data/spec/support/dns_seedlist_discovery_tests/txt-record-not-allowed-option.yml +5 -0
  150. data/spec/support/dns_seedlist_discovery_tests/txt-record-with-overridden-ssl-option.yml +11 -0
  151. data/spec/support/dns_seedlist_discovery_tests/txt-record-with-overridden-uri-option.yml +11 -0
  152. data/spec/support/dns_seedlist_discovery_tests/txt-record-with-unallowed-option.yml +5 -0
  153. data/spec/support/dns_seedlist_discovery_tests/uri-with-port.yml +5 -0
  154. data/spec/support/dns_seedlist_discovery_tests/uri-with-two-hosts.yml +5 -0
  155. data/spec/support/retryable_writes_tests/bulkWrite.yml +305 -0
  156. data/spec/support/retryable_writes_tests/deleteOne.yml +51 -0
  157. data/spec/support/retryable_writes_tests/findOneAndDelete.yml +52 -0
  158. data/spec/support/retryable_writes_tests/findOneAndReplace.yml +57 -0
  159. data/spec/support/retryable_writes_tests/findOneAndUpdate.yml +56 -0
  160. data/spec/support/retryable_writes_tests/insertMany.yml +72 -0
  161. data/spec/support/retryable_writes_tests/insertOne.yml +55 -0
  162. data/spec/support/retryable_writes_tests/replaceOne.yml +60 -0
  163. data/spec/support/retryable_writes_tests/updateOne.yml +120 -0
  164. data/spec/support/shared/session.rb +525 -24
  165. metadata +437 -350
  166. metadata.gz.sig +0 -0
  167. data/lib/mongo/operation/commands/user_query.rb +0 -72
  168. data/lib/mongo/operation/write/create_index.rb +0 -67
  169. data/lib/mongo/operation/write/create_user.rb +0 -50
  170. data/lib/mongo/operation/write/drop_index.rb +0 -63
  171. data/lib/mongo/operation/write/remove_user.rb +0 -48
  172. data/lib/mongo/operation/write/update_user.rb +0 -50
@@ -35,6 +35,7 @@ describe Mongo::Server::ConnectionPool::Queue do
35
35
  context 'when waiting for a connection to be enqueued' do
36
36
 
37
37
  before do
38
+ allow(connection).to receive(:record_checkin!).and_return(connection)
38
39
  Thread.new do
39
40
  sleep(0.5)
40
41
  queue.enqueue(connection)
@@ -66,7 +67,9 @@ describe Mongo::Server::ConnectionPool::Queue do
66
67
  describe '#enqueue' do
67
68
 
68
69
  let(:connection) do
69
- double('connection')
70
+ double('connection').tap do |con|
71
+ allow(con).to receive(:record_checkin!).and_return(con)
72
+ end
70
73
  end
71
74
 
72
75
  let(:queue) do
@@ -105,7 +108,7 @@ describe Mongo::Server::ConnectionPool::Queue do
105
108
  described_class.new { double('connection') }
106
109
  end
107
110
 
108
- it 'creates the queue with the default connections' do
111
+ it 'creates the queue with the number of default connections' do
109
112
  expect(queue.size).to eq(1)
110
113
  end
111
114
  end
@@ -187,4 +190,34 @@ describe Mongo::Server::ConnectionPool::Queue do
187
190
  end
188
191
  end
189
192
  end
193
+
194
+ describe 'close_stale_sockets!!' do
195
+
196
+ let(:queue) do
197
+ described_class.new(max_pool_size: 2, max_idle_time: 0.5) do
198
+ double('connection').tap do |con|
199
+ expect(con).to receive(:disconnect!).and_return(true)
200
+ allow(con).to receive(:record_checkin!) do
201
+ allow(con).to receive(:last_checkin).and_return(Time.now)
202
+ con
203
+ end
204
+ end
205
+ end
206
+ end
207
+
208
+ let(:connection) do
209
+ queue.dequeue
210
+ end
211
+
212
+ before do
213
+ queue.enqueue(connection)
214
+ expect(connection).to receive(:connect!).and_return(true)
215
+ sleep(0.5)
216
+ queue.close_stale_sockets!
217
+ end
218
+
219
+ it 'disconnects and reconnects up to min_size the expired connections' do
220
+ expect(queue.size).to eq(1)
221
+ end
222
+ end
190
223
  end
@@ -110,6 +110,17 @@ describe Mongo::Server::ConnectionPool do
110
110
  expect(pool.checkout).to_not eql(connection)
111
111
  end
112
112
  end
113
+
114
+ context 'when connections are checked out and checked back in' do
115
+
116
+ it 'pulls the connection from the front of the queue' do
117
+ first = pool.checkout
118
+ second = pool.checkout
119
+ pool.checkin(second)
120
+ pool.checkin(first)
121
+ expect(pool.checkout).to be(first)
122
+ end
123
+ end
113
124
  end
114
125
 
115
126
  describe '#disconnect!' do
@@ -217,7 +228,7 @@ describe Mongo::Server::ConnectionPool do
217
228
  before do
218
229
  t = Thread.new {
219
230
  # Kill the thread when it's authenticating
220
- allow(Mongo::Auth).to receive(:get) { t.kill }
231
+ allow(Mongo::Auth).to receive(:get) { t.kill and t.stop? }
221
232
  pool.with_connection { |c| c.send(:ensure_connected) { |socket| socket } }
222
233
  }
223
234
  t.join
@@ -227,4 +238,226 @@ describe Mongo::Server::ConnectionPool do
227
238
  expect(pool.checkout.send(:socket)).to be_nil
228
239
  end
229
240
  end
241
+
242
+ describe '#close_stale_sockets!' do
243
+
244
+ let(:server) do
245
+ Mongo::Server.new(address, authorized_client.cluster, monitoring, listeners, options)
246
+ end
247
+
248
+ let!(:pool) do
249
+ described_class.get(server)
250
+ end
251
+
252
+ let(:queue) do
253
+ pool.instance_variable_get(:@queue).queue
254
+ end
255
+
256
+ context 'when there is a max_idle_time specified' do
257
+
258
+ let(:options) do
259
+ TEST_OPTIONS.merge(max_pool_size: 2, max_idle_time: 0.5)
260
+ end
261
+
262
+ context 'when the connections have not been checked out' do
263
+
264
+ before do
265
+ queue.each do |conn|
266
+ expect(conn).not_to receive(:disconnect!)
267
+ end
268
+ sleep(0.5)
269
+ pool.close_stale_sockets!
270
+ end
271
+
272
+ it 'does not close any sockets' do
273
+ expect(queue.none? { |c| c.connected? }).to be(true)
274
+ end
275
+ end
276
+
277
+ context 'when the sockets have already been checked out and returned to the pool' do
278
+
279
+ context 'when min size is 0' do
280
+
281
+ let(:options) do
282
+ TEST_OPTIONS.merge(max_pool_size: 2, min_pool_size: 0, max_idle_time: 0.5)
283
+ end
284
+
285
+ before do
286
+ queue.each do |conn|
287
+ expect(conn).to receive(:disconnect!).and_call_original
288
+ end
289
+ pool.checkin(pool.checkout)
290
+ pool.checkin(pool.checkout)
291
+ sleep(0.5)
292
+ pool.close_stale_sockets!
293
+ end
294
+
295
+ it 'closes all stale sockets' do
296
+ expect(queue.all? { |c| !c.connected? }).to be(true)
297
+ end
298
+ end
299
+
300
+ context 'when min size is > 0' do
301
+
302
+ context 'when more than the number of min_size are checked out' do
303
+
304
+ let(:options) do
305
+ TEST_OPTIONS.merge(max_pool_size: 5, min_pool_size: 3, max_idle_time: 0.5)
306
+ end
307
+
308
+ before do
309
+ first = pool.checkout
310
+ second = pool.checkout
311
+ third = pool.checkout
312
+ fourth = pool.checkout
313
+ fifth = pool.checkout
314
+
315
+ pool.checkin(fifth)
316
+
317
+ expect(fifth).to receive(:disconnect!).and_call_original
318
+ expect(fifth).not_to receive(:connect!)
319
+
320
+ sleep(0.5)
321
+ pool.close_stale_sockets!
322
+ end
323
+
324
+ it 'closes all stale sockets and does not connect new ones' do
325
+ expect(queue.size).to be(1)
326
+ expect(queue[0].connected?).to be(false)
327
+ end
328
+ end
329
+
330
+ context 'when between 0 and min_size number of connections are checked out' do
331
+
332
+ let(:options) do
333
+ TEST_OPTIONS.merge(max_pool_size: 5, min_pool_size: 3, max_idle_time: 0.5)
334
+ end
335
+
336
+ before do
337
+ first = pool.checkout
338
+ second = pool.checkout
339
+ third = pool.checkout
340
+ fourth = pool.checkout
341
+ fifth = pool.checkout
342
+
343
+ pool.checkin(third)
344
+ pool.checkin(fourth)
345
+ pool.checkin(fifth)
346
+
347
+
348
+ expect(third).to receive(:disconnect!).and_call_original
349
+ expect(third).not_to receive(:connect!)
350
+
351
+ expect(fourth).to receive(:disconnect!).and_call_original
352
+ expect(fourth).not_to receive(:connect!)
353
+
354
+ expect(fifth).to receive(:disconnect!).and_call_original
355
+ expect(fifth).to receive(:connect!).and_call_original
356
+
357
+ sleep(0.5)
358
+ pool.close_stale_sockets!
359
+ end
360
+
361
+ it 'closes all stale sockets and does not connect new ones' do
362
+ expect(queue.size).to be(3)
363
+ expect(queue[0].connected?).to be(true)
364
+ expect(queue[1].connected?).to be(false)
365
+ expect(queue[2].connected?).to be(false)
366
+ end
367
+ end
368
+
369
+ context 'when a stale connection is unsuccessfully reconnected' do
370
+
371
+ let(:options) do
372
+ TEST_OPTIONS.merge(max_pool_size: 5, min_pool_size: 3, max_idle_time: 0.5)
373
+ end
374
+
375
+ before do
376
+ first = pool.checkout
377
+ second = pool.checkout
378
+ third = pool.checkout
379
+ fourth = pool.checkout
380
+ fifth = pool.checkout
381
+
382
+ pool.checkin(third)
383
+ pool.checkin(fourth)
384
+ pool.checkin(fifth)
385
+
386
+
387
+ expect(third).to receive(:disconnect!).and_call_original
388
+ expect(third).not_to receive(:connect!)
389
+
390
+ expect(fourth).to receive(:disconnect!).and_call_original
391
+ expect(fourth).not_to receive(:connect!)
392
+
393
+ expect(fifth).to receive(:disconnect!).and_call_original
394
+ allow(fifth).to receive(:connect!).and_raise(Mongo::Error::SocketError)
395
+
396
+ sleep(0.5)
397
+ pool.close_stale_sockets!
398
+ end
399
+
400
+ it 'is kept in the pool' do
401
+ expect(queue.size).to be(3)
402
+ expect(queue[0].connected?).to be(false)
403
+ expect(queue[1].connected?).to be(false)
404
+ expect(queue[2].connected?).to be(false)
405
+ end
406
+ end
407
+
408
+ context 'when exactly the min_size number of connections is checked out' do
409
+
410
+ let(:options) do
411
+ TEST_OPTIONS.merge(max_pool_size: 5, min_pool_size: 3, max_idle_time: 0.5)
412
+ end
413
+
414
+ before do
415
+ first = pool.checkout
416
+ second = pool.checkout
417
+ third = pool.checkout
418
+ fourth = pool.checkout
419
+ fifth = pool.checkout
420
+
421
+ pool.checkin(fourth)
422
+ pool.checkin(fifth)
423
+
424
+ expect(fourth).to receive(:disconnect!).and_call_original
425
+ expect(fourth).not_to receive(:connect!)
426
+
427
+ expect(fifth).to receive(:disconnect!).and_call_original
428
+ expect(fifth).not_to receive(:connect!)
429
+
430
+ sleep(0.5)
431
+ pool.close_stale_sockets!
432
+ end
433
+
434
+ it 'closes all stale sockets and does not connect new ones' do
435
+ expect(queue.size).to be(2)
436
+ expect(queue[0].connected?).to be(false)
437
+ expect(queue[1].connected?).to be(false)
438
+ end
439
+ end
440
+ end
441
+ end
442
+ end
443
+
444
+ context 'when there is no max_idle_time specified' do
445
+
446
+ let(:connection) do
447
+ conn = pool.checkout
448
+ conn.connect!
449
+ pool.checkin(conn)
450
+ conn
451
+ end
452
+
453
+ before do
454
+ expect(connection).not_to receive(:disconnect!)
455
+ pool.close_stale_sockets!
456
+ end
457
+
458
+ it 'does not close any sockets' do
459
+ expect(connection.connected?).to be(true)
460
+ end
461
+ end
462
+ end
230
463
  end
@@ -336,7 +336,7 @@ describe Mongo::Server::Connection do
336
336
  it 'closes the socket and does not use it for subsequent requests' do
337
337
  t = Thread.new {
338
338
  # Kill the thread just before the reply is read
339
- allow(Mongo::Protocol::Message).to receive(:deserialize_header) { t.kill }
339
+ allow(Mongo::Protocol::Reply).to receive(:deserialize_header) { t.kill and t.stop? }
340
340
  connection.dispatch([ query_bob ])
341
341
  }
342
342
  t.join
@@ -439,13 +439,17 @@ describe Mongo::Server::Connection do
439
439
 
440
440
  it 'raises a timeout when it expires' do
441
441
  start = Time.now
442
- expect {
443
- Timeout::timeout(3) do
442
+ begin
443
+ Timeout::timeout(1.5 + 2) do
444
444
  client[authorized_collection.name].find("$where" => "sleep(2000) || true").first
445
445
  end
446
- }.to raise_exception(Timeout::Error, "Took more than 1.5 seconds to receive data.")
447
- end_time = Time.now
448
- expect(end_time - start).to be_within(0.2).of(1.5)
446
+ rescue => ex
447
+ end_time = Time.now
448
+ expect(ex).to be_a(Timeout::Error)
449
+ expect(ex.message).to eq("Took more than 1.5 seconds to receive data.")
450
+ end
451
+ # Account for wait queue timeout (2s) and rescue
452
+ expect(end_time - start).to be_within(2.5).of(1.5)
449
453
  end
450
454
 
451
455
  context 'when the socket_timeout is negative' do
@@ -2,12 +2,16 @@ require 'spec_helper'
2
2
 
3
3
  describe Mongo::Server::Description::Features do
4
4
 
5
+ let(:features) do
6
+ described_class.new(wire_versions, default_address)
7
+ end
8
+
5
9
  describe '#initialize' do
6
10
 
7
11
  context 'when the server wire version range is the same' do
8
12
 
9
- let(:features) do
10
- described_class.new(0..3)
13
+ let(:wire_versions) do
14
+ 0..3
11
15
  end
12
16
 
13
17
  it 'sets the server wire version range' do
@@ -17,17 +21,21 @@ describe Mongo::Server::Description::Features do
17
21
 
18
22
  context 'when the server wire version range min is higher' do
19
23
 
24
+ let(:wire_versions) do
25
+ described_class::DRIVER_WIRE_VERSIONS.max+1..described_class::DRIVER_WIRE_VERSIONS.max+2
26
+ end
27
+
20
28
  it 'raises an exception' do
21
29
  expect {
22
- described_class.new(described_class::DRIVER_WIRE_VERSIONS.max+1..described_class::DRIVER_WIRE_VERSIONS.max+2)
30
+ features
23
31
  }.to raise_error(Mongo::Error::UnsupportedFeatures)
24
32
  end
25
33
  end
26
34
 
27
35
  context 'when the server wire version range max is higher' do
28
36
 
29
- let(:features) do
30
- described_class.new(0..4)
37
+ let(:wire_versions) do
38
+ 0..4
31
39
  end
32
40
 
33
41
  it 'sets the server wire version range' do
@@ -37,17 +45,21 @@ describe Mongo::Server::Description::Features do
37
45
 
38
46
  context 'when the server wire version range max is lower' do
39
47
 
48
+ let(:wire_versions) do
49
+ described_class::DRIVER_WIRE_VERSIONS.min-2..described_class::DRIVER_WIRE_VERSIONS.min-1
50
+ end
51
+
40
52
  it 'raises an exception' do
41
53
  expect {
42
- described_class.new(described_class::DRIVER_WIRE_VERSIONS.min-2..described_class::DRIVER_WIRE_VERSIONS.min-1)
54
+ features
43
55
  }.to raise_error(Mongo::Error::UnsupportedFeatures)
44
56
  end
45
57
  end
46
58
 
47
59
  context 'when the server wire version range max is lower' do
48
60
 
49
- let(:features) do
50
- described_class.new(0..2)
61
+ let(:wire_versions) do
62
+ 0..2
51
63
  end
52
64
 
53
65
  it 'sets the server wire version range' do
@@ -60,8 +72,8 @@ describe Mongo::Server::Description::Features do
60
72
 
61
73
  context 'when the wire range includes 5' do
62
74
 
63
- let(:features) do
64
- described_class.new(0..5)
75
+ let(:wire_versions) do
76
+ 0..5
65
77
  end
66
78
 
67
79
  it 'returns true' do
@@ -71,8 +83,8 @@ describe Mongo::Server::Description::Features do
71
83
 
72
84
  context 'when the wire range does not include 5' do
73
85
 
74
- let(:features) do
75
- described_class.new(0..2)
86
+ let(:wire_versions) do
87
+ 0..2
76
88
  end
77
89
 
78
90
  it 'returns false' do
@@ -85,8 +97,8 @@ describe Mongo::Server::Description::Features do
85
97
 
86
98
  context 'when the wire range includes 5' do
87
99
 
88
- let(:features) do
89
- described_class.new(0..5)
100
+ let(:wire_versions) do
101
+ 0..5
90
102
  end
91
103
 
92
104
  it 'returns true' do
@@ -96,8 +108,8 @@ describe Mongo::Server::Description::Features do
96
108
 
97
109
  context 'when the wire range does not include 5' do
98
110
 
99
- let(:features) do
100
- described_class.new(0..2)
111
+ let(:wire_versions) do
112
+ 0..2
101
113
  end
102
114
 
103
115
  it 'returns false' do
@@ -110,8 +122,8 @@ describe Mongo::Server::Description::Features do
110
122
 
111
123
  context 'when the wire range includes 4' do
112
124
 
113
- let(:features) do
114
- described_class.new(0..4)
125
+ let(:wire_versions) do
126
+ 0..4
115
127
  end
116
128
 
117
129
  it 'returns true' do
@@ -121,8 +133,8 @@ describe Mongo::Server::Description::Features do
121
133
 
122
134
  context 'when the wire range does not include 4' do
123
135
 
124
- let(:features) do
125
- described_class.new(0..2)
136
+ let(:wire_versions) do
137
+ 0..2
126
138
  end
127
139
 
128
140
  it 'returns false' do
@@ -135,8 +147,8 @@ describe Mongo::Server::Description::Features do
135
147
 
136
148
  context 'when the wire range includes 3' do
137
149
 
138
- let(:features) do
139
- described_class.new(0..3)
150
+ let(:wire_versions) do
151
+ 0..3
140
152
  end
141
153
 
142
154
  it 'returns true' do
@@ -146,8 +158,8 @@ describe Mongo::Server::Description::Features do
146
158
 
147
159
  context 'when the wire range does not include 3' do
148
160
 
149
- let(:features) do
150
- described_class.new(0..2)
161
+ let(:wire_versions) do
162
+ 0..2
151
163
  end
152
164
 
153
165
  it 'returns false' do
@@ -160,8 +172,8 @@ describe Mongo::Server::Description::Features do
160
172
 
161
173
  context 'when the wire range includes 3' do
162
174
 
163
- let(:features) do
164
- described_class.new(0..3)
175
+ let(:wire_versions) do
176
+ 0..3
165
177
  end
166
178
 
167
179
  it 'returns true' do
@@ -171,8 +183,8 @@ describe Mongo::Server::Description::Features do
171
183
 
172
184
  context 'when the wire range does not include 3' do
173
185
 
174
- let(:features) do
175
- described_class.new(0..2)
186
+ let(:wire_versions) do
187
+ 0..2
176
188
  end
177
189
 
178
190
  it 'returns false' do
@@ -185,8 +197,8 @@ describe Mongo::Server::Description::Features do
185
197
 
186
198
  context 'when the wire range includes 2' do
187
199
 
188
- let(:features) do
189
- described_class.new(0..3)
200
+ let(:wire_versions) do
201
+ 0..3
190
202
  end
191
203
 
192
204
  it 'returns true' do
@@ -196,12 +208,14 @@ describe Mongo::Server::Description::Features do
196
208
 
197
209
  context 'when the wire range does not include 2' do
198
210
 
199
- let(:features) do
200
- described_class.new(0..1)
211
+ let(:wire_versions) do
212
+ 0..1
201
213
  end
202
214
 
203
215
  it 'returns false' do
204
- expect(features).to_not be_write_command_enabled
216
+ expect {
217
+ features
218
+ }.to raise_exception(Mongo::Error::UnsupportedFeatures)
205
219
  end
206
220
  end
207
221
  end
@@ -210,8 +224,8 @@ describe Mongo::Server::Description::Features do
210
224
 
211
225
  context 'when the wire range includes 3' do
212
226
 
213
- let(:features) do
214
- described_class.new(0..3)
227
+ let(:wire_versions) do
228
+ 0..3
215
229
  end
216
230
 
217
231
  it 'returns true' do
@@ -221,8 +235,8 @@ describe Mongo::Server::Description::Features do
221
235
 
222
236
  context 'when the wire range does not include 3' do
223
237
 
224
- let(:features) do
225
- described_class.new(0..2)
238
+ let(:wire_versions) do
239
+ 0..2
226
240
  end
227
241
 
228
242
  it 'returns false' do