mongo 2.9.2 → 2.10.0.rc0

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 (227) 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.rb +1 -0
  5. data/lib/mongo/auth/user/view.rb +4 -4
  6. data/lib/mongo/bulk_write.rb +14 -8
  7. data/lib/mongo/bulk_write/result.rb +1 -1
  8. data/lib/mongo/bulk_write/result_combiner.rb +2 -2
  9. data/lib/mongo/bulk_write/transformable.rb +17 -9
  10. data/lib/mongo/client.rb +107 -16
  11. data/lib/mongo/cluster.rb +47 -25
  12. data/lib/mongo/cluster/topology/replica_set_no_primary.rb +1 -1
  13. data/lib/mongo/cluster_time.rb +139 -0
  14. data/lib/mongo/collection.rb +84 -25
  15. data/lib/mongo/collection/view.rb +7 -3
  16. data/lib/mongo/collection/view/aggregation.rb +4 -4
  17. data/lib/mongo/collection/view/builder/aggregation.rb +31 -6
  18. data/lib/mongo/collection/view/builder/find_command.rb +4 -1
  19. data/lib/mongo/collection/view/builder/map_reduce.rb +4 -1
  20. data/lib/mongo/collection/view/change_stream.rb +54 -66
  21. data/lib/mongo/collection/view/iterable.rb +2 -2
  22. data/lib/mongo/collection/view/map_reduce.rb +6 -4
  23. data/lib/mongo/collection/view/readable.rb +36 -16
  24. data/lib/mongo/collection/view/writable.rb +68 -22
  25. data/lib/mongo/cursor.rb +87 -20
  26. data/lib/mongo/database.rb +47 -43
  27. data/lib/mongo/database/view.rb +54 -11
  28. data/lib/mongo/error.rb +13 -4
  29. data/lib/mongo/error/invalid_write_concern.rb +2 -2
  30. data/lib/mongo/error/operation_failure.rb +65 -11
  31. data/lib/mongo/error/parser.rb +41 -8
  32. data/lib/mongo/grid/fs_bucket.rb +26 -6
  33. data/lib/mongo/grid/stream/read.rb +9 -2
  34. data/lib/mongo/grid/stream/write.rb +21 -5
  35. data/lib/mongo/index/view.rb +3 -3
  36. data/lib/mongo/lint.rb +10 -3
  37. data/lib/mongo/operation.rb +2 -0
  38. data/lib/mongo/operation/aggregate/result.rb +19 -6
  39. data/lib/mongo/operation/collections_info.rb +1 -1
  40. data/lib/mongo/operation/get_more/result.rb +9 -0
  41. data/lib/mongo/operation/list_collections/command.rb +1 -3
  42. data/lib/mongo/operation/list_collections/op_msg.rb +1 -2
  43. data/lib/mongo/operation/parallel_scan/command.rb +4 -1
  44. data/lib/mongo/operation/parallel_scan/op_msg.rb +4 -1
  45. data/lib/mongo/operation/result.rb +27 -4
  46. data/lib/mongo/operation/shared/executable.rb +19 -5
  47. data/lib/mongo/operation/shared/executable_no_validate.rb +1 -2
  48. data/lib/mongo/operation/shared/executable_transaction_label.rb +0 -9
  49. data/lib/mongo/operation/shared/polymorphic_result.rb +9 -1
  50. data/lib/mongo/operation/shared/result/aggregatable.rb +2 -2
  51. data/lib/mongo/operation/shared/sessions_supported.rb +42 -32
  52. data/lib/mongo/operation/shared/specifiable.rb +40 -0
  53. data/lib/mongo/operation/shared/unpinnable.rb +39 -0
  54. data/lib/mongo/operation/shared/write.rb +1 -1
  55. data/lib/mongo/protocol/update.rb +6 -2
  56. data/lib/mongo/retryable.rb +79 -39
  57. data/lib/mongo/server/connection.rb +10 -3
  58. data/lib/mongo/server/description.rb +25 -1
  59. data/lib/mongo/server/monitor/connection.rb +1 -1
  60. data/lib/mongo/server_selector.rb +10 -0
  61. data/lib/mongo/server_selector/selectable.rb +172 -32
  62. data/lib/mongo/session.rb +654 -581
  63. data/lib/mongo/session/session_pool.rb +1 -1
  64. data/lib/mongo/socket.rb +7 -28
  65. data/lib/mongo/socket/ssl.rb +26 -1
  66. data/lib/mongo/socket/tcp.rb +3 -0
  67. data/lib/mongo/socket/unix.rb +3 -0
  68. data/lib/mongo/uri.rb +112 -265
  69. data/lib/mongo/uri/srv_protocol.rb +4 -1
  70. data/lib/mongo/version.rb +1 -1
  71. data/lib/mongo/write_concern.rb +10 -29
  72. data/lib/mongo/write_concern/acknowledged.rb +12 -0
  73. data/lib/mongo/write_concern/base.rb +17 -13
  74. data/lib/mongo/write_concern/unacknowledged.rb +12 -0
  75. data/spec/atlas/atlas_connectivity_spec.rb +7 -37
  76. data/spec/atlas/operations_spec.rb +25 -0
  77. data/spec/integration/change_stream_examples_spec.rb +45 -31
  78. data/spec/integration/change_stream_spec.rb +305 -5
  79. data/spec/integration/client_spec.rb +44 -0
  80. data/spec/integration/command_monitoring_spec.rb +1 -0
  81. data/spec/integration/command_spec.rb +7 -1
  82. data/spec/integration/mmapv1_spec.rb +28 -0
  83. data/spec/integration/mongos_pinning_spec.rb +34 -0
  84. data/spec/integration/operation_failure_code_spec.rb +2 -2
  85. data/spec/integration/{read_concern.rb → read_concern_spec.rb} +7 -1
  86. data/spec/integration/read_preference_spec.rb +485 -0
  87. data/spec/integration/retryable_writes_spec.rb +8 -19
  88. data/spec/integration/sdam_error_handling_spec.rb +1 -1
  89. data/spec/integration/sdam_events_spec.rb +2 -2
  90. data/spec/integration/server_description_spec.rb +14 -17
  91. data/spec/integration/server_selector_spec.rb +7 -3
  92. data/spec/integration/server_spec.rb +48 -0
  93. data/spec/integration/ssl_uri_options_spec.rb +1 -1
  94. data/spec/integration/step_down_spec.rb +10 -4
  95. data/spec/integration/transactions_examples_spec.rb +11 -10
  96. data/spec/lite_spec_helper.rb +19 -16
  97. data/spec/mongo/auth/scram/negotiation_spec.rb +11 -8
  98. data/spec/mongo/bulk_write/ordered_combiner_spec.rb +6 -6
  99. data/spec/mongo/bulk_write/unordered_combiner_spec.rb +4 -4
  100. data/spec/mongo/bulk_write_spec.rb +12 -2
  101. data/spec/mongo/client_construction_spec.rb +160 -8
  102. data/spec/mongo/client_spec.rb +5 -4
  103. data/spec/mongo/cluster_spec.rb +6 -6
  104. data/spec/mongo/cluster_time_spec.rb +148 -0
  105. data/spec/mongo/collection/view/aggregation_spec.rb +34 -15
  106. data/spec/mongo/collection/view/change_stream_spec.rb +62 -3
  107. data/spec/mongo/collection/view/map_reduce_spec.rb +7 -5
  108. data/spec/mongo/collection/view/readable_spec.rb +4 -4
  109. data/spec/mongo/collection_spec.rb +331 -14
  110. data/spec/mongo/cursor_spec.rb +117 -5
  111. data/spec/mongo/database_spec.rb +240 -8
  112. data/spec/mongo/error/operation_failure_spec.rb +47 -1
  113. data/spec/mongo/error/parser_spec.rb +160 -23
  114. data/spec/mongo/operation/insert/bulk_spec.rb +2 -1
  115. data/spec/mongo/operation/result_spec.rb +27 -0
  116. data/spec/mongo/operation/update/bulk_spec.rb +1 -0
  117. data/spec/mongo/retryable_spec.rb +2 -0
  118. data/spec/mongo/server/app_metadata_spec.rb +2 -2
  119. data/spec/mongo/server/connection_spec.rb +13 -17
  120. data/spec/mongo/server/monitor/connection_spec.rb +13 -10
  121. data/spec/mongo/server_selector_spec.rb +34 -2
  122. data/spec/mongo/session/session_pool_spec.rb +14 -3
  123. data/spec/mongo/session_spec.rb +3 -3
  124. data/spec/mongo/session_transaction_spec.rb +4 -3
  125. data/spec/mongo/socket/ssl_spec.rb +19 -5
  126. data/spec/mongo/socket_spec.rb +1 -62
  127. data/spec/mongo/uri/srv_protocol_spec.rb +14 -20
  128. data/spec/mongo/uri_option_parsing_spec.rb +94 -8
  129. data/spec/mongo/uri_spec.rb +23 -10
  130. data/spec/mongo/write_concern_spec.rb +56 -3
  131. data/spec/spec_tests/change_streams_spec.rb +2 -1
  132. data/spec/spec_tests/cmap_spec.rb +1 -1
  133. data/spec/spec_tests/crud_spec.rb +12 -2
  134. data/spec/spec_tests/data/change_streams/change-streams-errors.yml +24 -1
  135. data/spec/spec_tests/data/change_streams/change-streams.yml +172 -3
  136. data/spec/spec_tests/data/command_monitoring/bulkWrite.yml +1 -1
  137. data/spec/spec_tests/data/command_monitoring/updateMany.yml +0 -2
  138. data/spec/spec_tests/data/command_monitoring/updateOne.yml +0 -5
  139. data/spec/spec_tests/data/crud/read/aggregate-out.yml +0 -6
  140. data/spec/spec_tests/data/crud/read/count-empty.yml +29 -0
  141. data/spec/spec_tests/data/crud/write/bulkWrite-arrayFilters.yml +1 -0
  142. data/spec/spec_tests/data/crud/write/bulkWrite-collation.yml +101 -0
  143. data/spec/spec_tests/data/crud/write/bulkWrite.yml +401 -0
  144. data/spec/spec_tests/data/crud/write/insertMany.yml +58 -2
  145. data/spec/spec_tests/data/crud/write/updateMany-arrayFilters.yml +3 -0
  146. data/spec/spec_tests/data/crud/write/updateOne-arrayFilters.yml +6 -1
  147. data/spec/spec_tests/data/crud_v2/aggregate-merge.yml +103 -0
  148. data/spec/spec_tests/data/crud_v2/aggregate-out-readConcern.yml +110 -0
  149. data/spec/spec_tests/data/crud_v2/bulkWrite-arrayFilters.yml +81 -0
  150. data/spec/spec_tests/data/crud_v2/db-aggregate.yml +38 -0
  151. data/spec/spec_tests/data/crud_v2/updateWithPipelines.yml +92 -0
  152. data/spec/spec_tests/data/retryable_writes/insertOne-serverErrors.yml +2 -2
  153. data/spec/spec_tests/data/transactions/abort.yml +3 -0
  154. data/spec/spec_tests/data/transactions/bulk.yml +3 -8
  155. data/spec/spec_tests/data/transactions/causal-consistency.yml +3 -8
  156. data/spec/spec_tests/data/transactions/commit.yml +3 -1
  157. data/spec/spec_tests/data/transactions/count.yml +3 -0
  158. data/spec/spec_tests/data/transactions/delete.yml +3 -0
  159. data/spec/spec_tests/data/transactions/error-labels.yml +4 -1
  160. data/spec/spec_tests/data/transactions/errors-client.yml +56 -0
  161. data/spec/spec_tests/data/transactions/errors.yml +3 -0
  162. data/spec/spec_tests/data/transactions/findOneAndDelete.yml +3 -0
  163. data/spec/spec_tests/data/transactions/findOneAndReplace.yml +3 -0
  164. data/spec/spec_tests/data/transactions/findOneAndUpdate.yml +3 -0
  165. data/spec/spec_tests/data/transactions/insert.yml +3 -0
  166. data/spec/spec_tests/data/transactions/isolation.yml +3 -0
  167. data/spec/spec_tests/data/transactions/mongos-pin-auto.yml +1671 -0
  168. data/spec/spec_tests/data/transactions/mongos-recovery-token.yml +347 -0
  169. data/spec/spec_tests/data/transactions/pin-mongos.yml +557 -0
  170. data/spec/spec_tests/data/transactions/read-concern.yml +3 -0
  171. data/spec/spec_tests/data/transactions/read-pref.yml +3 -0
  172. data/spec/spec_tests/data/transactions/reads.yml +3 -0
  173. data/spec/spec_tests/data/transactions/retryable-abort.yml +5 -2
  174. data/spec/spec_tests/data/transactions/retryable-commit.yml +4 -1
  175. data/spec/spec_tests/data/transactions/retryable-writes.yml +3 -0
  176. data/spec/spec_tests/data/transactions/run-command.yml +3 -0
  177. data/spec/spec_tests/data/transactions/transaction-options.yml +6 -0
  178. data/spec/spec_tests/data/transactions/update.yml +3 -8
  179. data/spec/spec_tests/data/transactions/write-concern.yml +348 -38
  180. data/spec/spec_tests/data/transactions_api/callback-aborts.yml +6 -0
  181. data/spec/spec_tests/data/transactions_api/callback-commits.yml +5 -0
  182. data/spec/spec_tests/data/transactions_api/callback-retry.yml +7 -2
  183. data/spec/spec_tests/data/transactions_api/commit-retry.yml +70 -15
  184. data/spec/spec_tests/data/transactions_api/commit-transienttransactionerror-4.2.yml +3 -0
  185. data/spec/spec_tests/data/transactions_api/commit-transienttransactionerror.yml +3 -0
  186. data/spec/spec_tests/data/transactions_api/commit-writeconcernerror.yml +59 -109
  187. data/spec/spec_tests/data/transactions_api/commit.yml +5 -0
  188. data/spec/spec_tests/data/transactions_api/transaction-options.yml +10 -0
  189. data/spec/spec_tests/retryable_reads_spec.rb +5 -2
  190. data/spec/spec_tests/retryable_writes_spec.rb +5 -2
  191. data/spec/spec_tests/sdam_monitoring_spec.rb +3 -3
  192. data/spec/spec_tests/sdam_spec.rb +2 -2
  193. data/spec/spec_tests/transactions_api_spec.rb +1 -67
  194. data/spec/spec_tests/transactions_spec.rb +2 -66
  195. data/spec/support/authorization.rb +4 -0
  196. data/spec/support/change_streams.rb +30 -10
  197. data/spec/support/change_streams/operation.rb +27 -0
  198. data/spec/support/client_registry.rb +44 -25
  199. data/spec/support/cluster_config.rb +25 -14
  200. data/spec/support/cluster_tools.rb +32 -10
  201. data/spec/support/command_monitoring.rb +1 -1
  202. data/spec/support/common_shortcuts.rb +30 -0
  203. data/spec/support/connection_string.rb +8 -3
  204. data/spec/support/constraints.rb +34 -0
  205. data/spec/support/crud.rb +31 -16
  206. data/spec/support/crud/context.rb +23 -0
  207. data/spec/support/crud/operation.rb +311 -14
  208. data/spec/support/crud/spec.rb +2 -1
  209. data/spec/support/crud/test.rb +24 -27
  210. data/spec/support/crud/test_base.rb +22 -0
  211. data/spec/support/crud/verifier.rb +15 -1
  212. data/spec/support/event_subscriber.rb +12 -0
  213. data/spec/support/sdam_formatter_integration.rb +12 -6
  214. data/spec/support/shared/server_selector.rb +10 -0
  215. data/spec/support/shared/session.rb +13 -12
  216. data/spec/support/spec_config.rb +32 -22
  217. data/spec/support/spec_setup.rb +2 -2
  218. data/spec/support/transactions.rb +87 -0
  219. data/spec/support/transactions/context.rb +33 -0
  220. data/spec/support/transactions/operation.rb +99 -349
  221. data/spec/support/transactions/spec.rb +1 -3
  222. data/spec/support/transactions/test.rb +110 -49
  223. data/spec/support/utils.rb +74 -1
  224. metadata +52 -10
  225. metadata.gz.sig +0 -0
  226. data/spec/support/crud/read.rb +0 -265
  227. data/spec/support/crud/write.rb +0 -284
