mongo 2.19.3 → 2.20.1

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 (178) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +37 -1
  3. data/Rakefile +81 -172
  4. data/lib/mongo/cluster/topology/base.rb +16 -0
  5. data/lib/mongo/cluster.rb +27 -1
  6. data/lib/mongo/collection/view/iterable.rb +1 -0
  7. data/lib/mongo/collection.rb +4 -2
  8. data/lib/mongo/config.rb +2 -2
  9. data/lib/mongo/error/transactions_not_supported.rb +34 -0
  10. data/lib/mongo/error.rb +1 -0
  11. data/lib/mongo/grid/fs_bucket.rb +6 -0
  12. data/lib/mongo/monitoring/event/secure.rb +1 -1
  13. data/lib/mongo/operation/shared/executable.rb +43 -27
  14. data/lib/mongo/operation/shared/response_handling.rb +23 -25
  15. data/lib/mongo/retryable/base_worker.rb +28 -3
  16. data/lib/mongo/retryable/read_worker.rb +16 -14
  17. data/lib/mongo/retryable/write_worker.rb +11 -8
  18. data/lib/mongo/retryable.rb +2 -2
  19. data/lib/mongo/server/app_metadata/environment.rb +64 -9
  20. data/lib/mongo/server/app_metadata.rb +5 -4
  21. data/lib/mongo/server/description/features.rb +1 -0
  22. data/lib/mongo/server/pending_connection.rb +19 -6
  23. data/lib/mongo/server_selector/base.rb +32 -6
  24. data/lib/mongo/session/server_session/dirtyable.rb +52 -0
  25. data/lib/mongo/session/server_session.rb +3 -0
  26. data/lib/mongo/session/session_pool.rb +12 -18
  27. data/lib/mongo/session.rb +32 -0
  28. data/lib/mongo/socket/ssl.rb +22 -1
  29. data/lib/mongo/uri.rb +0 -4
  30. data/lib/mongo/version.rb +1 -5
  31. data/mongo.gemspec +9 -18
  32. data/spec/atlas/atlas_connectivity_spec.rb +4 -4
  33. data/spec/faas/ruby-sam-app/Gemfile +9 -0
  34. data/spec/faas/ruby-sam-app/mongodb/Gemfile +4 -0
  35. data/spec/faas/ruby-sam-app/mongodb/app.rb +149 -0
  36. data/spec/faas/ruby-sam-app/template.yaml +48 -0
  37. data/spec/integration/client_side_encryption/corpus_spec.rb +10 -2
  38. data/spec/integration/client_side_encryption/range_explicit_encryption_prose_spec.rb +3 -0
  39. data/spec/integration/retryable_reads_errors_spec.rb +196 -31
  40. data/spec/integration/retryable_writes_errors_spec.rb +156 -0
  41. data/spec/integration/sdam_error_handling_spec.rb +2 -0
  42. data/spec/lite_spec_helper.rb +0 -10
  43. data/spec/mongo/cluster_spec.rb +36 -0
  44. data/spec/mongo/collection/view/aggregation_spec.rb +6 -1
  45. data/spec/mongo/collection/view/explainable_spec.rb +2 -0
  46. data/spec/mongo/collection_crud_spec.rb +2 -1
  47. data/spec/mongo/operation/insert_spec.rb +1 -1
  48. data/spec/mongo/retryable/write_worker_spec.rb +39 -0
  49. data/spec/mongo/server/app_metadata/environment_spec.rb +135 -0
  50. data/spec/mongo/server/app_metadata_spec.rb +12 -2
  51. data/spec/mongo/server/connection_spec.rb +26 -0
  52. data/spec/mongo/session/session_pool_spec.rb +1 -16
  53. data/spec/mongo/session_transaction_spec.rb +15 -0
  54. data/spec/mongo/uri_spec.rb +0 -9
  55. data/spec/runners/crud/test.rb +0 -8
  56. data/spec/runners/crud.rb +1 -1
  57. data/spec/runners/transactions/test.rb +12 -3
  58. data/spec/runners/unified/assertions.rb +16 -3
  59. data/spec/runners/unified/crud_operations.rb +12 -0
  60. data/spec/runners/unified/support_operations.rb +3 -5
  61. data/spec/runners/unified/test.rb +8 -1
  62. data/spec/spec_tests/data/client_side_encryption/explain.yml +2 -2
  63. data/spec/spec_tests/data/client_side_encryption/fle2v2-BypassQueryAnalysis.yml +1 -0
  64. data/spec/spec_tests/data/client_side_encryption/fle2v2-Compact.yml +1 -0
  65. data/spec/spec_tests/data/client_side_encryption/fle2v2-CreateCollection.yml +1 -0
  66. data/spec/spec_tests/data/client_side_encryption/fle2v2-DecryptExistingData.yml +1 -0
  67. data/spec/spec_tests/data/client_side_encryption/fle2v2-Delete.yml +1 -0
  68. data/spec/spec_tests/data/client_side_encryption/fle2v2-EncryptedFields-vs-EncryptedFieldsMap.yml +1 -0
  69. data/spec/spec_tests/data/client_side_encryption/fle2v2-EncryptedFields-vs-jsonSchema.yml +1 -0
  70. data/spec/spec_tests/data/client_side_encryption/fle2v2-EncryptedFieldsMap-defaults.yml +1 -0
  71. data/spec/spec_tests/data/client_side_encryption/fle2v2-FindOneAndUpdate.yml +1 -0
  72. data/spec/spec_tests/data/client_side_encryption/fle2v2-InsertFind-Indexed.yml +1 -0
  73. data/spec/spec_tests/data/client_side_encryption/fle2v2-InsertFind-Unindexed.yml +1 -0
  74. data/spec/spec_tests/data/client_side_encryption/fle2v2-MissingKey.yml +1 -0
  75. data/spec/spec_tests/data/client_side_encryption/fle2v2-NoEncryption.yml +1 -0
  76. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Aggregate.yml +1 -0
  77. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Correctness.yml +1 -0
  78. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Delete.yml +1 -0
  79. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-FindOneAndUpdate.yml +1 -0
  80. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-InsertFind.yml +1 -0
  81. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Update.yml +1 -0
  82. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Aggregate.yml +1 -0
  83. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Correctness.yml +1 -0
  84. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Delete.yml +1 -0
  85. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-FindOneAndUpdate.yml +1 -0
  86. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-InsertFind.yml +1 -0
  87. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Update.yml +1 -0
  88. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Aggregate.yml +1 -0
  89. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Correctness.yml +1 -0
  90. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Delete.yml +1 -0
  91. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-FindOneAndUpdate.yml +1 -0
  92. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-InsertFind.yml +1 -0
  93. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Update.yml +1 -0
  94. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Aggregate.yml +1 -0
  95. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Correctness.yml +1 -0
  96. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Delete.yml +1 -0
  97. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-FindOneAndUpdate.yml +1 -0
  98. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-InsertFind.yml +1 -0
  99. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Update.yml +1 -0
  100. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Aggregate.yml +1 -0
  101. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Correctness.yml +1 -0
  102. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Delete.yml +1 -0
  103. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-FindOneAndUpdate.yml +1 -0
  104. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-InsertFind.yml +1 -0
  105. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Update.yml +1 -0
  106. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Aggregate.yml +1 -0
  107. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Correctness.yml +1 -0
  108. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Delete.yml +1 -0
  109. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-FindOneAndUpdate.yml +1 -0
  110. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-InsertFind.yml +1 -0
  111. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Update.yml +1 -0
  112. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Aggregate.yml +1 -0
  113. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Correctness.yml +1 -0
  114. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Delete.yml +1 -0
  115. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-FindOneAndUpdate.yml +1 -0
  116. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-InsertFind.yml +1 -0
  117. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Update.yml +1 -0
  118. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-WrongType.yml +1 -0
  119. data/spec/spec_tests/data/client_side_encryption/fle2v2-Update.yml +1 -0
  120. data/spec/spec_tests/data/client_side_encryption/fle2v2-validatorAndPartialFieldExpression.yml +2 -1
  121. data/spec/spec_tests/data/connection_string/invalid-uris.yml +0 -10
  122. data/spec/spec_tests/data/connection_string/valid-options.yml +13 -0
  123. data/spec/spec_tests/data/crud_unified/aggregate-write-readPreference.yml +2 -0
  124. data/spec/spec_tests/data/crud_unified/db-aggregate-write-readPreference.yml +2 -0
  125. data/spec/spec_tests/data/crud_unified/find-test-all-options.yml +348 -0
  126. data/spec/spec_tests/data/index_management/createSearchIndex.yml +5 -3
  127. data/spec/spec_tests/data/index_management/createSearchIndexes.yml +7 -4
  128. data/spec/spec_tests/data/index_management/dropSearchIndex.yml +2 -1
  129. data/spec/spec_tests/data/index_management/listSearchIndexes.yml +13 -7
  130. data/spec/spec_tests/data/index_management/updateSearchIndex.yml +2 -1
  131. data/spec/spec_tests/data/retryable_writes/unified/bulkWrite-serverErrors.yml +3 -6
  132. data/spec/spec_tests/data/retryable_writes/unified/insertOne-serverErrors.yml +3 -6
  133. data/spec/spec_tests/data/run_command_unified/runCommand.yml +319 -0
  134. data/spec/spec_tests/data/sessions_unified/driver-sessions-dirty-session-errors.yml +351 -0
  135. data/spec/spec_tests/data/unified/valid-pass/poc-crud.yml +1 -1
  136. data/spec/spec_tests/data/unified/valid-pass/poc-retryable-writes.yml +7 -7
  137. data/spec/spec_tests/data/unified/valid-pass/poc-sessions.yml +3 -4
  138. data/spec/spec_tests/data/unified/valid-pass/poc-transactions-convenient-api.yml +1 -1
  139. data/spec/spec_tests/data/unified/valid-pass/poc-transactions-mongos-pin-auto.yml +1 -1
  140. data/spec/spec_tests/data/unified/valid-pass/poc-transactions.yml +3 -3
  141. data/spec/spec_tests/run_command_unified_spec.rb +13 -0
  142. data/spec/spec_tests/sdam_unified_spec.rb +2 -0
  143. data/spec/spec_tests/transactions_unified_spec.rb +2 -1
  144. data/spec/support/certificates/atlas-ocsp-ca.crt +89 -77
  145. data/spec/support/certificates/atlas-ocsp.crt +117 -122
  146. data/spec/support/certificates/retrieve-atlas-cert +1 -1
  147. data/spec/support/constraints.rb +6 -0
  148. data/spec/support/ocsp +1 -1
  149. data/spec/support/recording_logger.rb +27 -0
  150. metadata +1245 -1298
  151. checksums.yaml.gz.sig +0 -0
  152. data/spec/shared/LICENSE +0 -20
  153. data/spec/shared/bin/get-mongodb-download-url +0 -17
  154. data/spec/shared/bin/s3-copy +0 -45
  155. data/spec/shared/bin/s3-upload +0 -69
  156. data/spec/shared/lib/mrss/child_process_helper.rb +0 -80
  157. data/spec/shared/lib/mrss/cluster_config.rb +0 -231
  158. data/spec/shared/lib/mrss/constraints.rb +0 -378
  159. data/spec/shared/lib/mrss/docker_runner.rb +0 -295
  160. data/spec/shared/lib/mrss/eg_config_utils.rb +0 -51
  161. data/spec/shared/lib/mrss/event_subscriber.rb +0 -210
  162. data/spec/shared/lib/mrss/lite_constraints.rb +0 -238
  163. data/spec/shared/lib/mrss/server_version_registry.rb +0 -113
  164. data/spec/shared/lib/mrss/session_registry.rb +0 -69
  165. data/spec/shared/lib/mrss/session_registry_legacy.rb +0 -60
  166. data/spec/shared/lib/mrss/spec_organizer.rb +0 -179
  167. data/spec/shared/lib/mrss/utils.rb +0 -37
  168. data/spec/shared/share/Dockerfile.erb +0 -330
  169. data/spec/shared/share/haproxy-1.conf +0 -16
  170. data/spec/shared/share/haproxy-2.conf +0 -17
  171. data/spec/shared/shlib/config.sh +0 -27
  172. data/spec/shared/shlib/distro.sh +0 -74
  173. data/spec/shared/shlib/server.sh +0 -416
  174. data/spec/shared/shlib/set_env.sh +0 -169
  175. data/spec/spec_tests/data/cmap/pool-clear-interrupt-immediately.yml +0 -49
  176. data/spec/support/faas/app/aws_lambda/mongodb/Gemfile.lock +0 -19
  177. data.tar.gz.sig +0 -3
  178. metadata.gz.sig +0 -0
