mongo 2.4.0.rc1 → 2.4.0

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 (128) 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 +1 -1
  5. data/lib/mongo/auth/ldap/conversation.rb +1 -1
  6. data/lib/mongo/auth/scram/conversation.rb +1 -1
  7. data/lib/mongo/auth/x509/conversation.rb +4 -2
  8. data/lib/mongo/client.rb +7 -4
  9. data/lib/mongo/cluster.rb +55 -5
  10. data/lib/mongo/cluster/app_metadata.rb +7 -1
  11. data/lib/mongo/cluster/topology.rb +7 -6
  12. data/lib/mongo/cluster/topology/replica_set.rb +48 -2
  13. data/lib/mongo/cluster/topology/sharded.rb +47 -1
  14. data/lib/mongo/cluster/topology/single.rb +55 -4
  15. data/lib/mongo/cluster/topology/unknown.rb +65 -9
  16. data/lib/mongo/error/invalid_server_preference.rb +3 -1
  17. data/lib/mongo/event.rb +8 -0
  18. data/lib/mongo/event/description_changed.rb +20 -2
  19. data/lib/mongo/event/member_discovered.rb +65 -0
  20. data/lib/mongo/event/primary_elected.rb +3 -1
  21. data/lib/mongo/event/standalone_discovered.rb +1 -1
  22. data/lib/mongo/monitoring.rb +41 -0
  23. data/lib/mongo/monitoring/event.rb +6 -0
  24. data/lib/mongo/monitoring/event/server_closed.rb +46 -0
  25. data/lib/mongo/monitoring/event/server_description_changed.rb +58 -0
  26. data/lib/mongo/monitoring/event/server_opening.rb +46 -0
  27. data/lib/mongo/monitoring/event/topology_changed.rb +46 -0
  28. data/lib/mongo/monitoring/event/topology_closed.rb +41 -0
  29. data/lib/mongo/monitoring/event/topology_opening.rb +41 -0
  30. data/lib/mongo/monitoring/publishable.rb +12 -0
  31. data/lib/mongo/monitoring/sdam_log_subscriber.rb +54 -0
  32. data/lib/mongo/monitoring/server_closed_log_subscriber.rb +30 -0
  33. data/lib/mongo/monitoring/server_description_changed_log_subscriber.rb +33 -0
  34. data/lib/mongo/monitoring/server_opening_log_subscriber.rb +30 -0
  35. data/lib/mongo/monitoring/topology_changed_log_subscriber.rb +40 -0
  36. data/lib/mongo/monitoring/topology_opening_log_subscriber.rb +30 -0
  37. data/lib/mongo/server.rb +6 -0
  38. data/lib/mongo/server/connection.rb +1 -1
  39. data/lib/mongo/server/description.rb +23 -3
  40. data/lib/mongo/server/description/inspector.rb +4 -2
  41. data/lib/mongo/server/description/inspector/description_changed.rb +2 -2
  42. data/lib/mongo/server/description/inspector/member_discovered.rb +59 -0
  43. data/lib/mongo/server/description/inspector/primary_elected.rb +2 -0
  44. data/lib/mongo/server_selector.rb +10 -5
  45. data/lib/mongo/server_selector/nearest.rb +1 -1
  46. data/lib/mongo/server_selector/primary_preferred.rb +1 -1
  47. data/lib/mongo/server_selector/secondary.rb +1 -1
  48. data/lib/mongo/server_selector/secondary_preferred.rb +1 -1
  49. data/lib/mongo/server_selector/selectable.rb +24 -12
  50. data/lib/mongo/uri.rb +1 -1
  51. data/lib/mongo/version.rb +1 -1
  52. data/mongo.gemspec +1 -1
  53. data/spec/mongo/auth/cr_spec.rb +6 -1
  54. data/spec/mongo/auth/ldap_spec.rb +6 -1
  55. data/spec/mongo/auth/scram_spec.rb +6 -1
  56. data/spec/mongo/auth/x509/conversation_spec.rb +69 -0
  57. data/spec/mongo/auth/x509_spec.rb +9 -4
  58. data/spec/mongo/client_spec.rb +40 -2
  59. data/spec/mongo/cluster/topology/replica_set_spec.rb +218 -9
  60. data/spec/mongo/cluster/topology/sharded_spec.rb +17 -2
  61. data/spec/mongo/cluster/topology/single_spec.rb +19 -4
  62. data/spec/mongo/cluster/topology/unknown_spec.rb +19 -1
  63. data/spec/mongo/cluster/topology_spec.rb +11 -7
  64. data/spec/mongo/cluster_spec.rb +25 -7
  65. data/spec/mongo/max_staleness_spec.rb +40 -22
  66. data/spec/mongo/monitoring_spec.rb +2 -2
  67. data/spec/mongo/sdam_monitoring_spec.rb +60 -0
  68. data/spec/mongo/sdam_spec.rb +77 -0
  69. data/spec/mongo/server/connection_pool_spec.rb +6 -1
  70. data/spec/mongo/server/connection_spec.rb +6 -1
  71. data/spec/mongo/server/description_spec.rb +90 -1
  72. data/spec/mongo/server_selection_spec.rb +7 -6
  73. data/spec/mongo/server_selector/nearest_spec.rb +7 -7
  74. data/spec/mongo/server_selector/primary_preferred_spec.rb +7 -7
  75. data/spec/mongo/server_selector/primary_spec.rb +4 -4
  76. data/spec/mongo/server_selector/secondary_preferred_spec.rb +6 -6
  77. data/spec/mongo/server_selector/secondary_spec.rb +6 -6
  78. data/spec/mongo/server_selector_spec.rb +8 -0
  79. data/spec/mongo/server_spec.rb +6 -1
  80. data/spec/mongo/uri_spec.rb +4 -4
  81. data/spec/spec_helper.rb +2 -0
  82. data/spec/support/max_staleness/ReplicaSetNoPrimary/Incompatible.yml +4 -4
  83. data/spec/support/max_staleness/ReplicaSetNoPrimary/LastUpdateTime.yml +3 -3
  84. data/spec/support/max_staleness/ReplicaSetNoPrimary/Nearest.yml +3 -3
  85. data/spec/support/max_staleness/ReplicaSetNoPrimary/Nearest2.yml +3 -3
  86. data/spec/support/max_staleness/ReplicaSetNoPrimary/NoKnownServers.yml +15 -0
  87. data/spec/support/max_staleness/ReplicaSetNoPrimary/PrimaryPreferred.yml +1 -1
  88. data/spec/support/max_staleness/ReplicaSetNoPrimary/PrimaryPreferred_tags.yml +3 -3
  89. data/spec/support/max_staleness/ReplicaSetNoPrimary/Secondary.yml +3 -3
  90. data/spec/support/max_staleness/ReplicaSetNoPrimary/SecondaryPreferred.yml +1 -1
  91. data/spec/support/max_staleness/ReplicaSetNoPrimary/SecondaryPreferred_tags.yml +3 -3
  92. data/spec/support/max_staleness/ReplicaSetNoPrimary/ZeroMaxStaleness.yml +23 -0
  93. data/spec/support/max_staleness/ReplicaSetWithPrimary/Incompatible.yml +4 -4
  94. data/spec/support/max_staleness/ReplicaSetWithPrimary/LastUpdateTime.yml +5 -5
  95. data/spec/support/max_staleness/ReplicaSetWithPrimary/{ShortHeartbeartShortMaxStaleness2.yml → LongHeartbeat.yml} +4 -4
  96. data/spec/support/max_staleness/ReplicaSetWithPrimary/{ShortHeartbeartShortMaxStaleness.yml → LongHeartbeat2.yml} +6 -10
  97. data/spec/support/max_staleness/ReplicaSetWithPrimary/MaxStalenessTooSmall.yml +3 -2
  98. data/spec/support/max_staleness/ReplicaSetWithPrimary/MaxStalenessWithModePrimary.yml +2 -2
  99. data/spec/support/max_staleness/ReplicaSetWithPrimary/Nearest.yml +3 -3
  100. data/spec/support/max_staleness/ReplicaSetWithPrimary/Nearest2.yml +3 -3
  101. data/spec/support/max_staleness/ReplicaSetWithPrimary/Nearest_tags.yml +3 -3
  102. data/spec/support/max_staleness/ReplicaSetWithPrimary/PrimaryPreferred.yml +2 -2
  103. data/spec/support/max_staleness/ReplicaSetWithPrimary/PrimaryPreferred_incompatible.yml +3 -3
  104. data/spec/support/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred.yml +1 -1
  105. data/spec/support/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred_tags.yml +3 -3
  106. data/spec/support/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred_tags2.yml +3 -3
  107. data/spec/support/max_staleness/ReplicaSetWithPrimary/Secondary_tags.yml +3 -3
  108. data/spec/support/max_staleness/ReplicaSetWithPrimary/Secondary_tags2.yml +3 -3
  109. data/spec/support/max_staleness/ReplicaSetWithPrimary/ZeroMaxStaleness.yml +7 -11
  110. data/spec/support/max_staleness/Sharded/Incompatible.yml +4 -4
  111. data/spec/support/max_staleness/Sharded/SmallMaxStaleness.yml +10 -2
  112. data/spec/support/max_staleness/Single/Incompatible.yml +4 -4
  113. data/spec/support/max_staleness/Single/SmallMaxStaleness.yml +2 -2
  114. data/spec/support/max_staleness/Unknown/SmallMaxStaleness.yml +14 -0
  115. data/spec/support/sdam/rs/primary_mismatched_me.yml +2 -2
  116. data/spec/support/sdam/rs/secondary_mismatched_me.yml +2 -2
  117. data/spec/support/sdam_monitoring.rb +144 -0
  118. data/spec/support/sdam_monitoring/replica_set_with_no_primary.yml +112 -0
  119. data/spec/support/sdam_monitoring/replica_set_with_primary.yml +111 -0
  120. data/spec/support/sdam_monitoring/replica_set_with_removal.yml +106 -0
  121. data/spec/support/sdam_monitoring/required_replica_set.yml +84 -0
  122. data/spec/support/sdam_monitoring/standalone.yml +70 -0
  123. data/spec/support/server_discovery_and_monitoring.rb +34 -1
  124. data/spec/support/server_selection.rb +14 -11
  125. data/spec/support/shared/server_selector.rb +6 -0
  126. metadata +49 -13
  127. metadata.gz.sig +0 -0
  128. data/spec/mongo/server_discovery_and_monitoring_spec.rb +0 -115