@@ -2,6 +2,9 @@ runOn:
2
2
  -
3
3
  minServerVersion: "4.0"
4
4
  topology: ["replicaset"]
5
+ -
6
+ minServerVersion: "4.1.8"
7
+ topology: ["sharded"]
5
8
 
6
9
  database_name: &database_name "withTransaction-tests"
7
10
  collection_name: &collection_name "test"
@@ -11,6 +14,7 @@ data: []
11
14
  tests:
12
15
  -
13
16
  description: withTransaction commits after callback returns
17
+ useMultipleMongoses: true
14
18
  operations:
15
19
  -
16
20
  name: withTransaction
@@ -91,6 +95,7 @@ tests:
91
95
  # withTransaction only examines the session's state, it should commit that
92
96
  # second transaction after the callback returns.
93
97
  description: withTransaction commits after callback returns (second transaction)
98
+ useMultipleMongoses: true
94
99
  operations:
95
100
  -
96
101
  name: withTransaction
@@ -2,6 +2,10 @@ runOn:
2
2
  -
3
3
  minServerVersion: "4.0"
4
4
  topology: ["replicaset"]
5
+ # Disabled due to https://jira.mongodb.org/browse/SERVER-41532
6
+ #-
7
+ # minServerVersion: "4.1.8"
8
+ # topology: ["sharded"]
5
9
 
