mongo 2.14.0.rc1 → 2.14.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +1 -1
  4. data/Rakefile +39 -4
  5. data/lib/mongo/address.rb +1 -1
  6. data/lib/mongo/collection.rb +5 -0
  7. data/lib/mongo/collection/view/readable.rb +4 -0
  8. data/lib/mongo/cursor.rb +15 -3
  9. data/lib/mongo/database/view.rb +1 -1
  10. data/lib/mongo/operation/collections_info/command.rb +5 -0
  11. data/lib/mongo/operation/collections_info/result.rb +16 -1
  12. data/lib/mongo/operation/find/result.rb +10 -0
  13. data/lib/mongo/server/description.rb +8 -1
  14. data/lib/mongo/session.rb +2 -1
  15. data/lib/mongo/version.rb +1 -1
  16. data/spec/README.md +7 -0
  17. data/spec/integration/bson_symbol_spec.rb +4 -2
  18. data/spec/integration/change_stream_spec.rb +1 -1
  19. data/spec/integration/connection_pool_populator_spec.rb +1 -1
  20. data/spec/integration/cursor_reaping_spec.rb +1 -1
  21. data/spec/integration/fork_reconnect_spec.rb +56 -1
  22. data/spec/integration/query_cache_transactions_spec.rb +29 -18
  23. data/spec/integration/sdam_error_handling_spec.rb +17 -0
  24. data/spec/integration/sdam_events_spec.rb +8 -5
  25. data/spec/integration/transactions_examples_spec.rb +17 -7
  26. data/spec/lite_spec_helper.rb +5 -3
  27. data/spec/mongo/auth/user_spec.rb +1 -1
  28. data/spec/mongo/bulk_write_spec.rb +2 -2
  29. data/spec/mongo/client_construction_spec.rb +3 -3
  30. data/spec/mongo/client_encryption_spec.rb +16 -10
  31. data/spec/mongo/client_spec.rb +7 -0
  32. data/spec/mongo/cluster/topology/replica_set_spec.rb +1 -1
  33. data/spec/mongo/cluster/topology/sharded_spec.rb +1 -1
  34. data/spec/mongo/cluster/topology/single_spec.rb +1 -1
  35. data/spec/mongo/cluster/topology/unknown_spec.rb +1 -1
  36. data/spec/mongo/cluster/topology_spec.rb +1 -1
  37. data/spec/mongo/collection/view/change_stream_resume_spec.rb +1 -1
  38. data/spec/mongo/collection/view/readable_spec.rb +36 -0
  39. data/spec/mongo/collection_spec.rb +12 -0
  40. data/spec/mongo/crypt/binary_spec.rb +1 -6
  41. data/spec/mongo/crypt/binding/binary_spec.rb +1 -6
  42. data/spec/mongo/crypt/binding/context_spec.rb +2 -7
  43. data/spec/mongo/crypt/binding/helpers_spec.rb +1 -6
  44. data/spec/mongo/crypt/binding/mongocrypt_spec.rb +2 -7
  45. data/spec/mongo/crypt/binding/status_spec.rb +1 -6
  46. data/spec/mongo/crypt/binding/version_spec.rb +1 -6
  47. data/spec/mongo/crypt/data_key_context_spec.rb +1 -1
  48. data/spec/mongo/crypt/status_spec.rb +1 -6
  49. data/spec/mongo/database_spec.rb +64 -0
  50. data/spec/mongo/monitoring/event/server_closed_spec.rb +1 -1
  51. data/spec/mongo/monitoring/event/server_opening_spec.rb +1 -1
  52. data/spec/mongo/monitoring/event/topology_changed_spec.rb +1 -1
  53. data/spec/mongo/monitoring/event/topology_closed_spec.rb +1 -1
  54. data/spec/mongo/monitoring/event/topology_opening_spec.rb +1 -1
  55. data/spec/mongo/operation/delete/op_msg_spec.rb +3 -3
  56. data/spec/mongo/operation/insert/command_spec.rb +2 -2
  57. data/spec/mongo/operation/insert/op_msg_spec.rb +3 -3
  58. data/spec/mongo/operation/read_preference_op_msg_spec.rb +1 -1
  59. data/spec/mongo/operation/update/command_spec.rb +2 -2
  60. data/spec/mongo/operation/update/op_msg_spec.rb +3 -3
  61. data/spec/mongo/query_cache_spec.rb +1 -0
  62. data/spec/mongo/server/app_metadata_shared.rb +2 -2
  63. data/spec/mongo/server/connection_spec.rb +1 -1
  64. data/spec/mongo/server/description_spec.rb +18 -0
  65. data/spec/mongo/server_selector_spec.rb +2 -2
  66. data/spec/mongo/socket/ssl_spec.rb +3 -3
  67. data/spec/runners/change_streams/test.rb +1 -1
  68. data/spec/runners/crud/test_base.rb +0 -19
  69. data/spec/runners/server_selection.rb +1 -1
  70. data/spec/runners/transactions/test.rb +2 -2
  71. data/spec/shared/LICENSE +20 -0
  72. data/spec/shared/lib/mrss/child_process_helper.rb +80 -0
  73. data/spec/shared/lib/mrss/constraints.rb +303 -0
  74. data/spec/shared/lib/mrss/lite_constraints.rb +175 -0
  75. data/spec/shared/lib/mrss/spec_organizer.rb +149 -0
  76. data/spec/spec_helper.rb +3 -1
  77. data/spec/stress/fork_reconnect_stress_spec.rb +1 -1
  78. data/spec/support/constraints.rb +0 -270
  79. data/spec/support/utils.rb +19 -0
  80. metadata +956 -952
  81. metadata.gz.sig +0 -0
  82. data/spec/support/child_process_helper.rb +0 -78
  83. data/spec/support/lite_constraints.rb +0 -165
  84. data/spec/support/spec_organizer.rb +0 -129
