mongo 2.11.0 → 2.11.5

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 (95) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/Rakefile +24 -0
  5. data/lib/mongo/address.rb +53 -37
  6. data/lib/mongo/auth.rb +30 -10
  7. data/lib/mongo/auth/cr.rb +1 -0
  8. data/lib/mongo/auth/cr/conversation.rb +13 -13
  9. data/lib/mongo/auth/ldap.rb +2 -1
  10. data/lib/mongo/auth/ldap/conversation.rb +9 -12
  11. data/lib/mongo/auth/scram.rb +1 -0
  12. data/lib/mongo/auth/scram/conversation.rb +36 -27
  13. data/lib/mongo/auth/user.rb +7 -1
  14. data/lib/mongo/auth/x509.rb +2 -1
  15. data/lib/mongo/auth/x509/conversation.rb +9 -9
  16. data/lib/mongo/bulk_write/transformable.rb +3 -3
  17. data/lib/mongo/client.rb +17 -6
  18. data/lib/mongo/cluster.rb +67 -49
  19. data/lib/mongo/cluster/sdam_flow.rb +87 -3
  20. data/lib/mongo/collection/view/readable.rb +3 -1
  21. data/lib/mongo/collection/view/writable.rb +3 -3
  22. data/lib/mongo/cursor/builder/kill_cursors_command.rb +8 -1
  23. data/lib/mongo/cursor/builder/op_kill_cursors.rb +8 -1
  24. data/lib/mongo/database.rb +1 -1
  25. data/lib/mongo/grid/file.rb +5 -0
  26. data/lib/mongo/grid/file/chunk.rb +2 -0
  27. data/lib/mongo/grid/fs_bucket.rb +15 -13
  28. data/lib/mongo/grid/stream/write.rb +9 -3
  29. data/lib/mongo/protocol/serializers.rb +12 -2
  30. data/lib/mongo/retryable.rb +33 -8
  31. data/lib/mongo/server.rb +13 -6
  32. data/lib/mongo/server/connection.rb +15 -8
  33. data/lib/mongo/server/connection_base.rb +7 -4
  34. data/lib/mongo/server/description.rb +34 -21
  35. data/lib/mongo/server/monitor.rb +1 -1
  36. data/lib/mongo/server/monitor/connection.rb +2 -3
  37. data/lib/mongo/session.rb +10 -10
  38. data/lib/mongo/socket.rb +10 -1
  39. data/lib/mongo/uri.rb +1 -1
  40. data/lib/mongo/version.rb +1 -1
  41. data/mongo.gemspec +1 -1
  42. data/spec/README.md +13 -0
  43. data/spec/integration/auth_spec.rb +27 -8
  44. data/spec/integration/bson_symbol_spec.rb +34 -0
  45. data/spec/integration/client_construction_spec.rb +14 -0
  46. data/spec/integration/client_options_spec.rb +5 -5
  47. data/spec/integration/connection_spec.rb +57 -9
  48. data/spec/integration/crud_spec.rb +45 -0
  49. data/spec/integration/cursor_reaping_spec.rb +2 -1
  50. data/spec/integration/grid_fs_bucket_spec.rb +48 -0
  51. data/spec/integration/retryable_errors_spec.rb +204 -39
  52. data/spec/integration/retryable_writes_spec.rb +36 -36
  53. data/spec/integration/size_limit_spec.rb~12e1e9c4f... RUBY-2242 Fix zlib compression (#2021) +98 -0
  54. data/spec/lite_spec_helper.rb +1 -0
  55. data/spec/mongo/address_spec.rb +19 -13
  56. data/spec/mongo/auth/ldap/conversation_spec.rb +1 -1
  57. data/spec/mongo/auth/scram/conversation_spec.rb +25 -14
  58. data/spec/mongo/auth/user/view_spec.rb +36 -1
  59. data/spec/mongo/auth/user_spec.rb +12 -0
  60. data/spec/mongo/auth/x509/conversation_spec.rb +1 -1
  61. data/spec/mongo/bulk_write_spec.rb +2 -2
  62. data/spec/mongo/client_construction_spec.rb +1 -21
  63. data/spec/mongo/cluster_spec.rb +57 -0
  64. data/spec/mongo/collection/view/map_reduce_spec.rb +1 -1
  65. data/spec/mongo/collection_spec.rb +26 -2
  66. data/spec/mongo/cursor/builder/op_kill_cursors_spec.rb +56 -0
  67. data/spec/mongo/server/connection_spec.rb +76 -8
  68. data/spec/mongo/server/monitor/connection_spec.rb +14 -7
  69. data/spec/mongo/socket/ssl_spec.rb +132 -98
  70. data/spec/mongo/socket/tcp_spec.rb +1 -9
  71. data/spec/mongo/uri_spec.rb +1 -1
  72. data/spec/runners/sdam/verifier.rb +91 -0
  73. data/spec/spec_tests/data/sdam/rs/primary_address_change.yml +29 -0
  74. data/spec/spec_tests/data/sdam/rs/primary_mismatched_me.yml +27 -23
  75. data/spec/spec_tests/data/sdam/rs/primary_to_no_primary_mismatched_me.yml +56 -79
  76. data/spec/spec_tests/data/sdam/sharded/primary_address_change.yml +21 -0
  77. data/spec/spec_tests/data/sdam/sharded/primary_mismatched_me.yml +22 -0
  78. data/spec/spec_tests/data/sdam/single/primary_address_change.yml +24 -0
  79. data/spec/spec_tests/data/sdam/single/primary_mismatched_me.yml +25 -0
  80. data/spec/spec_tests/data/sdam_monitoring/replica_set_with_me_mismatch.yml +159 -0
  81. data/spec/spec_tests/data/sdam_monitoring/{replica_set_other_seed.yml → replica_set_with_primary_change.yml} +97 -101
  82. data/spec/spec_tests/data/sdam_monitoring/replica_set_with_primary_removal.yml +22 -18
  83. data/spec/spec_tests/data/sdam_monitoring/standalone_to_rs_with_me_mismatch.yml +90 -0
  84. data/spec/spec_tests/sdam_monitoring_spec.rb +9 -4
  85. data/spec/support/cluster_config.rb +36 -0
  86. data/spec/support/cluster_tools.rb +5 -3
  87. data/spec/support/command_monitoring.rb +1 -1
  88. data/spec/support/constraints.rb +18 -18
  89. data/spec/support/lite_constraints.rb +8 -0
  90. data/spec/support/sdam_monitoring.rb +0 -115
  91. data/spec/support/server_discovery_and_monitoring.rb +2 -0
  92. data/spec/support/spec_config.rb +1 -1
  93. data/spec/support/utils.rb +11 -1
  94. metadata +687 -659
  95. metadata.gz.sig +3 -2
@@ -102,22 +102,22 @@ describe 'Retryable writes integration tests' do
102
102
  end
103
103
 
104
104
  it 'does not retry writes' do
105
- expect {
105
+ expect do
106
106
  operation
107
- }.to raise_error(Mongo::Error::OperationFailure, /other error/)
107
+ end.to raise_error(Mongo::Error::OperationFailure, /other error/)
108
108
  expect(expectation).to eq(unsuccessful_retry_value)
109
109
  end
110
110
 
111
111
  it 'indicates server used for operation' do
112
- expect {
112
+ expect do
113
113
  operation
114
- }.to raise_error(Mongo::Error::OperationFailure, /on #{ClusterConfig.instance.primary_address_str}/)
114
+ end.to raise_error(Mongo::Error::OperationFailure, /on #{ClusterConfig.instance.primary_address_str}/)
115
115
  end
116
116
 
117
117
  it 'indicates first attempt' do
118
- expect {
118
+ expect do
119
119
  operation
120
- }.to raise_error(Mongo::Error::OperationFailure, /attempt 1/)
120
+ end.to raise_error(Mongo::Error::OperationFailure, /attempt 1/)
121
121
  end
122
122
  end
123
123
  end
@@ -144,9 +144,9 @@ describe 'Retryable writes integration tests' do
144
144
  end
145
145
 
146
146
  it 'does not retry writes and raises the original error' do
147
- expect {
147
+ expect do
148
148
  operation
149
- }.to raise_error(error)
149
+ end.to raise_error(error)
150
150
  expect(expectation).to eq(unsuccessful_retry_value)
151
151
  end
152
152
  end
@@ -158,9 +158,9 @@ describe 'Retryable writes integration tests' do
158
158
  end
159
159
 
160
160
  it 'does not retry writes and raises the original error' do
161
- expect {
161
+ expect do
162
162
  operation
163
- }.to raise_error(error)
163
+ end.to raise_error(error)
164
164
  expect(expectation).to eq(unsuccessful_retry_value)
165
165
  end
166
166
  end
@@ -172,9 +172,9 @@ describe 'Retryable writes integration tests' do
172
172
  end
173
173
 
174
174
  it 'does not retry writes and raises the original error' do
175
- expect {
175
+ expect do
176
176
  operation
177
- }.to raise_error(error)
177
+ end.to raise_error(error)
178
178
  expect(expectation).to eq(unsuccessful_retry_value)
179
179
  end
180
180
  end
@@ -211,22 +211,22 @@ describe 'Retryable writes integration tests' do
211
211
  end
212
212
 
213
213
  it 'raises the second error' do
214
- expect {
214
+ expect do
215
215
  operation
216
- }.to raise_error(second_error)
216
+ end.to raise_error(second_error)
217
217
  expect(expectation).to eq(unsuccessful_retry_value)
218
218
  end
219
219
 
220
220
  it 'indicates server used for operation' do
221
- expect {
221
+ expect do
222
222
  operation
223
- }.to raise_error(Mongo::Error, /on #{ClusterConfig.instance.primary_address_str}/)
223
+ end.to raise_error(Mongo::Error, /on #{ClusterConfig.instance.primary_address_str}/)
224
224
  end
225
225
 
226
226
  it 'indicates second attempt' do
227
- expect {
227
+ expect do
228
228
  operation
229
- }.to raise_error(Mongo::Error, /attempt 2/)
229
+ end.to raise_error(Mongo::Error, /attempt 2/)
230
230
  end
231
231
  end
232
232
 
@@ -237,9 +237,9 @@ describe 'Retryable writes integration tests' do
237
237
  end
238
238
 
239
239
  it 'raises the second error' do
240
- expect {
240
+ expect do
241
241
  operation
242
- }.to raise_error(second_error)
242
+ end.to raise_error(second_error)
243
243
  expect(expectation).to eq(unsuccessful_retry_value)
244
244
  end
245
245
  end
@@ -251,9 +251,9 @@ describe 'Retryable writes integration tests' do
251
251
  end
252
252
 
253
253
  it 'raises the second error' do
254
- expect {
254
+ expect do
255
255
  operation
256
- }.to raise_error(second_error)
256
+ end.to raise_error(second_error)
257
257
  expect(expectation).to eq(unsuccessful_retry_value)
258
258
  end
259
259
  end
@@ -265,9 +265,9 @@ describe 'Retryable writes integration tests' do
265
265
  end
266
266
 
267
267
  it 'does not retry writes and raises the first error' do
268
- expect {
268
+ expect do
269
269
  operation
270
- }.to raise_error(error)
270
+ end.to raise_error(error)
271
271
  expect(expectation).to eq(unsuccessful_retry_value)
272
272
  end
273
273
  end
@@ -279,28 +279,28 @@ describe 'Retryable writes integration tests' do
279
279
  end
280
280
 
281
281
  it 'raises the first error' do
282
- expect {
282
+ expect do
283
283
  operation
284
- }.to raise_error(error)
284
+ end.to raise_error(error)
285
285
  expect(expectation).to eq(unsuccessful_retry_value)
286
286
  end
287
287
 
288
288
  it 'indicates server used for operation' do
289
- expect {
289
+ expect do
290
290
  operation
291
- }.to raise_error(Mongo::Error, /on #{ClusterConfig.instance.primary_address_str}/)
291
+ end.to raise_error(Mongo::Error, /on #{ClusterConfig.instance.primary_address_str}/)
292
292
  end
293
293
 
294
294
  it 'indicates first attempt' do
295
- expect {
295
+ expect do
296
296
  operation
297
- }.to raise_error(Mongo::Error, /attempt 1/)
297
+ end.to raise_error(Mongo::Error, /attempt 1/)
298
298
  end
299
299
 
300
300
  it 'indicates retry was performed' do
301
- expect {
301
+ expect do
302
302
  operation
303
- }.to raise_error(Mongo::Error, /later retry failed: StandardError/)
303
+ end.to raise_error(Mongo::Error, /later retry failed: StandardError/)
304
304
  end
305
305
  end
306
306
  end
@@ -319,9 +319,9 @@ describe 'Retryable writes integration tests' do
319
319
  end
320
320
 
321
321
  it 'does not retry writes' do
322
- expect {
322
+ expect do
323
323
  operation
324
- }.to raise_error(Mongo::Error::SocketError)
324
+ end.to raise_error(Mongo::Error::SocketError)
325
325
  expect(expectation).to eq(unsuccessful_retry_value)
326
326
  end
327
327
  end
@@ -341,9 +341,9 @@ describe 'Retryable writes integration tests' do
341
341
  end
342
342
 
343
343
  it 'does not retry writes' do
344
- expect {
344
+ expect do
345
345
  operation
346
- }.to raise_error(Mongo::Error::SocketError)
346
+ end.to raise_error(Mongo::Error::SocketError)
347
347
  expect(expectation).to eq(unsuccessful_retry_value)
348
348
  end
349
349
  end
@@ -0,0 +1,98 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'BSON & command size limits' do
4
+ let(:max_document_size) { 16*1024*1024 }
5
+
6
+ before do
7
+ authorized_collection.delete_many
8
+ end
9
+
10
+ # This test uses a large document that is significantly smaller than the
11
+ # size limit. It is a basic sanity check.
12
+ it 'allows user-provided documents to be 15MiB' do
13
+ document = { key: 'a' * 15*1024*1024, _id: 'foo' }
14
+
15
+ authorized_collection.insert_one(document)
16
+ end
17
+
18
+ # This test uses a large document that is significantly larger than the
19
+ # size limit. It is a basic sanity check.
20
+ it 'fails single write of oversized documents' do
21
+ document = { key: 'a' * 17*1024*1024, _id: 'foo' }
22
+
23
+ lambda do
24
+ authorized_collection.insert_one(document)
25
+ end.should raise_error(Mongo::Error::MaxBSONSize, /The document exceeds maximum allowed BSON object size after serialization/)
26
+ end
27
+
28
+ # This test checks our bulk write splitting when documents are not close
29
+ # to the limit, but where splitting is definitely required.
30
+ it 'allows split bulk write of medium sized documents' do
31
+ # 8 documents of 4 MiB each = 32 MiB total data, should be split over
32
+ # either 2 or 3 bulk writes depending on how well the driver splits
33
+ documents = []
34
+ 1.upto(8) do |index|
35
+ documents << { key: 'a' * 4*1024*1024, _id: "in#{index}" }
36
+ end
37
+
38
+ authorized_collection.insert_many(documents)
39
+ authorized_collection.count_documents({}).should == 8
40
+ end
41
+
42
+ # This test ensures that document which are too big definitely fail insertion.
43
+ it 'fails bulk write of oversized documents' do
44
+ documents = []
45
+ 1.upto(3) do |index|
46
+ documents << { key: 'a' * 17*1024*1024, _id: "in#{index}" }
47
+ end
48
+
49
+ lambda do
50
+ authorized_collection.insert_many(documents)
51
+ end.should raise_error(Mongo::Error::MaxBSONSize, /The document exceeds maximum allowed BSON object size after serialization/)
52
+ authorized_collection.count_documents({}).should == 0
53
+ end
54
+
55
+ it 'allows user-provided documents to be exactly 16MiB' do
56
+ # The document must contain the _id field, otherwise the server will
57
+ # add it which will increase the size of the document as persisted by
58
+ # the server.
59
+ document = { key: 'a' * (max_document_size - 28), _id: 'foo' }
60
+ expect(document.to_bson.length).to eq(max_document_size)
61
+
62
+ authorized_collection.insert_one(document)
63
+ end
64
+
65
+ it 'fails on the server when a document larger than 16MiB is inserted' do
66
+ document = { key: 'a' * (max_document_size - 27), _id: 'foo' }
67
+ expect(document.to_bson.length).to eq(max_document_size+1)
68
+
69
+ lambda do
70
+ authorized_collection.insert_one(document)
71
+ end.should raise_error(Mongo::Error::OperationFailure, /object to insert too large/)
72
+ end
73
+
74
+ it 'fails in the driver when a document larger than 16MiB+16KiB is inserted' do
75
+ document = { key: 'a' * (max_document_size - 27 + 16*1024), _id: 'foo' }
76
+ expect(document.to_bson.length).to eq(max_document_size+16*1024+1)
77
+
78
+ lambda do
79
+ authorized_collection.insert_one(document)
80
+ end.should raise_error(Mongo::Error::MaxBSONSize, /The document exceeds maximum allowed BSON object size after serialization/)
81
+ end
82
+
83
+ it 'allows bulk writes of multiple documents of exactly 16 MiB each' do
84
+ if SpecConfig.instance.compressors
85
+ pending "RUBY-2234"
86
+ end
87
+
88
+ documents = []
89
+ 1.upto(3) do |index|
90
+ document = { key: 'a' * (max_document_size - 28), _id: "in#{index}" }
91
+ expect(document.to_bson.length).to eq(max_document_size)
92
+ documents << document
93
+ end
94
+
95
+ authorized_collection.insert_many(documents)
96
+ authorized_collection.count_documents({}).should == 3
97
+ end
98
+ end
@@ -127,6 +127,7 @@ RSpec.configure do |config|
127
127
  end
128
128
 
129
129
  config.expect_with :rspec do |c|
130
+ c.syntax = [:should, :expect]
130
131
  c.max_formatted_output_length = 10000
131
132
  end
132
133
  end
@@ -249,11 +249,7 @@ describe Mongo::Address do
249
249
  end
250
250
  end
251
251
 
252
- context 'when creating a socket using the resolver' do
253
-
254
- before do
255
- address.send(:create_resolver, SpecConfig.instance.ssl_options)
256
- end
252
+ context 'when creating a socket' do
257
253
 
258
254
  it 'uses the host, not the IP address' do
259
255
  expect(address.socket(0.0).host).to eq(socket_address_or_host)
@@ -285,6 +281,24 @@ describe Mongo::Address do
285
281
  end
286
282
  end
287
283
  end
284
+
285
+ describe ':connect_timeout option' do
286
+ clean_slate
287
+
288
+ let(:address) { Mongo::Address.new('127.0.0.1') }
289
+
290
+ it 'defaults to 10' do
291
+ RSpec::Mocks.with_temporary_scope do
292
+ resolved_address = double('address')
293
+ # This test's expectation
294
+ expect(resolved_address).to receive(:socket).with(0, {}, connect_timeout: 10)
295
+
296
+ expect(Mongo::Address::IPv4).to receive(:new).and_return(resolved_address)
297
+
298
+ address.socket(0)
299
+ end
300
+ end
301
+ end
288
302
  end
289
303
 
290
304
  describe '#to_s' do
@@ -320,12 +334,4 @@ describe Mongo::Address do
320
334
  end
321
335
  end
322
336
  end
323
-
324
- describe '#connect_timeout' do
325
- let(:address) { Mongo::Address.new('127.0.0.1') }
326
-
327
- it 'defaults to 10' do
328
- expect(address.send(:connect_timeout)).to eq(10)
329
- end
330
- end
331
337
  end
@@ -17,7 +17,7 @@ describe Mongo::Auth::LDAP::Conversation do
17
17
  describe '#start' do
18
18
 
19
19
  let(:query) do
20
- conversation.start
20
+ conversation.start(nil)
21
21
  end
22
22
 
23
23
  let(:selector) do
@@ -7,6 +7,15 @@ describe Mongo::Auth::SCRAM::Conversation, retry: 3 do
7
7
  described_class.new(user, mechanism)
8
8
  end
9
9
 
10
+ let(:connection) do
11
+ double('connection').tap do |connection|
12
+ features = double('features')
13
+ allow(features).to receive(:op_msg_enabled?)
14
+ allow(connection).to receive(:features).and_return(features)
15
+ allow(connection).to receive(:server)
16
+ end
17
+ end
18
+
10
19
  context 'when SCRAM-SHA-1 is used' do
11
20
  min_server_fcv '3.0'
12
21
 
@@ -26,9 +35,11 @@ describe Mongo::Auth::SCRAM::Conversation, retry: 3 do
26
35
  end
27
36
 
28
37
  describe '#start' do
38
+ # Test uses global assertions
39
+ clean_slate
29
40
 
30
41
  let(:query) do
31
- conversation.start
42
+ conversation.start(nil)
32
43
  end
33
44
 
34
45
  before do
@@ -85,7 +96,7 @@ describe Mongo::Auth::SCRAM::Conversation, retry: 3 do
85
96
  end
86
97
 
87
98
  let(:query) do
88
- conversation.continue(reply)
99
+ conversation.continue(reply, connection)
89
100
  end
90
101
 
91
102
  let(:selector) do
@@ -117,7 +128,7 @@ describe Mongo::Auth::SCRAM::Conversation, retry: 3 do
117
128
 
118
129
  it 'raises an error' do
119
130
  expect {
120
- conversation.continue(reply)
131
+ conversation.continue(reply, connection)
121
132
  }.to raise_error(Mongo::Error::InvalidNonce)
122
133
  end
123
134
  end
@@ -170,8 +181,8 @@ describe Mongo::Auth::SCRAM::Conversation, retry: 3 do
170
181
  end
171
182
 
172
183
  let(:query) do
173
- conversation.continue(continue_reply)
174
- conversation.finalize(reply)
184
+ conversation.continue(continue_reply, connection)
185
+ conversation.finalize(reply, connection)
175
186
  end
176
187
 
177
188
  let(:selector) do
@@ -199,8 +210,8 @@ describe Mongo::Auth::SCRAM::Conversation, retry: 3 do
199
210
 
200
211
  it 'raises an error' do
201
212
  expect {
202
- conversation.continue(continue_reply)
203
- conversation.finalize(reply)
213
+ conversation.continue(continue_reply, connection)
214
+ conversation.finalize(reply, connection)
204
215
  }.to raise_error(Mongo::Error::InvalidSignature)
205
216
  end
206
217
  end
@@ -226,7 +237,7 @@ describe Mongo::Auth::SCRAM::Conversation, retry: 3 do
226
237
  describe '#start' do
227
238
 
228
239
  let(:query) do
229
- conversation.start
240
+ conversation.start(nil)
230
241
  end
231
242
 
232
243
  before do
@@ -283,7 +294,7 @@ describe Mongo::Auth::SCRAM::Conversation, retry: 3 do
283
294
  end
284
295
 
285
296
  let(:query) do
286
- conversation.continue(reply)
297
+ conversation.continue(reply, connection)
287
298
  end
288
299
 
289
300
  let(:selector) do
@@ -315,7 +326,7 @@ describe Mongo::Auth::SCRAM::Conversation, retry: 3 do
315
326
 
316
327
  it 'raises an error' do
317
328
  expect {
318
- conversation.continue(reply)
329
+ conversation.continue(reply, connection)
319
330
  }.to raise_error(Mongo::Error::InvalidNonce)
320
331
  end
321
332
  end
@@ -368,8 +379,8 @@ describe Mongo::Auth::SCRAM::Conversation, retry: 3 do
368
379
  end
369
380
 
370
381
  let(:query) do
371
- conversation.continue(continue_reply)
372
- conversation.finalize(reply)
382
+ conversation.continue(continue_reply, connection)
383
+ conversation.finalize(reply, connection)
373
384
  end
374
385
 
375
386
  let(:selector) do
@@ -397,8 +408,8 @@ describe Mongo::Auth::SCRAM::Conversation, retry: 3 do
397
408
 
398
409
  it 'raises an error' do
399
410
  expect {
400
- conversation.continue(continue_reply)
401
- conversation.finalize(reply)
411
+ conversation.continue(continue_reply, connection)
412
+ conversation.finalize(reply, connection)
402
413
  }.to raise_error(Mongo::Error::InvalidSignature)
403
414
  end
404
415
  end