mongo 2.0.2 → 2.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) 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/address.rb +70 -11
  5. data/lib/mongo/address/ipv4.rb +23 -22
  6. data/lib/mongo/address/ipv6.rb +23 -22
  7. data/lib/mongo/address/unix.rb +18 -18
  8. data/lib/mongo/auth.rb +0 -1
  9. data/lib/mongo/auth/cr.rb +21 -2
  10. data/lib/mongo/auth/cr/conversation.rb +7 -4
  11. data/lib/mongo/auth/ldap.rb +14 -1
  12. data/lib/mongo/auth/scram.rb +15 -1
  13. data/lib/mongo/auth/scram/conversation.rb +3 -3
  14. data/lib/mongo/auth/user.rb +1 -1
  15. data/lib/mongo/auth/x509.rb +15 -1
  16. data/lib/mongo/cluster.rb +22 -8
  17. data/lib/mongo/cluster/topology.rb +7 -6
  18. data/lib/mongo/cluster/topology/replica_set.rb +5 -5
  19. data/lib/mongo/cluster/topology/sharded.rb +5 -5
  20. data/lib/mongo/cluster/topology/{standalone.rb → single.rb} +26 -22
  21. data/lib/mongo/cluster/topology/unknown.rb +6 -5
  22. data/lib/mongo/collection.rb +6 -1
  23. data/lib/mongo/collection/view.rb +1 -0
  24. data/lib/mongo/collection/view/readable.rb +5 -0
  25. data/lib/mongo/error.rb +4 -0
  26. data/lib/mongo/error/invalid_document.rb +1 -1
  27. data/lib/mongo/error/invalid_server_preference.rb +36 -0
  28. data/lib/mongo/error/invalid_uri.rb +37 -0
  29. data/lib/mongo/error/invalid_uri_option.rb +38 -0
  30. data/lib/mongo/error/no_server_available.rb +37 -0
  31. data/lib/mongo/operation/read_preferrable.rb +20 -4
  32. data/lib/mongo/protocol/query.rb +14 -1
  33. data/lib/mongo/server.rb +12 -0
  34. data/lib/mongo/server/connectable.rb +5 -1
  35. data/lib/mongo/server/connection.rb +1 -1
  36. data/lib/mongo/server/context.rb +2 -1
  37. data/lib/mongo/server_selector.rb +0 -19
  38. data/lib/mongo/server_selector/selectable.rb +4 -22
  39. data/lib/mongo/uri.rb +9 -55
  40. data/lib/mongo/version.rb +1 -1
  41. data/spec/mongo/address/ipv4_spec.rb +27 -6
  42. data/spec/mongo/address/ipv6_spec.rb +27 -6
  43. data/spec/mongo/address/unix_spec.rb +15 -4
  44. data/spec/mongo/auth/cr_spec.rb +2 -2
  45. data/spec/mongo/auth/ldap_spec.rb +2 -2
  46. data/spec/mongo/auth/scram_spec.rb +2 -2
  47. data/spec/mongo/auth/x509_spec.rb +2 -2
  48. data/spec/mongo/client_spec.rb +8 -0
  49. data/spec/mongo/cluster/topology/replica_set_spec.rb +6 -6
  50. data/spec/mongo/cluster/topology/sharded_spec.rb +5 -5
  51. data/spec/mongo/cluster/topology/{standalone_spec.rb → single_spec.rb} +7 -7
  52. data/spec/mongo/cluster/topology_spec.rb +31 -5
  53. data/spec/mongo/cluster_spec.rb +103 -21
  54. data/spec/mongo/collection/view/readable_spec.rb +18 -7
  55. data/spec/mongo/collection/view_spec.rb +13 -0
  56. data/spec/mongo/collection_spec.rb +7 -0
  57. data/spec/mongo/database_spec.rb +2 -2
  58. data/spec/mongo/protocol/query_spec.rb +29 -0
  59. data/spec/mongo/server/connection_pool_spec.rb +4 -4
  60. data/spec/mongo/server/connection_spec.rb +46 -10
  61. data/spec/mongo/server/monitor_spec.rb +2 -2
  62. data/spec/mongo/server_discovery_and_monitoring_spec.rb +23 -0
  63. data/spec/mongo/server_selection_rtt_spec.rb +2 -1
  64. data/spec/mongo/server_selection_spec.rb +6 -15
  65. data/spec/mongo/server_selector/nearest_spec.rb +1 -1
  66. data/spec/mongo/server_selector_spec.rb +53 -2
  67. data/spec/mongo/server_spec.rb +9 -9
  68. data/spec/mongo/socket/ssl_spec.rb +1 -1
  69. data/spec/mongo/uri_spec.rb +2 -2
  70. data/spec/spec_helper.rb +34 -5
  71. data/spec/support/authorization.rb +32 -46
  72. data/spec/support/server_discovery_and_monitoring.rb +1 -1
  73. data/spec/support/server_selection.rb +1 -25
  74. data/spec/support/shared/operation.rb +3 -0
  75. data/spec/support/shared/server_selector.rb +1 -1
  76. metadata +10 -7
  77. metadata.gz.sig +0 -0
  78. data/lib/mongo/auth/executable.rb +0 -52
