mongo 2.0.2 → 2.0.3

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