mongo 2.2.5 → 2.2.6
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.tar.gz.sig +0 -0
- data/lib/mongo/auth/scram/conversation.rb +9 -3
- data/lib/mongo/error.rb +1 -0
- data/lib/mongo/error/unexpected_response.rb +38 -0
- data/lib/mongo/operation/commands/map_reduce/result.rb +1 -1
- data/lib/mongo/operation/commands/user_query.rb +1 -1
- data/lib/mongo/operation/commands/users_info/result.rb +6 -0
- data/lib/mongo/protocol/message.rb +10 -3
- data/lib/mongo/retryable.rb +23 -0
- data/lib/mongo/server/connectable.rb +7 -6
- data/lib/mongo/server/connection.rb +18 -2
- data/lib/mongo/server/connection_pool.rb +4 -6
- data/lib/mongo/server/monitor/connection.rb +6 -3
- data/lib/mongo/uri.rb +7 -8
- data/lib/mongo/version.rb +1 -1
- data/mongo.gemspec +1 -0
- data/spec/mongo/address_spec.rb +2 -2
- data/spec/mongo/auth/cr_spec.rb +1 -1
- data/spec/mongo/auth/ldap_spec.rb +1 -1
- data/spec/mongo/auth/scram_spec.rb +1 -1
- data/spec/mongo/auth/user/view_spec.rb +12 -0
- data/spec/mongo/auth/x509_spec.rb +1 -1
- data/spec/mongo/client_spec.rb +1 -9
- data/spec/mongo/operation/result_spec.rb +3 -3
- data/spec/mongo/operation/write/update_spec.rb +1 -1
- data/spec/mongo/server/connection_spec.rb +168 -4
- data/spec/mongo/server/monitor_spec.rb +34 -4
- data/spec/mongo/server_selector/nearest_spec.rb +4 -4
- data/spec/mongo/server_selector/primary_preferred_spec.rb +4 -4
- data/spec/mongo/server_selector/primary_spec.rb +2 -2
- data/spec/mongo/server_selector/secondary_preferred_spec.rb +4 -4
- data/spec/mongo/server_selector/secondary_spec.rb +3 -3
- data/spec/mongo/server_spec.rb +3 -3
- data/spec/mongo/socket/ssl_spec.rb +1 -1
- data/spec/mongo/uri_spec.rb +124 -23
- data/spec/support/authorization.rb +10 -6
- data/spec/support/shared/server_selector.rb +1 -1
- metadata +18 -3
- metadata.gz.sig +0 -0
data/spec/mongo/client_spec.rb
CHANGED
@@ -2,14 +2,6 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Mongo::Client do
|
4
4
|
|
5
|
-
before do
|
6
|
-
if running_ssl?
|
7
|
-
allow_any_instance_of(Mongo::Server::Monitor).to receive(:ismaster) do
|
8
|
-
[{}, 1]
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
5
|
describe '#==' do
|
14
6
|
|
15
7
|
let(:client) do
|
@@ -482,7 +474,7 @@ describe Mongo::Client do
|
|
482
474
|
context 'when the read preference is printed' do
|
483
475
|
|
484
476
|
let(:client) do
|
485
|
-
described_class.new([
|
477
|
+
described_class.new([ default_address.to_s ], options)
|
486
478
|
end
|
487
479
|
|
488
480
|
let(:options) do
|
@@ -292,14 +292,14 @@ describe Mongo::Operation::Result do
|
|
292
292
|
|
293
293
|
before do
|
294
294
|
class Result
|
295
|
-
def get_result
|
296
|
-
Mongo::Client.new([
|
295
|
+
def get_result(address)
|
296
|
+
Mongo::Client.new([address], TEST_OPTIONS).database.command(:ping => 1)
|
297
297
|
end
|
298
298
|
end
|
299
299
|
end
|
300
300
|
|
301
301
|
let(:result) do
|
302
|
-
Result.new.get_result
|
302
|
+
Result.new.get_result(default_address.to_s)
|
303
303
|
end
|
304
304
|
|
305
305
|
it 'uses the Result class of the operation' do
|
@@ -95,7 +95,7 @@ describe Mongo::Operation::Write::Update do
|
|
95
95
|
context 'when the update succeeds' do
|
96
96
|
|
97
97
|
let(:document) do
|
98
|
-
{ 'q' => { name: 'test' }, 'u' => { '$set' => { field: 'blah' }}
|
98
|
+
{ 'q' => { name: 'test' }, 'u' => { '$set' => { field: 'blah' }} }
|
99
99
|
end
|
100
100
|
|
101
101
|
let(:result) do
|
@@ -3,7 +3,7 @@ require 'spec_helper'
|
|
3
3
|
describe Mongo::Server::Connection do
|
4
4
|
|
5
5
|
let(:address) do
|
6
|
-
|
6
|
+
default_address
|
7
7
|
end
|
8
8
|
|
9
9
|
let(:monitoring) do
|
@@ -117,10 +117,21 @@ describe Mongo::Server::Connection do
|
|
117
117
|
)
|
118
118
|
end
|
119
119
|
|
120
|
+
let!(:error) do
|
121
|
+
e = begin; connection.send(:ensure_connected); rescue => ex; ex; end
|
122
|
+
end
|
123
|
+
|
120
124
|
it 'raises an error' do
|
121
|
-
expect
|
122
|
-
|
123
|
-
|
125
|
+
expect(error).to be_a(Mongo::Auth::Unauthorized)
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'disconnects the socket' do
|
129
|
+
expect(connection.send(:socket)).to be(nil)
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'marks the server as unknown' do
|
133
|
+
pending 'Server must be set as unknown'
|
134
|
+
expect(server).to be_unknown
|
124
135
|
end
|
125
136
|
end
|
126
137
|
|
@@ -239,6 +250,89 @@ describe Mongo::Server::Connection do
|
|
239
250
|
end
|
240
251
|
end
|
241
252
|
|
253
|
+
context 'when the response_to does not match the request_id' do
|
254
|
+
|
255
|
+
let(:documents) do
|
256
|
+
[{ 'name' => 'bob' }, { 'name' => 'alice' }]
|
257
|
+
end
|
258
|
+
|
259
|
+
let(:insert) do
|
260
|
+
Mongo::Protocol::Insert.new(TEST_DB, TEST_COLL, documents)
|
261
|
+
end
|
262
|
+
|
263
|
+
let(:query_bob) do
|
264
|
+
Mongo::Protocol::Query.new(TEST_DB, TEST_COLL, { 'name' => 'bob' })
|
265
|
+
end
|
266
|
+
|
267
|
+
let(:query_alice) do
|
268
|
+
Mongo::Protocol::Query.new(TEST_DB, TEST_COLL, { 'name' => 'alice' })
|
269
|
+
end
|
270
|
+
|
271
|
+
after do
|
272
|
+
authorized_collection.delete_many
|
273
|
+
end
|
274
|
+
|
275
|
+
before do
|
276
|
+
# Fake a query for which we did not read the response. See RUBY-1117
|
277
|
+
allow(query_bob).to receive(:replyable?) { false }
|
278
|
+
connection.dispatch([ insert, query_bob ])
|
279
|
+
end
|
280
|
+
|
281
|
+
it 'raises an UnexpectedResponse' do
|
282
|
+
expect {
|
283
|
+
connection.dispatch([ query_alice ])
|
284
|
+
}.to raise_error(Mongo::Error::UnexpectedResponse,
|
285
|
+
/Got response for request ID \d+ but expected response for request ID \d+/)
|
286
|
+
end
|
287
|
+
|
288
|
+
it "doesn't break subsequent requests" do
|
289
|
+
expect {
|
290
|
+
connection.dispatch([ query_alice ])
|
291
|
+
}.to raise_error(Mongo::Error::UnexpectedResponse)
|
292
|
+
|
293
|
+
expect(connection.dispatch([ query_alice ]).documents.first['name']).to eq('alice')
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
context 'when a request is brutaly interrupted (Thread.kill)' do
|
298
|
+
|
299
|
+
let(:documents) do
|
300
|
+
[{ 'name' => 'bob' }, { 'name' => 'alice' }]
|
301
|
+
end
|
302
|
+
|
303
|
+
let(:insert) do
|
304
|
+
Mongo::Protocol::Insert.new(TEST_DB, TEST_COLL, documents)
|
305
|
+
end
|
306
|
+
|
307
|
+
let(:query_bob) do
|
308
|
+
Mongo::Protocol::Query.new(TEST_DB, TEST_COLL, { 'name' => 'bob' })
|
309
|
+
end
|
310
|
+
|
311
|
+
let(:query_alice) do
|
312
|
+
Mongo::Protocol::Query.new(TEST_DB, TEST_COLL, { 'name' => 'alice' })
|
313
|
+
end
|
314
|
+
|
315
|
+
before do
|
316
|
+
connection.dispatch([ insert ])
|
317
|
+
end
|
318
|
+
|
319
|
+
after do
|
320
|
+
authorized_collection.delete_many
|
321
|
+
end
|
322
|
+
|
323
|
+
it "closes the socket and does not use it for subsequent requests" do
|
324
|
+
t = Thread.new {
|
325
|
+
# Kill the thread just before the reply is read
|
326
|
+
allow(Mongo::Protocol::Reply).to receive(:deserialize_header) { t.kill }
|
327
|
+
connection.dispatch([ query_bob ])
|
328
|
+
}
|
329
|
+
t.join
|
330
|
+
allow(Mongo::Protocol::Reply).to receive(:deserialize_header).and_call_original
|
331
|
+
expect(connection.dispatch([ query_alice ]).documents.first['name']).to eq('alice')
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
|
242
336
|
context 'when the message exceeds the max size' do
|
243
337
|
|
244
338
|
context 'when the message is an insert' do
|
@@ -438,4 +532,74 @@ describe Mongo::Server::Connection do
|
|
438
532
|
end
|
439
533
|
end
|
440
534
|
end
|
535
|
+
|
536
|
+
describe '#auth_mechanism' do
|
537
|
+
|
538
|
+
let(:connection) do
|
539
|
+
described_class.new(server)
|
540
|
+
end
|
541
|
+
|
542
|
+
let(:reply) do
|
543
|
+
double('reply').tap do |r|
|
544
|
+
allow(r).to receive(:documents).and_return([ ismaster ])
|
545
|
+
end
|
546
|
+
end
|
547
|
+
|
548
|
+
before do
|
549
|
+
connection.connect!
|
550
|
+
socket = connection.instance_variable_get(:@socket)
|
551
|
+
max_message_size = connection.send(:max_message_size)
|
552
|
+
allow(Mongo::Protocol::Reply).to receive(:deserialize).with(socket, max_message_size).and_return(reply)
|
553
|
+
end
|
554
|
+
|
555
|
+
context 'when the ismaster response indicates the auth mechanism is :scram' do
|
556
|
+
|
557
|
+
let(:ismaster) do
|
558
|
+
{
|
559
|
+
'maxWireVersion' => 3,
|
560
|
+
'minWireVersion' => 0,
|
561
|
+
'ok' => 1
|
562
|
+
}
|
563
|
+
end
|
564
|
+
|
565
|
+
context 'when the server auth mechanism is scram', if: scram_sha_1_enabled? do
|
566
|
+
|
567
|
+
it 'uses scram' do
|
568
|
+
expect(connection.send(:default_mechanism)).to eq(:scram)
|
569
|
+
end
|
570
|
+
end
|
571
|
+
|
572
|
+
context 'when the server auth mechanism is the default (mongodb_cr)', unless: scram_sha_1_enabled? do
|
573
|
+
|
574
|
+
it 'uses scram' do
|
575
|
+
expect(connection.send(:default_mechanism)).to eq(:scram)
|
576
|
+
end
|
577
|
+
end
|
578
|
+
end
|
579
|
+
|
580
|
+
context 'when the ismaster response indicates the auth mechanism is :mongodb_cr' do
|
581
|
+
|
582
|
+
let(:ismaster) do
|
583
|
+
{
|
584
|
+
'maxWireVersion' => 2,
|
585
|
+
'minWireVersion' => 0,
|
586
|
+
'ok' => 1
|
587
|
+
}
|
588
|
+
end
|
589
|
+
|
590
|
+
context 'when the server auth mechanism is scram', if: scram_sha_1_enabled? do
|
591
|
+
|
592
|
+
it 'uses scram' do
|
593
|
+
expect(connection.send(:default_mechanism)).to eq(:scram)
|
594
|
+
end
|
595
|
+
end
|
596
|
+
|
597
|
+
context 'when the server auth mechanism is the default (mongodb_cr)', unless: scram_sha_1_enabled? do
|
598
|
+
|
599
|
+
it 'uses mongodb_cr' do
|
600
|
+
expect(connection.send(:default_mechanism)).to eq(:mongodb_cr)
|
601
|
+
end
|
602
|
+
end
|
603
|
+
end
|
604
|
+
end
|
441
605
|
end
|
@@ -3,7 +3,7 @@ require 'spec_helper'
|
|
3
3
|
describe Mongo::Server::Monitor do
|
4
4
|
|
5
5
|
let(:address) do
|
6
|
-
|
6
|
+
default_address
|
7
7
|
end
|
8
8
|
|
9
9
|
let(:listeners) do
|
@@ -26,6 +26,36 @@ describe Mongo::Server::Monitor do
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
+
context 'when the ismaster fails the first time' do
|
30
|
+
|
31
|
+
let(:monitor) do
|
32
|
+
described_class.new(address, listeners, TEST_OPTIONS)
|
33
|
+
end
|
34
|
+
|
35
|
+
let(:socket) do
|
36
|
+
monitor.connection.connect!
|
37
|
+
monitor.connection.__send__(:socket)
|
38
|
+
end
|
39
|
+
|
40
|
+
before do
|
41
|
+
expect(socket).to receive(:write).once.and_raise(Mongo::Error::SocketError)
|
42
|
+
expect(socket).to receive(:write).and_call_original
|
43
|
+
monitor.scan!
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'retries the ismaster', if: standalone? do
|
47
|
+
expect(monitor.description).to be_standalone
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'retries the ismaster', if: replica_set? do
|
51
|
+
expect(monitor.description).to be_primary
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'retries the ismaster', if: sharded? do
|
55
|
+
expect(monitor.description).to be_mongos
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
29
59
|
context 'when the ismaster command succeeds' do
|
30
60
|
|
31
61
|
let(:monitor) do
|
@@ -73,7 +103,7 @@ describe Mongo::Server::Monitor do
|
|
73
103
|
context 'when the socket gets an exception' do
|
74
104
|
|
75
105
|
let(:bad_address) do
|
76
|
-
|
106
|
+
default_address
|
77
107
|
end
|
78
108
|
|
79
109
|
let(:monitor) do
|
@@ -86,7 +116,7 @@ describe Mongo::Server::Monitor do
|
|
86
116
|
end
|
87
117
|
|
88
118
|
before do
|
89
|
-
expect(socket).to receive(:write).and_raise(Mongo::Error::SocketError)
|
119
|
+
expect(socket).to receive(:write).twice.and_raise(Mongo::Error::SocketError)
|
90
120
|
monitor.scan!
|
91
121
|
end
|
92
122
|
|
@@ -120,7 +150,7 @@ describe Mongo::Server::Monitor do
|
|
120
150
|
described_class.new(address, listeners)
|
121
151
|
end
|
122
152
|
|
123
|
-
it 'defaults to
|
153
|
+
it 'defaults to 10' do
|
124
154
|
expect(monitor.heartbeat_frequency).to eq(10)
|
125
155
|
end
|
126
156
|
end
|
@@ -85,10 +85,10 @@ describe Mongo::ServerSelector::Nearest do
|
|
85
85
|
context 'tag sets provided' do
|
86
86
|
let(:tag_sets) { [tag_set] }
|
87
87
|
let(:matching_primary) do
|
88
|
-
server(:primary, :tags => server_tags)
|
88
|
+
server(:primary, :tags => server_tags, address: default_address)
|
89
89
|
end
|
90
90
|
let(:matching_secondary) do
|
91
|
-
server(:secondary, :tags => server_tags)
|
91
|
+
server(:secondary, :tags => server_tags, address: default_address)
|
92
92
|
end
|
93
93
|
|
94
94
|
context 'single candidate' do
|
@@ -173,8 +173,8 @@ describe Mongo::ServerSelector::Nearest do
|
|
173
173
|
end
|
174
174
|
|
175
175
|
context 'high latency servers' do
|
176
|
-
let(:far_primary) { server(:primary, :average_round_trip_time => 113) }
|
177
|
-
let(:far_secondary) { server(:secondary, :average_round_trip_time => 114) }
|
176
|
+
let(:far_primary) { server(:primary, :average_round_trip_time => 113, address: default_address) }
|
177
|
+
let(:far_secondary) { server(:secondary, :average_round_trip_time => 114, address: default_address) }
|
178
178
|
|
179
179
|
context 'single candidate' do
|
180
180
|
|
@@ -81,11 +81,11 @@ describe Mongo::ServerSelector::PrimaryPreferred do
|
|
81
81
|
let(:tag_sets) { [tag_set] }
|
82
82
|
|
83
83
|
let(:matching_primary) do
|
84
|
-
server(:primary, :tags => server_tags )
|
84
|
+
server(:primary, :tags => server_tags, address: default_address )
|
85
85
|
end
|
86
86
|
|
87
87
|
let(:matching_secondary) do
|
88
|
-
server(:secondary, :tags => server_tags )
|
88
|
+
server(:secondary, :tags => server_tags, address: default_address )
|
89
89
|
end
|
90
90
|
|
91
91
|
context 'single candidate' do
|
@@ -171,8 +171,8 @@ describe Mongo::ServerSelector::PrimaryPreferred do
|
|
171
171
|
end
|
172
172
|
|
173
173
|
context 'high latency servers' do
|
174
|
-
let(:far_primary) { server(:primary, :average_round_trip_time => 100) }
|
175
|
-
let(:far_secondary) { server(:secondary, :average_round_trip_time => 113) }
|
174
|
+
let(:far_primary) { server(:primary, :average_round_trip_time => 100, address: default_address) }
|
175
|
+
let(:far_secondary) { server(:secondary, :average_round_trip_time => 113, address: default_address) }
|
176
176
|
|
177
177
|
context 'single candidate' do
|
178
178
|
|
@@ -76,8 +76,8 @@ describe Mongo::ServerSelector::Primary do
|
|
76
76
|
end
|
77
77
|
|
78
78
|
context 'high latency candidates' do
|
79
|
-
let(:far_primary) { server(:primary, :average_round_trip_time => 100) }
|
80
|
-
let(:far_secondary) { server(:secondary, :average_round_trip_time => 120) }
|
79
|
+
let(:far_primary) { server(:primary, :average_round_trip_time => 100, address: default_address) }
|
80
|
+
let(:far_secondary) { server(:secondary, :average_round_trip_time => 120, address: default_address) }
|
81
81
|
|
82
82
|
context 'single candidate' do
|
83
83
|
|
@@ -87,11 +87,11 @@ describe Mongo::ServerSelector::SecondaryPreferred do
|
|
87
87
|
end
|
88
88
|
|
89
89
|
let(:matching_primary) do
|
90
|
-
server(:primary, :tags => server_tags)
|
90
|
+
server(:primary, :tags => server_tags, address: default_address)
|
91
91
|
end
|
92
92
|
|
93
93
|
let(:matching_secondary) do
|
94
|
-
server(:secondary, :tags => server_tags)
|
94
|
+
server(:secondary, :tags => server_tags, address: default_address)
|
95
95
|
end
|
96
96
|
|
97
97
|
context 'single candidate' do
|
@@ -170,8 +170,8 @@ describe Mongo::ServerSelector::SecondaryPreferred do
|
|
170
170
|
end
|
171
171
|
|
172
172
|
context 'high latency servers' do
|
173
|
-
let(:far_primary) { server(:primary, :average_round_trip_time => 100) }
|
174
|
-
let(:far_secondary) { server(:secondary, :average_round_trip_time => 113) }
|
173
|
+
let(:far_primary) { server(:primary, :average_round_trip_time => 100, address: default_address) }
|
174
|
+
let(:far_secondary) { server(:secondary, :average_round_trip_time => 113, address: default_address) }
|
175
175
|
|
176
176
|
context 'single candidate' do
|
177
177
|
|
@@ -76,7 +76,7 @@ describe Mongo::ServerSelector::Secondary do
|
|
76
76
|
|
77
77
|
context 'tag sets provided' do
|
78
78
|
let(:tag_sets) { [tag_set] }
|
79
|
-
let(:matching_secondary) { server(:secondary, :tags => server_tags) }
|
79
|
+
let(:matching_secondary) { server(:secondary, :tags => server_tags, address: default_address) }
|
80
80
|
|
81
81
|
context 'single candidate' do
|
82
82
|
|
@@ -134,8 +134,8 @@ describe Mongo::ServerSelector::Secondary do
|
|
134
134
|
end
|
135
135
|
|
136
136
|
context 'high latency servers' do
|
137
|
-
let(:far_primary) { server(:primary, :average_round_trip_time => 100) }
|
138
|
-
let(:far_secondary) { server(:secondary, :average_round_trip_time => 113) }
|
137
|
+
let(:far_primary) { server(:primary, :average_round_trip_time => 100, address: default_address) }
|
138
|
+
let(:far_secondary) { server(:secondary, :average_round_trip_time => 113, address: default_address) }
|
139
139
|
|
140
140
|
context 'single candidate' do
|
141
141
|
|
data/spec/mongo/server_spec.rb
CHANGED
@@ -15,7 +15,7 @@ describe Mongo::Server do
|
|
15
15
|
end
|
16
16
|
|
17
17
|
let(:address) do
|
18
|
-
|
18
|
+
default_address
|
19
19
|
end
|
20
20
|
|
21
21
|
let(:pool) do
|
@@ -167,11 +167,11 @@ describe Mongo::Server do
|
|
167
167
|
end
|
168
168
|
|
169
169
|
it 'sets the address host' do
|
170
|
-
expect(server.address.host).to eq(
|
170
|
+
expect(server.address.host).to eq(default_address.host)
|
171
171
|
end
|
172
172
|
|
173
173
|
it 'sets the address port' do
|
174
|
-
expect(server.address.port).to eq(
|
174
|
+
expect(server.address.port).to eq(default_address.port)
|
175
175
|
end
|
176
176
|
|
177
177
|
it 'sets the options' do
|