@@ -436,11 +436,11 @@ describe Mongo::Collection::View::Readable do
436
436
 
437
437
  describe '#projection' do
438
438
 
439
- context 'when projection are specified' do
439
+ let(:options) do
440
+ { :projection => { 'x' => 1 } }
441
+ end
440
442
 
441
- let(:options) do
442
- { :projection => { 'x' => 1 } }
443
- end
443
+ context 'when projection are specified' do
444
444
 
445
445
  let(:new_projection) do
446
446
  { 'y' => 1 }
@@ -456,14 +456,25 @@ describe Mongo::Collection::View::Readable do
456
456
  end
457
457
  end
458
458
 
459
- context 'when projection are not specified' do
460
-
461
- let(:options) { { :projection => { 'x' => 1 } } }
459
+ context 'when projection is not specified' do
462
460
 
463
461
  it 'returns the projection' do
464
462
  expect(view.projection).to eq(options[:projection])
465
463
  end
466
464
  end
465
+
466
+ context 'when projection is not a document' do
467
+
468
+ let(:new_projection) do
469
+ 'y'
470
+ end
471
+
472
+ it 'raises an error' do
473
+ expect do
474
+ view.projection(new_projection)
475
+ end.to raise_error(Mongo::Error::InvalidDocument)
476
+ end
477
+ end
467
478
  end
468
479
 
469
480
  describe '#read' do
@@ -496,6 +496,19 @@ describe Mongo::Collection::View do
496
496
  it 'dups the options' do
497
497
  expect(view.options).not_to be(options)
498
498
  end
499
+
500
+ context 'when the selector is not a valid document' do
501
+
502
+ let(:selector) do
503
+ 'y'
504
+ end
505
+
506
+ it 'raises an error' do
507
+ expect do
508
+ view
509
+ end.to raise_error(Mongo::Error::InvalidDocument)
510
+ end
511
+ end
499
512
  end
500
513
 
501
514
  describe '#inspect' do
@@ -229,6 +229,13 @@ describe Mongo::Collection do
229
229
  it 'drops the collection from the database' do
230
230
  expect(database.collection_names).to_not include('specs')
231
231
  end
232
+
233
+ context 'when the collection does not exist' do
234
+
235
+ it 'does not raise an error' do
236
+ expect(database['non-existent-coll'].drop).to be(false)
237
+ end
238
+ end
232
239
  end
233
240
 
234
241
  describe '#find' do
@@ -158,7 +158,7 @@ describe Mongo::Database do
158
158
  context 'when an alternate read preference is specified' do
