mongo 2.0.5 → 2.0.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 (85) 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/cr/conversation.rb +0 -1
  5. data/lib/mongo/client.rb +19 -5
  6. data/lib/mongo/cluster.rb +84 -16
  7. data/lib/mongo/cluster/topology.rb +3 -4
  8. data/lib/mongo/cluster/topology/replica_set.rb +75 -0
  9. data/lib/mongo/cluster/topology/sharded.rb +60 -0
  10. data/lib/mongo/cluster/topology/single.rb +51 -0
  11. data/lib/mongo/cluster/topology/unknown.rb +62 -0
  12. data/lib/mongo/error/invalid_bulk_operation.rb +2 -1
  13. data/lib/mongo/event.rb +9 -9
  14. data/lib/mongo/event/{server_added.rb → description_changed.rb} +6 -5
  15. data/lib/mongo/event/{server_removed.rb → standalone_discovered.rb} +15 -15
  16. data/lib/mongo/operation/aggregate.rb +6 -5
  17. data/lib/mongo/operation/command.rb +5 -6
  18. data/lib/mongo/operation/kill_cursors.rb +3 -2
  19. data/lib/mongo/operation/map_reduce.rb +6 -5
  20. data/lib/mongo/operation/read/collections_info.rb +5 -4
  21. data/lib/mongo/operation/read/get_more.rb +8 -7
  22. data/lib/mongo/operation/read/indexes.rb +4 -3
  23. data/lib/mongo/operation/read/list_collections.rb +5 -4
  24. data/lib/mongo/operation/read/list_indexes.rb +7 -6
  25. data/lib/mongo/operation/read/query.rb +8 -7
  26. data/lib/mongo/operation/read_preferrable.rb +6 -2
  27. data/lib/mongo/operation/write/bulk/bulk_delete.rb +13 -12
  28. data/lib/mongo/operation/write/bulk/bulk_insert.rb +10 -9
  29. data/lib/mongo/operation/write/bulk/bulk_insert/result.rb +2 -2
  30. data/lib/mongo/operation/write/bulk/bulk_update.rb +12 -11
  31. data/lib/mongo/operation/write/create_index.rb +8 -7
  32. data/lib/mongo/operation/write/create_user.rb +4 -3
  33. data/lib/mongo/operation/write/delete.rb +13 -12
  34. data/lib/mongo/operation/write/drop_index.rb +6 -5
  35. data/lib/mongo/operation/write/insert.rb +8 -7
  36. data/lib/mongo/operation/write/insert/result.rb +1 -1
  37. data/lib/mongo/operation/write/remove_user.rb +4 -3
  38. data/lib/mongo/operation/write/update.rb +10 -9
  39. data/lib/mongo/operation/write/update_user.rb +4 -3
  40. data/lib/mongo/server.rb +8 -15
  41. data/lib/mongo/server/context.rb +2 -2
  42. data/lib/mongo/server/description.rb +65 -3
  43. data/lib/mongo/server/description/features.rb +2 -1
  44. data/lib/mongo/server/description/inspector.rb +5 -5
  45. data/lib/mongo/server/description/inspector/{server_added.rb → description_changed.rb} +3 -5
  46. data/lib/mongo/server/description/inspector/{server_removed.rb → standalone_discovered.rb} +12 -15
  47. data/lib/mongo/version.rb +1 -1
  48. data/spec/mongo/auth/cr_spec.rb +1 -1
  49. data/spec/mongo/auth/ldap_spec.rb +1 -1
  50. data/spec/mongo/auth/scram_spec.rb +1 -1
  51. data/spec/mongo/auth/x509_spec.rb +1 -1
  52. data/spec/mongo/client_spec.rb +4 -0
  53. data/spec/mongo/cluster/topology/replica_set_spec.rb +254 -4
  54. data/spec/mongo/cluster/topology/sharded_spec.rb +70 -19
  55. data/spec/mongo/cluster/topology/single_spec.rb +25 -4
  56. data/spec/mongo/cluster/topology/unknown_spec.rb +167 -0
  57. data/spec/mongo/cluster/topology_spec.rb +6 -6
  58. data/spec/mongo/cluster_spec.rb +179 -1
  59. data/spec/mongo/operation/read_preferrable_spec.rb +81 -28
  60. data/spec/mongo/operation/write/bulk/bulk_delete_spec.rb +1 -0
  61. data/spec/mongo/server/connection_pool_spec.rb +10 -10
  62. data/spec/mongo/server/connection_spec.rb +1 -1
  63. data/spec/mongo/server/description/features_spec.rb +23 -3
  64. data/spec/mongo/server/description/inspector/description_changed_spec.rb +78 -0
  65. data/spec/mongo/server/description_spec.rb +238 -0
  66. data/spec/mongo/server/monitor_spec.rb +1 -1
  67. data/spec/mongo/server_discovery_and_monitoring_spec.rb +20 -4
  68. data/spec/mongo/server_selection_spec.rb +2 -2
  69. data/spec/mongo/server_spec.rb +12 -8
  70. data/spec/support/authorization.rb +8 -8
  71. data/spec/support/sdam/rs/discover_passives.yml +36 -0
  72. data/spec/support/sdam/rs/new_primary_wrong_set_name.yml +2 -2
  73. data/spec/support/sdam/rs/primary_becomes_standalone.yml +1 -1
  74. data/spec/support/sdam/rs/primary_changes_set_name.yml +2 -2
  75. data/spec/support/sdam/rs/primary_disconnect.yml +1 -1
  76. data/spec/support/sdam/rs/primary_wrong_set_name.yml +1 -1
  77. data/spec/support/sdam/rs/secondary_wrong_set_name.yml +1 -1
  78. data/spec/support/sdam/rs/secondary_wrong_set_name_with_primary.yml +2 -2
  79. data/spec/support/sdam/sharded/single_mongos.yml +33 -0
  80. data/spec/support/shared/operation.rb +12 -4
  81. data/spec/support/shared/server_selector.rb +1 -1
  82. metadata +12 -10
  83. metadata.gz.sig +0 -0
  84. data/spec/mongo/server/description/inspector/server_added_spec.rb +0 -92
  85. data/spec/mongo/server/description/inspector/server_removed_spec.rb +0 -95
