mongo 2.9.2 → 2.10.0.rc0

Sign up to get free protection for your applications and to get access to all the features.
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
metadata.gz.sig CHANGED
Binary file
@@ -1,265 +0,0 @@
1
- # Copyright (C) 2014-2019 MongoDB, Inc.
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- module Mongo
16
- module CRUD
17
- module Operation
18
-
19
- # Defines common behavior for running CRUD read operation tests
20
- # on a collection.
21
- #
22
- # @since 2.0.0
23
- class Read
24
-
25
- # Map of method names to test operation argument names.
26
- #
27
- # @since 2.0.0
28
- ARGUMENT_MAP = { :sort => 'sort',
29
- :skip => 'skip',
30
- :batch_size => 'batchSize',
31
- :limit => 'limit',
32
- :collation => 'collation'
33
- }.freeze
34
-
35
- # Map of read preference mode names to their equivalent Ruby-formatted symbols.
36
- #
37
- # @since 2.4.0
38
- READ_PREFERENCE_MAP = { 'primary' => :primary,
39
- 'secondary' => :secondary,
40
- 'primaryPreferred' => :primary_preferred,
41
- 'secondaryPreferred' => :secondary_preferred,
42
- 'nearest' => :nearest
43
- }.freeze
44
-
45
- # Instantiate the operation.
46
- #
47
- # @return [ Hash ] spec The operation spec.
48
- #
49
- # @since 2.0.0
50
- def initialize(spec, outcome_spec = nil)
51
- @spec = spec
52
- @outcome = Outcome.new(outcome_spec || spec)
53
- @name = spec['name']
54
- end
55
-
56
- # The operation name.
57
- #
58
- # @return [ String ] name The operation name.
59
- #
60
- # @since 2.0.0
61
- attr_reader :name
62
-
63
- attr_reader :outcome
64
-
65
- def object
66
- @spec['object'] || 'collection'
67
- end
68
-
69
- # Which collection to verify results from.
70
- # Returns the collection name specified on the operation, or
71
- # the collection name for the entire spec file.
72
- def verify_collection_name
73
- if outcome && outcome.collection_name
74
- outcome.collection_name
75
- else
76
- spec.collection_name.tap do |cn|
77
- if cn.nil?
78
- raise "Collection name cannot be nil"
79
- end
80
- end
81
- end
82
- end
83
-
84
- # Execute the operation.
85
- #
86
- # @example Execute the operation.
87
- # operation.execute
88
- #
89
- # @param [ Collection ] collection The collection to execute the operation on.
90
- #
91
- # @return [ Result, Array<Hash> ] The result of executing the operation.
92
- #
93
- # @since 2.0.0
94
- def execute(target)
95
- op_name = Utils.underscore(name)
96
- if target.is_a?(Mongo::Database)
97
- op_name = "db_#{op_name}"
98
- elsif target.is_a?(Mongo::Client)
99
- op_name= "client_#{op_name}"
100
- end
101
- send(op_name, target)
102
- end
103
-
104
- # Whether the operation is expected to have results.
105
- #
106
- # @example Whether the operation is expected to have results.
107
- # operation.has_results?
108
- #
109
- # @return [ true, false ] If the operation is expected to have results.
110
- #
111
- # @since 2.0.0
112
- def has_results?
113
- !(name == 'aggregate' &&
114
- pipeline.find {|op| op.keys.include?('$out') })
115
- end
116
-
117
- private
118
-
119
- def count(collection)
120
- options = ARGUMENT_MAP.reduce({}) do |opts, (key, value)|
121
- opts.merge!(key => arguments[value]) if arguments[value]
122
- opts
123
- end
124
- collection.count(filter, options)
125
- end
126
-
127
- def count_documents(collection)
128
- options = ARGUMENT_MAP.reduce({}) do |opts, (key, value)|
129
- opts.merge!(key => arguments[value]) if arguments[value]
130
- opts
131
- end
132
- collection.count_documents(filter, options)
133
- end
134
-
135
- def estimated_document_count(collection)
136
- # estimated_document_count defaults options to {}
137
- args = arguments || {}
138
- options = ARGUMENT_MAP.reduce({}) do |opts, (key, value)|
139
- opts.merge!(key => args[value]) if args[value]
140
- opts
141
- end
142
- collection.estimated_document_count(options)
143
- end
144
-
145
- def aggregate(collection)
146
- collection.aggregate(pipeline, options).to_a
147
- end
148
-
149
- def distinct(collection)
150
- collection.distinct(field_name, filter, options)
151
- end
152
-
153
- def find(collection)
154
- opts = modifiers ? options.merge(modifiers: BSON::Document.new(modifiers)) : options
155
- (read_preference ? collection.with(read: read_preference) : collection).find(filter, opts).to_a
156
- end
157
-
158
- def find_one(collection)
159
- find(collection).first
160
- end
161
-
162
- def client_list_databases(client)
163
- client.list_databases
164
- end
165
-
166
- def client_list_database_names(client)
167
- client.list_databases({}, true)
168
- end
169
-
170
- def client_list_database_objects(client)
171
- client.list_mongo_databases
172
- end
173
-
174
- def db_list_collections(database)
175
- database.list_collections
176
- end
177
-
178
- def db_list_collection_names(database)
179
- database.collection_names
180
- end
181
-
182
- def db_list_collection_objects(database)
183
- database.collections
184
- end
185
-
186
- def list_indexes(collection)
187
- collection.indexes.to_a
188
- end
189
-
190
- def watch(collection)
191
- collection.watch
192
- end
193
-
194
- def db_watch(database)
195
- database.watch
196
- end
197
-
198
- def client_watch(client)
199
- client.watch
200
- end
201
-
202
- def download(fs_bucket)
203
- stream = fs_bucket.open_download_stream(BSON::ObjectId.from_string(arguments['id']['$oid']))
204
- stream.read
205
- end
206
-
207
- def download_by_name(fs_bucket)
208
- stream = fs_bucket.open_download_stream_by_name(arguments['filename'])
209
- stream.read
210
- end
211
-
212
- def map_reduce(collection)
213
- view = Mongo::Collection::View.new(collection)
214
- mr = Mongo::Collection::View::MapReduce.new(view, arguments['map']['$code'], arguments['reduce']['$code'])
215
- mr.to_a
216
- end
217
-
218
- def options
219
- ARGUMENT_MAP.reduce({}) do |opts, (key, value)|
220
- value = if arguments[value].is_a?(Hash) && arguments[value]['$numberLong']
221
- arguments[value]['$numberLong'].to_i
222
- else
223
- arguments[value]
224
- end
225
- value ? opts.merge!(key => value) : opts
226
- end
227
- end
228
-
229
- def collation
230
- arguments['collation']
231
- end
232
-
233
- def batch_size
234
- arguments['batchSize']
235
- end
236
-
237
- def filter
238
- arguments['filter']
239
- end
240
-
241
- def pipeline
242
- arguments['pipeline']
243
- end
244
-
245
- def modifiers
246
- arguments['modifiers']
247
- end
248
-
249
- def field_name
250
- arguments['fieldName']
251
- end
252
-
253
- def arguments
254
- @spec['arguments']
255
- end
256
-
257
- def read_preference
258
- if @spec['read_preference'] && @spec['read_preference']['mode']
259
- { mode: READ_PREFERENCE_MAP[@spec['read_preference']['mode']] }
260
- end
261
- end
262
- end
263
- end
264
- end
265
- end
@@ -1,284 +0,0 @@
1
- # Copyright (C) 2014-2019 MongoDB, Inc.
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- module Mongo
16
- module CRUD
17
- module Operation
18
-
19
- # Defines common behavior for running CRUD write operation tests on a
20
- # collection.
21
- #
22
- # @since 2.0.0
23
- class Write
24
-
25
- # Map of CRUD operation names to method names.
26
- #
27
- # @since 2.0.0
28
- OPERATIONS = { 'deleteMany' => :delete_many,
29
- 'deleteOne' => :delete_one,
30
- 'insertMany' => :insert_many,
31
- 'insertOne' => :insert_one,
32
- 'replaceOne' => :replace_one,
33
- 'updateMany' => :update_many,
34
- 'updateOne' => :update_one,
35
- 'findOneAndDelete' => :find_one_and_delete,
36
- 'findOneAndReplace' => :find_one_and_replace,
37
- 'findOneAndUpdate' => :find_one_and_update,
38
- 'bulkWrite' => :bulk_write
39
- }.freeze
40
-
41
- # Map of operation options to method names.
42
- #
43
- # @since 2.0.0
44
- ARGUMENT_MAP = {
45
- :sort => 'sort',
46
- :projection => 'projection',
47
- :return_document => 'returnDocument',
48
- :upsert => 'upsert',
49
- :ordered => 'ordered',
50
- :write_concern => 'writeConcern',
51
- :collation => 'collation',
52
- :array_filters => 'arrayFilters'
53
- }.freeze
54
-
55
- # The operation name.
56
- #
57
- # @return [ String ] name The operation name.
58
- #
59
- # @since 2.0.0
60
- attr_reader :name
61
-
62
- # Instantiate the operation.
63
- #
64
- # @param [ Hash ] spec The operation specification.
65
- # @param [ Hash ] outcome_spec The outcome specification.
66
- # If not provided, outcome is taken out of operation specification.
67
- #
68
- # @since 2.0.0
69
- def initialize(spec, outcome_spec = nil)
70
- @spec = spec
71
- @name = spec['name']
72
- @outcome = Outcome.new(outcome_spec || spec)
73
- end
74
-
75
- attr_reader :outcome
76
-
77
- def object
78
- 'collection'
79
- end
80
-
81
- def verify_collection_name
82
- 'crud_spec_test'
83
- end
84
-
85
- # Whether the operation is expected to have results.
86
- #
87
- # @example Whether the operation is expected to have results.
88
- # operation.has_results?
89
- #
90
- # @return [ true ] If the operation is expected to have results.
91
- #
92
- # @since 2.0.0
93
- def has_results?
94
- true
95
- end
96
-
97
- # Execute the operation.
98
- #
99
- # @example Execute the operation.
100
- # operation.execute
101
- #
102
- # @param [ Collection ] collection The collection to execute
103
- # the operation on.
104
- #
105
- # @return [ Result, Array<Hash> ] The result of executing the operation.
106
- #
107
- # @since 2.0.0
108
- def execute(collection)
109
- send(OPERATIONS[name], collection)
110
- end
111
-
112
- private
113
-
114
- def bulk_write(collection)
115
- result = collection.bulk_write(requests, options)
116
- return_doc = {}
117
- return_doc['deletedCount'] = result.deleted_count if result.deleted_count
118
- return_doc['insertedIds'] = result.inserted_ids if result.inserted_ids
119
- return_doc['upsertedIds'] = result.upserted_ids if result.upserted_ids
120
- return_doc['upsertedId'] = result.upserted_id if upsert
121
- return_doc['upsertedCount'] = result.upserted_count if result.upserted_count
122
- return_doc['insertedCount'] = result.inserted_count if result.inserted_count
123
- return_doc['matchedCount'] = result.matched_count if result.matched_count
124
- return_doc['modifiedCount'] = result.modified_count if result.modified_count
125
- return_doc
126
- end
127
-
128
- def delete_many(collection)
129
- result = collection.delete_many(filter, options)
130
- { 'deletedCount' => result.deleted_count }
131
- end
132
-
133
- def delete_one(collection)
134
- result = collection.delete_one(filter, options)
135
- { 'deletedCount' => result.deleted_count }
136
- end
137
-
138
- def insert_many(collection)
139
- result = collection.insert_many(documents, options)
140
- { 'insertedIds' => result.inserted_ids }
141
- end
142
-
143
- def insert_one(collection)
144
- result = collection.insert_one(document)
145
- { 'insertedId' => result.inserted_id }
146
- end
147
-
148
- def update_return_doc(result)
149
- return_doc = {}
150
- return_doc['upsertedId'] = result.upserted_id if upsert
151
- return_doc['upsertedCount'] = result.upserted_count
152
- return_doc['matchedCount'] = result.matched_count
153
- return_doc['modifiedCount'] = result.modified_count if result.modified_count
154
- return_doc
155
- end
156
-
157
- def replace_one(collection)
158
- result = collection.replace_one(filter, replacement, options)
159
- update_return_doc(result)
160
- end
161
-
162
- def update_many(collection)
163
- result = collection.update_many(filter, update, options)
164
- update_return_doc(result)
165
- end
166
-
167
- def update_one(collection)
168
- result = collection.update_one(filter, update, options)
169
- update_return_doc(result)
170
- end
171
-
172
- def find_one_and_delete(collection)
173
- collection.find_one_and_delete(filter, options)
174
- end
175
-
176
- def find_one_and_replace(collection)
177
- collection.find_one_and_replace(filter, replacement, options)
178
- end
179
-
180
- def find_one_and_update(collection)
181
- collection.find_one_and_update(filter, update, options)
182
- end
183
-
184
- def options
185
- args = (arguments['options'] || {}).reduce({}) do |a, kv|
186
- a[kv.first.to_sym] = kv.last
187
- a
188
- end
189
-
190
- ARGUMENT_MAP.reduce(args) do |opts, (key, value)|
191
- arguments.key?(value) ? opts.merge!(key => send(key)) : opts
192
- end
193
- end
194
-
195
- def collation
196
- arguments['collation']
197
- end
198
-
199
- def replacement
200
- arguments['replacement']
201
- end
202
-
203
- def sort
204
- arguments['sort']
205
- end
206
-
207
- def projection
208
- arguments['projection']
209
- end
210
-
211
- def documents
212
- arguments['documents']
213
- end
214
-
215
- def document
216
- arguments['document']
217
- end
218
-
219
- def write_concern
220
- arguments['writeConcern']
221
- end
222
-
223
- def ordered
224
- arguments['ordered']
225
- end
226
-
227
- def filter
228
- arguments['filter']
229
- end
230
-
231
- def array_filters
232
- arguments['arrayFilters']
233
- end
234
-
235
- def requests
236
- arguments['requests'].map do |request|
237
- case request.keys.first
238
- when 'insertOne' then
239
- { insert_one: request['insertOne']['document'] }
240
- when 'updateOne' then
241
- update = request['updateOne']
242
- { update_one: { filter: update['filter'], update: update['update'] } }
243
- when 'name' then
244
- bulk_request(request)
245
- end
246
- end
247
- end
248
-
249
- def bulk_request(request)
250
- op_name = OPERATIONS[request['name']]
251
- op = { op_name => {} }
252
- op[op_name].merge!(filter: request['arguments']['filter']) if request['arguments']['filter']
253
- op[op_name].merge!(update: request['arguments']['update']) if request['arguments']['update']
254
- op[op_name].merge!(upsert: request['arguments']['upsert']) if request['arguments']['upsert']
255
- op[op_name].merge!(replacement: request['arguments']['replacement']) if request['arguments']['replacement']
256
- op[op_name].merge!(array_filters: request['arguments']['arrayFilters']) if request['arguments']['arrayFilters']
257
- op[op_name] = request['arguments']['document'] if request['arguments']['document']
258
- op
259
- end
260
-
261
- def upsert
262
- arguments['upsert']
263
- end
264
-
265
- def return_document
266
- case arguments['returnDocument']
267
- when 'Before'
268
- :before
269
- when 'After'
270
- :after
271
- end
272
- end
273
-
274
- def update
275
- arguments['update']
276
- end
277
-
278
- def arguments
279
- @spec['arguments']
280
- end
281
- end
282
- end
283
- end
284
- end