@@ -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.4.0.rc1'.freeze
20
+ VERSION = '2.4.0'.freeze
21
21
  end
@@ -30,5 +30,5 @@ Gem::Specification.new do |s|
30
30
  s.has_rdoc = 'yard'
31
31
  s.bindir = 'bin'
32
32
 
33
- s.add_dependency 'bson', '~> 4.2.0.rc1'
33
+ s.add_dependency 'bson', '~> 4.2.0'
34
34
  end
@@ -7,7 +7,7 @@ describe Mongo::Auth::CR do
7
7
  end
8
8
 
9
9
  let(:monitoring) do
10
- Mongo::Monitoring.new
10
+ Mongo::Monitoring.new(monitoring: false)
11
11
  end
12
12
 
13
13
  let(:listeners) do
@@ -16,10 +16,15 @@ describe Mongo::Auth::CR do
16
16
 
17
17
  let(:cluster) do
18
18
  double('cluster').tap do |cl|
19
+ allow(cl).to receive(:topology).and_return(topology)
19
20
  allow(cl).to receive(:app_metadata).and_return(app_metadata)
20
21
  end
21
22
  end
22
23
 
24
+ let(:topology) do
25
+ double('topology')
26
+ end
27
+
23
28
  let(:server) do
24
29
  Mongo::Server.new(address, cluster, monitoring, listeners, TEST_OPTIONS)