@@ -1,8 +1,52 @@
1
1
  # frozen_string_literal: true
2
+ # rubocop:todo all
2
3
 
3
4
  require 'spec_helper'
5
+ require 'fileutils'
6
+
7
+ MOCKED_DOCKERENV_PATH = File.expand_path(File.join(Dir.pwd, '.dockerenv-mocked'))
8
+
9
+ module ContainerChecking
10
+ def mock_dockerenv_path
11
+ before do
12
+ allow_any_instance_of(Mongo::Server::AppMetadata::Environment)
13
+ .to receive(:dockerenv_path)
14
+ .and_return(MOCKED_DOCKERENV_PATH)
15
+ end
16
+ end
17
+
18
+ def with_docker
19
+ mock_dockerenv_path
20
+
21
+ around do |example|
22
+ File.write(MOCKED_DOCKERENV_PATH, 'placeholder')
23
+ example.run
24
+ ensure
25
+ File.delete(MOCKED_DOCKERENV_PATH)
26
+ end
27
+ end
28
+
29
+ def without_docker
30
+ mock_dockerenv_path
31
+
32
+ around do |example|
33
+ FileUtils.rm_f(MOCKED_DOCKERENV_PATH)
34
+ example.run
35
+ end
36
+ end
37
+
38
+ def with_kubernetes
39
+ local_env 'KUBERNETES_SERVICE_HOST' => 'kubernetes.default.svc.cluster.local'
40
+ end
41
+
42
+ def without_kubernetes
43
+ local_env 'KUBERNETES_SERVICE_HOST' => nil
44
+ end
45
+ end
4
46
 
