mongo 2.5.0.beta → 2.5.0

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 (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