@@ -13,8 +13,8 @@
13
13
  # limitations under the License.
14
14
 
15
15
  require 'mongo/server/description/inspector/primary_elected'
16
- require 'mongo/server/description/inspector/server_added'
17
- require 'mongo/server/description/inspector/server_removed'
16
+ require 'mongo/server/description/inspector/description_changed'
17
+ require 'mongo/server/description/inspector/standalone_discovered'
18
18
 
19
19
  module Mongo
20
20
  class Server
@@ -32,9 +32,9 @@ module Mongo
32
32
  #
33
33
  # @since 2.0.0
34
34
  INSPECTORS = [
35
- Inspector::PrimaryElected,
36
- Inspector::ServerAdded,
37
- Inspector::ServerRemoved
35
+ Inspector::StandaloneDiscovered,
36
+ Inspector::DescriptionChanged,
37
+ Inspector::PrimaryElected
38
38
  ].freeze
39
39
 
40
40
  # @return [ Array ] inspectors The description inspectors.
@@ -21,7 +21,7 @@ module Mongo
21
21
  # added to the cluster.
22
22
  #
23
23
  # @since 2.0.0
24
- class ServerAdded
24
+ class DescriptionChanged
25
25
  include Event::Publisher
26
26
 
27
27
  # Instantiate the server added inspection.
@@ -46,10 +46,8 @@ module Mongo
46
46
  #
47
47
  # @since 2.0.0
48
48
  def run(description, updated)
49
- updated.servers.each do |host|
50
- unless description.servers.include?(host)
51
- publish(Event::SERVER_ADDED, host)
52
- end
49
+ unless description == updated
50
+ publish(Event::DESCRIPTION_CHANGED, updated)
53
51
  end
54
52
  end
55
53
  end
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2014-2015 MongoDB, Inc.
1
+ # Copyright (C) 2015 MongoDB, Inc.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the 'License');
4
4
  # you may not use this file except in compliance with the License.
@@ -17,39 +17,36 @@ module Mongo
17
17
  class Description
18
18
  class Inspector
19
19
 
20
- # Handles inspecting the result of an ismaster command for servers
21
- # that were removed from the cluster.
20
+ # Handles notifying the cluster that a standalone was discovered.
22
21
  #
23
- # @since 2.0.0
24
- class ServerRemoved
22
+ # @since 2.0.6
23
+ class StandaloneDiscovered
25
24
  include Event::Publisher
26
25
 
27
- # Instantiate the server removed inspection.
26
+ # Instantiate the standalone discovered inspection.
28
27
  #
29
28
  # @example Instantiate the inspection.
30
- # ServerRemoved.new(listeners)
29
+ # StandaloneDiscovered.new(listeners)
31
30
  #
