mongo 2.16.3 → 2.17.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +1 -1
  4. data/lib/mongo/auth/aws/request.rb +0 -1
  5. data/lib/mongo/client.rb +4 -0
  6. data/lib/mongo/cluster/reapers/cursor_reaper.rb +26 -14
  7. data/lib/mongo/collection/view/aggregation.rb +62 -17
  8. data/lib/mongo/collection/view/builder/aggregation.rb +11 -13
  9. data/lib/mongo/collection/view/builder/map_reduce.rb +1 -1
  10. data/lib/mongo/collection/view/change_stream.rb +7 -3
  11. data/lib/mongo/collection/view/iterable.rb +2 -3
  12. data/lib/mongo/collection/view/map_reduce.rb +2 -0
  13. data/lib/mongo/collection/view/readable.rb +24 -1
  14. data/lib/mongo/collection/view/writable.rb +23 -0
  15. data/lib/mongo/collection.rb +21 -1
  16. data/lib/mongo/cursor/kill_spec.rb +19 -2
  17. data/lib/mongo/cursor.rb +5 -5
  18. data/lib/mongo/database/view.rb +4 -2
  19. data/lib/mongo/database.rb +6 -6
  20. data/lib/mongo/error/snapshot_session_invalid_server_version.rb +31 -0
  21. data/lib/mongo/error/snapshot_session_transaction_prohibited.rb +30 -0
  22. data/lib/mongo/error.rb +2 -0
  23. data/lib/mongo/operation/delete/op_msg.rb +2 -1
  24. data/lib/mongo/operation/find/builder/command.rb +1 -0
  25. data/lib/mongo/operation/result.rb +6 -0
  26. data/lib/mongo/operation/shared/executable.rb +4 -0
  27. data/lib/mongo/operation/shared/sessions_supported.rb +18 -2
  28. data/lib/mongo/operation/update/op_msg.rb +2 -1
  29. data/lib/mongo/server/description/features.rb +3 -1
  30. data/lib/mongo/server_selector/base.rb +26 -4
  31. data/lib/mongo/session.rb +19 -0
  32. data/lib/mongo/socket/ocsp_cache.rb +2 -3
  33. data/lib/mongo/socket.rb +1 -5
  34. data/lib/mongo/utils.rb +0 -6
  35. data/lib/mongo/version.rb +1 -1
  36. data/mongo.gemspec +1 -1
  37. data/spec/integration/read_preference_spec.rb +16 -12
  38. data/spec/mongo/cluster/cursor_reaper_spec.rb +22 -15
  39. data/spec/mongo/collection/view/aggregation_spec.rb +71 -95
  40. data/spec/mongo/collection/view/change_stream_spec.rb +1 -1
  41. data/spec/mongo/collection/view/map_reduce_spec.rb +14 -1
  42. data/spec/mongo/cursor_spec.rb +3 -2
  43. data/spec/mongo/operation/read_preference_op_msg_spec.rb +24 -1
  44. data/spec/mongo/server_selector_spec.rb +136 -15
  45. data/spec/mongo/socket/ssl_spec.rb +26 -58
  46. data/spec/mongo/utils_spec.rb +0 -14
  47. data/spec/runners/crud/verifier.rb +1 -2
  48. data/spec/runners/unified/assertions.rb +3 -1
  49. data/spec/runners/unified/crud_operations.rb +77 -23
  50. data/spec/runners/unified/ddl_operations.rb +29 -1
  51. data/spec/runners/unified/entity_map.rb +3 -3
  52. data/spec/runners/unified/support_operations.rb +6 -1
  53. data/spec/runners/unified/test.rb +15 -3
  54. data/spec/spec_tests/data/crud_unified/aggregate-let.yml +138 -0
  55. data/spec/spec_tests/data/crud_unified/aggregate-write-readPreference.yml +155 -0
  56. data/spec/spec_tests/data/crud_unified/db-aggregate-write-readPreference.yml +151 -0
  57. data/spec/spec_tests/data/crud_unified/deleteMany-let.yml +91 -0
  58. data/spec/spec_tests/data/crud_unified/deleteOne-let.yml +89 -0
  59. data/spec/spec_tests/data/crud_unified/find-let.yml +71 -0
  60. data/spec/spec_tests/data/crud_unified/findOneAndDelete-let.yml +88 -0
  61. data/spec/spec_tests/data/crud_unified/findOneAndReplace-let.yml +94 -0
  62. data/spec/spec_tests/data/crud_unified/findOneAndUpdate-let.yml +96 -0
  63. data/spec/spec_tests/data/crud_unified/updateMany-let.yml +103 -0
  64. data/spec/spec_tests/data/crud_unified/updateOne-let.yml +98 -0
  65. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/DefaultNoMaxStaleness.yml +2 -2
  66. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/LastUpdateTime.yml +3 -3
  67. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/Nearest.yml +3 -3
  68. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/Nearest2.yml +3 -3
  69. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/PrimaryPreferred.yml +2 -2
  70. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/PrimaryPreferred_tags.yml +2 -2
  71. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/Secondary.yml +4 -4
  72. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/SecondaryPreferred.yml +2 -2
  73. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/SecondaryPreferred_tags.yml +4 -4
  74. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/ZeroMaxStaleness.yml +2 -2
  75. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/DefaultNoMaxStaleness.yml +2 -2
  76. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/LastUpdateTime.yml +3 -3
  77. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/LongHeartbeat.yml +2 -2
  78. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/LongHeartbeat2.yml +2 -2
  79. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/MaxStalenessTooSmall.yml +2 -2
  80. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/MaxStalenessWithModePrimary.yml +2 -2
  81. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Nearest.yml +3 -3
  82. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Nearest2.yml +3 -3
  83. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Nearest_tags.yml +2 -2
  84. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/PrimaryPreferred.yml +2 -2
  85. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred.yml +2 -2
  86. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred_tags.yml +5 -5
  87. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred_tags2.yml +3 -3
  88. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Secondary_tags.yml +5 -5
  89. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Secondary_tags2.yml +3 -3
  90. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/ZeroMaxStaleness.yml +2 -2
  91. data/spec/spec_tests/data/max_staleness/Sharded/SmallMaxStaleness.yml +2 -2
  92. data/spec/spec_tests/data/max_staleness/Single/SmallMaxStaleness.yml +1 -1
  93. data/spec/spec_tests/data/max_staleness/Unknown/SmallMaxStaleness.yml +1 -1
  94. data/spec/spec_tests/data/sessions_unified/snapshot-sessions-not-supported-client-error.yml +69 -0
  95. data/spec/spec_tests/data/sessions_unified/snapshot-sessions-not-supported-server-error.yml +102 -0
  96. data/spec/spec_tests/data/sessions_unified/snapshot-sessions-unsupported-ops.yml +258 -0
  97. data/spec/spec_tests/data/sessions_unified/snapshot-sessions.yml +482 -0
  98. data/spec/spec_tests/sessions_unified_spec.rb +13 -0
  99. data.tar.gz.sig +0 -0
  100. metadata +36 -2
  101. metadata.gz.sig +0 -0