5
47
  describe Mongo::Server::AppMetadata::Environment do
48
+ extend ContainerChecking
49
+
6
50
  let(:env) { described_class.new }
7
51
 
8
52
  shared_examples_for 'running in a FaaS environment' do
@@ -17,6 +61,36 @@ describe Mongo::Server::AppMetadata::Environment do
17
61
  end
18
62
  end
19
63
 
64
+ shared_examples_for 'not running in a Docker container' do
65
+ it 'does not detect Docker' do
66
+ expect(env.container || {}).not_to include :runtime
67
+ end
68
+ end
69
+
70
+ shared_examples_for 'not running under Kubernetes' do
71
+ it 'does not detect Kubernetes' do
72
+ expect(env.container || {}).not_to include :orchestrator
73
+ end
74
+ end
75
+
76
+ shared_examples_for 'running under Kubernetes' do
77
+ it 'detects that Kubernetes is present' do
78
+ expect(env.container[:orchestrator]).to be == 'kubernetes'
79
+ end
80
+ end
81
+
82
+ shared_examples_for 'running in a Docker container' do
83
+ it 'detects that Docker is present' do
84
+ expect(env.container[:runtime]).to be == 'docker'
85
+ end
86
+ end
87
+
88
+ shared_examples_for 'running under Kerbenetes' do
89
+ it 'detects that kubernetes is present' do
90
+ expect(env.container['orchestrator']).to be == 'kubernetes'
91
+ end
92
+ end
93
+
20
94
  context 'when run outside of a FaaS environment' do
