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