mongo 2.5.0 → 2.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/README.md +2 -0
  5. data/Rakefile +4 -1
  6. data/lib/mongo/address.rb +2 -1
  7. data/lib/mongo/client.rb +6 -51
  8. data/lib/mongo/cluster.rb +34 -4
  9. data/lib/mongo/cluster/reapers/socket_reaper.rb +1 -1
  10. data/lib/mongo/cluster/topology/replica_set.rb +3 -1
  11. data/lib/mongo/collection.rb +6 -6
  12. data/lib/mongo/collection/view.rb +2 -4
  13. data/lib/mongo/cursor.rb +9 -4
  14. data/lib/mongo/error.rb +2 -0
  15. data/lib/mongo/operation/uses_command_op_msg.rb +1 -1
  16. data/lib/mongo/server.rb +3 -0
  17. data/lib/mongo/server/description.rb +1 -1
  18. data/lib/mongo/server/description/features.rb +18 -12
  19. data/lib/mongo/server_selector/selectable.rb +5 -1
  20. data/lib/mongo/session.rb +38 -43
  21. data/lib/mongo/session/session_pool.rb +12 -30
  22. data/lib/mongo/socket.rb +24 -0
  23. data/lib/mongo/socket/tcp.rb +0 -1
  24. data/lib/mongo/uri.rb +26 -5
  25. data/lib/mongo/version.rb +1 -1
  26. data/spec/mongo/address_spec.rb +37 -2
  27. data/spec/mongo/bulk_write_spec.rb +4 -10
  28. data/spec/mongo/change_stream_examples_spec.rb +40 -0
  29. data/spec/mongo/client_spec.rb +47 -12
  30. data/spec/mongo/cluster/topology/replica_set_spec.rb +2 -0
  31. data/spec/mongo/collection/view/aggregation_spec.rb +2 -8
  32. data/spec/mongo/collection/view/change_stream_spec.rb +1 -5
  33. data/spec/mongo/collection/view/map_reduce_spec.rb +2 -8
  34. data/spec/mongo/collection/view/readable_spec.rb +1 -1
  35. data/spec/mongo/collection_spec.rb +11 -29
  36. data/spec/mongo/crud_spec.rb +6 -2
  37. data/spec/mongo/cursor_spec.rb +84 -1
  38. data/spec/mongo/database_spec.rb +2 -8
  39. data/spec/mongo/dns_seedlist_discovery_spec.rb +67 -63
  40. data/spec/mongo/max_staleness_spec.rb +1 -0
  41. data/spec/mongo/retryable_writes_spec.rb +7 -9
  42. data/spec/mongo/sdam_spec.rb +42 -24
  43. data/spec/mongo/server/description/features_spec.rb +3 -3
  44. data/spec/mongo/server_selection_spec.rb +2 -0
  45. data/spec/mongo/server_selector_spec.rb +2 -0
  46. data/spec/mongo/session/session_pool_spec.rb +16 -22
  47. data/spec/mongo/session_spec.rb +13 -8
  48. data/spec/mongo/uri/srv_protocol_spec.rb +481 -478
  49. data/spec/mongo/uri_spec.rb +1 -1
  50. data/spec/spec_helper.rb +11 -63
  51. data/spec/support/authorization.rb +35 -1
  52. data/spec/support/connection_string_tests/invalid-uris.yml +27 -11
  53. data/spec/support/event_subscriber.rb +66 -0
  54. data/spec/support/sdam/rs/compatible.yml +41 -0
  55. data/spec/support/sdam/rs/discover_arbiters.yml +3 -1
  56. data/spec/support/sdam/rs/discover_passives.yml +6 -2
  57. data/spec/support/sdam/rs/discover_primary.yml +3 -1
  58. data/spec/support/sdam/rs/discover_secondary.yml +3 -1
  59. data/spec/support/sdam/rs/discovery.yml +12 -4
  60. data/spec/support/sdam/rs/equal_electionids.yml +6 -2
  61. data/spec/support/sdam/rs/ghost_discovered.yml +3 -1
  62. data/spec/support/sdam/rs/hosts_differ_from_seeds.yml +3 -1
  63. data/spec/support/sdam/rs/ls_timeout.yml +169 -14
  64. data/spec/support/sdam/rs/member_reconfig.yml +6 -2
  65. data/spec/support/sdam/rs/member_standalone.yml +6 -2
  66. data/spec/support/sdam/rs/new_primary.yml +6 -2
  67. data/spec/support/sdam/rs/new_primary_new_electionid.yml +9 -3
  68. data/spec/support/sdam/rs/new_primary_new_setversion.yml +9 -3
  69. data/spec/support/sdam/rs/new_primary_wrong_set_name.yml +6 -2
  70. data/spec/support/sdam/rs/non_rs_member.yml +3 -2
  71. data/spec/support/sdam/rs/normalize_case.yml +3 -1
  72. data/spec/support/sdam/rs/null_election_id.yml +12 -4
  73. data/spec/support/sdam/rs/primary_becomes_standalone.yml +6 -4
  74. data/spec/support/sdam/rs/primary_changes_set_name.yml +6 -2
  75. data/spec/support/sdam/rs/primary_disconnect.yml +3 -1
  76. data/spec/support/sdam/rs/primary_disconnect_electionid.yml +15 -5
  77. data/spec/support/sdam/rs/primary_disconnect_setversion.yml +15 -5
  78. data/spec/support/sdam/rs/primary_hint_from_secondary_with_mismatched_me.yml +6 -2
  79. data/spec/support/sdam/rs/primary_mismatched_me.yml +26 -37
  80. data/spec/support/sdam/rs/primary_reports_new_member.yml +12 -4
  81. data/spec/support/sdam/rs/primary_to_no_primary_mismatched_me.yml +6 -2
  82. data/spec/support/sdam/rs/primary_wrong_set_name.yml +3 -1
  83. data/spec/support/sdam/rs/response_from_removed.yml +6 -2
  84. data/spec/support/sdam/rs/rsother_discovered.yml +6 -2
  85. data/spec/support/sdam/rs/sec_not_auth.yml +6 -2
  86. data/spec/support/sdam/rs/secondary_mismatched_me.yml +26 -37
  87. data/spec/support/sdam/rs/secondary_wrong_set_name.yml +3 -1
  88. data/spec/support/sdam/rs/secondary_wrong_set_name_with_primary.yml +6 -2
  89. data/spec/support/sdam/rs/setversion_without_electionid.yml +6 -2
  90. data/spec/support/sdam/rs/stepdown_change_set_name.yml +6 -2
  91. data/spec/support/sdam/rs/too_new.yml +41 -0
  92. data/spec/support/sdam/rs/too_old.yml +39 -0
  93. data/spec/support/sdam/rs/unexpected_mongos.yml +3 -1
  94. data/spec/support/sdam/rs/use_setversion_without_electionid.yml +9 -3
  95. data/spec/support/sdam/rs/wrong_set_name.yml +3 -1
  96. data/spec/support/server_discovery_and_monitoring.rb +13 -0
  97. data/spec/support/shared/session.rb +10 -30
  98. metadata +10 -2
  99. metadata.gz.sig +0 -0