32
31
  # @param [ Event::Listeners ] event_listeners The event listeners.
33
32
  #
34
- # @since 2.0.0
33
+ # @since 2.0.6
35
34
  def initialize(event_listeners)
36
35
  @event_listeners = event_listeners
37
36
  end
38
37
 
39
- # Run the server added inspection.
38
+ # Run the standalone discovered inspection.
40
39
  #
41
40
  # @example Run the inspection.
42
- # ServerAdded.run(description, {})
41
+ # StandaloneDiscovered.run(description, {})
43
42
  #
44
43
  # @param [ Description ] description The server description.
45
44
  # @param [ Description ] updated The updated description.
46
45
  #
47
- # @since 2.0.0
46
+ # @since 2.0.6
48
47
  def run(description, updated)
49
- description.hosts.each do |host|
50
- if updated.primary? && !updated.hosts.include?(host)
51
- publish(Event::SERVER_REMOVED, host)
52
- end
48
+ if !description.standalone? && updated.standalone?
49
+ publish(Event::STANDALONE_DISCOVERED, updated)
53
50
  end
54
51
  end
55
52
  end
@@ -17,5 +17,5 @@ module Mongo
17
17
  # The current version of the driver.
18
18
  #
19
19
  # @since 2.0.0
20
- VERSION = '2.0.5'.freeze
20
+ VERSION = '2.0.6'.freeze
21
21
  end
@@ -7,7 +7,7 @@ describe Mongo::Auth::CR do
7
7
  end
8
8
 
9
9
  let(:server) do
10
- Mongo::Server.new(address, Mongo::Event::Listeners.new, TEST_OPTIONS)
10
+ Mongo::Server.new(address, double('cluster'), Mongo::Event::Listeners.new, TEST_OPTIONS)
11
11
  end
12
12
 
13
13
  let(:connection) do
@@ -7,7 +7,7 @@ describe Mongo::Auth::LDAP do
7
7
  end
8
8
 
9
9
  let(:server) do
10
- Mongo::Server.new(address, Mongo::Event::Listeners.new, TEST_OPTIONS)
10
+ Mongo::Server.new(address, double('cluster'), Mongo::Event::Listeners.new, TEST_OPTIONS)
11
11
  end
12
12
 
13
13
  let(:connection) do
@@ -7,7 +7,7 @@ describe Mongo::Auth::SCRAM do
7
7
  end
8
8
 
9
9
  let(:server) do
10
- Mongo::Server.new(address, Mongo::Event::Listeners.new, TEST_OPTIONS)
10
+ Mongo::Server.new(address, double('cluster'), Mongo::Event::Listeners.new, TEST_OPTIONS)
11
11
  end
12
12
 
13
13
  let(:connection) do
@@ -7,7 +7,7 @@ describe Mongo::Auth::X509 do
7
7
  end
8
8
 
9
9
  let(:server) do
10
- Mongo::Server.new(address, Mongo::Event::Listeners.new, TEST_OPTIONS)
10
+ Mongo::Server.new(address, double('cluster'), Mongo::Event::Listeners.new, TEST_OPTIONS)
11
11
  end
12
12
 
13
13
  let(:connection) do
@@ -412,6 +412,10 @@ describe Mongo::Client do
412
412
  it 'returns the new client' do
413
413
  expect(client.send(:database).name).to eq('ruby-driver')
414
414
  end
415
+
416
+ it 'keeps the same cluster' do
417
+ expect(database.cluster).to equal(client.cluster)
418
+ end
415
419
  end
416
420
 
417
421
  context 'when provided a string' do
@@ -9,19 +9,19 @@ describe Mongo::Cluster::Topology::ReplicaSet do
9
9
  describe '#servers' do
10
10
 
11
11
  let(:mongos) do
12
- Mongo::Server.new(address, Mongo::Event::Listeners.new, TEST_OPTIONS)
12
+ Mongo::Server.new(address, double('cluster'), Mongo::Event::Listeners.new, TEST_OPTIONS)
13
13
  end
14
14
 
15
15
  let(:standalone) do
16
- Mongo::Server.new(address, Mongo::Event::Listeners.new, TEST_OPTIONS)
16
+ Mongo::Server.new(address, double('cluster'), Mongo::Event::Listeners.new, TEST_OPTIONS)
17
17
  end
18
18
 
19
19
  let(:replica_set) do
20
- Mongo::Server.new(address, Mongo::Event::Listeners.new, TEST_OPTIONS)
20
+ Mongo::Server.new(address, double('cluster'), Mongo::Event::Listeners.new, TEST_OPTIONS)
21
21
  end