@@ -29,8 +29,16 @@ describe Mongo::Collection::View::Aggregation do
29
29
  described_class.new(view, pipeline, options)
30
30
  end
31
31
 
32
+ let(:server) do
33
+ double('server')
34
+ end
35
+
36
+ let(:session) do
37
+ double('session')
38
+ end
39
+
32
40
  let(:aggregation_spec) do
33
- aggregation.send(:aggregate_spec, double('session'))
41
+ aggregation.send(:aggregate_spec, server, session, nil)
34
42
  end
35
43
 
36
44
  before do
@@ -351,15 +359,15 @@ describe Mongo::Collection::View::Aggregation do
351
359
 
352
360
  describe '#aggregate_spec' do
353
361
 
354
- context 'when the collection has a read preference' do
362
+ context 'when a read preference is given' do
355
363
 
356
364
  let(:read_preference) do
357
- {mode: :secondary}
365
+ BSON::Document.new({mode: :secondary})
358
366
  end
359
367
 
360
368
  it 'includes the read preference in the spec' do
361
- allow(authorized_collection).to receive(:read_preference).and_return(read_preference)
362
- expect(aggregation_spec[:read]).to eq(read_preference)
369
+ spec = aggregation.send(:aggregate_spec, server, session, read_preference)
370
+ expect(spec[:read]).to eq(read_preference)
363
371
  end
364
372
  end