@@ -17,7 +17,7 @@ describe Mongo::URI do
17
17
  end
18
18
  end
19
19
 
20
- context 'when the scheme is mongodb+srv://' do
20
+ context 'when the scheme is mongodb+srv://', if: test_connecting_externally? do
21
21
 
22
22
  let(:string) do
23
23
  'mongodb+srv://test5.test.build.10gen.cc'
@@ -38,6 +38,7 @@ Encoding.default_external = Encoding::UTF_8
38
38
 
39
39
  require 'support/travis'
40
40
  require 'support/matchers'
41
+ require 'support/event_subscriber'
41
42
  require 'support/authorization'
42
43
  require 'support/server_discovery_and_monitoring'
43
44
  require 'support/server_selection_rtt'
@@ -50,7 +51,7 @@ require 'support/gridfs'
50
51
 
51
52
  RSpec.configure do |config|
52
53
  config.color = true
53
- config.fail_fast = true unless ENV['CI'] || ENV['JENKINS_HOME']
54
+ config.fail_fast = true unless ENV['CI']
54
55
  config.formatter = 'documentation'
55
56
  config.include(Authorization)
56
57
 
@@ -193,11 +194,18 @@ def list_command_enabled?
193
194
  $list_command_enabled ||= $mongo_client.cluster.servers.first.features.list_indexes_enabled?