159
159
 
160
160
  before do
161
- allow(database.cluster).to receive(:standalone?).and_return(false)
161
+ allow(database.cluster).to receive(:single?).and_return(false)
162
162
  end
163
163
 
164
164
  let(:read) do
@@ -176,7 +176,7 @@ describe Mongo::Database do
176
176
  it 'uses that read preference', unless: sharded? do
177
177
  expect do
178
178
  database.command({ ping: 1 }, { read: read })
179
- end.to raise_error(Mongo::ServerSelector::NoServerAvailable)
179
+ end.to raise_error(Mongo::Error::NoServerAvailable)
180
180
  end
181
181
  end
182
182
  end
@@ -282,4 +282,33 @@ describe Mongo::Protocol::Query do
282
282
  end
283
283
  end
284
284
  end
285
+
286
+ describe '#log_message' do
287
+
288
+ context 'when the selector is greater than LOG_STRING_LIMIT characters' do
289
+
290
+ let(:selector) do
291
+ 'z'*260
292
+ end
293
+
294
+ it 'Only prints LOG_STRING_LIMIT number of characters' do
295
+ expect(message.log_message.scan(/z/).length).to eq(Mongo::Protocol::Query::LOG_STRING_LIMIT)
296
+ end
297
+ end
298
+
299
+ context 'when the selector cannot be inspected' do
300
+
301
+ let(:selector) do
302
+ 'invalid string'
303
+ end
304
+
305
+ before do
306
+ allow(selector).to receive(:inspect).and_raise(ArgumentError)
307
+ end
308
+
309
+ it 'Does not include the selector in the log message' do
310
+ expect(message.log_message.scan(/invalid string/).length).to eq(0)
311
+ end
312
+ end
313
+ end
285
314
  end
@@ -9,7 +9,7 @@ describe Mongo::Server::ConnectionPool do
9
9
  describe '#checkin' do
10
10
 
11
11
  let(:server) do
12
- Mongo::Server.new(address, Mongo::Event::Listeners.new)
12
+ Mongo::Server.new(address, Mongo::Event::Listeners.new, ssl: SSL)
13
13
  end
14
14
 
15
15
  let(:pool) do
@@ -39,7 +39,7 @@ describe Mongo::Server::ConnectionPool do
39
39
  describe '#checkout' do
40
40
 
41
41
  let(:server) do
42
- Mongo::Server.new(address, Mongo::Event::Listeners.new)
42
+ Mongo::Server.new(address, Mongo::Event::Listeners.new, ssl: SSL)
43
43
  end
44
44
 
45
45
  let(:pool) do
@@ -87,7 +87,7 @@ describe Mongo::Server::ConnectionPool do
87
87
  describe '.get' do
88
88
 
89
89
  let(:server) do
90
- Mongo::Server.new(address, Mongo::Event::Listeners.new)
90
+ Mongo::Server.new(address, Mongo::Event::Listeners.new, ssl: SSL)
91
91
  end
92
92
 
93
93
  let(:pool) do
@@ -102,7 +102,7 @@ describe Mongo::Server::ConnectionPool do
102
102
  describe '#inspect' do
103
103
 
104
104
  let(:server) do
105
- Mongo::Server.new(address, Mongo::Event::Listeners.new)
105
+ Mongo::Server.new(address, Mongo::Event::Listeners.new, ssl: SSL)
106
106
  end
107
107
 
108
108
  let(:pool) do
@@ -7,7 +7,7 @@ describe Mongo::Server::Connection do
7
7
  end
8
8
 
9
9
  let(:server) do
10
- Mongo::Server.new(address, Mongo::Event::Listeners.new)
10
+ Mongo::Server.new(address, Mongo::Event::Listeners.new, ssl: SSL)
11
11
  end
12
12
 
13
13
  describe '#connect!' do
@@ -66,9 +66,10 @@ describe Mongo::Server::Connection do
66
66
  let(:connection) do
