mongo 2.16.3 → 2.17.2
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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/README.md +1 -1
- data/lib/mongo/auth/aws/request.rb +0 -1
- data/lib/mongo/client.rb +4 -0
- data/lib/mongo/cluster/reapers/cursor_reaper.rb +26 -14
- data/lib/mongo/collection/view/aggregation.rb +62 -17
- data/lib/mongo/collection/view/builder/aggregation.rb +11 -13
- data/lib/mongo/collection/view/builder/map_reduce.rb +1 -1
- data/lib/mongo/collection/view/change_stream.rb +7 -3
- data/lib/mongo/collection/view/iterable.rb +2 -3
- data/lib/mongo/collection/view/map_reduce.rb +2 -0
- data/lib/mongo/collection/view/readable.rb +24 -1
- data/lib/mongo/collection/view/writable.rb +23 -0
- data/lib/mongo/collection.rb +21 -1
- data/lib/mongo/cursor/kill_spec.rb +19 -2
- data/lib/mongo/cursor.rb +5 -5
- data/lib/mongo/database/view.rb +4 -2
- data/lib/mongo/database.rb +6 -6
- data/lib/mongo/error/snapshot_session_invalid_server_version.rb +31 -0
- data/lib/mongo/error/snapshot_session_transaction_prohibited.rb +30 -0
- data/lib/mongo/error.rb +2 -0
- data/lib/mongo/operation/delete/op_msg.rb +2 -1
- data/lib/mongo/operation/find/builder/command.rb +1 -0
- data/lib/mongo/operation/result.rb +6 -0
- data/lib/mongo/operation/shared/executable.rb +4 -0
- data/lib/mongo/operation/shared/sessions_supported.rb +18 -2
- data/lib/mongo/operation/update/op_msg.rb +2 -1
- data/lib/mongo/server/description/features.rb +3 -1
- data/lib/mongo/server_selector/base.rb +26 -4
- data/lib/mongo/session.rb +19 -0
- data/lib/mongo/socket/ocsp_cache.rb +2 -3
- data/lib/mongo/socket.rb +1 -5
- data/lib/mongo/utils.rb +0 -6
- data/lib/mongo/version.rb +1 -1
- data/mongo.gemspec +1 -1
- data/spec/integration/read_preference_spec.rb +16 -12
- data/spec/mongo/cluster/cursor_reaper_spec.rb +22 -15
- data/spec/mongo/collection/view/aggregation_spec.rb +71 -95
- data/spec/mongo/collection/view/change_stream_spec.rb +1 -1
- data/spec/mongo/collection/view/map_reduce_spec.rb +14 -1
- data/spec/mongo/cursor_spec.rb +3 -2
- data/spec/mongo/operation/read_preference_op_msg_spec.rb +24 -1
- data/spec/mongo/server_selector_spec.rb +136 -15
- data/spec/mongo/socket/ssl_spec.rb +26 -58
- data/spec/mongo/utils_spec.rb +0 -14
- data/spec/runners/crud/verifier.rb +1 -2
- data/spec/runners/unified/assertions.rb +3 -1
- data/spec/runners/unified/crud_operations.rb +77 -23
- data/spec/runners/unified/ddl_operations.rb +29 -1
- data/spec/runners/unified/entity_map.rb +3 -3
- data/spec/runners/unified/support_operations.rb +6 -1
- data/spec/runners/unified/test.rb +15 -3
- data/spec/spec_tests/data/crud_unified/aggregate-let.yml +138 -0
- data/spec/spec_tests/data/crud_unified/aggregate-write-readPreference.yml +155 -0
- data/spec/spec_tests/data/crud_unified/db-aggregate-write-readPreference.yml +151 -0
- data/spec/spec_tests/data/crud_unified/deleteMany-let.yml +91 -0
- data/spec/spec_tests/data/crud_unified/deleteOne-let.yml +89 -0
- data/spec/spec_tests/data/crud_unified/find-let.yml +71 -0
- data/spec/spec_tests/data/crud_unified/findOneAndDelete-let.yml +88 -0
- data/spec/spec_tests/data/crud_unified/findOneAndReplace-let.yml +94 -0
- data/spec/spec_tests/data/crud_unified/findOneAndUpdate-let.yml +96 -0
- data/spec/spec_tests/data/crud_unified/updateMany-let.yml +103 -0
- data/spec/spec_tests/data/crud_unified/updateOne-let.yml +98 -0
- data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/DefaultNoMaxStaleness.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/LastUpdateTime.yml +3 -3
- data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/Nearest.yml +3 -3
- data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/Nearest2.yml +3 -3
- data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/PrimaryPreferred.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/PrimaryPreferred_tags.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/Secondary.yml +4 -4
- data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/SecondaryPreferred.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/SecondaryPreferred_tags.yml +4 -4
- data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/ZeroMaxStaleness.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/DefaultNoMaxStaleness.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/LastUpdateTime.yml +3 -3
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/LongHeartbeat.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/LongHeartbeat2.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/MaxStalenessTooSmall.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/MaxStalenessWithModePrimary.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Nearest.yml +3 -3
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Nearest2.yml +3 -3
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Nearest_tags.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/PrimaryPreferred.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred_tags.yml +5 -5
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred_tags2.yml +3 -3
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Secondary_tags.yml +5 -5
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Secondary_tags2.yml +3 -3
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/ZeroMaxStaleness.yml +2 -2
- data/spec/spec_tests/data/max_staleness/Sharded/SmallMaxStaleness.yml +2 -2
- data/spec/spec_tests/data/max_staleness/Single/SmallMaxStaleness.yml +1 -1
- data/spec/spec_tests/data/max_staleness/Unknown/SmallMaxStaleness.yml +1 -1
- data/spec/spec_tests/data/sessions_unified/snapshot-sessions-not-supported-client-error.yml +69 -0
- data/spec/spec_tests/data/sessions_unified/snapshot-sessions-not-supported-server-error.yml +102 -0
- data/spec/spec_tests/data/sessions_unified/snapshot-sessions-unsupported-ops.yml +258 -0
- data/spec/spec_tests/data/sessions_unified/snapshot-sessions.yml +482 -0
- data/spec/spec_tests/sessions_unified_spec.rb +13 -0
- data.tar.gz.sig +0 -0
- metadata +36 -2
- 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,
|
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
|
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
|
-
|
362
|
-
expect(
|
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
|
-
|
575
|
-
|
576
|
-
|
577
|
-
"
|
578
|
-
|
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
|
-
|
600
|
+
let(:features) do
|
601
|
+
double()
|
602
|
+
end
|
620
603
|
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
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
|
-
|
610
|
+
context 'when the view has a write concern' do
|
629
611
|
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
end
|
612
|
+
let(:collection) do
|
613
|
+
authorized_collection.with(write: INVALID_WRITE_CONCERN)
|
614
|
+
end
|
634
615
|
|
635
|
-
|
616
|
+
let(:view) do
|
617
|
+
Mongo::Collection::View.new(collection, selector, view_options)
|
618
|
+
end
|
636
619
|
|
637
|
-
|
638
|
-
|
639
|
-
end
|
620
|
+
context 'when the server supports write concern on the aggregate command' do
|
621
|
+
min_server_fcv '3.4'
|
640
622
|
|
641
|
-
|
642
|
-
|
643
|
-
|
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
|
-
|
646
|
-
|
630
|
+
context 'when the server does not support write concern on the aggregation command' do
|
631
|
+
max_server_version '3.2'
|
647
632
|
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
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
|
-
|
656
|
-
|
641
|
+
before do
|
642
|
+
authorized_collection.insert_many(documents)
|
643
|
+
aggregation.to_a
|
644
|
+
end
|
657
645
|
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
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
|
-
|
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
|
data/spec/mongo/cursor_spec.rb
CHANGED
@@ -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(
|
335
|
-
|
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
|
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 '
|
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(:
|
230
|
-
|
231
|
-
allow(
|
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
|
-
|
236
|
-
|
237
|
-
|
238
|
-
end
|
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
|
-
|
385
|
-
|
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
|
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
|
-
|
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
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
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
|
-
|
331
|
+
# jruby 9.1
|
332
|
+
OpenSSL::OpenSSLError
|
362
333
|
end
|
334
|
+
else
|
335
|
+
NoMethodError
|
363
336
|
end
|
337
|
+
end
|
364
338
|
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
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
|
-
|
407
|
-
|
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
|
data/spec/mongo/utils_spec.rb
CHANGED
@@ -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
|
-
|
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('
|
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
|