194
195
  end
195
196
 
196
- # Is the test suite running locally (not on Travis or Jenkins).
197
+ # Is the test suite running locally (not on Travis).
197
198
  #
198
199
  # @since 2.1.0
199
200
  def testing_ssl_locally?
200
- running_ssl? && !(ENV['CI'] || ENV['JENKINS_CI'])
201
+ running_ssl? && !(ENV['CI'])
202
+ end
203
+
204
+ # Should tests relying on external connections be run.
205
+ #
206
+ # @since 2.5.1
207
+ def test_connecting_externally?
208
+ !ENV['CI'] && !ENV['EXTERNAL_DISABLED']
201
209
  end
202
210
 
203
211
  # Is the test suite running on SSL.
@@ -247,65 +255,5 @@ def initialize_scanned_client!
247
255
  Mongo::Client.new(ADDRESSES, TEST_OPTIONS.merge(database: TEST_DB))
248
256
  end
249
257
 
250
- # Test event subscriber.
251
- #
252
- # @since 2.5.0
253
- class EventSubscriber
254
-
255
- # The started events.
256
- #
257
- # @since 2.5.0
258
- attr_reader :started_events
259
-
260
- # The succeeded events.
261
- #
262
- # @since 2.5.0
263
- attr_reader :succeeded_events
264
-
265
- # The failed events.
266
- #
267
- # @since 2.5.0
268
- attr_reader :failed_events
269
-
270
- # Create the test event subscriber.
271
- #
272
- # @example Create the subscriber
273
- # EventSubscriber.new
274
- #
275
- # @since 2.5.0
276
- def initialize
277
- @started_events = []
278
- @succeeded_events = []
279
- @failed_events = []
280
- end
281
-
282
- # Cache the succeeded event.
283
- #
284
- # @param [ Event ] event The event.
285
- #
286
- # @since 2.5.0
287
- def succeeded(event)
288
- @succeeded_events.push(event)
289
- end
290
-
291
- # Cache the started event.
292
- #
293
- # @param [ Event ] event The event.
294
- #
295
- # @since 2.5.0
296
- def started(event)
297
- @started_events.push(event)
298
- end
299
-
300
- # Cache the failed event.
301
- #
302
- # @param [ Event ] event The event.
303
- #
304
- # @since 2.5.0
305
- def failed(event)
306
- @failed_events.push(event)
307
- end
308
- end
309
-
310
258
  # require all shared examples
311
259
  Dir['./spec/support/shared/*.rb'].sort.each { |file| require file }
@@ -36,7 +36,7 @@ if ENV['MONGODB_URI']
36
36
  ADDRESSES = MONGODB_URI.servers
37
37
  CONNECT = { connect: :direct }
38
38
  end
39
- else # For Jenkins
39
+ else
40
40
  ADDRESSES = ENV['MONGODB_ADDRESSES'] ? ENV['MONGODB_ADDRESSES'].split(',').freeze : [ '127.0.0.1:27017' ].freeze
41
41
  if ENV['RS_ENABLED']
42
42
  CONNECT = { connect: :replica_set, replica_set: ENV['RS_NAME'] }