25
30
  end
@@ -7,7 +7,7 @@ describe Mongo::Auth::LDAP do
7
7
  end
8
8
 
9
9
  let(:monitoring) do
10
- Mongo::Monitoring.new
10
+ Mongo::Monitoring.new(monitoring: false)
11
11
  end
12
12
 
13
13
  let(:listeners) do
@@ -16,10 +16,15 @@ describe Mongo::Auth::LDAP do
16
16
 
17
17
  let(:cluster) do
18
18
  double('cluster').tap do |cl|
19
+ allow(cl).to receive(:topology).and_return(topology)
19
20
  allow(cl).to receive(:app_metadata).and_return(app_metadata)
20
21
  end
21
22
  end
22
23
 
24
+ let(:topology) do
25
+ double('topology')
26
+ end
27
+
23
28
  let(:server) do
24
29
  Mongo::Server.new(address, cluster, monitoring, listeners, TEST_OPTIONS)
25
30
  end
@@ -7,7 +7,7 @@ describe Mongo::Auth::SCRAM do
7
7
  end
8
8
 
9
9
  let(:monitoring) do
10
- Mongo::Monitoring.new
10
+ Mongo::Monitoring.new(monitoring: false)
11
11
  end
12
12
 
13
13
  let(:listeners) do
@@ -16,10 +16,15 @@ describe Mongo::Auth::SCRAM do
16
16
 