@@ -0,0 +1,149 @@
1
+ autoload :JSON, 'json'
2
+ autoload :FileUtils, 'fileutils'
3
+ autoload :Find, 'find'
4
+
5
+ module Mrss
6
+
7
+ autoload :ChildProcessHelper, 'mrss/child_process_helper'
8
+
9
+ # Organizes and runs all of the tests in the test suite in batches.
10
+ #
11
+ # Organizing the tests in batches serves two purposes:
12
+ #
13
+ # 1. This allows running unit tests before integration tests, therefore
14
+ # in theory revealing failures quicker on average.
15
+ # 2. This allows running some tests that have high intermittent failure rate
16
+ # in their own test process.
17
+ #
18
+ # This class aggregates RSpec results after the test runs.
19
+ class SpecOrganizer
20
+
21
+ class BucketsNotPrioritized < StandardError
22
+ end
23
+
24
+ def initialize(root: nil, classifiers:, priority_order:,
25
+ spec_root: nil, rspec_json_path: nil, rspec_all_json_path: nil
26
+ )
27
+ @spec_root = spec_root || File.join(root, 'spec')
28
+ @classifiers = classifiers
29
+ @priority_order = priority_order
30
+ @rspec_json_path = rspec_json_path || File.join(root, 'tmp/rspec.json')
31
+ @rspec_all_json_path = rspec_all_json_path || File.join(root, 'tmp/rspec-all.json')
32
+ end
33
+
34
+ attr_reader :spec_root, :classifiers, :priority_order
35
+ attr_reader :rspec_json_path, :rspec_all_json_path
36
+
37
+ def buckets
38
+ @buckets ||= {}.tap do |buckets|
39
+ Find.find(spec_root) do |path|
40
+ next unless File.file?(path)
41
+ next unless path =~ /_spec\.rb\z/
42
+ rel_path = path[(spec_root.length + 1)..path.length]
43
+
44
+ found = false
45
+ classifiers.each do |(regexp, category)|
46
+ if regexp =~ rel_path
47
+ buckets[category] ||= []
48
+ buckets[category] << File.join('spec', rel_path)
49
+ found = true
50
+ break
51
+ end
52
+ end
53
+
54
+ unless found
55
+ buckets[nil] ||= []
56
+ buckets[nil] << File.join('spec', rel_path)
57
+ end
58
+ end
59
+ end.freeze
60
+ end
61
+
62
+ def ordered_buckets
63
+ @ordered_buckets ||= {}.tap do |ordered_buckets|
64
+ buckets = self.buckets.dup
65
+ priority_order.each do |category|
66
+ files = buckets.delete(category)
67
+ ordered_buckets[category] = files
68
+ end
69
+
70
+ if files = buckets.delete(nil)
71
+ ordered_buckets[nil] = files
72
+ end
73
+
74
+ unless buckets.empty?
75
+ raise BucketsNotPrioritized, "Some buckets were not prioritized: #{buckets.keys.map(&:to_s).join(', ')}"
76
+ end
77
+ end.freeze
78
+ end
79
+
80
+ def run
81
+ FileUtils.rm_f(rspec_all_json_path)
82
+
83
+ failed = []
84
+ buckets = self.buckets.dup
85
+
86
+ priority_order.each do |category|
87
+ if files = buckets.delete(category)
88
+ unless run_files(category, files)
89
+ failed << category
90
+ end
91
+ end
92
+ end
93
+ if files = buckets.delete(nil)
94
+ unless run_files('remaining', files)
95
+ failed << 'remaining'
96
+ end
97
+ end
98
+
99
+ unless buckets.empty?
100
+ raise "Some buckets were not executed: #{buckets.keys.map(&:to_s).join(', ')}"
101
+ end
102
+
103
+ if failed.any?
104
+ raise "The following buckets failed: #{failed.map(&:to_s).join(', ')}"
105
+ end
106
+ end
107
+
108
+ def run_files(category, paths)
109
+ puts "Running #{category.to_s.gsub('_', ' ')} tests"
110
+ FileUtils.rm_f(rspec_json_path)
111
+ cmd = %w(rspec) + paths
112
+
113
+ begin
114
+ ChildProcessHelper.check_call(cmd)
115
+ ensure
116
+ if File.exist?(rspec_json_path)
117
+ if File.exist?(rspec_all_json_path)
118
+ merge_rspec_results
119
+ else
120
+ FileUtils.cp(rspec_json_path, rspec_all_json_path)
121
+ end
122
+ end
123
+ end
124
+
125
+ true
126
+ rescue ChildProcessHelper::SpawnError
127
+ false
128
+ end
129
+
130
+ def merge_rspec_results
131
+ all = JSON.parse(File.read(rspec_all_json_path))
132
+ new = JSON.parse(File.read(rspec_json_path))
133
+ all['examples'] += new.delete('examples')
134
+ new.delete('summary').each do |k, v|
135
+ all['summary'][k] += v
136
+ end
137
+ new.delete('version')
138
+ new.delete('summary_line')
139
+ unless new.empty?
140
+ raise "Unhandled rspec results keys: #{new.keys.join(', ')}"
141
+ end
142
+ # We do not merge summary lines, delete them from aggregated results
143
+ all.delete('summary_line')
144
+ File.open(rspec_all_json_path, 'w') do |f|
145
+ f << JSON.dump(all)
146
+ end
147
+ end
148
+ end
149
+ end
@@ -1,8 +1,9 @@
1
1
  require 'lite_spec_helper'