22
22
 
23
23
  let(:replica_set_two) do
24
- Mongo::Server.new(address, Mongo::Event::Listeners.new, TEST_OPTIONS)
24
+ Mongo::Server.new(address, double('cluster'), Mongo::Event::Listeners.new, TEST_OPTIONS)
25
25
  end
26
26
 
27
27
  let(:mongos_description) do
@@ -98,4 +98,254 @@ describe Mongo::Cluster::Topology::ReplicaSet do
98
98
  expect(described_class.new({})).to_not be_single
99
99
  end
100
100
  end
101
+
102
+ describe '#add_hosts?' do
103
+
104
+ let(:primary) do
105
+ Mongo::Server.new(address, double('cluster'), Mongo::Event::Listeners.new, TEST_OPTIONS)
106
+ end
107
+
108
+ let(:secondary) do
109
+ Mongo::Server.new(address, double('cluster'), Mongo::Event::Listeners.new, TEST_OPTIONS)
110
+ end
111
+
112
+ let(:primary_description) do
113
+ Mongo::Server::Description.new(address, { 'ismaster' => true, 'setName' => 'testing' })
114
+ end
115
+
116
+ let(:secondary_description) do
117
+ Mongo::Server::Description.new(address, { 'ismaster' => false, 'secondary' => true,
118
+ 'setName' => 'testing' })
119
+ end
120
+
121
+ let(:topology) do
122
+ described_class.new(:replica_set => 'testing')
123
+ end
124
+
125
+ before do
126
+ primary.monitor.instance_variable_set(:@description, primary_description)
127
+ secondary.monitor.instance_variable_set(:@description, secondary_description)
128
+ end
129
+
130
+ context 'when the list of servers does not include a primary' do
131
+
132
+ let(:servers) do
133
+ [ secondary ]
134
+ end
135
+
136
+ context 'when the description is a member of the replica set' do
137
+
138
+ let(:description) do
139
+ double('description').tap do |d|
140
+ allow(d).to receive(:replica_set_member?).and_return(true)
141
+ allow(d).to receive(:replica_set_name).and_return('testing')
142
+ end
143
+ end
144
+
145
+ it 'returns true' do
146
+ expect(topology.add_hosts?(description, servers)).to eq(true)
147
+ end
148
+ end
149
+
150
+ context 'when the description is not a member of the replica set' do
151
+
152
+ let(:description) do
153
+ double('description').tap do |d|
154
+ allow(d).to receive(:replica_set_member?).and_return(false)
155
+ end
156
+ end
157
+
158
+ it 'returns false' do
159
+ expect(topology.add_hosts?(description, servers)).to eq(false)
160
+ end
161
+ end
162
+ end
163
+
164
+ context 'when the list of servers has a primary' do
165
+
166
+ let(:servers) do
167
+ [ primary, secondary ]
168
+ end
169
+
170
+ let(:description) do
171
+ double('description').tap do |d|
172
+ allow(d).to receive(:replica_set_member?).and_return(true)
173
+ allow(d).to receive(:replica_set_name).and_return('testing')
174
+ end
175
+ end
176
+
177
+ it 'returns false' do
178
+ expect(topology.add_hosts?(description, servers)).to eq(false)
179
+ end
180
+ end
181
+ end
182
+
183
+ describe '#remove_hosts?' do
184
+
185
+ let(:primary) do
186
+ Mongo::Server.new(address, double('cluster'), Mongo::Event::Listeners.new, TEST_OPTIONS)
187
+ end
188
+
189
+ let(:primary_description) do
190
+ Mongo::Server::Description.new(address, { 'ismaster' => true, 'setName' => 'testing' })
191
+ end
192
+
193
+ let(:topology) do
194
+ described_class.new(:replica_set => 'testing')
195
+ end
196
+
197
+ before do
198
+ primary.monitor.instance_variable_set(:@description, primary_description)
199
+ end
200
+
201
+ context 'when the description has an empty config' do
202
+
203
+ let(:description) do
204
+ double('description').tap do |d|
205
+ allow(d).to receive(:config).and_return({})
206
+ end
207
+ end
208
+
209
+ it 'returns false' do
210
+ expect(topology.remove_hosts?(description)).to eq(false)
211
+ end
212
+ end
213
+
214
+ context 'when the description is from a primary' do
215
+
216
+ let(:description) do
217
+ double('description').tap do |d|
218
+ allow(d).to receive(:config).and_return({ 'ismaster' => true })
219
+ allow(d).to receive(:primary?).and_return(true)
220
+ end
221
+ end
222
+
223
+ it 'returns true' do
224
+ expect(topology.remove_hosts?(description)).to eq(true)
225
+ end
226
+ end
227
+
228
+ context 'when the description has an empty hosts list' do
229
+
230
+ let(:description) do
231
+ double('description').tap do |d|
232
+ allow(d).to receive(:config).and_return({ 'ismaster' => true })
233
+ allow(d).to receive(:primary?).and_return(false)
234
+ allow(d).to receive(:hosts).and_return([])
235
+ end
236
+ end
237
+
238
+ it 'returns true' do
239
+ expect(topology.remove_hosts?(description)).to eq(true)
240
+ end
241
+ end
242
+
243
+ context 'when the description is not from the replica set' do
244
+
245
+ let(:description) do
246
+ double('description').tap do |d|
247
+ allow(d).to receive(:config).and_return({ 'ismaster' => true })
248
+ allow(d).to receive(:primary?).and_return(false)
249
+ allow(d).to receive(:hosts).and_return([ primary ])
250
+ allow(d).to receive(:replica_set_name).and_return('test')
251
+ allow(d).to receive(:replica_set_member?).and_return(true)
252
+ end
253
+ end
254
+
255
+ it 'returns true' do
256
+ expect(topology.remove_hosts?(description)).to eq(true)
257
+ end
258
+ end
259
+
260
+ end
261
+
262
+ describe '#remove_server?' do
263
+
264
+ let(:secondary) do
265
+ Mongo::Server.new(address, double('cluster'), Mongo::Event::Listeners.new, TEST_OPTIONS)
266
+ end
267
+
268
+ let(:secondary_description) do
269
+ Mongo::Server::Description.new(address, { 'ismaster' => false, 'secondary' => true,
270
+ 'setName' => 'test' })
271
+ end
272
+
273
+ let(:topology) do
274
+ described_class.new(:replica_set => 'testing')
275
+ end
276
+
277
+ before do
278
+ secondary.monitor.instance_variable_set(:@description, secondary_description)
279
+ end
280
+
281
+ context 'when the description is from a server that should itself be removed' do
282
+
283
+ let(:description) do
284
+ double('description').tap do |d|
285
+ allow(d).to receive(:config).and_return({ 'setName' => 'test' })
286
+ allow(d).to receive(:replica_set_member?).and_return(true)
287
+ allow(d).to receive(:replica_set_name).and_return('test')
288
+ allow(d).to receive(:is_server?).and_return(true)
289
+ allow(d).to receive(:ghost?).and_return(false)
290
+ end
291
+ end
292
+
293
+ it 'returns true' do
294
+ expect(topology.remove_server?(description, secondary)).to eq(true)
295
+ end
296
+ end
297
+
298
+ context 'when the description is a member of the replica set' do
299
+
300
+ context 'when the description includes the server in question' do
301
+
302
+ let(:description) do
303
+ double('description').tap do |d|
304
+ allow(d).to receive(:config).and_return({ 'setName' => 'testing' })
305
+ allow(d).to receive(:replica_set_member?).and_return(true)
306
+ allow(d).to receive(:replica_set_name).and_return('testing')
307
+ allow(d).to receive(:lists_server?).and_return(true)
308
+ end
309
+ end
310
+
311
+ it 'returns false' do
312
+ expect(topology.remove_server?(description, secondary)).to eq(false)
313
+ end
314
+ end
315
+
316
+ context 'when the description does not include the server in question' do
317
+
318
+ let(:description) do
319
+ double('description').tap do |d|
320
+ allow(d).to receive(:config).and_return({ 'setName' => 'testing' })
321
+ allow(d).to receive(:replica_set_member?).and_return(true)
322
+ allow(d).to receive(:replica_set_name).and_return('testing')
323
+ allow(d).to receive(:is_server?).and_return(false)
324
+ allow(d).to receive(:lists_server?).and_return(false)
325
+ end
326
+ end
327
+
328
+ it 'returns true' do
329
+ expect(topology.remove_server?(description, secondary)).to eq(true)
330
+ end
331
+ end
332
+ end
333
+
334
+ context 'when the description is not a member of the replica set' do
335
+
336
+ let(:description) do
337
+ double('description').tap do |d|
338
+ allow(d).to receive(:config).and_return({ 'setName' => 'test' })
339
+ allow(d).to receive(:replica_set_member?).and_return(true)
340
+ allow(d).to receive(:replica_set_name).and_return('test')
341
+ allow(d).to receive(:is_server?).and_return(false)
342
+ end
343
+ end
344
+
345
+ it 'returns false' do
346
+ expect(topology.remove_server?(description, secondary)).to eq(false)
347
+ end
348
+ end
349
+
350
+ end
101
351
  end