6
10
  database_name: &database_name "withTransaction-tests"
7
11
  collection_name: &collection_name "test"
@@ -11,6 +15,7 @@ data: []
11
15
  tests:
12
16
  -
13
17
  description: withTransaction and no transaction options set
18
+ useMultipleMongoses: true
14
19
  operations: &operations
15
20
  -
16
21
  name: withTransaction
@@ -62,6 +67,7 @@ tests:
62
67
  - { _id: 1 }
63
68
  -
64
69
  description: withTransaction inherits transaction options from client
70
+ useMultipleMongoses: true
65
71
  clientOptions:
66
72
  readConcernLevel: local
67
73
  w: 1
@@ -99,6 +105,7 @@ tests:
99
105
  outcome: *outcome
100
106
  -
101
107
  description: withTransaction inherits transaction options from defaultTransactionOptions
108
+ useMultipleMongoses: true
102
109
  sessionOptions:
103
110
  session0:
104
111
  defaultTransactionOptions:
@@ -138,6 +145,7 @@ tests:
138
145
  outcome: *outcome
139
146
  -
140
147
  description: withTransaction explicit transaction options
148
+ useMultipleMongoses: true
141
149
  operations: &operations_explicit_transactionOptions
142
150
  -
143
151
  name: withTransaction
@@ -189,6 +197,7 @@ tests:
189
197
  outcome: *outcome