@@ -166,6 +166,11 @@ AUTHORIZED_CLIENT = Mongo::Client.new(
166
166
  password: TEST_USER.password)
167
167
  )
168
168
 
169
+ # Provides an authorized mongo client that retries writes.
170
+ #
171
+ # @since 2.5.1
172
+ AUTHROIZED_CLIENT_WITH_RETRY_WRITES = AUTHORIZED_CLIENT.with(retry_writes: true)
173
+
169
174
  # Provides an unauthorized mongo client on the default test database.
170
175
  #
171
176
  # @since 2.0.0
@@ -195,6 +200,19 @@ ADMIN_AUTHORIZED_TEST_CLIENT = ADMIN_UNAUTHORIZED_CLIENT.with(
195
200
  monitoring: false
196
201
  )
197
202
 
203
+ # A client that has an event subscriber for commands.
204
+ #
205
+ # @since 2.5.1
206
+ SUBSCRIBED_CLIENT = Mongo::Client.new(
207
+ ADDRESSES,
208
+ TEST_OPTIONS.merge(
209
+ database: TEST_DB,
210
+ user: TEST_USER.name,
211
+ password: TEST_USER.password)
212
+ )
213
+ SUBSCRIBED_CLIENT.subscribe(Mongo::Monitoring::COMMAND, EventSubscriber)
214
+ AUTHROIZED_CLIENT_WITH_RETRY_WRITES.subscribe(Mongo::Monitoring::COMMAND, EventSubscriber)
215
+
198
216
  module Authorization
199
217
 
200
218
  # On inclusion provides helpers for use with testing with and without
@@ -220,6 +238,22 @@ module Authorization
220
238
  # @since 2.0.0
221
239
  context.let(:authorized_client) { AUTHORIZED_CLIENT }
222
240
 
241
+ # Provides an authorized mongo client on the default test database that retries writes.
242
+ #
243
+ # @since 2.5.1
244
+ context.let(:authorized_client_with_retry_writes) do
245
+ EventSubscriber.clear_events!
246
+ AUTHROIZED_CLIENT_WITH_RETRY_WRITES
247
+ end
248
+
249
+ # Provides an authorized mongo client that has a Command subscriber.
250
+ #
251
+ # @since 2.5.1
252
+ context.let(:subscribed_client) do
253
+ EventSubscriber.clear_events!
254
+ SUBSCRIBED_CLIENT
255
+ end
256
+
223
257
  # Provides an unauthorized mongo client on the default test database.
224
258
  #
225
259
  # @since 2.0.0
@@ -167,14 +167,6 @@ tests:
167
167
  hosts: ~
168
168
  auth: ~
169
169
  options: ~
170
- -
171
- description: "Username with password containing an unescaped colon"
172
- uri: "mongodb://alice:foo:bar@127.0.0.1"
173
- valid: false
174
- warning: ~
175
- hosts: ~
176
- auth: ~
177
- options: ~
178
170
  -
179
171
  description: "Username containing an unescaped at-sign"
180
172
  uri: "mongodb://alice@@127.0.0.1"
@@ -193,7 +185,7 @@ tests:
193
185
  options: ~
194
186
  -
195
187
  description: "Username containing an unescaped slash"
196
- uri: "mongodb://alice/@127.0.0.1/db"
188
+ uri: "mongodb://alice/@localhost/db"
197
189
  valid: false
198
190
  warning: ~
199
191
  hosts: ~
@@ -201,7 +193,7 @@ tests:
201
193
  options: ~
202
194
  -
203
195
  description: "Username containing unescaped slash with password"
204
- uri: "mongodb://alice/bob:foo@127.0.0.1/db"
196
+ uri: "mongodb://alice/bob:foo@localhost/db"
205
197
  valid: false
206
198
  warning: ~
207
199
  hosts: ~
@@ -209,7 +201,7 @@ tests:
209
201
  options: ~
210
202
  -