365
373
 
@@ -570,109 +578,77 @@ describe Mongo::Collection::View::Aggregation do
570
578
  end
571
579
 
572
580
  context 'when $out is in the pipeline' do
573
-
574
- let(:pipeline) do
575
- [{
576
- "$group" => {
577
- "_id" => "$city",
578
- "totalpop" => { "$sum" => "$pop" }
581
+ [['$out', 'string'], [:$out, 'symbol']].each do |op, type|
582
+ context "when #{op} is a #{type}" do
583
+ let(:pipeline) do
584
+ [{
585
+ "$group" => {
586
+ "_id" => "$city",
587
+ "totalpop" => { "$sum" => "$pop" }
588
+ }
589
+ },
590
+ {
591
+ op => 'output_collection'
579
592
  }
580
- },
581
- {
582
- '$out' => 'output_collection'
583
- }
584
- ]
585
- end
586
-
587
- before do
588
- authorized_client['output_collection'].delete_many
589
- end
590
-
591
- context 'when $out is a string' do
592
-
593
- it 'does not allow the operation on a secondary' do
594
- expect(aggregation.send(:secondary_ok?)).to be(false)
595
- end
596
- end
597
-
598
- context 'when $out is a symbol' do
599
-
600
- let(:pipeline) do
601
- [{
602
- "$group" => {
603
- "_id" => "$city",
604
- "totalpop" => { "$sum" => "$pop" }
605
- }
606
- },
607
- {
608
- :$out => 'output_collection'
609
- }
610
- ]
611
- end
612
-
613
- it 'does not allow the operation on a secondary' do
614
- expect(aggregation.send(:secondary_ok?)).to be(false)
615
- end
616
- end
593
+ ]
594
+ end
617
595
 
596
+ before do
597
+ authorized_client['output_collection'].delete_many
598
+ end
618
599
 
619
- context 'when the server is not a valid for writing' do
600
+ let(:features) do
601
+ double()
602
+ end
620
603
 
621
- it 'reroutes the operation to a primary' do
622
- allow(aggregation).to receive(:valid_server?).and_return(false)
623
- expect(Mongo::Logger.logger).to receive(:warn).and_call_original
624
- aggregation.to_a
625
- end
626
- end
604
+ let(:server) do
605
+ double().tap do |server|
606
+ allow(server).to receive(:features).and_return(features)
607
+ end
608
+ end
627
609
 
628
- context 'when the server is a valid for writing' do
610
+ context 'when the view has a write concern' do
629
611
 
630
- it 'does not reroute the operation to a primary' do
631
- expect(Mongo::Logger.logger).not_to receive(:warn)
632
- aggregation.to_a
633
- end
612
+ let(:collection) do
613
+ authorized_collection.with(write: INVALID_WRITE_CONCERN)
614
+ end
634
615
 
635
- context 'when the view has a write concern' do
616
+ let(:view) do
617
+ Mongo::Collection::View.new(collection, selector, view_options)
618
+ end
636
619
 
637
- let(:collection) do
638
- authorized_collection.with(write: INVALID_WRITE_CONCERN)
639
- end
620
+ context 'when the server supports write concern on the aggregate command' do
621
+ min_server_fcv '3.4'
640
622
 
641
- let(:view) do
642
- Mongo::Collection::View.new(collection, selector, view_options)
643
- end
623
+ it 'uses the write concern' do
624
+ expect {
625
+ aggregation.to_a
626
+ }.to raise_exception(Mongo::Error::OperationFailure)
627
+ end
628
+ end
644
629
 
645
- context 'when the server supports write concern on the aggregate command' do
646
- min_server_fcv '3.4'
630
+ context 'when the server does not support write concern on the aggregation command' do
631
+ max_server_version '3.2'
647
632
 
648
- it 'uses the write concern' do
649
- expect {
650
- aggregation.to_a
651
- }.to raise_exception(Mongo::Error::OperationFailure)
652
- end
653
- end
633
+ let(:documents) do
634
+ [
635
+ { city: "Berlin", pop: 18913, neighborhood: "Kreuzberg" },
636
+ { city: "Berlin", pop: 84143, neighborhood: "Mitte" },
637
+ { city: "New York", pop: 40270, neighborhood: "Brooklyn" }
638
+ ]
639
+ end
654
640
 
655
- context 'when the server does not support write concern on the aggregation command' do
656
- max_server_version '3.2'
641
+ before do
642
+ authorized_collection.insert_many(documents)
643
+ aggregation.to_a
644
+ end
657
645
 
658
- let(:documents) do
659
- [
660
- { city: "Berlin", pop: 18913, neighborhood: "Kreuzberg" },
661
- { city: "Berlin", pop: 84143, neighborhood: "Mitte" },
662
- { city: "New York", pop: 40270, neighborhood: "Brooklyn" }
663
- ]
664
- end
665
-
666
- before do
667
- authorized_collection.insert_many(documents)
668
- aggregation.to_a
669
- end
670
-
671
- it 'does not apply the write concern' do
672
- expect(authorized_client['output_collection'].find.count).to eq(2)
673
- end
674
- end
675
- end
646
+ it 'does not apply the write concern' do
647
+ expect(authorized_client['output_collection'].find.count).to eq(2)
648
+ end
649
+ end
650
+ end
651
+ end
676
652
  end
677
653
  end
678
654
  end
@@ -56,7 +56,7 @@ describe Mongo::Collection::View::ChangeStream do
56
56
 
57
57
  let(:command_spec) do
58
58
  change_stream.send(:instance_variable_set, '@resuming', false)
59
- change_stream.send(:aggregate_spec, double('session'))
59
+ change_stream.send(:aggregate_spec, double('server'), double('session'), nil)
60
60
  end
61
61
 
62
62
  let(:cursor) do
@@ -60,6 +60,14 @@ describe Mongo::Collection::View::MapReduce do
60
60
  described_class.new(view, map, reduce, options)
61
61
  end
62
62
 
63
+ describe '#initialize' do
64
+ it 'warns of deprecation' do
65
+ Mongo::Logger.logger.should receive(:warn).with('MONGODB | The map_reduce operation is deprecated, please use the aggregation pipeline instead')
66
+
67
+ map_reduce
68
+ end
69
+ end
70
+
63
71
  describe '#map_function' do
64
72
 
65
73
  it 'returns the map function' do
@@ -672,7 +680,12 @@ describe Mongo::Collection::View::MapReduce do
672
680
  end
673
681
 
674
682
  it 'does not reroute the operation to a primary' do
675
- expect(Mongo::Logger.logger).not_to receive(:warn)
683
+ # We produce a deprecation warning, but there shouldn't be
684
+ # the reroute warning.
685
+ expect(Mongo::Logger.logger).to receive(:warn).once do |msg|
686
+ expect(msg).not_to include('Rerouting the MapReduce operation to the primary server')
687
+ end
688
+
676
689
  map_reduce.to_a
677
690
  end
678
691
  end
@@ -331,8 +331,9 @@ describe Mongo::Cursor do
331
331
 
332
332
  before do
333
333
  authorized_collection.insert_many(documents)
334
- cluster.schedule_kill_cursor(cursor.kill_spec,
335
- cursor.instance_variable_get(:@server))
334
+ cluster.schedule_kill_cursor(
335
+ cursor.kill_spec(cursor.instance_variable_get(:@server))
336
+ )
336
337
  end
337
338
 
338
339
  let(:view) do
@@ -99,6 +99,29 @@ describe Mongo::Operation::SessionsSupported do
99
99
  end
100
100
  end
101
101
 
102
+ shared_examples_for 'sends read preference correctly for replica set' do
103
+ context "when read preference mode is primary" do
104
+ let(:mode) { :primary}
105
+
106
+ it_behaves_like 'does not modify selector'
107
+ end
108
+ %i(primary_preferred secondary secondary_preferred nearest).each do |_mode|
109
+ active_mode = _mode
110
+
111
+ context "when read preference mode is #{active_mode}" do
112
+ let(:mode) { active_mode }
113
+
114
+ let(:expected) do
115
+ selector.merge(:$readPreference => expected_read_preference)
116
+ end
117
+
118
+ it 'adds read preference' do
119
+ expect(actual).to eq(expected)
120
+ end
121
+ end
122
+ end
123
+ end
124
+
102
125
  shared_examples_for 'sends user-specified read preference' do
103
126
  %i(primary primary_preferred secondary secondary_preferred nearest).each do |_mode|
104
127
  active_mode = _mode
@@ -302,7 +325,7 @@ describe Mongo::Operation::SessionsSupported do
302
325
  let(:standalone?) { false }
303
326
  let(:mongos?) { false }
304
327
 
305
- it_behaves_like 'sends user-specified read preference'
328
+ it_behaves_like 'sends read preference correctly for replica set'
306
329
  end
307
330
  end
308
331
  end
@@ -202,12 +202,7 @@ describe Mongo::ServerSelector do
202
202
  describe "#select_server" do
203
203
  require_no_linting
204
204
 
205
- context 'when #select_in_replica_set returns a list of nils' do
206
-
207
- let(:servers) do
208
- [ make_server(:primary) ]
209
- end
210
-
205
+ context 'replica set topology' do
211
206
  let(:cluster) do
212
207
  double('cluster').tap do |c|
213
208
  allow(c).to receive(:connected?).and_return(true)
@@ -223,19 +218,141 @@ describe Mongo::ServerSelector do
223
218
  allow(c).to receive(:scan!).and_return(true)
224
219
  allow(c).to receive(:options).and_return(server_selection_timeout: 0.1)
225
220
  allow(c).to receive(:server_selection_semaphore).and_return(nil)
221
+ allow(topology).to receive(:compatible?).and_return(true)
226
222
  end
227
223
  end
228
224
 
229
- let(:read_pref) do
230
- described_class.get(mode: :primary).tap do |pref|
231
- allow(pref).to receive(:select_in_replica_set).and_return([ nil, nil ])
225
+ let(:primary) do
226
+ make_server(:primary).tap do |server|
227
+ allow(server).to receive(:features).and_return(double("primary features"))
232
228
  end
233
229
  end
234
230
 
235
- it 'raises a NoServerAvailable error' do
236
- expect do
237
- read_pref.select_server(cluster)
238
- end.to raise_exception(Mongo::Error::NoServerAvailable)
231
+ let(:secondary) do
232
+ make_server(:secondary).tap do |server|
233
+ allow(server).to receive(:features).and_return(double("secondary features"))
234
+ end
235
+ end
236
+
237
+ context "when #select_in_replica_set returns a list of nils" do
238
+ let(:servers) do
239
+ [ primary ]
240
+ end
241
+
242
+ let(:read_pref) do
243
+ described_class.get(mode: :primary).tap do |pref|
244
+ allow(pref).to receive(:select_in_replica_set).and_return([ nil, nil ])
245
+ end
246
+ end
247
+
248
+ it 'raises a NoServerAvailable error' do
249
+ expect do
250
+ read_pref.select_server(cluster)
251
+ end.to raise_exception(Mongo::Error::NoServerAvailable)
252
+ end
253
+ end
254
+
255
+ context "write_aggregation is true" do
256
+
257
+ before do
258
+ # It does not matter for this context whether primary supports secondary wites or not,
259
+ # but we need to mock out this call.
260
+ allow(primary.features).to receive(:merge_out_on_secondary_enabled?).and_return(false)
261
+ end
262
+
263
+ context "read preference is primary" do
264
+ let(:selector) { Mongo::ServerSelector::Primary.new }
265
+
266
+ let(:servers) do
267
+ [ primary, secondary ]
268
+ end
269
+
270
+ [true, false].each do |secondary_support_writes|
271
+ context "secondary #{secondary_support_writes ? 'supports' : 'does not support' } writes" do
272
+ it "selects a primary" do
273
+ allow(secondary.features).to receive(:merge_out_on_secondary_enabled?).and_return(secondary_support_writes)
274
+
275
+ expect(selector.select_server(cluster, write_aggregation: true)).to eq(primary)
276
+ end
277
+ end
278
+ end
279
+ end
280
+
281
+ context "read preference is primary preferred" do
282
+ let(:selector) { Mongo::ServerSelector::PrimaryPreferred.new }
283
+
284
+ let(:servers) do
285
+ [ primary, secondary ]
286
+ end
287
+
288
+ [true, false].each do |secondary_support_writes|
289
+ context "secondary #{secondary_support_writes ? 'supports' : 'does not support' } writes" do
290
+ it "selects a primary" do
291
+ allow(secondary.features).to receive(:merge_out_on_secondary_enabled?).and_return(secondary_support_writes)
292
+
293
+ expect(selector.select_server(cluster, write_aggregation: true)).to eq(primary)
294
+ end
295
+ end
296
+ end
297
+ end
298
+
299
+ context "read preference is secondary preferred" do
300
+ let(:selector) { Mongo::ServerSelector::SecondaryPreferred.new }
301
+
302
+ let(:servers) do
303
+ [ primary, secondary ]
304
+ end
305
+
306
+ context "secondary supports writes" do
307
+ it "selects a secondary" do
308
+ allow(secondary.features).to receive(:merge_out_on_secondary_enabled?).and_return(true)
309
+
310
+ expect(selector.select_server(cluster, write_aggregation: true)).to eq(secondary)
311
+ end
312
+ end
313
+
314
+ context "secondary does not support writes" do
315
+ it "selects a primary" do
316
+ allow(secondary.features).to receive(:merge_out_on_secondary_enabled?).and_return(false)
317
+
318
+ expect(selector.select_server(cluster, write_aggregation: true)).to eq(primary)
319
+ end
320
+ end
321
+ end
322
+
323
+ context "read preference is secondary" do
324
+ let(:selector) { Mongo::ServerSelector::Secondary.new }
325
+
326
+ let(:servers) do
327
+ [ primary, secondary ]
328
+ end
329
+
330
+ context "secondary supports writes" do
331
+ it "selects a secondary" do
332
+ allow(secondary.features).to receive(:merge_out_on_secondary_enabled?).and_return(true)
333
+
334
+ expect(selector.select_server(cluster, write_aggregation: true)).to eq(secondary)
335
+ end
336
+ end
337
+
338
+ context "secondary does not support writes" do
339
+ it "selects a primary" do
340
+ allow(secondary.features).to receive(:merge_out_on_secondary_enabled?).and_return(false)
341
+
342
+ expect(selector.select_server(cluster, write_aggregation: true)).to eq(primary)
343
+ end
344
+ end
345
+
346
+ context "no secondaries in cluster" do
347
+ let(:servers) do
348
+ [ primary ]
349
+ end
350
+
351
+ it "selects a primary" do
352
+ expect(selector.select_server(cluster, write_aggregation: true)).to eq(primary)
353
+ end
354
+ end
355
+ end
239
356
  end
240
357
  end
241
358
 
@@ -381,8 +498,12 @@ describe Mongo::ServerSelector do
381
498
  let(:servers) { [unknown, mongos] }
382
499
  let(:selector) { described_class.primary }
383
500
 
384
- it 'returns the mongos' do
385
- expect(selector.select_server(cluster)).to eq(mongos)
501
+ [true, false].each do |write_aggregation|
502
+ context "write_aggregation is #{write_aggregation}" do
503
+ it 'returns the mongos' do
504
+ expect(selector.select_server(cluster, write_aggregation: write_aggregation)).to eq(mongos)
505
+ end
506
+ end
386
507
  end
387
508
  end
388
509
  end
@@ -306,67 +306,40 @@ describe Mongo::Socket::SSL, retry: 3 do
306
306
  end
307
307
  end
308
308
 
309
- context 'when ruby version is < 2.4.1' do
310
- ruby_version_lt '2.4.1'
311
-
312
- context 'when a key is passed, but it is not of the right type' do
313
-
314
- let(:ssl_options) do
315
- key = "This is a string not a key"
316
- {
317
- :ssl => true,
318
- :ssl_key_object => key,
319
- :ssl_cert => SpecConfig.instance.client_cert_path,
320
- :ssl_verify => false
321
- }
322
- end
323
-
324
- it 'raises a TypeError' do
325
- expect do
326
- socket
327
- end.to raise_exception(TypeError)
328
- end
329
- end
330
- end
331
-
332
309
  # Note that as of MRI 2.4, Creating a socket with the wrong key type raises
333
310
  # a NoMethodError because #private? is attempted to be called on the key.
334
311
  # In jruby 9.2 a TypeError is raised.
335
312
  # In jruby 9.1 a OpenSSL::PKey::PKeyError is raised.
336
- context 'when ruby version is >= 2.4.1' do
337
- ruby_version_gte '2.4.1'
313
+ context 'when a key is passed, but it is not of the right type' do
338
314
 
339
- context 'when a key is passed, but it is not of the right type' do
315
+ let(:ssl_options) do
316
+ key = "This is a string not a key"
317
+ {
318
+ :ssl => true,
319
+ :ssl_key_object => key,
320
+ :ssl_cert => SpecConfig.instance.client_cert_path,
321
+ :ssl_verify => false
322
+ }
323
+ end
340
324
 
341
- let(:ssl_options) do
342
- key = "This is a string not a key"
343
- {
344
- :ssl => true,
345
- :ssl_key_object => key,
346
- :ssl_cert => SpecConfig.instance.client_cert_path,
347
- :ssl_verify => false
348
- }
349
- end
350
-
351
- let(:expected_exception) do
352
- if SpecConfig.instance.jruby?
353
- if RUBY_VERSION >= '2.5.0'
354
- # jruby 9.2
355
- TypeError
356
- else
357
- # jruby 9.1
358
- OpenSSL::OpenSSLError
359
- end
325
+ let(:expected_exception) do
326
+ if SpecConfig.instance.jruby?
327
+ if RUBY_VERSION >= '2.5.0'
328
+ # jruby 9.2
329
+ TypeError
360
330
  else
361
- NoMethodError
331
+ # jruby 9.1
332
+ OpenSSL::OpenSSLError
362
333
  end
334
+ else
335
+ NoMethodError
363
336
  end
337
+ end
364
338
 
365
- it 'raises a NoMethodError' do
366
- expect do
367
- socket
368
- end.to raise_exception(expected_exception)
369
- end
339
+ it 'raises a NoMethodError' do
340
+ expect do
341
+ socket
342
+ end.to raise_exception(expected_exception)
370
343
  end
371
344
  end
372
345
 
@@ -403,13 +376,8 @@ describe Mongo::Socket::SSL, retry: 3 do
403
376
  context 'when a bad key is provided' do
404
377
 
405
378
  let(:expected_exception) do
406
- if RUBY_VERSION >= '2.4.0'
407
- # OpenSSL::PKey::PKeyError: Could not parse PKey: no start line
408
- [OpenSSL::OpenSSLError, /Could not parse PKey/]
409
- else
410
- # ArgumentError: Could not parse PKey: no start line
411
- [ArgumentError, /Could not parse PKey/]
412
- end
379
+ # OpenSSL::PKey::PKeyError: Could not parse PKey: no start line
380
+ [OpenSSL::OpenSSLError, /Could not parse PKey/]
413
381
  end
414
382
 
415
383
  let(:ssl_options) do
@@ -39,18 +39,4 @@ describe Mongo::Utils do
39
39
  }