190
198
  -
191
199
  description: withTransaction explicit transaction options override defaultTransactionOptions
200
+ useMultipleMongoses: true
192
201
  sessionOptions:
193
202
  session0:
194
203
  defaultTransactionOptions:
@@ -228,6 +237,7 @@ tests:
228
237
  outcome: *outcome
229
238
  -
230
239
  description: withTransaction explicit transaction options override client options
240
+ useMultipleMongoses: true
231
241
  clientOptions:
232
242
  readConcernLevel: majority
233
243
  w: majority
@@ -1,7 +1,10 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe do
4
- define_crud_spec_tests('Retryable reads spec tests', RETRYABLE_READS_TESTS.sort) do |spec, req, test|
3
+ describe 'Retryable reads spec tests' do
4
+ require_wired_tiger
5
+ require_no_multi_shard
6
+
7
+ define_crud_spec_tests(RETRYABLE_READS_TESTS) do |spec, req, test|
5
8
  let(:client) do
6
9
  root_authorized_client.with({max_read_retries: 0}.update(test.client_options)).tap do |client|
7
10
  client.subscribe(Mongo::Monitoring::COMMAND, event_subscriber)
@@ -1,7 +1,10 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe do
4
- define_crud_spec_tests('Retryable writes spec tests', RETRYABLE_WRITES_TESTS.sort) do |spec, req, test|
3
+ describe 'Retryable writes spec tests' do
4
+ require_wired_tiger
5
+ require_no_multi_shard
6
+
7
+ define_crud_spec_tests(RETRYABLE_WRITES_TESTS) do |spec, req, test|
5
8
  let(:client) do