2
2
 
3
+ require 'mrss/constraints'
4
+ require 'support/constraints'
3
5
  require 'support/authorization'
4
6
  require 'support/primary_socket'
5
- require 'support/constraints'
6
7
  require 'support/cluster_config'
7
8
  require 'support/cluster_tools'
8
9
  require 'rspec/retry'
@@ -11,6 +12,7 @@ require 'support/local_resource_registry'
11
12
 
12
13
  RSpec.configure do |config|
13
14
  config.include(Authorization)
15
+ config.extend(Mrss::Constraints)
14
16
  config.extend(Constraints)
15
17
 
16
18
  config.before(:all) do
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  describe 'fork reconnect' do
4
4
  require_fork
5
- only_mri
5
+ require_mri
6
6
 
7
7
  # On multi-shard sharded clusters a succeeding write request does not
8
8
  # guarantee that the next operation will succeed (since it could be sent to
@@ -1,105 +1,4 @@
1
1
  module Constraints
2
- def min_server_version(version)
3
- unless version =~ /^\d+\.\d+$/
4
- raise ArgumentError, "Version can only be major.minor: #{version}"
5
- end
6
-
7
- before(:all) do
8
- if version > ClusterConfig.instance.server_version
9
- skip "Server version #{version} or higher required, we have #{ClusterConfig.instance.server_version}"
10
- end
11
- end
12
- end
13
-
14
- def max_server_version(version)
15
- unless version =~ /^\d+\.\d+$/
16
- raise ArgumentError, "Version can only be major.minor: #{version}"
17
- end
18
-
19
- before(:all) do
20
- if version < ClusterConfig.instance.short_server_version
21
- skip "Server version #{version} or lower required, we have #{ClusterConfig.instance.server_version}"
22
- end
23
- end
24
- end
25
-
26
- def min_server_fcv(version)
27
- unless version =~ /^\d+\.\d+$/
28
- raise ArgumentError, "FCV can only be major.minor: #{version}"
29
- end
30
-
31
- before(:all) do
32
- unless ClusterConfig.instance.fcv_ish >= version
33
- skip "FCV #{version} or higher required, we have #{ClusterConfig.instance.fcv_ish} (server #{ClusterConfig.instance.server_version})"
34
- end
35
- end
36
- end
37
-
38
- def max_server_fcv(version)
39
- unless version =~ /^\d+\.\d+$/
40
- raise ArgumentError, "Version can only be major.minor: #{version}"
41
- end
42
-
43
- before(:all) do
44
- if version < ClusterConfig.instance.fcv_ish
45
- skip "FCV #{version} or lower required, we have #{ClusterConfig.instance.fcv_ish} (server #{ClusterConfig.instance.server_version})"
46
- end
47
- end
48
- end
49
-
50
- def require_topology(*topologies)
51
- invalid_topologies = topologies - [:single, :replica_set, :sharded]
52
- unless invalid_topologies.empty?
53
- raise ArgumentError, "Invalid topologies requested: #{invalid_topologies.join(', ')}"
54
- end
55
- before(:all) do
56
- unless topologies.include?(topology = ClusterConfig.instance.topology)
57
- skip "Topology #{topologies.join(' or ')} required, we have #{topology}"
58
- end
59
- end
60
- end
61
-
62
- def max_example_run_time(timeout)
63
- around do |example|
64
- TimeoutInterrupt.timeout(timeout, TimeoutInterrupt::Error.new("Test execution terminated after #{timeout} seconds")) do
65
- example.run
66
- end
67
- end
68
- end
69
-
70
- def require_transaction_support
71
- min_server_fcv '4.0'
72
- require_topology :replica_set
73
- end
74
-
75
- # Fail command fail point was added to mongod in 4.0 and to mongos in 4.2.
76
- def require_fail_command
77
- min_server_fcv '4.0'
78
-
79
- before(:all) do
80
- if ClusterConfig.instance.topology == :sharded
81
- unless ClusterConfig.instance.short_server_version >= '4.2'
82
- skip 'Test requires failCommand fail point which was added to mongos in 4.2'
83
- end
84
- end
85
- end
86
- end
87
-
88
- def require_tls
89
- before(:all) do
90
- unless SpecConfig.instance.ssl?
91
- skip "SSL not enabled"
92
- end
93
- end
94
- end
95
-
96
- def require_no_tls
97
- before(:all) do
98
- if SpecConfig.instance.ssl?
99
- skip "SSL enabled"
100
- end
101
- end
102
- end
103
2
 