67
67
  described_class.new(
68
68
  server,
69
- :user => 'notauser',
70
- :password => 'password',
71
- :database => TEST_DB
69
+ TEST_OPTIONS.merge(
70
+ :user => 'notauser',
71
+ :password => 'password',
72
+ :database => TEST_DB )
72
73
  )
73
74
  end
74
75
 
@@ -84,9 +85,10 @@ describe Mongo::Server::Connection do
84
85
  let(:connection) do
85
86
  described_class.new(
86
87
  server,
87
- :user => TEST_USER.name,
88
- :password => TEST_USER.password,
89
- :database => TEST_DB
88
+ TEST_OPTIONS.merge(
89
+ :user => TEST_USER.name,
90
+ :password => TEST_USER.password,
91
+ :database => TEST_DB )
90
92
  )
91
93
  end
92
94
 
@@ -136,9 +138,10 @@ describe Mongo::Server::Connection do
136
138
  let!(:connection) do
137
139
  described_class.new(
138
140
  server,
139
- :user => TEST_USER.name,
140
- :password => TEST_USER.password,
141
- :database => TEST_DB
141
+ TEST_OPTIONS.merge(
142
+ :user => TEST_USER.name,
143
+ :password => TEST_USER.password,
144
+ :database => TEST_DB )
142
145
  )
143
146
  end
144
147
 
@@ -284,6 +287,39 @@ describe Mongo::Server::Connection do
284
287
  end
285
288
  end
286
289
 
290
+ context 'when ssl is false' do
291
+
292
+ context 'when ssl options are provided' do
293
+
294
+ let(:ssl_options) do
295
+ { :ssl => false, :ssl_key => 'file', :ssl_key_pass_phrase => 'iamaphrase' }
296
+ end
297
+
298
+ let(:connection) do
299
+ described_class.new(server, ssl_options)
300
+ end
301
+
302
+ it 'does not set the ssl options' do
303
+ expect(connection.send(:ssl_options)).to be_empty
304
+ end
305
+ end
306
+
307
+ context 'when ssl options are not provided' do
308
+
309
+ let(:ssl_options) do
310
+ { :ssl => false }
311
+ end
312
+
313
+ let(:connection) do
314
+ described_class.new(server, ssl_options)
315
+ end
316
+
317
+ it 'does not set the ssl options' do
318
+ expect(connection.send(:ssl_options)).to be_empty
319
+ end
320
+ end
321
+ end
322
+
287
323
  context 'when authentication options are provided' do
288
324
 
289
325
  let(:connection) do
@@ -15,7 +15,7 @@ describe Mongo::Server::Monitor do
15
15
  context 'when calling multiple times in succession' do
16
16
 
17
17
  let(:monitor) do
18
- described_class.new(address, listeners)
18
+ described_class.new(address, listeners, TEST_OPTIONS)
19
19
  end
20
20
 
21
21
  it 'throttles the scans to minimum 500ms' do
@@ -29,7 +29,7 @@ describe Mongo::Server::Monitor do
29
29
  context 'when the ismaster command succeeds' do
30
30
 
31
31
  let(:monitor) do
32
- described_class.new(address, listeners)
32
+ described_class.new(address, listeners, TEST_OPTIONS)
33
33
  end
34
34
 
35
35
  before do
@@ -11,6 +11,20 @@ describe 'Server Discovery and Monitoring' do
11
11
 
12
12
  before(:all) do
13
13
 
14
+ # We monkey-patch the address, so that looking up the spec's hostname does
15
+ # not throw an error.
16
+ #
17
+ # @since 2.0.0
18
+ class Mongo::Address
19
+ private
20
+
21
+ def family(host)
22
+ fam = host == 'localhost' ? ::Socket::AF_INET : ::Socket::AF_UNSPEC
23
+ ::Socket.getaddrinfo(host, nil, fam, ::Socket::SOCK_STREAM).first[4]
24
+ rescue SocketError
25
+ end
26
+ end
27
+
14
28
  # We monkey-patch the server here, so the monitors do not run and no