6
9
  authorized_client_with_retry_writes
7
10
  end
@@ -18,8 +18,8 @@ describe 'SDAM Monitoring' do
18
18
  client.subscribe(Mongo::Monitoring::TOPOLOGY_OPENING, @subscriber)
19
19
  client.subscribe(Mongo::Monitoring::TOPOLOGY_CHANGED, @subscriber)
20
20
  end
21
- @client = Mongo::Client.new(spec.uri_string,
22
- sdam_proc: sdam_proc, monitoring_io: false,
21
+ @client = new_local_client_nmio(spec.uri_string,
22
+ sdam_proc: sdam_proc,
23
23
  heartbeat_frequency: 100, connect_timeout: 0.1)
24
24
  # We do not want to create servers when an event referencing them
25
25
  # is processed, because this may result in server duplication
@@ -33,7 +33,7 @@ describe 'SDAM Monitoring' do
33
33
  end
34
34
 
35
35
  after(:all) do
36
- @client.close
36
+ @client.close(true)
37
37
  end
38
38
 
39
39
  spec.phases.each_with_index do |phase, phase_index|
@@ -36,7 +36,7 @@ describe 'Server Discovery and Monitoring' do
36
36
  end
37
37
 
38
38
  after(:all) do
39
- @client && @client.close
39
+ @client && @client.close(true)
40
40
  end
41
41
 
42
42
  spec.phases.each_with_index do |phase, index|
@@ -160,7 +160,7 @@ describe 'Server Discovery and Monitoring' do
160
160
 
161
161
  it 'raises an UnsupportedFeatures error' do
162
162
  expect {
163
- p = Mongo::ServerSelector.get(mode: :primary).select_server(@client.cluster)
163
+ p = Mongo::ServerSelector.primary.select_server(@client.cluster)
164
164
  s = Mongo::ServerSelector.get(mode: :secondary).select_server(@client.cluster)
165
165
  raise "UnsupportedFeatures not raised but we got #{p.inspect} as primary and #{s.inspect} as secondary"
166
166
  }.to raise_exception(Mongo::Error::UnsupportedFeatures)
@@ -1,71 +1,5 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe 'Transactions API' do
4
-
5
- TRANSACTIONS_API_TESTS.sort.each do |file|
6
-
7
- spec = Mongo::Transactions::Spec.new(file)
8
-
9
- context(spec.description) do
10
- define_spec_tests_with_requirements(spec) do |req|
11
- spec.tests.each do |test_factory|
12
- test_instance = test_factory.call
13
-
14
- context(test_instance.description) do
15
-
16
- let(:test) { test_factory.call }
17
-
18
- if test_instance.skip_reason
19
- before do
20
- skip test_instance.skip_reason
21
- end
22
- end
23
-
24
- before(:each) do
25
- if req.satisfied?
26
- test.setup_test
27
- end
28
- end
29
-
30
- after(:each) do
31
- if req.satisfied?
32
- test.teardown_test
33
- end
34
- end
35
-
36
- let(:results) do
37
- test.run
38
- end
39
-
40
- let(:verifier) { Mongo::CRUD::Verifier.new(test) }
41
-
42
- it 'returns the correct result' do
43
- verifier.verify_operation_result(test_instance.expected_results, results[:results])
44
- end
45
-
46
- it 'has the correct data in the collection', if: test_instance.outcome.collection_data? do
47
- results
48
- verifier.verify_collection_data(
49
- test_instance.outcome.collection_data,
50
- results[:contents])
51
- end
52
-
53
- if test_instance.expectations
54
- it 'has the correct number of command_started events' do
55
- verifier.verify_command_started_event_count(
56
- test_instance.expectations, results[:events])
57
- end
58
-
59
- test_instance.expectations.each_with_index do |expectation, i|
60
- it "has the correct command_started event #{i}" do
61
- verifier.verify_command_started_event(
62
- test_instance.expectations, results[:events], i)
63
- end
64
- end
65
- end
66
- end
67
- end
68
- end
69
- end
70
- end
4
+ define_transactions_spec_tests(TRANSACTIONS_API_TESTS)
71
5
  end
@@ -1,71 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe 'Transactions' do
4
+ clean_slate_on_evergreen
4
5
 
5
- TRANSACTIONS_TESTS.sort.each do |file|
6
-
7
- spec = Mongo::Transactions::Spec.new(file)
8
-
9
- context(spec.description) do
10
- define_spec_tests_with_requirements(spec) do |req|
11
- spec.tests.each do |test_factory|
12
- test_instance = test_factory.call
13
-
14
- context(test_instance.description) do
15
-
16
- let(:test) { test_factory.call }
17
-
18
- if test_instance.skip_reason
19
- before do
20
- skip test_instance.skip_reason
21
- end
22
- end
23
-
24
- before(:each) do
25
- if req.satisfied?
26
- test.setup_test
27
- end
28
- end
29
-
30
- after(:each) do
31
- if req.satisfied?
32
- test.teardown_test
33
- end
34
- end
35
-
36
- let(:results) do
37
- test.run
38
- end
39
-
40
- let(:verifier) { Mongo::CRUD::Verifier.new(test) }
41
-
42
- it 'returns the correct result' do
43
- verifier.verify_operation_result(test_instance.expected_results, results[:results])
44
- end
45
-
46
- it 'has the correct data in the collection', if: test_instance.outcome && test_instance.outcome.collection_data? do
47
- results
48
- verifier.verify_collection_data(
49
- test_instance.outcome.collection_data,
50
- results[:contents])
51
- end
52
-
53
- if test_instance.expectations
54
- it 'has the correct number of command_started events' do
55
- verifier.verify_command_started_event_count(
56
- test_instance.expectations, results[:events])
57
- end
58
-
59
- test_instance.expectations.each_with_index do |expectation, i|
60
- it "has the correct command_started event #{i}" do
61
- verifier.verify_command_started_event(
62
- test_instance.expectations, results[:events], i)
63
- end
64
- end
65
- end
66
- end
67
- end
68
- end
69
- end
70
- end
6
+ define_transactions_spec_tests(TRANSACTIONS_TESTS)
71
7
  end
@@ -111,6 +111,10 @@ module Authorization
111
111
  # @since 2.0.0
112
112
  context.let(:root_authorized_client) { ClientRegistry.instance.global_client('root_authorized') }
113
113
 
114
+ context.let(:root_authorized_admin_client) do
115
+ ClientRegistry.instance.global_client('root_authorized').use(:admin)
116
+ end
117
+
114
118
  # Gets the default test collection from the authorized client.
115
119
  #
116
120
  # @since 2.0.0
@@ -77,6 +77,11 @@ module Mongo
77
77
  # @since 2.0.0
78
78
  attr_reader :description
79
79
 
80
+ # Optional list of command-started events in Extended JSON format
81
+ #
82
+ # @return [ Array<Hash> ] The list of command-started events
83
+ attr_reader :expectations
84
+
80
85
  def initialize(test, coll1, coll2, db1, db2)
81
86
  @description = test['description']
82
87
  @min_server_version = test['minServerVersion']
@@ -132,22 +137,36 @@ module Mongo
132
137
  }