@@ -10,31 +10,32 @@ describe Mongo::Cluster::Topology::Sharded do
10
10
  described_class.new({})
11
11
  end
12
12
 
13
- describe '.servers' do
14
13
 
15
- let(:mongos) do
16
- Mongo::Server.new(address, Mongo::Event::Listeners.new, TEST_OPTIONS)
17
- end
14
+ let(:mongos) do
15
+ Mongo::Server.new(address, double('cluster'), Mongo::Event::Listeners.new, TEST_OPTIONS)
16
+ end
18
17
 
19
- let(:standalone) do
20
- Mongo::Server.new(address, Mongo::Event::Listeners.new, TEST_OPTIONS)
21
- end
18
+ let(:standalone) do
19
+ Mongo::Server.new(address, double('cluster'), Mongo::Event::Listeners.new, TEST_OPTIONS)
20
+ end
22
21
 
23
- let(:replica_set) do
24
- Mongo::Server.new(address, Mongo::Event::Listeners.new, TEST_OPTIONS)
25
- end
22
+ let(:replica_set) do
23
+ Mongo::Server.new(address, double('cluster'), Mongo::Event::Listeners.new, TEST_OPTIONS)
24
+ end
26
25
 
27
- let(:mongos_description) do
28
- Mongo::Server::Description.new(address, { 'msg' => 'isdbgrid' })
29
- end
26
+ let(:mongos_description) do
27
+ Mongo::Server::Description.new(address, { 'msg' => 'isdbgrid' })
28
+ end
30
29
 