104
3
  # Some tests hardcode the TLS certificates shipped with the driver's
105
4
  # test suite, and will fail when using TLS connections that use other
@@ -114,173 +13,4 @@ module Constraints
114
13
  end
115
14
  end
116
15
  end
117
-
118
- def require_no_retry_writes
119
- before(:all) do
120
- if SpecConfig.instance.retry_writes?
121
- skip "Retry writes is enabled"
122
- end
123
- end
124
- end
125
-
126
- def require_compression
127
- before(:all) do
128
- if SpecConfig.instance.compressors.nil?
129
- skip "Compression is not enabled"
130
- end
131
- end
132
- end
133
-
134
- def require_no_compression
135
- before(:all) do
136
- if SpecConfig.instance.compressors
137
- skip "Compression is enabled"
138
- end
139
- end
140
- end
141
-
142
- def ruby_version_gte(version)
143
- before(:all) do
144
- if RUBY_VERSION < version
145
- skip "Ruby version #{version} or higher required"
146
- end
147
- end
148
- end
149
-
150
- def ruby_version_lt(version)
151
- before(:all) do
152
- if RUBY_VERSION >= version
153
- skip "Ruby version less than #{version} required"
154
- end
155
- end
156
- end
157
-
158
- def require_auth(*values)
159
- before(:all) do
160
- if values.any?
161
- unless values.include?(ENV['AUTH'])
162
- msg = values.map { |v| "AUTH=#{v}" }.join(' or ')
163
- skip "This test requires #{msg}"
164
- end
165
- else
166
- unless ENV['AUTH'] == 'auth' || SpecConfig.instance.user || ClusterConfig.instance.auth_enabled?
167
- skip "Auth required"
168
- end
169
- end
170
- end
171
- end
172
-
173
- def require_no_auth
174
- before(:all) do
175
- if (ENV['AUTH'] && ENV['AUTH'] != 'noauth') || SpecConfig.instance.user || ClusterConfig.instance.auth_enabled?
176
- skip "Auth not allowed"
177
- end
178
- end
179
- end
180
-
181
- def require_x509_auth
182
- before(:all) do
183
- unless SpecConfig.instance.x509_auth?
184
- skip "X.509 auth required"
185
- end
186
- end
187
- end
188
-
189
- def require_no_external_user
190
- before(:all) do
191
- if SpecConfig.instance.external_user?
192
- skip "External user configurations are not compatible with this test"
193
- end
194
- end
195
- end
196
-
197
- # Can the driver specify a write concern that won't be overridden?
198
- # (mongos 4.0+ overrides the write concern)
199
- def require_set_write_concern
200
- before(:all) do
201
- if ClusterConfig.instance.topology == :sharded && ClusterConfig.instance.short_server_version >= '4.0'
202
- skip "mongos 4.0+ overrides write concern"
203
- end
204
- end
205
- end
206
-
207
- def require_multi_shard
208
- before(:all) do
209
- if ClusterConfig.instance.topology == :sharded && SpecConfig.instance.addresses.length == 1
210
- skip 'Test requires a minimum of two shards if run in sharded topology'
211
- end
212
- end
213
- end
214
-
215
- def require_no_multi_shard
216
- before(:all) do
217
- if ClusterConfig.instance.topology == :sharded && SpecConfig.instance.addresses.length > 1
218
- skip 'Test requires a single shard if run in sharded topology'
219
- end
220
- end
221
- end
222
-
223
- def require_wired_tiger
224
- before(:all) do
225
- if ClusterConfig.instance.storage_engine != :wired_tiger
226
- skip 'Test requires WiredTiger storage engine'
227
- end
228
- end
229
- end
230
-
231
- def require_wired_tiger_on_36
232
- before(:all) do
233
- if ClusterConfig.instance.short_server_version >= '3.6'
234
- if ClusterConfig.instance.storage_engine != :wired_tiger
235
- skip 'Test requires WiredTiger storage engine on 3.6+ servers'
236
- end
237
- end
238
- end
239
- end
240
-
241
- def require_mmapv1
242
- before(:all) do
243
- if ClusterConfig.instance.storage_engine != :mmapv1
244
- skip 'Test requires MMAPv1 storage engine'
245
- end
246
- end
247
- end
248
-
249
- def require_enterprise
250
- before(:all) do
251
- unless ClusterConfig.instance.enterprise?
252
- skip 'Test requires enterprise build of MongoDB'
253
- end
254
- end
255
- end
256
-
257
- # Integration tests for SRV polling require internet connectivity to
258
- # look up SRV records and a sharded cluster configured on default port on
259
- # localhost (localhost:27017, localhost:27018).
260
- def require_default_port_deployment
261
- # Because the DNS records at test1.test.build.10gen.cc point to
262
- # localhost:27017 & localhost:27018, the test suite must have been
263
- # configured to use these addresses
264
- before(:all) do
265
- have_default_port = SpecConfig.instance.addresses.any? do |address|
266
- %w(127.0.0.1 127.0.0.1:27017 localhost localhost:27017).include?(address)
267
- end
268
- unless have_default_port
269
- skip 'This test requires the test suite to be configured for localhost:27017'
270
- end
271
- end
272
- end
273
-
274
- # Some tests perform assertions on what the driver is logging.
275
- # Some test configurations, for example OCSP with unknown response,
276
- # produce warnings due to optional checks failing.
277
- # This constraint skips tests that issue logging assertions on configurations
278
- # that may produce non-test-originated log entries.
279
- def require_warning_clean
280
- before(:all) do
281
- if ENV['OCSP_STATUS'] == 'unknown'
282
- skip 'Unknown OCSP status is not global warning-clean'
283
- end
284
- end
285
- end
286
16
  end