mongo 2.14.0 → 2.15.0.alpha

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 (230) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/README.md +4 -1
  5. data/Rakefile +8 -15
  6. data/lib/mongo.rb +23 -0
  7. data/lib/mongo/auth/aws/conversation.rb +1 -4
  8. data/lib/mongo/auth/base.rb +13 -7
  9. data/lib/mongo/auth/conversation_base.rb +32 -0
  10. data/lib/mongo/auth/cr/conversation.rb +6 -29
  11. data/lib/mongo/auth/gssapi/conversation.rb +4 -15
  12. data/lib/mongo/auth/ldap/conversation.rb +3 -14
  13. data/lib/mongo/auth/sasl_conversation_base.rb +1 -13
  14. data/lib/mongo/auth/scram_conversation_base.rb +7 -34
  15. data/lib/mongo/auth/user/view.rb +16 -9
  16. data/lib/mongo/auth/x509/conversation.rb +4 -25
  17. data/lib/mongo/background_thread.rb +11 -0
  18. data/lib/mongo/bulk_write.rb +21 -18
  19. data/lib/mongo/client.rb +82 -6
  20. data/lib/mongo/cluster.rb +19 -28
  21. data/lib/mongo/cluster/reapers/cursor_reaper.rb +6 -2
  22. data/lib/mongo/cluster/sdam_flow.rb +14 -0
  23. data/lib/mongo/collection.rb +8 -6
  24. data/lib/mongo/collection/view/aggregation.rb +1 -1
  25. data/lib/mongo/collection/view/change_stream.rb +1 -1
  26. data/lib/mongo/collection/view/iterable.rb +1 -1
  27. data/lib/mongo/collection/view/map_reduce.rb +2 -2
  28. data/lib/mongo/collection/view/readable.rb +42 -20
  29. data/lib/mongo/collection/view/writable.rb +14 -14
  30. data/lib/mongo/cursor.rb +2 -2
  31. data/lib/mongo/database.rb +22 -5
  32. data/lib/mongo/database/view.rb +1 -1
  33. data/lib/mongo/error.rb +9 -1
  34. data/lib/mongo/error/bulk_write_error.rb +17 -3
  35. data/lib/mongo/error/internal_driver_error.rb +22 -0
  36. data/lib/mongo/error/operation_failure.rb +21 -2
  37. data/lib/mongo/error/parser.rb +65 -12
  38. data/lib/mongo/error/server_api_conflict.rb +23 -0
  39. data/lib/mongo/error/server_api_not_supported.rb +24 -0
  40. data/lib/mongo/error/unmet_dependency.rb +21 -0
  41. data/lib/mongo/grid/fs_bucket.rb +37 -37
  42. data/lib/mongo/index/view.rb +21 -11
  43. data/lib/mongo/monitoring.rb +13 -4
  44. data/lib/mongo/monitoring/event/server_heartbeat_failed.rb +27 -16
  45. data/lib/mongo/monitoring/event/server_heartbeat_succeeded.rb +26 -15
  46. data/lib/mongo/operation.rb +2 -2
  47. data/lib/mongo/operation/collections_info.rb +18 -1
  48. data/lib/mongo/operation/collections_info/command.rb +2 -2
  49. data/lib/mongo/operation/context.rb +99 -0
  50. data/lib/mongo/operation/indexes.rb +15 -1
  51. data/lib/mongo/operation/insert/command.rb +2 -2
  52. data/lib/mongo/operation/insert/legacy.rb +2 -2
  53. data/lib/mongo/operation/insert/op_msg.rb +2 -2
  54. data/lib/mongo/operation/list_collections/result.rb +4 -1
  55. data/lib/mongo/operation/result.rb +2 -0
  56. data/lib/mongo/operation/shared/executable.rb +24 -14
  57. data/lib/mongo/operation/shared/executable_no_validate.rb +2 -2
  58. data/lib/mongo/operation/shared/op_msg_or_command.rb +1 -7
  59. data/lib/mongo/operation/shared/op_msg_or_find_command.rb +1 -7
  60. data/lib/mongo/operation/shared/polymorphic_operation.rb +39 -0
  61. data/lib/mongo/operation/shared/response_handling.rb +23 -23
  62. data/lib/mongo/operation/shared/sessions_supported.rb +13 -2
  63. data/lib/mongo/operation/shared/write.rb +8 -18
  64. data/lib/mongo/protocol/compressed.rb +51 -5
  65. data/lib/mongo/protocol/message.rb +20 -2
  66. data/lib/mongo/protocol/msg.rb +36 -11
  67. data/lib/mongo/query_cache.rb +30 -0
  68. data/lib/mongo/retryable.rb +1 -1
  69. data/lib/mongo/server.rb +7 -15
  70. data/lib/mongo/server/app_metadata.rb +52 -18
  71. data/lib/mongo/server/connection.rb +5 -0
  72. data/lib/mongo/server/connection_base.rb +13 -10
  73. data/lib/mongo/server/connection_pool.rb +6 -4
  74. data/lib/mongo/server/description.rb +4 -0
  75. data/lib/mongo/server/description/features.rb +9 -8
  76. data/lib/mongo/server/monitor.rb +20 -1
  77. data/lib/mongo/server/monitor/app_metadata.rb +1 -1
  78. data/lib/mongo/server/monitor/connection.rb +9 -10
  79. data/lib/mongo/server/pending_connection.rb +24 -6
  80. data/lib/mongo/server/push_monitor.rb +11 -1
  81. data/lib/mongo/session.rb +2 -2
  82. data/lib/mongo/session/session_pool.rb +4 -2
  83. data/lib/mongo/socket.rb +29 -4
  84. data/lib/mongo/socket/ssl.rb +8 -0
  85. data/lib/mongo/srv/monitor.rb +0 -11
  86. data/lib/mongo/uri/options_mapper.rb +38 -0
  87. data/lib/mongo/utils.rb +15 -0
  88. data/lib/mongo/version.rb +1 -1
  89. data/spec/README.md +24 -1
  90. data/spec/integration/auth_spec.rb +25 -15
  91. data/spec/integration/bulk_write_error_message_spec.rb +41 -0
  92. data/spec/integration/change_stream_spec.rb +4 -4
  93. data/spec/integration/command_monitoring_spec.rb +2 -2
  94. data/spec/integration/connection_spec.rb +2 -0
  95. data/spec/integration/docs_examples_spec.rb +8 -1
  96. data/spec/integration/fork_reconnect_spec.rb +4 -1
  97. data/spec/integration/ocsp_verifier_spec.rb +13 -7
  98. data/spec/integration/operation_failure_code_spec.rb +1 -1
  99. data/spec/integration/operation_failure_message_spec.rb +90 -0
  100. data/spec/integration/reconnect_spec.rb +1 -1
  101. data/spec/integration/sdam_error_handling_spec.rb +1 -1
  102. data/spec/integration/sdam_events_spec.rb +3 -5
  103. data/spec/integration/snappy_compression_spec.rb +25 -0
  104. data/spec/integration/srv_monitoring_spec.rb +1 -1
  105. data/spec/integration/transactions_examples_spec.rb +6 -0
  106. data/spec/integration/zlib_compression_spec.rb +1 -1
  107. data/spec/integration/zstd_compression_spec.rb +26 -0
  108. data/spec/lite_spec_helper.rb +7 -1
  109. data/spec/mongo/address_spec.rb +15 -11
  110. data/spec/mongo/auth/ldap/conversation_spec.rb +1 -1
  111. data/spec/mongo/auth/ldap_spec.rb +5 -1
  112. data/spec/mongo/auth/scram_negotiation_spec.rb +1 -1
  113. data/spec/mongo/auth/scram_spec.rb +1 -1
  114. data/spec/mongo/auth/x509/conversation_spec.rb +3 -3
  115. data/spec/mongo/client_construction_spec.rb +207 -33
  116. data/spec/mongo/client_spec.rb +17 -0
  117. data/spec/mongo/cluster_spec.rb +3 -18
  118. data/spec/mongo/collection/view/explainable_spec.rb +1 -1
  119. data/spec/mongo/collection/view/readable_spec.rb +33 -19
  120. data/spec/mongo/collection_crud_spec.rb +4357 -0
  121. data/spec/mongo/collection_ddl_spec.rb +534 -0
  122. data/spec/mongo/collection_spec.rb +5 -4859
  123. data/spec/mongo/database_spec.rb +66 -4
  124. data/spec/mongo/error/bulk_write_error_spec.rb +3 -3
  125. data/spec/mongo/error/parser_spec.rb +37 -6
  126. data/spec/mongo/index/view_spec.rb +8 -2
  127. data/spec/mongo/monitoring/event/server_heartbeat_failed_spec.rb +1 -1
  128. data/spec/mongo/monitoring/event/server_heartbeat_succeeded_spec.rb +1 -1
  129. data/spec/mongo/operation/aggregate_spec.rb +2 -1
  130. data/spec/mongo/operation/collections_info_spec.rb +4 -1
  131. data/spec/mongo/operation/command_spec.rb +6 -3
  132. data/spec/mongo/operation/create_index_spec.rb +6 -3
  133. data/spec/mongo/operation/create_user_spec.rb +6 -3
  134. data/spec/mongo/operation/delete/bulk_spec.rb +9 -6
  135. data/spec/mongo/operation/delete_spec.rb +11 -7
  136. data/spec/mongo/operation/drop_index_spec.rb +6 -2
  137. data/spec/mongo/operation/find/legacy_spec.rb +3 -1
  138. data/spec/mongo/operation/get_more_spec.rb +3 -1
  139. data/spec/mongo/operation/indexes_spec.rb +5 -1
  140. data/spec/mongo/operation/insert/bulk_spec.rb +10 -7
  141. data/spec/mongo/operation/insert_spec.rb +15 -12
  142. data/spec/mongo/operation/map_reduce_spec.rb +5 -2
  143. data/spec/mongo/operation/remove_user_spec.rb +6 -3
  144. data/spec/mongo/operation/result_spec.rb +1 -1
  145. data/spec/mongo/operation/update/bulk_spec.rb +9 -6
  146. data/spec/mongo/operation/update_spec.rb +10 -7
  147. data/spec/mongo/operation/update_user_spec.rb +4 -1
  148. data/spec/mongo/protocol/compressed_spec.rb +26 -12
  149. data/spec/mongo/query_cache_middleware_spec.rb +55 -0
  150. data/spec/mongo/retryable_spec.rb +3 -2
  151. data/spec/mongo/server/app_metadata_spec.rb +2 -0
  152. data/spec/mongo/server/connection_pool/populator_spec.rb +3 -1
  153. data/spec/mongo/server/connection_pool_spec.rb +1 -1
  154. data/spec/mongo/server/connection_spec.rb +24 -17
  155. data/spec/mongo/server/monitor/connection_spec.rb +17 -7
  156. data/spec/mongo/server/monitor_spec.rb +9 -1
  157. data/spec/mongo/server_spec.rb +15 -2
  158. data/spec/mongo/socket/ssl_spec.rb +40 -0
  159. data/spec/mongo/socket_spec.rb +2 -2
  160. data/spec/mongo/tls_context_hooks_spec.rb +37 -0
  161. data/spec/runners/connection_string.rb +0 -4
  162. data/spec/runners/crud/requirement.rb +40 -3
  163. data/spec/runners/crud/verifier.rb +8 -0
  164. data/spec/runners/transactions/operation.rb +13 -2
  165. data/spec/runners/transactions/test.rb +1 -0
  166. data/spec/runners/unified.rb +96 -0
  167. data/spec/runners/unified/assertions.rb +249 -0
  168. data/spec/runners/unified/change_stream_operations.rb +26 -0
  169. data/spec/runners/unified/crud_operations.rb +199 -0
  170. data/spec/runners/unified/ddl_operations.rb +96 -0
  171. data/spec/runners/unified/entity_map.rb +39 -0
  172. data/spec/runners/unified/error.rb +25 -0
  173. data/spec/runners/unified/event_subscriber.rb +91 -0
  174. data/spec/runners/unified/exceptions.rb +21 -0
  175. data/spec/runners/unified/grid_fs_operations.rb +55 -0
  176. data/spec/runners/unified/support_operations.rb +250 -0
  177. data/spec/runners/unified/test.rb +393 -0
  178. data/spec/runners/unified/test_group.rb +28 -0
  179. data/spec/runners/unified/using_hash.rb +31 -0
  180. data/spec/shared/bin/get-mongodb-download-url +17 -0
  181. data/spec/shared/lib/mrss/cluster_config.rb +218 -0
  182. data/spec/shared/lib/mrss/constraints.rb +43 -0
  183. data/spec/shared/lib/mrss/docker_runner.rb +262 -0
  184. data/spec/shared/lib/mrss/server_version_registry.rb +112 -0
  185. data/spec/shared/lib/mrss/utils.rb +15 -0
  186. data/spec/shared/share/Dockerfile.erb +231 -0
  187. data/spec/shared/shlib/distro.sh +73 -0
  188. data/spec/shared/shlib/server.sh +290 -0
  189. data/spec/shared/shlib/set_env.sh +128 -0
  190. data/spec/solo/clean_exit_spec.rb +21 -0
  191. data/spec/spec_helper.rb +4 -1
  192. data/spec/spec_tests/crud_unified_spec.rb +10 -0
  193. data/spec/spec_tests/data/change_streams/change-streams.yml +0 -1
  194. data/spec/spec_tests/data/crud_unified/estimatedDocumentCount.yml +267 -0
  195. data/spec/spec_tests/data/retryable_reads/estimatedDocumentCount-4.9.yml +60 -0
  196. data/spec/spec_tests/data/retryable_reads/{estimatedDocumentCount.yml → estimatedDocumentCount-pre4.9.yml} +2 -0
  197. data/spec/spec_tests/data/retryable_reads/estimatedDocumentCount-serverErrors-4.9.yml +146 -0
  198. data/spec/spec_tests/data/retryable_reads/{estimatedDocumentCount-serverErrors.yml → estimatedDocumentCount-serverErrors-pre4.9.yml} +2 -0
  199. data/spec/spec_tests/data/retryable_reads/listIndexNames.yml +1 -1
  200. data/spec/spec_tests/data/unified/valid-fail/operation-failure.yml +31 -0
  201. data/spec/spec_tests/data/unified/valid-pass/poc-change-streams.yml +220 -0
  202. data/spec/spec_tests/data/unified/valid-pass/poc-command-monitoring.yml +102 -0
  203. data/spec/spec_tests/data/unified/valid-pass/poc-crud.yml +184 -0
  204. data/spec/spec_tests/data/unified/valid-pass/poc-gridfs.yml +155 -0
  205. data/spec/spec_tests/data/unified/valid-pass/poc-retryable-reads.yml +193 -0
  206. data/spec/spec_tests/data/unified/valid-pass/poc-retryable-writes.yml +210 -0
  207. data/spec/spec_tests/data/unified/valid-pass/poc-sessions.yml +215 -0
  208. data/spec/spec_tests/data/unified/valid-pass/poc-transactions-convenient-api.yml +235 -0
  209. data/spec/spec_tests/data/unified/valid-pass/poc-transactions-mongos-pin-auto.yml +169 -0
  210. data/spec/spec_tests/data/unified/valid-pass/poc-transactions.yml +170 -0
  211. data/spec/spec_tests/data/uri_options/compression-options.yml +1 -1
  212. data/spec/spec_tests/data/versioned_api/crud-api-version-1-strict.yml +416 -0
  213. data/spec/spec_tests/data/versioned_api/crud-api-version-1.yml +409 -0
  214. data/spec/spec_tests/data/versioned_api/runcommand-helper-no-api-version-declared.yml +67 -0
  215. data/spec/spec_tests/data/versioned_api/test-commands-deprecation-errors.yml +47 -0
  216. data/spec/spec_tests/data/versioned_api/test-commands-strict-mode.yml +44 -0
  217. data/spec/spec_tests/data/versioned_api/transaction-handling.yml +180 -0
  218. data/spec/spec_tests/unified_spec.rb +15 -0
  219. data/spec/spec_tests/uri_options_spec.rb +16 -0
  220. data/spec/spec_tests/versioned_api_spec.rb +10 -0
  221. data/spec/support/common_shortcuts.rb +15 -1
  222. data/spec/support/shared/session.rb +2 -2
  223. data/spec/support/spec_config.rb +46 -3
  224. data/spec/support/spec_setup.rb +48 -38
  225. data/spec/support/utils.rb +64 -3
  226. metadata +1104 -992
  227. metadata.gz.sig +0 -0
  228. data/lib/mongo/operation/shared/collections_info_or_list_collections.rb +0 -58
  229. data/lib/mongo/operation/shared/op_msg_or_list_indexes_command.rb +0 -47
  230. data/spec/support/cluster_config.rb +0 -207