21
95
  it_behaves_like 'running outside a FaaS environment'
22
96
  end
@@ -204,6 +278,67 @@ describe Mongo::Server::AppMetadata::Environment do
204
278
  timeout_sec: 60, region: 'us-central1',
205
279
  }
206
280
  end
281
+
282
+ context 'when a container is present' do
283
+ with_kubernetes
284
+ with_docker
285
+
286
+ it 'includes a container key' do
287
+ expect(env.to_h[:container]).to be == {
288
+ runtime: 'docker',
289
+ orchestrator: 'kubernetes'
290
+ }
291
+ end
292
+ end
293
+
294
+ context 'when no container is present' do
295
+ without_kubernetes
296
+ without_docker
297
+
298
+ it 'does not include a container key' do
299
+ expect(env.to_h).not_to include(:container)
300
+ end
301
+ end
302
+ end
303
+ end
304
+
305
+ # have a specific test for this, since the tests that check
306
+ # for Docker use a mocked value for the .dockerenv path.
307
+ it 'should look for dockerenv in root directory' do
308
+ expect(described_class::DOCKERENV_PATH).to be == '/.dockerenv'
309
+ end
310
+
311
+ context 'when no container is present' do
312
+ without_kubernetes
313
+ without_docker
314
+
315
+ it_behaves_like 'not running in a Docker container'
316
+ it_behaves_like 'not running under Kubernetes'
317
+ end
318
+
319
+ context 'when container is present' do
320
+ context 'when kubernetes is present' do
321
+ without_docker
322
+ with_kubernetes
323
+
324
+ it_behaves_like 'not running in a Docker container'
325
+ it_behaves_like 'running under Kubernetes'
326
+ end
327
+
328
+ context 'when docker is present' do
329
+ with_docker
330
+ without_kubernetes
331
+
332
+ it_behaves_like 'running in a Docker container'
333
+ it_behaves_like 'not running under Kubernetes'
334
+ end
335
+
336
+ context 'when both kubernetes and docker are present' do
337
+ with_docker
338
+ with_kubernetes
339
+
340
+ it_behaves_like 'running in a Docker container'
341
+ it_behaves_like 'running under Kubernetes'
207
342
  end
208
343
  end
209
344
  end
@@ -87,8 +87,18 @@ describe Mongo::Server::AppMetadata do
87
87
  end
88
88
 
89
89
  context 'when run outside of a FaaS environment' do
90
- it 'excludes the :env key from the client document' do
91
- expect(app_metadata.client_document.key?(:env)).to be false
90
+ context 'when a container is present' do
91
+ local_env 'KUBERNETES_SERVICE_HOST' => 'something'
92
+
93
+ it 'includes the :env key in the client document' do
94
+ expect(app_metadata.client_document.key?(:env)).to be true
95
+ end
96
+ end
97
+
98
+ context 'when no container is present' do
99
+ it 'excludes the :env key from the client document' do
100
+ expect(app_metadata.client_document.key?(:env)).to be false
101
+ end
92
102
  end
93
103
  end
94
104
 
@@ -265,6 +265,10 @@ describe Mongo::Server::Connection do
265
265
  context 'when #authenticate! raises an exception' do
266
266
  require_auth
267
267
 
268
+ # because the mock/stub flow here doesn't cover the flow used by
269
+ # the X.509 authentication mechanism...
270
+ forbid_x509_auth
271
+
268
272
  let(:server_options) do