17
17
  let(:cluster) do
18
18
  double('cluster').tap do |cl|
19
+ allow(cl).to receive(:topology).and_return(topology)
19
20
  allow(cl).to receive(:app_metadata).and_return(app_metadata)
20
21
  end
21
22
  end
22
23
 
24
+ let(:topology) do
25
+ double('topology')
26
+ end
27
+
23
28
  let(:server) do
24
29
  Mongo::Server.new(address, cluster, monitoring, listeners, TEST_OPTIONS)
25
30
  end
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongo::Auth::X509::Conversation do
4
+
5
+ let(:user) do
6
+ Mongo::Auth::User.new(
7
+ database: Mongo::Database::ADMIN,
8
+ user: 'user',
9
+ )
10
+ end
11
+
12
+ let(:conversation) do
13
+ described_class.new(user)
14
+ end
15
+
16
+ describe '#start' do
17
+
18
+ let(:query) do
19
+ conversation.start
20
+ end
21
+
22
+ let(:selector) do
23
+ query.selector
24
+ end
25
+
26
+ it 'sets username' do
27
+ expect(selector[:user]).to eq('user')
28
+ end
29
+
30
+ it 'sets the mechanism' do
31
+ expect(selector[:mechanism]).to eq('MONGODB-X509')
32
+ end
33
+
34
+ context 'when a username is not provided' do
35
+
36
+ let(:user) do
37
+ Mongo::Auth::User.new(
38
+ database: Mongo::Database::ADMIN
39
+ )
40
+ end
41
+
42
+ it 'does not set the username' do
43
+ expect(selector[:user]).to be_nil
44
+ end
45
+
46
+ it 'sets the mechanism' do
47
+ expect(selector[:mechanism]).to eq('MONGODB-X509')
48
+ end
49
+ end
50
+
51
+ context 'when the username is nil' do
52
+
53
+ let(:user) do
54
+ Mongo::Auth::User.new(
55
+ database: Mongo::Database::ADMIN,
56
+ user: nil
57
+ )
58
+ end
59
+
60
+ it 'does not set the username' do
61
+ expect(selector.has_key?(:user)).to be(false)
62
+ end
63
+
64
+ it 'sets the mechanism' do
65
+ expect(selector[:mechanism]).to eq('MONGODB-X509')
66
+ end
67
+ end
68
+ end
69
+ end
@@ -7,7 +7,7 @@ describe Mongo::Auth::X509 do
7
7
  end
8
8
 
9
9
  let(:monitoring) do
10
- Mongo::Monitoring.new
10
+ Mongo::Monitoring.new(monitoring: false)
11
11
  end
12
12
 
13
13
  let(:listeners) do
@@ -16,10 +16,15 @@ describe Mongo::Auth::X509 do
16
16
 
17
17
  let(:cluster) do
18
18
  double('cluster').tap do |cl|
19
+ allow(cl).to receive(:topology).and_return(topology)
19
20
  allow(cl).to receive(:app_metadata).and_return(app_metadata)
20
21
  end
21
22
  end
22
23
 
24
+ let(:topology) do
25
+ double('topology')
26
+ end
27
+
23
28
  let(:server) do