@@ -0,0 +1,26 @@
1
+ module Unified
2
+
3
+ module ChangeStreamOperations
4
+
5
+ def create_change_stream(op)
6
+ object_id = op.use!('object')
7
+ object = entities.get_any(object_id)
8
+ use_arguments(op) do |args|
9
+ pipeline = args.use!('pipeline')
10
+ opts = {}
11
+ if batch_size = args.use('batchSize')
12
+ opts[:batch_size] = batch_size
13
+ end
14
+ cs = object.watch(pipeline, **opts)
15
+ name = op.use!('saveResultAsEntity')
16
+ entities.set(:change_stream, name, cs)
17
+ end
18
+ end
19
+
20
+ def iterate_until_document_or_error(op)
21
+ object_id = op.use!('object')
22
+ object = entities.get(:change_stream, object_id)
23
+ object.to_enum.next
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,199 @@
1
+ module Unified
2
+
3
+ module CrudOperations
4
+
5
+ def find(op)
6
+ collection = entities.get(:collection, op.use!('object'))
7
+ use_arguments(op) do |args|
8
+ req = collection.find(args.use!('filter'))
9
+ if batch_size = args.use('batchSize')
10
+ req = req.batch_size(batch_size)
11
+ end
12
+ if sort = args.use('sort')
13
+ req = req.sort(sort)
14
+ end
15
+ if limit = args.use('limit')
16
+ req = req.limit(limit)
17
+ end
18
+ result = req.to_a
19
+ end
20
+ end
21
+
22
+ def count_documents(op)
23
+ collection = entities.get(:collection, op.use!('object'))
24
+ use_arguments(op) do |args|
25
+ collection.find(args.use!('filter')).count_documents
26
+ end
27
+ end
28
+
29
+ def estimated_document_count(op)
30
+ collection = entities.get(:collection, op.use!('object'))
31
+ use_arguments(op) do |args|
32
+ opts = {}
33
+ if max_time_ms = args.use('maxTimeMS')
34
+ opts[:max_time_ms] = max_time_ms
35
+ end
36
+ collection.estimated_document_count(**opts)
37
+ end
38
+ end
39
+
40
+ def distinct(op)
41
+ collection = entities.get(:collection, op.use!('object'))
42
+ use_arguments(op) do |args|
43
+ req = collection.find(args.use!('filter')).distinct(args.use!('fieldName'))
44
+ result = req.to_a
45
+ end
46
+ end
47
+
48
+ def find_one_and_update(op)
49
+ collection = entities.get(:collection, op.use!('object'))
50
+ use_arguments(op) do |args|
51
+ filter = args.use!('filter')
52
+ update = args.use!('update')
53
+ opts = {}
54
+ if return_document = args.use('returnDocument')
55
+ opts[:return_document] = return_document.downcase.to_sym
56
+ end
57
+ collection.find_one_and_update(filter, update, **opts)
58
+ end
59
+ end
60
+
61
+ def find_one_and_replace(op)
62
+ collection = entities.get(:collection, op.use!('object'))
63
+ use_arguments(op) do |args|
64
+ filter = args.use!('filter')
65
+ update = args.use!('replacement')
66
+ collection.find_one_and_replace(filter, update)
67
+ end
68
+ end
69
+
70
+ def find_one_and_delete(op)
71
+ collection = entities.get(:collection, op.use!('object'))
72
+ use_arguments(op) do |args|
73
+ filter = args.use!('filter')
74
+ collection.find_one_and_delete(filter)
75
+ end
76
+ end
77
+
78
+ def insert_one(op)
79
+ collection = entities.get(:collection, op.use!('object'))
80
+ use_arguments(op) do |args|
81
+ opts = {}
82
+ if session = args.use('session')
83
+ opts[:session] = entities.get(:session, session)
84
+ end
85
+ collection.insert_one(args.use!('document'), **opts)
86
+ end
87
+ end
88
+
89
+ def insert_many(op)
90
+ collection = entities.get(:collection, op.use!('object'))
91
+ use_arguments(op) do |args|
92
+ options = {}
93
+ unless (ordered = args.use('ordered')).nil?
94
+ options[:ordered] = ordered
95
+ end
96
+ collection.insert_many(args.use!('documents'), **options)
97
+ end
98
+ end
99
+
100
+ def update_one(op)
101
+ collection = entities.get(:collection, op.use!('object'))
102
+ use_arguments(op) do |args|
103
+ collection.update_one(args.use!('filter'), args.use!('update'))
104
+ end
105
+ end
106
+
107
+ def update_many(op)
108
+ collection = entities.get(:collection, op.use!('object'))
109
+ use_arguments(op) do |args|
110
+ collection.update_many(args.use!('filter'), args.use!('update'))
111
+ end
112
+ end
113
+
114
+ def replace_one(op)
115
+ collection = entities.get(:collection, op.use!('object'))
116
+ use_arguments(op) do |args|
117
+ collection.replace_one(
118
+ args.use!('filter'),
119
+ args.use!('replacement'),
120
+ upsert: args.use('upsert'),
121
+ )
122
+ end
123
+ end
124
+
125
+ def delete_one(op)
126
+ collection = entities.get(:collection, op.use!('object'))
127
+ use_arguments(op) do |args|
128
+ collection.delete_one(args.use!('filter'))
129
+ end
130
+ end
131
+
132
+ def delete_many(op)
133
+ collection = entities.get(:collection, op.use!('object'))
134
+ use_arguments(op) do |args|
135
+ collection.delete_many(args.use!('filter'))
136
+ end
137
+ end
138
+
139
+ def bulk_write(op)
140
+ collection = entities.get(:collection, op.use!('object'))
141
+ use_arguments(op) do |args|
142
+ requests = args.use!('requests').map do |req|
143
+ convert_bulk_write_spec(req)
144
+ end
145
+ opts = {}
146
+ if ordered = args.use('ordered')
147
+ opts[:ordered] = true
148
+ end
149
+ collection.bulk_write(requests, **opts)
150
+ end
151
+ end
152
+
153
+ private
154
+
155
+ def convert_bulk_write_spec(spec)
156
+ unless spec.keys.length == 1
157
+ raise NotImplementedError, "Must have exactly one item"
158
+ end
159
+ op, spec = spec.first
160
+ spec = UsingHash[spec]
161
+ out = case op
162
+ when 'insertOne'
163
+ spec.use!('document')
164
+ when 'updateOne', 'updateMany'
165
+ {
166
+ filter: spec.use('filter'),
167
+ update: spec.use('update'),
168
+ upsert: spec.use('upsert'),
169
+ }
170
+ when 'replaceOne'
171
+ {
172
+ filter: spec.use('filter'),
173
+ replacement: spec.use('replacement'),
174
+ upsert: spec.use('upsert'),
175
+ }
176
+ when 'deleteOne', 'deleteMany'
177
+ {
178
+ filter: spec.use('filter'),
179
+ }
180
+ else
181
+ raise NotImplementedError, "Unknown operation #{op}"
182
+ end
183
+ unless spec.empty?
184
+ raise NotImplementedError, "Unhandled keys: #{spec}"
185
+ end
186
+ {Utils.underscore(op) =>out}
187
+ end
188
+
189
+ def aggregate(op)
190
+ obj = entities.get_any(op.use!('object'))
191
+ args = op.use!('arguments')
192
+ pipeline = args.use!('pipeline')
193
+ unless args.empty?
194
+ raise NotImplementedError, "Unhandled spec keys: #{test_spec}"
195
+ end
196
+ obj.aggregate(pipeline).to_a
197
+ end
198
+ end
199
+ end
@@ -0,0 +1,96 @@
1
+ module Unified
2
+
3
+ module DdlOperations
4
+
5
+ def list_databases(op)
6
+ client = entities.get(:client, op.use!('object'))
7
+ client.list_databases
8
+ end
9
+
10
+ def create_collection(op)
11
+ database = entities.get(:database, op.use!('object'))
12
+ use_arguments(op) do |args|
13
+ opts = {}
14
+ if session = args.use('session')
15
+ opts[:session] = entities.get(:session, session)
16
+ end
17
+ database[args.use!('collection')].create(**opts)
18
+ end
19
+ end
20
+
21
+ def drop_collection(op)
22
+ database = entities.get(:database, op.use!('object'))
23
+ use_arguments(op) do |args|
24
+ collection = database[args.use!('collection')]
25
+ collection.drop
26
+ end
27
+ end
28
+
29
+ def assert_collection_exists(op, state = true)
30
+ consume_test_runner(op)
31
+ use_arguments(op) do |args|
32
+ client = ClientRegistry.instance.global_client('authorized')
33
+ database = client.use(args.use!('databaseName')).database
34
+ collection_name = args.use!('collectionName')
35
+ if state
36
+ unless database.collection_names.include?(collection_name)
37
+ raise Error::ResultMismatch, "Expected collection #{collection_name} to exist, but it does not"
38
+ end
39
+ else
40
+ if database.collection_names.include?(collection_name)
41
+ raise Error::ResultMismatch, "Expected collection #{collection_name} to not exist, but it does"
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ def assert_collection_not_exists(op)
48
+ assert_collection_exists(op, false)
49
+ end
50
+
51
+ def create_index(op)
52
+ collection = entities.get(:collection, op.use!('object'))
53
+ use_arguments(op) do |args|
54
+ opts = {}
55
+ if session = args.use('session')
56
+ opts[:session] = entities.get(:session, session)
57
+ end
58
+
59
+ collection.indexes.create_one(
60
+ args.use!('keys'),
61
+ name: args.use!('name'),
62
+ **opts,
63
+ )
64
+ end
65
+ end
66
+
67
+ def assert_index_exists(op)
68
+ consume_test_runner(op)
69
+ use_arguments(op) do |args|
70
+ client = ClientRegistry.instance.global_client('authorized')
71
+ database = client.use(args.use!('databaseName'))
72
+ collection = database[args.use!('collectionName')]
73
+ index = collection.indexes.get(args.use!('indexName'))
74
+ end
75
+ end
76
+
77
+ def assert_index_not_exists(op)
78
+ consume_test_runner(op)
79
+ use_arguments(op) do |args|
80
+ client = ClientRegistry.instance.global_client('authorized')
81
+ database = client.use(args.use!('databaseName'))
82
+ collection = database[args.use!('collectionName')]
83
+ begin
84
+ index = collection.indexes.get(args.use!('indexName'))
85
+ raise Error::ResultMismatch, "Index found"
86
+ rescue Mongo::Error::OperationFailure => e
87
+ if e.code == 26
88
+ # OK
89
+ else
90
+ raise
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,39 @@
1
+ module Unified
2
+ class EntityMap
3
+ def initialize
4
+ @map = {}
5
+ end
6
+
7
+ def set(type, id, value)
8
+ @map[type] ||= {}
9
+ if @map[type][id]
10
+ raise Error::EntityMapOverwriteAttempt,
11
+ "Cannot set #{type} #{id} because it is already defined"
12
+ end
13
+ @map[type][id] = value
14
+ end
15
+
16
+ def get(type, id)
17
+ unless @map[type]
18
+ raise Error::EntityMissing, "There are no #{type} entities known"
19
+ end
20
+ unless v = @map[type][id]
21
+ raise Error::EntityMissing, "There is no #{type} #{id} known"
22
+ end
23
+ v
24
+ end
25
+
26
+ def get_any(id)
27
+ @map.each do |type, sub|
28
+ if sub[id]
29
+ return sub[id]
30
+ end
31
+ end
32
+ raise Error::EntityMissing, "There is no #{id} known"
33
+ end
34
+
35
+ def [](type)
36
+ @map[type]
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,25 @@
1
+ module Unified
2
+
3
+ class Error < StandardError
4
+
5
+ class ResultMismatch < Error
6
+ end
7
+
8
+ class ErrorMismatch < Error
9
+ end
10
+
11
+ class UnhandledField < Error
12
+ end
13
+
14
+ class EntityMapOverwriteAttempt < Error
15
+ end
16
+
17
+ class EntityMissing < Error
18
+ end
19
+
20
+ class InvalidTest < Error
21
+ end
22
+
23
+ end
24
+
25
+ end
@@ -0,0 +1,91 @@
1
+ require 'support/event_subscriber'
2
+
3
+ module Unified
4
+
5
+ class EventSubscriber < ::EventSubscriber
6
+ def ignore_commands(command_names)
7
+ @ignore_commands = command_names
8
+ end
9
+
10
+ def wanted_events
11
+ all_events.select do |event|
12
+ kind = event.class.name.sub(/.*::/, '').sub('Command', '').downcase.to_sym
13
+ @wanted_events[kind]
14
+ end.select do |event|
15
+ event.command_name != 'configureFailPoint' &&
16
+ if @ignore_commands
17
+ !@ignore_commands.include?(event.command_name)
18
+ else
19
+ true
20
+ end
21
+ end.reject do |event|
22
+ %w(authenticate getnonce saslStart saslContinue).include?(event.command_name)
23
+ end
24
+ end
25
+
26
+ def add_wanted_events(kind)
27
+ @wanted_events ||= {}
28
+ @wanted_events[kind] = true
29
+ end
30
+ end
31
+
32
+ class StoringEventSubscriber
33
+ def initialize(&block)
34
+ @handler = block
35
+ end
36
+
37
+ def started(event)
38
+ @handler.call(
39
+ 'name' => event.class.name.sub(/.*::/, '') + 'Event',
40
+ 'commandName' => event.command_name,
41
+ 'databaseName' => event.database_name,
42
+ 'observedAt' => Time.now.to_f,
43
+ 'address' => event.address.seed,
44
+ 'requestId' => event.request_id,
45
+ 'operationId' => event.operation_id,
46
+ 'connectionId' => event.connection_id,
47
+ )
48
+ end
49
+
50
+ def succeeded(event)
51
+ @handler.call(
52
+ 'name' => event.class.name.sub(/.*::/, '') + 'Event',
53
+ 'commandName' => event.command_name,
54
+ 'duration' => event.duration,
55
+ 'observedAt' => Time.now.to_f,
56
+ 'address' => event.address.seed,
57
+ 'requestId' => event.request_id,
58
+ 'operationId' => event.operation_id,
59
+ )
60
+ end
61
+
62
+ def failed(event)
63
+ @handler.call(
64
+ 'name' => event.class.name.sub(/.*::/, '') + 'Event',
65
+ 'commandName' => event.command_name,
66
+ 'duration' => event.duration,
67
+ 'failure' => event.failure,
68
+ 'observedAt' => Time.now.to_f,
69
+ 'address' => event.address.seed,
70
+ 'requestId' => event.request_id,
71
+ 'operationId' => event.operation_id,
72
+ )
73
+ end
74
+
75
+ def published(event)
76
+ payload = {
77
+ 'name' => event.class.name.sub(/.*::/, '') + 'Event',
78
+ 'observedAt' => Time.now.to_f,
79
+ 'address' => event.address.seed,
80
+ }.tap do |entry|
81
+ if event.respond_to?(:connection_id)
82
+ entry['connectionId'] = event.connection_id
83
+ end
84
+ if event.respond_to?(:reason)
85
+ entry['reason'] = event.reason
86
+ end
87
+ end
88
+ @handler.call(payload)
89
+ end
90
+ end
91
+ end