211
203
  description: "Username with password containing an unescaped slash"
212
- uri: "mongodb://alice:foo/bar@127.0.0.1/db"
204
+ uri: "mongodb://alice:foo/bar@localhost/db"
213
205
  valid: false
214
206
  warning: ~
215
207
  hosts: ~
@@ -223,3 +215,27 @@ tests:
223
215
  hosts: ~
224
216
  auth: ~
225
217
  options: ~
218
+ -
219
+ description: "mongodb+srv with multiple service names"
220
+ uri: "mongodb+srv://test5.test.mongodb.com,test6.test.mongodb.com"
221
+ valid: false
222
+ warning: ~
223
+ hosts: ~
224
+ auth: ~
225
+ options: ~
226
+ -
227
+ description: "mongodb+srv with port number"
228
+ uri: "mongodb+srv://test7.test.mongodb.com:27018"
229
+ valid: false
230
+ warning: ~
231
+ hosts: ~
232
+ auth: ~
233
+ options: ~
234
+ -
235
+ description: "Username with password containing an unescaped percent sign"
236
+ uri: "mongodb://alice%foo:bar@127.0.0.1"
237
+ valid: false
238
+ warning: ~
239
+ hosts: ~
240
+ auth: ~
241
+ options: ~
@@ -0,0 +1,66 @@
1
+ # Test event subscriber.
2
+ #
3
+ # @since 2.5.0
4
+ class EventSubscriber
5
+
6
+ class << self
7
+
8
+ # The started events.
9
+ #
10
+ # @since 2.5.0
11
+ def started_events
12
+ @started_events ||= []
13
+ end
14
+
15
+ # The succeeded events.
16
+ #
17
+ # @since 2.5.0
18
+ def succeeded_events
19
+ @succeeded_events ||= []
20
+ end
21
+
22
+ # The failed events.
23
+ #
24
+ # @since 2.5.0
25
+ def failed_events
26
+ @failed_events ||= []
27
+ end
28
+
29
+ # Cache the succeeded event.
30
+ #
31
+ # @param [ Event ] event The event.
32
+ #
33
+ # @since 2.5.0
34
+ def succeeded(event)
35
+ succeeded_events.push(event)
36
+ end
37
+
38
+ # Cache the started event.
39
+ #
40
+ # @param [ Event ] event The event.
41
+ #
42
+ # @since 2.5.0
43
+ def started(event)
44
+ started_events.push(event)
45
+ end
46
+
47
+ # Cache the failed event.
48
+ #
49
+ # @param [ Event ] event The event.
50
+ #
51
+ # @since 2.5.0
52
+ def failed(event)
53
+ failed_events.push(event)
54
+ end
55
+
56
+ # Clear all cached events.
57
+ #
58
+ # @since 2.5.1
59
+ def clear_events!
60
+ @started_events = []
61
+ @succeeded_events = []
62
+ @failed_events = []
63
+ self
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,41 @@
1
+ description: "Replica set member with large maxWireVersion"
2
+ uri: "mongodb://a,b/?replicaSet=rs"
3
+ phases: [
4
+ {
5
+ responses: [
6
+ ["a:27017", {
7
+ ok: 1,
8
+ ismaster: true,
9
+ setName: "rs",
10
+ hosts: ["a:27017", "b:27017"],
11
+ minWireVersion: 0,
12
+ maxWireVersion: 6
13
+ }],
14
+ ["b:27017", {
15
+ ok: 1,
16
+ ismaster: false,
17
+ secondary: true,
18
+ setName: "rs",
19
+ hosts: ["a:27017", "b:27017"],
20
+ minWireVersion: 0,
21
+ maxWireVersion: 1000
22
+ }]
23
+ ],
24
+ outcome: {
25
+ servers: {
26
+ "a:27017": {
27
+ type: "RSPrimary",
28
+ setName: "rs"
29
+ },
30
+ "b:27017": {
31
+ type: "RSSecondary",
32
+ setName: "rs"
33
+ }
34
+ },
35
+ topologyType: "ReplicaSetWithPrimary",
36
+ setName: "rs",
37
+ logicalSessionTimeoutMinutes: null,
38
+ compatible: true
39
+ }
40
+ }
41
+ ]
@@ -13,7 +13,9 @@ phases: [
13
13
  ismaster: true,
14
14
  hosts: ["a:27017"],
15
15
  arbiters: ["b:27017"],
16
- setName: "rs"
16
+ setName: "rs",
17
+ minWireVersion: 0,
18
+ maxWireVersion: 6
17
19
  }]