24
29
  Mongo::Server.new(address, cluster, monitoring, listeners, TEST_OPTIONS)
25
30
  end
@@ -36,17 +41,17 @@ describe Mongo::Auth::X509 do
36
41
 
37
42
  context 'when the user is not authorized for the database' do
38
43
 
39
- let(:cr) do
44
+ let(:x509) do
40
45
  described_class.new(user)
41
46
  end
42
47
 
43
48
  let(:login) do
44
- cr.login(connection).documents[0]
49
+ x509.login(connection).documents[0]
45
50
  end
46
51
 
47
52
  it 'logs the user into the connection' do
48
53
  expect {
49
- cr.login(connection)
54
+ x509.login(connection)
50
55
  }.to raise_error(Mongo::Auth::Unauthorized)
51
56
  end
52
57
  end
@@ -158,7 +158,7 @@ describe Mongo::Client do
158
158
  described_class.new(
159
159
  ['127.0.0.1:27017'],
160
160
  :read => { :mode => :primary },
161
- :local_threshold => 10,
161
+ :local_threshold => 0.010,
162
162
  :server_selection_timeout => 10000,
163
163
  :database => TEST_DB
164
164
  )
@@ -166,7 +166,7 @@ describe Mongo::Client do
166
166
 
167
167
  let(:options) do
168
168
  Mongo::Options::Redacted.new(:read => { :mode => :primary },
169
- :local_threshold => 10,
169
+ :local_threshold => 0.010,
170
170
  :server_selection_timeout => 10000,
171
171
  :database => TEST_DB)
172
172
  end
@@ -271,6 +271,44 @@ describe Mongo::Client do
271
271
  expect(client.cluster.options[:heartbeat_frequency]).to eq(client.options[:heartbeat_frequency])
272
272
  end
273
273
  end
274
+
275
+ context 'when platform details are specified' do
276
+
277
+ let(:app_metadata) do
278
+ client.cluster.app_metadata
279
+ end
280
+
281
+ let(:client) do
282
+ described_class.new(['127.0.0.1:27017'], :platform => 'mongoid-6.0.2')
283
+ end
284
+
285
+ it 'includes the platform info in the app metadata' do
286
+ expect(app_metadata.send(:full_client_document)[:platform]).to match(/mongoid-6\.0\.2/)
287
+ end
288
+ end
289
+
290
+ context 'when platform details are not specified' do
291
+
292
+ let(:app_metadata) do
293
+ client.cluster.app_metadata
294
+ end
295
+
296
+ let(:client) do
297
+ described_class.new(['127.0.0.1:27017'])
298
+ end
299
+
300
+ let(:platform_string) do
301
+ [
302
+ RUBY_VERSION,
303
+ RUBY_PLATFORM,
304
+ RbConfig::CONFIG['build']
305
+ ].join(', ')
306
+ end
307
+
308
+ it 'does not include the platform info in the app metadata' do
309
+ expect(app_metadata.send(:full_client_document)[:platform]).to eq(platform_string)
310
+ end
311
+ end
274
312
  end
275
313
 
276
314
  context 'when providing a connection string' do
@@ -11,11 +11,12 @@ describe Mongo::Cluster::Topology::ReplicaSet do
11
11
  end
12
12
 
13
13
  let(:monitoring) do
14
- Mongo::Monitoring.new
14
+ Mongo::Monitoring.new(monitoring: false)
15
15
  end
16
16
 
17
17
  let(:cluster) do
18
18
  double('cluster').tap do |cl|
19
+ allow(cl).to receive(:topology).and_return(topology)
19
20
  allow(cl).to receive(:app_metadata).and_return(app_metadata)
20
21
  end
21
22
  end
@@ -64,7 +65,7 @@ describe Mongo::Cluster::Topology::ReplicaSet do
64
65
  context 'when no replica set name is provided' do
65
66
 
66
67
  let(:topology) do
67
- described_class.new({})
68
+ described_class.new({}, monitoring, [])
68
69
  end
69
70
 
70
71
  let(:servers) do
@@ -79,7 +80,7 @@ describe Mongo::Cluster::Topology::ReplicaSet do
79
80
  context 'when a replica set name is provided' do