15
29
  # real TCP connection is attempted. Thus we can control the server
16
30
  # descriptions per-phase.
@@ -60,6 +74,15 @@ describe 'Server Discovery and Monitoring' do
60
74
  @monitor.stop! and true
61
75
  end
62
76
  end
77
+
78
+ class Mongo::Address
79
+ private
80
+
81
+ def family(host)
82
+ fam = host == 'localhost' ? ::Socket::AF_INET : ::Socket::AF_UNSPEC
83
+ ::Socket.getaddrinfo(host, nil, fam, ::Socket::SOCK_STREAM).first[4]
84
+ end
85
+ end
63
86
  end
64
87
 
65
88
  spec.phases.each_with_index do |phase, index|
@@ -88,7 +88,8 @@ describe 'Server Selection moving average round trip time calculation' do
88
88
  end
89
89
 
90
90
  let(:monitor) do
91
- Mongo::Server::Monitor.new(address, Mongo::Event::Listeners.new, avg_rtt_ms: spec.avg_rtt_ms)
91
+ Mongo::Server::Monitor.new(address, Mongo::Event::Listeners.new,
92
+ TEST_OPTIONS.merge(avg_rtt_ms: spec.avg_rtt_ms))
92
93
  end
93
94
 
94
95
  before do
@@ -17,7 +17,7 @@ describe 'Server Selection' do
17
17
  let(:cluster) do
18
18
  double('cluster').tap do |c|
19
19
  allow(c).to receive(:topology).and_return(topology)
20
- allow(c).to receive(:standalone?).and_return(topology.standalone?)
20
+ allow(c).to receive(:single?).and_return(topology.single?)
21
21
  allow(c).to receive(:sharded?).and_return(topology.sharded?)
22
22
  allow(c).to receive(:replica_set?).and_return(topology.replica_set?)
23
23
  end
@@ -26,7 +26,7 @@ describe 'Server Selection' do
26
26
  let(:candidate_servers) do
27
27
  spec.candidate_servers.collect do |server|
28
28
  address = Mongo::Address.new(server['address'])
29
- Mongo::Server.new(address, Mongo::Event::Listeners.new).tap do |s|
29
+ Mongo::Server.new(address, Mongo::Event::Listeners.new, TEST_OPTIONS).tap do |s|
30
30
  allow(s).to receive(:average_round_trip_time).and_return(server['avg_rtt_ms'])
31
31
  allow(s).to receive(:tags).and_return(server['tags'])
32
32
  allow(s).to receive(:secondary?).and_return(server['type'] == 'RSSecondary')
@@ -38,7 +38,7 @@ describe 'Server Selection' do
38
38
  let(:in_latency_window) do
39
39
  spec.in_latency_window.collect do |server|
40
40
  address = Mongo::Address.new(server['address'])
41
- Mongo::Server.new(address, Mongo::Event::Listeners.new).tap do |s|
41
+ Mongo::Server.new(address, Mongo::Event::Listeners.new, TEST_OPTIONS).tap do |s|
42
42
  allow(s).to receive(:average_round_trip_time).and_return(server['avg_rtt_ms'])
43
43
  allow(s).to receive(:tags).and_return(server['tags'])
44
44
  end
@@ -56,7 +56,7 @@ describe 'Server Selection' do
56
56
  allow(cluster).to receive(:scan!).and_return(true)
57
57
  end
58
58
 
59
- context 'Valid read preference and matching server available', unless: spec.raises_exception? do
59
+ context 'Valid read preference and matching server available', if: spec.server_available? do
60
60
 
61
61
  it 'Finds all suitable servers in the latency window', if: spec.replica_set? do