40
40
  end
41
41
  end
42
-
43
- describe '#slice_hash' do
44
- it do
45
- hash = {'key1' => 1, :key2 => 's', :key3 => true}
46
- expect(
47
- described_class.slice_hash(hash, 'key1', :key3)
48
- ).to eq(
49
- {
50
- 'key1' => 1,
51
- :key3 => true
52
- }
53
- )
54
- end
55
- end
56
42
  end
@@ -110,8 +110,7 @@ EOT
110
110
  expected_command = expected_event.delete('command')
111
111
  actual_command = actual_event.delete('command')
112
112
 
113
- # Hash#compact is ruby 2.4+
114
- expected_presence = expected_command.select { |k, v| !v.nil? }
113
+ expected_presence = expected_command.compact
115
114
  expected_absence = expected_command.select { |k, v| v.nil? }
116
115
 
117
116
  expected_presence.each do |k, v|
@@ -62,7 +62,7 @@ module Unified
62
62
  def assert_outcome
63
63
  return unless outcome
64
64
 
65
- client = ClientRegistry.instance.global_client('authorized')
65
+ client = ClientRegistry.instance.global_client('root_authorized')
66
66
  outcome.each do |spec|
67
67
  spec = UsingHash[spec]
68
68
  collection = client.use(spec.use!('databaseName'))[spec.use!('collectionName')]
@@ -217,6 +217,8 @@ module Unified
217
217
  BSON::ObjectId === object
218
218
  when 'date'
219
219
  Time === object
220
+ when 'double'
221
+ Float === object
220
222
  else
221
223
  raise NotImplementedError, "Unhandled type #{type}"
222
224
  end