80
81
 
81
82
  let(:topology) do
82
- described_class.new(:replica_set => 'testing')
83
+ described_class.new({ :replica_set => 'testing' }, monitoring)
83
84
  end
84
85
 
85
86
  let(:servers) do
@@ -95,21 +96,229 @@ describe Mongo::Cluster::Topology::ReplicaSet do
95
96
  describe '.replica_set?' do
96
97
 
97
98
  it 'returns true' do
98
- expect(described_class.new({})).to be_replica_set
99
+ expect(described_class.new({}, monitoring)).to be_replica_set
99
100
  end
100
101
  end
101
102
 
102
103
  describe '.sharded?' do
103
104
 
104
105
  it 'returns false' do
105
- expect(described_class.new({})).to_not be_sharded
106
+ expect(described_class.new({}, monitoring)).to_not be_sharded
106
107
  end
107
108
  end
108
109
 
109
110
  describe '.single?' do
110
111
 
111
112
  it 'returns false' do
112
- expect(described_class.new({})).to_not be_single
113
+ expect(described_class.new({}, monitoring)).to_not be_single
114
+ end
115
+ end
116
+
117
+ describe '#has_readable_servers?' do
118
+
119
+ let(:topology) do
120
+ described_class.new({}, monitoring, [])
121
+ end
122
+
123
+ let(:cluster) do
124
+ double('cluster', servers: servers, single?: false, sharded?: false, unknown?: false)
125
+ end
126
+
127
+ context 'when the read preference is primary' do
128
+
129
+ let(:selector) do
130
+ Mongo::ServerSelector.get(:mode => :primary)
131
+ end
132
+
133
+ context 'when a primary exists' do
134
+
135
+ let(:servers) do
136
+ [ double('server', primary?: true) ]
137
+ end
138
+
139
+ it 'returns true' do
140
+ expect(topology).to have_readable_server(cluster, selector)
141
+ end
142
+ end
143
+
144
+ context 'when a primary does not exist' do
145
+
146
+ let(:servers) do
147
+ [ double('server', primary?: false) ]
148
+ end
149
+
150
+ it 'returns false' do
151
+ expect(topology).to_not have_readable_server(cluster, selector)
152
+ end
153
+ end
154
+ end
155
+
156
+ context 'when the read preference is primary preferred' do
157
+
158
+ let(:selector) do
159
+ Mongo::ServerSelector.get(:mode => :primary_preferred)
160
+ end
161
+
162
+ context 'when a primary exists' do
163
+
164
+ let(:servers) do
165
+ [ double('server', primary?: true, secondary?: false) ]
166
+ end
167
+
168
+ it 'returns true' do
169
+ expect(topology).to have_readable_server(cluster, selector)
170
+ end
171
+ end
172
+
173
+ context 'when a primary does not exist' do
174
+
175
+ let(:servers) do
176
+ [ double('server', primary?: false, secondary?: true, average_round_trip_time: 0.01) ]
177
+ end
178
+
179
+ it 'returns true' do
180
+ expect(topology).to have_readable_server(cluster, selector)
181
+ end
182
+ end
183
+ end
184
+
185
+ context 'when the read preference is secondary' do
186
+
187
+ let(:selector) do
188
+ Mongo::ServerSelector.get(:mode => :secondary)
189
+ end
190
+
191
+ context 'when a secondary exists' do
192
+
193
+ let(:servers) do
194
+ [ double('server', primary?: false, secondary?: true, average_round_trip_time: 0.01) ]
195
+ end
196
+
197
+ it 'returns true' do
198
+ expect(topology).to have_readable_server(cluster, selector)
199
+ end
200
+ end
201
+
202
+ context 'when a secondary does not exist' do
203
+
204
+ let(:servers) do
205
+ [ double('server', primary?: true, secondary?: false) ]
206
+ end
207
+
208
+ it 'returns false' do
209
+ expect(topology).to_not have_readable_server(cluster, selector)
210
+ end
211
+ end
212
+ end
213
+
214
+ context 'when the read preference is secondary preferred' do
215
+
216
+ let(:selector) do
217
+ Mongo::ServerSelector.get(:mode => :secondary_preferred)
218
+ end
219
+
220
+ context 'when a secondary exists' do
221
+
222
+ let(:servers) do
223
+ [ double('server', primary?: false, secondary?: true, average_round_trip_time: 0.01) ]
224
+ end
225
+
226
+ it 'returns true' do
227
+ expect(topology).to have_readable_server(cluster, selector)
228
+ end
229
+ end
230
+
231
+ context 'when a secondary does not exist' do
232
+
233
+ let(:servers) do
234
+ [ double('server', secondary?: false, primary?: true) ]
235
+ end
236
+
237
+ it 'returns true' do
238
+ expect(topology).to have_readable_server(cluster, selector)
239
+ end
240
+ end
241
+ end
242
+
243
+ context 'when the read preference is nearest' do
244
+
245
+ let(:selector) do
246
+ Mongo::ServerSelector.get(:mode => :nearest)
247
+ end
248
+
249
+ let(:servers) do
250
+ [ double('server', primary?: false, secondary?: true, average_round_trip_time: 0.01) ]
251
+ end
252
+
253
+ it 'returns true' do
254
+ expect(topology).to have_readable_server(cluster, selector)
255
+ end
256
+ end
257
+
258
+ context 'when the read preference is not provided' do
259
+
260
+ context 'when a primary exists' do
261
+
262
+ let(:servers) do
263
+ [ double('server', primary?: true, secondary?: false) ]
264
+ end
265
+
266
+ it 'returns true' do
267
+ expect(topology).to have_readable_server(cluster)
268
+ end
269
+ end
270
+
271
+ context 'when a primary does not exist' do
272
+
273
+ let(:servers) do
274
+ [ double('server', primary?: false, secondary?: true, average_round_trip_time: 0.01) ]
275
+ end
276
+
277
+ it 'returns false' do
278
+ expect(topology).to_not have_readable_server(cluster)
279
+ end
280
+ end
281
+ end
282
+ end
283
+
284
+ describe '#has_writable_servers?' do
285
+
286
+ let(:topology) do
287
+ described_class.new({}, monitoring, [])
288
+ end
289
+
290
+ context 'when a primary server exists' do
291
+
292
+ let(:primary) do
293
+ double('server', :primary? => true)
294
+ end
295
+
296
+ let(:secondary) do
297
+ double('server', :primary? => false)
298
+ end
299
+
300
+ let(:cluster) do
301
+ double('cluster', servers: [ primary, secondary ])
302
+ end
303
+
304
+ it 'returns true' do
305
+ expect(topology).to have_writable_server(cluster)
306
+ end
307
+ end
308
+
309
+ context 'when no primary server exists' do
310
+
311
+ let(:server) do
312
+ double('server', :primary? => false)
313
+ end
314
+
315
+ let(:cluster) do
316
+ double('cluster', servers: [ server ])
317
+ end
318
+
319
+ it 'returns false' do
320
+ expect(topology).to_not have_writable_server(cluster)
321
+ end
113
322
  end
114
323
  end
115
324
 
@@ -133,7 +342,7 @@ describe Mongo::Cluster::Topology::ReplicaSet do
133
342
  end
134
343
 
135
344
  let(:topology) do
136
- described_class.new(:replica_set => 'testing')
345
+ described_class.new({ :replica_set => 'testing' }, monitoring)
137
346
  end
138
347
 
139
348
  before do
@@ -207,7 +416,7 @@ describe Mongo::Cluster::Topology::ReplicaSet do
207
416
  end
208
417
 
209
418
  let(:topology) do
210
- described_class.new(:replica_set => 'testing')
419
+ described_class.new({ :replica_set => 'testing' }, monitoring)
211
420
  end
212
421
 
213
422
  before do
@@ -289,7 +498,7 @@ describe Mongo::Cluster::Topology::ReplicaSet do
289
498
  end
290
499
 
291
500
  let(:topology) do
292
- described_class.new(:replica_set => 'testing')
501
+ described_class.new({ :replica_set => 'testing' }, monitoring)
293
502
  end
294
503
 
295
504
  before do