133
138
  end
134
139
 
140
+ # JRuby must iterate the same object, not switch from
141
+ # enum to change stream
142
+ enum = change_stream.to_enum
143
+
135
144
  @operations.each do |op|
136
145
  op.execute(@db1, @db2)
137
146
  end
138
147
 
139
- changes = [].tap do |changes|
140
- next unless @result['success']
148
+ changes = []
141
149
 
142
- unless @result['success'].empty?
143
- change_stream.take_while do |change|
144
- changes << change
145
- changes.length < @result['success'].length
146
- end
147
- end
150
+ # attempt first next call (catch NonResumableChangeStreamError errors)
151
+ begin
152
+ change = enum.next
153
+ changes << change
154
+ rescue Mongo::Error::OperationFailure => e
155
+ return {
156
+ result: { 'error' => { 'code' => e.code, 'errorLabels' => e.labels} },
157
+ events: events
158
+ }
159
+ end
160
+
161
+ # continue until changeStream has received as many changes as there
162
+ # are in result.success
163
+ if @result['success'] && changes.length < @result['success'].length
164
+ while changes.length < @result['success'].length
165
+ changes << enum.next
166
+ end
167
+ end
148
168
 
149
- change_stream.close
150
- end
169
+ change_stream.close
151
170
 
152
171
  {
153
172
  result: { 'success' => changes },
@@ -204,6 +223,7 @@ module Mongo
204
223
 
205
224
  def match_array?(expected, actual)
206
225
  return false unless actual.is_a?(Array)
226
+ return false unless expected.length == actual.length
207
227
 
208
228
  expected.each_with_index.all? do |e, i|
209
229
  actual[i] && match?(e, actual[i])
@@ -50,6 +50,29 @@ module Mongo
50
50
  coll.insert_one(document)
51
51
  end
52
52
 
53
+ def update_one(coll)
54
+ coll.update_one(filter, arguments['update'])
55
+ end
56
+
57
+ def replace_one(coll)
58
+ coll.replace_one(filter, arguments['replacement'])
59
+ end
60
+
61
+ def delete_one(coll)
62
+ coll.delete_one(filter)
63
+ end
64
+
65
+ def drop(coll)
66
+ coll.drop
67
+ end
68
+
69
+ def rename(coll)
70
+ coll.client.use(:admin).command({
71
+ renameCollection: "#{coll.database.name}.#{coll.name}",
72
+ to: "#{coll.database.name}.#{arguments['to']}"
73
+ })
74
+ end
75
+
53
76
  def arguments
54
77
  @spec['arguments']
55
78
  end
@@ -57,6 +80,10 @@ module Mongo
57
80
  def document
58
81
  arguments['document']
59
82
  end
83
+
84
+ def filter
85
+ arguments['filter']
86
+ end
60
87
  end
61
88
  end
62
89
  end
@@ -45,24 +45,38 @@ class ClientRegistry
45
45
  # clients global to the test suite, should not be closed in an after hooks
46
46
  # but their monitoring may need to be suspended/resumed
47
47
  @global_clients = {}
48
+
49
+ # JRuby appears to somehow manage to access client registry concurrently
50
+ @lock = Mutex.new
48
51
  end
49
52
 
50
- def global_client(name)
51
- if client = @global_clients[name]
53
+ class << self
54
+ def client_perished?(client)
52
55
  if !client.cluster.connected?
53
- reconnect = true
56
+ true
54
57
  else
55
- reconnect = false
58
+ perished = false
56
59
  client.cluster.servers_list.each do |server|
57
60
  thread = server.monitor.instance_variable_get('@thread')
58
61
  if thread.nil? || !thread.alive?
59
- reconnect = true
62
+ perished = true
60
63
  end
61
64
  end
65
+ perished
62
66
  end
63
- if reconnect
67
+ end
68
+ private :client_perished?
69
+
70
+ def reconnect_client_if_perished(client)
71
+ if client_perished?(client)
64
72
  client.reconnect
65
73
  end
74
+ end
75
+ end
76
+
77
+ def global_client(name)
78
+ if client = @global_clients[name]
79
+ self.class.reconnect_client_if_perished(client)
66
80
  return client
67
81
  end
68
82
 
@@ -122,6 +136,15 @@ class ClientRegistry
122
136
  ).tap do |client|