31
- let(:standalone_description) do
32
- Mongo::Server::Description.new(address, { 'ismaster' => true })
33
- end
30
+ let(:standalone_description) do
31
+ Mongo::Server::Description.new(address, { 'ismaster' => true })
32
+ end
34
33
 
35
- let(:replica_set_description) do
36
- Mongo::Server::Description.new(address, { 'ismaster' => true, 'setName' => 'testing' })
37
- end
34
+ let(:replica_set_description) do
35
+ Mongo::Server::Description.new(address, { 'ismaster' => true, 'setName' => 'testing', 'ok' => 1 })
36
+ end
37
+
38
+ describe '.servers' do
38
39
 
39
40
  before do
40
41
  mongos.monitor.instance_variable_set(:@description, mongos_description)
@@ -71,4 +72,54 @@ describe Mongo::Cluster::Topology::Sharded do
71
72
  expect(topology).to_not be_single
72
73
  end
73
74
  end
75
+
76
+ describe '#add_hosts?' do
77
+
78
+ it 'returns false' do
79
+ expect(topology.add_hosts?(double('description'), [])).to eq(false)
80
+ end
81
+ end
82
+
83
+ describe '#remove_hosts?' do
84
+
85
+ it 'returns true' do
86
+ expect(topology.remove_hosts?(double('description'))).to eq(true)
87
+ end
88
+ end
89
+
90
+ describe '#remove_server?' do
91
+
92
+ before do
93
+ mongos.monitor.instance_variable_set(:@description, mongos_description)
94
+ replica_set.monitor.instance_variable_set(:@description, replica_set_description)
95
+ end
96
+
97
+ context 'when the server itself should be removed' do
98
+
99
+ let(:description) do
100
+ double('description').tap do |d|
101
+ allow(d).to receive(:mongos?).and_return(false)
102
+ allow(d).to receive(:is_server?).and_return(true)
103
+ end
104
+ end
105
+
106
+ it 'returns true' do
107
+ expect(topology.remove_server?(description, mongos)).to eq(true)
108
+ end
109
+ end
110
+
111
+ context 'when the server is neither a mongos nor an unknown' do
112
+
113
+ let(:description) do
114
+ double('description').tap do |d|
115
+ allow(d).to receive(:mongos?).and_return(true)
116
+ allow(d).to receive(:is_server?).and_return(false)
117
+ end
118
+ end
119
+
120
+ it 'returns true' do
121
+ expect(topology.remove_server?(description, replica_set)).to eq(true)
122
+ end
123
+ end
124
+ end
74
125
  end