18
20
  ],
19
21
 
@@ -13,7 +13,9 @@ phases: [
13
13
  ismaster: true,
14
14
  hosts: ["a:27017"],
15
15
  passives: ["b:27017"],
16
- setName: "rs"
16
+ setName: "rs",
17
+ minWireVersion: 0,
18
+ maxWireVersion: 6
17
19
  }]
18
20
  ],
19
21
 
@@ -49,7 +51,9 @@ phases: [
49
51
  passive: true,
50
52
  hosts: ["a:27017"],
51
53
  passives: ["b:27017"],
52
- setName: "rs"
54
+ setName: "rs",
55
+ minWireVersion: 0,
56
+ maxWireVersion: 6
53
57
  }]
54
58
  ],
55
59
 
@@ -12,7 +12,9 @@ phases: [
12
12
  ok: 1,
13
13
  ismaster: true,
14
14
  setName: "rs",
15
- hosts: ["a:27017", "b:27017"]
15
+ hosts: ["a:27017", "b:27017"],
16
+ minWireVersion: 0,
17
+ maxWireVersion: 6
16
18
  }]
17
19
  ],
18
20
 
@@ -13,7 +13,9 @@ phases: [
13
13
  ismaster: false,
14
14
  secondary: true,
15
15
  setName: "rs",
16
- hosts: ["a:27017", "b:27017"]
16
+ hosts: ["a:27017", "b:27017"],
17
+ minWireVersion: 0,
18
+ maxWireVersion: 6
17
19
  }]
18
20
  ],
19
21
 
@@ -14,7 +14,9 @@ phases: [
14
14
  ismaster: false,
15
15
  secondary: true,
16
16
  setName: "rs",
17
- hosts: ["a:27017", "b:27017", "c:27017"]
17
+ hosts: ["a:27017", "b:27017", "c:27017"],
18
+ minWireVersion: 0,
19
+ maxWireVersion: 6
18
20
  }]
19
21
  ],
20
22
 
@@ -57,7 +59,9 @@ phases: [
57
59
  secondary: true,
58
60
  setName: "rs",
59
61
  primary: "d:27017",
60
- hosts: ["b:27017", "c:27017", "d:27017"]
62
+ hosts: ["b:27017", "c:27017", "d:27017"],
63
+ minWireVersion: 0,
64
+ maxWireVersion: 6
61
65
  }]
62
66
  ],
63
67
 
@@ -104,7 +108,9 @@ phases: [
104
108
  ok: 1,
105
109
  ismaster: true,
106
110
  setName: "rs",
107
- hosts: ["b:27017", "c:27017", "d:27017", "e:27017"]
111
+ hosts: ["b:27017", "c:27017", "d:27017", "e:27017"],
112
+ minWireVersion: 0,
113
+ maxWireVersion: 6
108
114
  }]
109
115
  ],
110
116
 
@@ -153,7 +159,9 @@ phases: [
153
159
  ismaster: false,
154
160
  secondary: true,
155
161
  setName: "rs",
156
- hosts: ["a:27017", "b:27017", "c:27017"]
162
+ hosts: ["a:27017", "b:27017", "c:27017"],
163
+ minWireVersion: 0,
164
+ maxWireVersion: 6
157
165
  }]
158
166
  ],
159
167