123
137
  client.subscribe(Mongo::Monitoring::COMMAND, EventSubscriber)
124
138
  end
139
+ # Provides an authorized mongo client that does not retry writes
140
+ # using either modern or legacy mechanisms.
141
+ when 'authorized_without_any_retry_writes'
142
+ global_client('authorized').with(
143
+ retry_writes: false, max_write_retries: 0,
144
+ server_selection_timeout: 4.99,
145
+ ).tap do |client|
146
+ client.subscribe(Mongo::Monitoring::COMMAND, EventSubscriber)
147
+ end
125
148
  # Provides an authorized mongo client that does not retry reads or writes
126
149
  # at all.
127
150
  when 'authorized_without_any_retries'
@@ -152,19 +175,6 @@ class ClientRegistry
152
175
  monitoring: false
153
176
  ),
154
177
  )
155
- # Get an authorized client on the admin database logged in as the admin
156
- # root user.
157
- when 'root_authorized_admin'
158
- Mongo::Client.new(
159
- SpecConfig.instance.addresses,
160
- SpecConfig.instance.test_options.merge(
161
- user: SpecConfig.instance.root_user.name,
162
- password: SpecConfig.instance.root_user.password,
163
- database: 'admin',
164
- auth_source: SpecConfig.instance.auth_source || Mongo::Database::ADMIN,
165
- monitoring: false
166
- ),
167
- )
168
178
  # A client that has an event subscriber for commands.
169
179
  when 'subscribed'
170
180
  Mongo::Client.new(
@@ -184,24 +194,33 @@ class ClientRegistry
184
194
 
185
195
  def new_local_client(*args)
186
196
  Mongo::Client.new(*args).tap do |client|
187
- @local_clients << client
197
+ @lock.synchronize do
198
+ @local_clients << client
199
+ end
188
200
  end
189
201
  end
190
202
 
191
203
  def register_local_client(client)
192
- @local_clients << client
204
+ @lock.synchronize do
205
+ @local_clients << client
206
+ end
193
207
  client
194
208
  end
195
209
 
196
210
  def close_local_clients
197
- @local_clients.map(&:close)
198
- @local_clients = []
211
+ @lock.synchronize do
212
+ @local_clients.map(&:close)
213
+ @local_clients = []
214
+ end
199
215
  end
200
216
 
201
217
  def close_all_clients
218
+ ClusterTools.instance.close_clients
202
219
  close_local_clients
203
- @global_clients.each do |name, client|
204
- client.close(true)
220
+ @lock.synchronize do
221
+ @global_clients.each do |name, client|
222
+ client.close(true)
223
+ end
205
224
  end
206
225
  end
207
226
  end