269
273
  Mongo::Client.canonicalize_ruby_options(
270
274
  SpecConfig.instance.all_test_options,
@@ -579,6 +583,28 @@ describe Mongo::Server::Connection do
579
583
  end
580
584
  end
581
585
 
586
+ context 'when the server returns unknown saslSupportedMechs' do
587
+ min_server_version '4.0'
588
+
589
+ let(:connection) do
590
+ described_class.new(server, server.options.merge(connection_pool: pool))
591
+ end
592
+
593
+ before do
594
+ expect_any_instance_of(Mongo::Server::PendingConnection).to receive(:get_handshake_response).and_wrap_original do |original_method, *args|
595
+ original_method.call(*args).tap do |result|
596
+ if result.documents.first.fetch('saslSupportedMechs', nil).is_a?(Array)
597
+ result.documents.first['saslSupportedMechs'].append('unknownMechanism')
598
+ end
599
+ end
600
+ end
601
+ end
602
+
603
+ it 'does not raise an error' do
604
+ expect { connection.connect! }.not_to raise_error
605
+ end
606
+ end
607
+
582
608
  end
583
609
 
584
610
  describe '#disconnect!' do
@@ -17,21 +17,6 @@ describe Mongo::Session::SessionPool do
17
17
  end
18
18
  end
19
19
 
20
- describe '.create' do
21
-
22
- let!(:pool) do
23
- described_class.create(cluster)
24
- end
25
-
26
- it 'creates a session pool' do
27
- expect(pool).to be_a(Mongo::Session::SessionPool)
28
- end
29
-
30
- it 'adds the pool as an instance variable on the cluster' do
31
- expect(cluster.session_pool).to eq(pool)
32
- end
33
- end
34
-
35
20
  describe '#initialize' do
36
21
 
37
22
  let(:pool) do
@@ -181,7 +166,7 @@ describe Mongo::Session::SessionPool do
181
166
  describe '#end_sessions' do
182
167
 
183
168
  let(:pool) do
184
- described_class.create(client.cluster)
169
+ client.cluster.session_pool
185
170
  end
186
171
 
187
172
  let!(:session_a) do
@@ -26,6 +26,17 @@ describe Mongo::Session do
26
26
  collection.delete_many
27
27
  end
28
28
 
29
+ describe 'start_transaction' do
30
+ context 'when topology is sharded and server is < 4.2' do
31
+ max_server_fcv '4.1'
32
+ require_topology :sharded
33
+
34
+ it 'raises an error' do
35
+ expect { session.start_transaction }.to raise_error(Mongo::Error::TransactionsNotSupported, /sharded transactions require server version/)
36
+ end
37
+ end
38
+ end
39
+
29
40
  describe '#abort_transaction' do
30
41
  require_topology :replica_set
31
42
 
@@ -75,6 +86,8 @@ describe Mongo::Session do
75
86
  end
76
87
 
77
88
  describe '#with_transaction' do
89
+ require_topology :replica_set
90
+
78
91
  context 'callback successful' do
79
92
  it 'commits' do
80
93
  session.with_transaction do
@@ -123,6 +136,7 @@ describe Mongo::Session do
123
136
  expect(Mongo::Utils).to receive(:monotonic_time).ordered.and_return(start + 1)
124
137
  expect(Mongo::Utils).to receive(:monotonic_time).ordered.and_return(start + 2)
125
138
  expect(Mongo::Utils).to receive(:monotonic_time).ordered.and_return(start + 200)
139
+ allow(session).to receive('check_transactions_supported!').and_return true
126
140
 
127
141
  expect do
128
142
  session.with_transaction do
@@ -156,6 +170,7 @@ describe Mongo::Session do
156
170
  expect(Mongo::Utils).to receive(:monotonic_time).ordered.and_return(start + i)
157
171
  end
158
172
  expect(Mongo::Utils).to receive(:monotonic_time).ordered.and_return(start + 200)
173
+ allow(session).to receive('check_transactions_supported!').and_return true
159
174
 
160
175
  exc = Mongo::Error::OperationFailure.new('timeout test')
161
176
  exc.add_label(label)
@@ -266,15 +266,6 @@ describe Mongo::URI do
266
266
  end
267
267
  end
268
268
 
269
- context 'no slash after hosts, and options' do
270
-
271
- let(:string) { 'mongodb://example.com?tls=true' }
272
-
273
- it 'raises an error' do
274
- expect { uri }.to raise_error(Mongo::Error::InvalidURI, %r,MongoDB URI must have a slash \(/\) after the hosts if options are given,)
275
- end
276
- end
277
-
278
269
  context 'mongodb://example.com/?w' do
279
270
 
280
271
  let(:string) { 'mongodb://example.com/?w' }
@@ -110,14 +110,6 @@ module Mongo
110
110
  end
111
111
  setup_fail_point(client)
112
112
  end
113
-
114
- def actual_collection_contents(client)
115
- unless @spec.collection_name
116
- raise ArgumentError, 'Spec does not specify a global collection'
117
- end
118
-
119
- client[@spec.collection_name, read_concern: {level: :majority}].find.to_a
120
- end
121
113
  end
122
114
  end
123
115
  end
data/spec/runners/crud.rb CHANGED
@@ -26,7 +26,7 @@ require 'runners/crud/operation'
26
26
  require 'runners/crud/verifier'
27
27
 
28
28
  def collection_data(collection)
29
- collection.find.to_a
29
+ collection.find.sort(_id: 1).to_a
30
30
  end
31
31
 
32
32
  def crud_execute_operations(spec, test, num_ops, event_subscriber, expect_error,
@@ -132,7 +132,6 @@ module Mongo
132
132
  @test_client ||= begin
133
133
  sdam_proc = lambda do |test_client|
134
134
  test_client.subscribe(Mongo::Monitoring::COMMAND, command_subscriber)
135
-
136
135
  test_client.subscribe(Mongo::Monitoring::TOPOLOGY_OPENING, sdam_subscriber)
137
136
  test_client.subscribe(Mongo::Monitoring::SERVER_OPENING, sdam_subscriber)
138
137
  test_client.subscribe(Mongo::Monitoring::SERVER_DESCRIPTION_CHANGED, sdam_subscriber)
@@ -321,6 +320,9 @@ module Mongo
321
320
  # without auto_encryption_options for querying results.
322
321
  result_collection_name = outcome&.collection_name || @spec.collection_name
323
322
  @result_collection = support_client.use(@spec.database_name)[result_collection_name]
323
+
324
+ # DRIVERS-2816, adjusted for legacy spec runner
325
+ @cluster_time = support_client.command(ping: 1).cluster_time
324
326
  end
325
327
 
326
328
  def teardown_test
@@ -358,12 +360,19 @@ module Mongo
358
360
  end
359
361
  end
360
362
 
363
+ def new_session(options)
364
+ test_client.start_session(options || {}).tap do |s|
365
+ # DRIVERS-2816, adjusted for legacy spec runner
366
+ s.advance_cluster_time(@cluster_time)
367
+ end
368
+ end
369
+
361
370
  def session0
362
- @session0 ||= test_client.start_session(@session_options[:session0] || {})
371
+ @session0 ||= new_session(@session_options[:session0])
363
372
  end
364
373
 
365
374
  def session1
366
- @session1 ||= test_client.start_session(@session_options[:session1] || {})
375
+ @session1 ||= new_session(@session_options[:session1])
367
376
  end
368
377
  end
369
378
  end
@@ -251,11 +251,11 @@ module Unified
251
251
  end
252
252
  when Hash
253
253
  if expected.keys == %w($$unsetOrMatches) && expected.values.first.keys == %w(insertedId)
254
- actual_v = actual.inserted_id
254
+ actual_v = get_actual_value(actual, 'inserted_id')
255
255
  expected_v = expected.values.first.values.first
256
256
  assert_value_matches(actual_v, expected_v, 'inserted_id')
257
257
  elsif expected.keys == %w(insertedId)
258
- actual_v = actual.inserted_id
258
+ actual_v = get_actual_value(actual, 'inserted_id')
259
259
  expected_v = expected.values.first
260
260
  assert_value_matches(actual_v, expected_v, 'inserted_id')
261
261
  else
@@ -270,7 +270,7 @@ module Unified
270
270
  if k.start_with?('$$')
271
271
  assert_value_matches(actual, expected, k)
272
272
  else
273
- actual_v = actual[k]
273
+ actual_v = get_actual_value(actual, k)
274
274
  if Hash === expected_v && expected_v.length == 1 && expected_v.keys.first.start_with?('$$')
275
275
  assert_value_matches(actual_v, expected_v, k)
276
276
  else
@@ -290,6 +290,19 @@ module Unified
290
290
  end
291
291
  end
292
292
 
293
+ # The actual value may be of different types depending on the operation.
294
+ # In order to avoid having to write a lot of code to handle the different
295
+ # types, we use this method to get the actual value.
296
+ def get_actual_value(actual, key)
297
+ if Hash === actual
298
+ actual[key]
299
+ elsif Mongo::Operation::Result === actual && !actual.respond_to?(key.to_sym)
300
+ actual.documents.first[key]
301
+ else
302
+ actual.send(key)
303
+ end
304
+ end
305
+
293
306
  def assert_type(object, type)
294
307
  ok = [*type].reduce(false) { |acc, x| acc || type_matches?(object, x) }
295
308
 
@@ -32,6 +32,18 @@ module Unified
32
32
  if session = args.use('session')
33
33
  opts[:session] = entities.get(:session, session)
34
34
  end
35
+ if collation = args.use('collation')
36
+ opts[:collation] = collation
37
+ end
38
+ if args.key?('noCursorTimeout')
39
+ opts[:no_cursor_timeout] = args.use('noCursorTimeout')
40
+ end
41
+ if args.key?('oplogReplay')
42
+ opts[:oplog_replay] = args.use('oplogReplay')
43
+ end
44
+ if args.key?('allowPartialResults')
45
+ opts[:allow_partial_results] = args.use('allowPartialResults')
46
+ end
35
47
  req = collection.find(args.use!('filter'), **opts)
36
48
  if batch_size = args.use('batchSize')
37
49
  req = req.batch_size(batch_size)
@@ -70,8 +70,7 @@ module Unified
70
70
  consume_test_runner(op)
71
71
  use_arguments(op) do |args|
72
72
  session = entities.get(:session, args.use!('session'))
73
- # https://jira.mongodb.org/browse/RUBY-1813
74
- true
73
+ session.dirty? || raise(Error::ResultMismatch, 'expected session to be dirty')
75
74
  end
76
75
  end
77
76
 
@@ -79,8 +78,7 @@ module Unified
79
78
  consume_test_runner(op)
80
79
  use_arguments(op) do |args|
81
80
  session = entities.get(:session, args.use!('session'))
82
- # https://jira.mongodb.org/browse/RUBY-1813
83
- true
81
+ session.dirty? && raise(Error::ResultMismatch, 'expected session to be not dirty')
84
82
  end
85
83
  end
86
84
 
@@ -92,7 +90,7 @@ module Unified
92
90
  unless subscriber.started_events.length >= 2
93
91
  raise Error::ResultMismatch, "Must have at least 2 events, have #{subscriber.started_events.length}"
94
92
  end
95
- lsids = subscriber.started_events[-2...-1].map do |cmd|
93
+ lsids = subscriber.started_events[-2..-1].map do |cmd|
96
94
  cmd.command.fetch('lsid')
97
95
  end
98
96
  if expected
@@ -227,7 +227,9 @@ module Unified
227
227
  opts = {}
228
228
  end
229
229
 
230
- client.start_session(**opts)
230
+ client.start_session(**opts).tap do |session|
231
+ session.advance_cluster_time(@cluster_time)
232
+ end
231
233
  when 'clientEncryption'
232
234
  client_encryption_opts = spec.use!('clientEncryptionOpts')
233
235
  key_vault_client = entities.get(:client, client_encryption_opts['keyVaultClient'])
@@ -342,6 +344,11 @@ module Unified
342
344
  raise NotImplementedError, "Unhandled spec keys: #{spec}"
343
345
  end
344
346
  end
347
+
348
+ # the cluster time is used to advance the cluster time of any
349
+ # sessions created during this test.
350
+ # -> see DRIVERS-2816
351
+ @cluster_time = root_authorized_client.command(ping: 1).cluster_time
345
352
  end
346
353
 
347
354
  def run
@@ -1,5 +1,5 @@
1
1
  runOn:
2
- - minServerVersion: "4.1.10"
2
+ - minServerVersion: "7.0.0"
3
3
  database_name: &database_name "default"
4
4
  collection_name: &collection_name "default"
5
5
 
@@ -54,4 +54,4 @@ tests:
54
54
  # Outcome is checked using a separate MongoClient without auto encryption.
55
55
  data:
56
56
  - *doc0_encrypted
57
- - *doc1_encrypted
57
+ - *doc1_encrypted
@@ -1,6 +1,7 @@
1
1
  # Requires libmongocrypt 1.8.0.
2
2
  runOn:
3
3
  - minServerVersion: "7.0.0"
4
+ maxServerVersion: "7.99.99"
4
5
  # Skip QEv2 (also referred to as FLE2v2) tests on Serverless. Unskip once Serverless enables the QEv2 protocol.
5
6
  # FLE 2 Encrypted collections are not supported on standalone.
6
7
  topology: [ "replicaset", "sharded", "load-balanced" ]
@@ -1,6 +1,7 @@
1
1
  # Requires libmongocrypt 1.8.0.
2
2
  runOn:
3
3
  - minServerVersion: "7.0.0"
4
+ maxServerVersion: "7.99.99"
4
5
  # Skip QEv2 (also referred to as FLE2v2) tests on Serverless. Unskip once Serverless enables the QEv2 protocol.
5
6
  # FLE 2 Encrypted collections are not supported on standalone.
6
7
  topology: [ "replicaset", "sharded", "load-balanced" ]
@@ -1,6 +1,7 @@
1
1
  # Requires libmongocrypt 1.8.0.
2
2
  runOn:
3
3
  - minServerVersion: "7.0.0"
4
+ maxServerVersion: "7.99.99"
4
5
  # Skip QEv2 (also referred to as FLE2v2) tests on Serverless. Unskip once Serverless enables the QEv2 protocol.
5
6
  # FLE 2 Encrypted collections are not supported on standalone.
6
7
  topology: [ "replicaset", "sharded", "load-balanced" ]
@@ -1,6 +1,7 @@
1
1
  # Requires libmongocrypt 1.8.0.
2
2
  runOn:
3
3
  - minServerVersion: "7.0.0"
4
+ maxServerVersion: "7.99.99"
4
5
  # Skip QEv2 (also referred to as FLE2v2) tests on Serverless. Unskip once Serverless enables the QEv2 protocol.
5
6
  # FLE 2 Encrypted collections are not supported on standalone.
6
7
  topology: [ "replicaset", "sharded", "load-balanced" ]
@@ -1,6 +1,7 @@
1
1
  # Requires libmongocrypt 1.8.0.
2
2
  runOn:
3
3
  - minServerVersion: "7.0.0"
4
+ maxServerVersion: "7.99.99"
4
5
  # Skip QEv2 (also referred to as FLE2v2) tests on Serverless. Unskip once Serverless enables the QEv2 protocol.
5
6
  # FLE 2 Encrypted collections are not supported on standalone.
6
7
  topology: [ "replicaset", "sharded", "load-balanced" ]
@@ -1,6 +1,7 @@
1
1
  # Requires libmongocrypt 1.8.0.
2
2
  runOn:
3
3
  - minServerVersion: "7.0.0"
4
+ maxServerVersion: "7.99.99"
4
5
  # Skip QEv2 (also referred to as FLE2v2) tests on Serverless. Unskip once Serverless enables the QEv2 protocol.
5
6
  # FLE 2 Encrypted collections are not supported on standalone.
6
7
  topology: [ "replicaset", "sharded", "load-balanced" ]
@@ -1,6 +1,7 @@
1
1
  # Requires libmongocrypt 1.8.0.
2
2
  runOn:
3
3
  - minServerVersion: "7.0.0"
4
+ maxServerVersion: "7.99.99"
4
5
  # Skip QEv2 (also referred to as FLE2v2) tests on Serverless. Unskip once Serverless enables the QEv2 protocol.
5
6
  # FLE 2 Encrypted collections are not supported on standalone.
6
7
  topology: [ "replicaset", "sharded", "load-balanced" ]
@@ -1,6 +1,7 @@
1
1
  # Requires libmongocrypt 1.8.0.
2
2
  runOn:
3
3
  - minServerVersion: "7.0.0"
4
+ maxServerVersion: "7.99.99"
4
5
  # Skip QEv2 (also referred to as FLE2v2) tests on Serverless. Unskip once Serverless enables the QEv2 protocol.
5
6
  # FLE 2 Encrypted collections are not supported on standalone.
6
7
  topology: [ "replicaset", "sharded", "load-balanced" ]
@@ -1,6 +1,7 @@
1
1
  # Requires libmongocrypt 1.8.0.
2
2
  runOn:
3
3
  - minServerVersion: "7.0.0"
4
+ maxServerVersion: "7.99.99"
4
5
  # Skip QEv2 (also referred to as FLE2v2) tests on Serverless. Unskip once Serverless enables the QEv2 protocol.
5
6
  # FLE 2 Encrypted collections are not supported on standalone.
6
7
  topology: [ "replicaset", "sharded", "load-balanced" ]
@@ -1,6 +1,7 @@
1
1
  # Requires libmongocrypt 1.8.0.
2
2
  runOn:
3
3
  - minServerVersion: "7.0.0"
4
+ maxServerVersion: "7.99.99"
4
5
  # Skip QEv2 (also referred to as FLE2v2) tests on Serverless. Unskip once Serverless enables the QEv2 protocol.
5
6
  # FLE 2 Encrypted collections are not supported on standalone.
6
7
  topology: [ "replicaset", "sharded", "load-balanced" ]
@@ -1,6 +1,7 @@
1
1
  # Requires libmongocrypt 1.8.0.
2
2
  runOn:
3
3
  - minServerVersion: "7.0.0"
4
+ maxServerVersion: "7.99.99"
4
5
  # Skip QEv2 (also referred to as FLE2v2) tests on Serverless. Unskip once Serverless enables the QEv2 protocol.
5
6
  # FLE 2 Encrypted collections are not supported on standalone.
6
7
  topology: [ "replicaset", "sharded", "load-balanced" ]
@@ -1,6 +1,7 @@
1
1
  # Requires libmongocrypt 1.8.0.
2
2
  runOn:
3
3
  - minServerVersion: "7.0.0"
4
+ maxServerVersion: "7.99.99"
4
5
  # Skip QEv2 (also referred to as FLE2v2) tests on Serverless. Unskip once Serverless enables the QEv2 protocol.
5
6
  # FLE 2 Encrypted collections are not supported on standalone.
6
7
  topology: [ "replicaset", "sharded", "load-balanced" ]
@@ -1,6 +1,7 @@
1
1
  # Requires libmongocrypt 1.8.0.
2
2
  runOn:
3
3
  - minServerVersion: "7.0.0"
4
+ maxServerVersion: "7.99.99"
4
5
  # Skip QEv2 (also referred to as FLE2v2) tests on Serverless. Unskip once Serverless enables the QEv2 protocol.
5
6
  # FLE 2 Encrypted collections are not supported on standalone.
6
7
  topology: [ "replicaset", "sharded", "load-balanced" ]
@@ -2,6 +2,7 @@
2
2
  # Requires libmongocrypt 1.8.0.
3
3
  runOn:
4
4
  - minServerVersion: "7.0.0"
5
+ maxServerVersion: "7.99.99"
5
6
  # Skip QEv2 (also referred to as FLE2v2) tests on Serverless. Unskip once Serverless enables the QEv2 protocol.
6
7
  # FLE 2 Encrypted collections are not supported on standalone.
7
8
  topology: [ "replicaset", "sharded", "load-balanced" ]
@@ -4,6 +4,7 @@
4
4
  # Requires libmongocrypt 1.8.0.
5
5
  runOn:
6
6
  - minServerVersion: "7.0.0"
7
+ maxServerVersion: "7.99.99"
7
8
  # Skip QEv2 (also referred to as FLE2v2) tests on Serverless. Unskip once Serverless enables the QEv2 protocol.
8
9
  # FLE 2 Encrypted collections are not supported on standalone.
9
10
  topology: [ "replicaset", "sharded", "load-balanced" ]
@@ -2,6 +2,7 @@
2
2
  # Requires libmongocrypt 1.8.0.
3
3
  runOn:
4
4
  - minServerVersion: "7.0.0"
5
+ maxServerVersion: "7.99.99"
5
6
  # Skip QEv2 (also referred to as FLE2v2) tests on Serverless. Unskip once Serverless enables the QEv2 protocol.
6
7
  # FLE 2 Encrypted collections are not supported on standalone.
7
8
  topology: [ "replicaset", "sharded", "load-balanced" ]
@@ -2,6 +2,7 @@
2
2
  # Requires libmongocrypt 1.8.0.
3
3
  runOn:
4
4
  - minServerVersion: "7.0.0"
5
+ maxServerVersion: "7.99.99"
5
6
  # Skip QEv2 (also referred to as FLE2v2) tests on Serverless. Unskip once Serverless enables the QEv2 protocol.
6
7
  # FLE 2 Encrypted collections are not supported on standalone.
7
8
  topology: [ "replicaset", "sharded", "load-balanced" ]