mongo 2.2.5 → 2.2.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) 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/auth/scram/conversation.rb +9 -3
  5. data/lib/mongo/error.rb +1 -0
  6. data/lib/mongo/error/unexpected_response.rb +38 -0
  7. data/lib/mongo/operation/commands/map_reduce/result.rb +1 -1
  8. data/lib/mongo/operation/commands/user_query.rb +1 -1
  9. data/lib/mongo/operation/commands/users_info/result.rb +6 -0
  10. data/lib/mongo/protocol/message.rb +10 -3
  11. data/lib/mongo/retryable.rb +23 -0
  12. data/lib/mongo/server/connectable.rb +7 -6
  13. data/lib/mongo/server/connection.rb +18 -2
  14. data/lib/mongo/server/connection_pool.rb +4 -6
  15. data/lib/mongo/server/monitor/connection.rb +6 -3
  16. data/lib/mongo/uri.rb +7 -8
  17. data/lib/mongo/version.rb +1 -1
  18. data/mongo.gemspec +1 -0
  19. data/spec/mongo/address_spec.rb +2 -2
  20. data/spec/mongo/auth/cr_spec.rb +1 -1
  21. data/spec/mongo/auth/ldap_spec.rb +1 -1
  22. data/spec/mongo/auth/scram_spec.rb +1 -1
  23. data/spec/mongo/auth/user/view_spec.rb +12 -0
  24. data/spec/mongo/auth/x509_spec.rb +1 -1
  25. data/spec/mongo/client_spec.rb +1 -9
  26. data/spec/mongo/operation/result_spec.rb +3 -3
  27. data/spec/mongo/operation/write/update_spec.rb +1 -1
  28. data/spec/mongo/server/connection_spec.rb +168 -4
  29. data/spec/mongo/server/monitor_spec.rb +34 -4
  30. data/spec/mongo/server_selector/nearest_spec.rb +4 -4
  31. data/spec/mongo/server_selector/primary_preferred_spec.rb +4 -4
  32. data/spec/mongo/server_selector/primary_spec.rb +2 -2
  33. data/spec/mongo/server_selector/secondary_preferred_spec.rb +4 -4
  34. data/spec/mongo/server_selector/secondary_spec.rb +3 -3
  35. data/spec/mongo/server_spec.rb +3 -3
  36. data/spec/mongo/socket/ssl_spec.rb +1 -1
  37. data/spec/mongo/uri_spec.rb +124 -23
  38. data/spec/support/authorization.rb +10 -6
  39. data/spec/support/shared/server_selector.rb +1 -1
  40. metadata +18 -3
  41. metadata.gz.sig +0 -0
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe Mongo::Auth::X509 do
4
4
 
5
5
  let(:address) do
6
- Mongo::Address.new(DEFAULT_ADDRESS)
6
+ default_address
7
7
  end
8
8
 
9
9
  let(:monitoring) do
@@ -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([ DEFAULT_ADDRESS ], options)
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([DEFAULT_ADDRESS], TEST_OPTIONS).database.command(:ping => 1)
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' }}, limit: 1 }
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
- Mongo::Address.new(DEFAULT_ADDRESS)
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
- connection.connect!
123
- }.to raise_error(Mongo::Auth::Unauthorized)
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
- Mongo::Address.new(DEFAULT_ADDRESS)
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
- Mongo::Address.new(DEFAULT_ADDRESS)
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 5' do
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
 
@@ -15,7 +15,7 @@ describe Mongo::Server do
15
15
  end
16
16
 
17
17
  let(:address) do
18
- Mongo::Address.new('127.0.0.1:27017')
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('127.0.0.1')
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(27017)
174
+ expect(server.address.port).to eq(default_address.port)
175
175
  end
176
176
 
177
177
  it 'sets the options' do