62
62
  expect(server_selector.send(:select, cluster.servers)).to eq(in_latency_window)
@@ -67,21 +67,12 @@ describe 'Server Selection' do
67
67
  end
68
68
  end
69
69
 
70
- context 'Invalid read preference', if: spec.invalid_server_preference? do
70
+ context 'No matching server available', if: !spec.server_available? do
71
71
 
72
72
  it 'Raises exception' do
73
73
  expect do
74
74
  server_selector.select_server(cluster)
75
- end.to raise_exception(Mongo::ServerSelector::InvalidServerPreference)
76
- end
77
- end
78
-
79
- context 'No matching server available', unless: spec.server_available? do
80
-
81
- it 'Raises exception' do
82
- expect do
83
- server_selector.select_server(cluster)
84
- end.to raise_exception(Mongo::ServerSelector::NoServerAvailable)
75
+ end.to raise_exception(Mongo::Error::NoServerAvailable)
85
76
  end
86
77
  end
87
78
  end
@@ -118,7 +118,7 @@ describe Mongo::ServerSelector::Nearest do
118
118
  end
119
119
  end
120
120
 
121
- context 'mtuliple candidates' do
121
+ context 'multiple candidates' do
122
122
 
123
123
  context 'no matching servers' do
124
124
  let(:candidates) { [primary, secondary, secondary] }
@@ -79,7 +79,7 @@ describe Mongo::ServerSelector do
79
79
  let(:cluster) do
80
80
  double('cluster').tap do |c|
81
81
  allow(c).to receive(:servers).and_return(servers)
82
- allow(c).to receive(:standalone?).and_return(false)
82
+ allow(c).to receive(:single?).and_return(false)
83
83
  allow(c).to receive(:sharded?).and_return(false)
84
84
  allow(c).to receive(:scan!).and_return(true)
85
85
  end
@@ -94,8 +94,59 @@ describe Mongo::ServerSelector do
94
94
  it 'raises a NoServerAvailable error' do
95
95
  expect do
96
96
  read_pref.select_server(cluster)
97
- end.to raise_exception(Mongo::ServerSelector::NoServerAvailable)
97
+ end.to raise_exception(Mongo::Error::NoServerAvailable)
98
98
  end
99
99
  end
100
100
  end
101
+
102
+ shared_context 'a ServerSelector' do
103
+
104
+ context 'when cluster#servers is empty' do
105
+
106
+ let(:servers) { [] }
107
+
108
+ let(:cluster) do
109
+ double('cluster').tap do |c|
110
+ allow(c).to receive(:servers).and_return(servers)
111
+ allow(c).to receive(:single?).and_return(single)
112
+ allow(c).to receive(:sharded?).and_return(sharded)
113
+ allow(c).to receive(:scan!).and_return(true)
114
+ end
115
+ end
116
+
117
+ let(:read_pref) do
118
+ described_class.get({ mode: :primary }, server_selection_timeout: 1)
119
+ end
120
+
121
+ it 'raises a NoServerAvailable error' do
122
+ expect do
123
+ read_pref.select_server(cluster)
124
+ end.to raise_exception(Mongo::Error::NoServerAvailable)
125
+ end
126
+ end
127
+ end
128
+
129
+ context 'when the cluster has a Single topology' do
130
+
131
+ let(:single) { true }
132
+ let(:sharded) { false }
133
+
134
+ it_behaves_like 'a ServerSelector'
135
+ end
136
+
137
+ context 'when the cluster has a ReplicaSet topology' do
138
+
139
+ let(:single) { false }
140
+ let(:sharded) { false }
141
+
142
+ it_behaves_like 'a ServerSelector'
143
+ end
144
+
145
+ context 'when the cluster has a Sharded topology' do
146
+
147
+ let(:single) { false }
148
+ let(:sharded) { true }
149
+
150
+ it_behaves_like 'a ServerSelector'
151
+ end
101
152
  end