mongo 2.8.0 → 2.9.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 (276) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/Rakefile +12 -0
  5. data/lib/mongo.rb +15 -1
  6. data/lib/mongo/address/ipv6.rb +0 -2
  7. data/lib/mongo/auth/scram/conversation.rb +0 -3
  8. data/lib/mongo/bulk_write/result_combiner.rb +12 -2
  9. data/lib/mongo/client.rb +59 -6
  10. data/lib/mongo/cluster.rb +19 -8
  11. data/lib/mongo/cluster/reapers/cursor_reaper.rb +0 -2
  12. data/lib/mongo/cluster/reapers/socket_reaper.rb +12 -9
  13. data/lib/mongo/collection.rb +1 -1
  14. data/lib/mongo/collection/view/aggregation.rb +5 -1
  15. data/lib/mongo/collection/view/builder/map_reduce.rb +1 -1
  16. data/lib/mongo/collection/view/change_stream.rb +30 -10
  17. data/lib/mongo/collection/view/iterable.rb +13 -6
  18. data/lib/mongo/collection/view/map_reduce.rb +12 -10
  19. data/lib/mongo/collection/view/readable.rb +19 -14
  20. data/lib/mongo/cursor.rb +12 -8
  21. data/lib/mongo/database.rb +10 -7
  22. data/lib/mongo/database/view.rb +18 -11
  23. data/lib/mongo/error.rb +2 -2
  24. data/lib/mongo/error/connection_check_out_timeout.rb +49 -0
  25. data/lib/mongo/error/operation_failure.rb +9 -9
  26. data/lib/mongo/error/parser.rb +25 -3
  27. data/lib/mongo/error/pool_closed_error.rb +43 -0
  28. data/lib/mongo/error/sdam_error_detection.rb +18 -0
  29. data/lib/mongo/grid/file/chunk.rb +0 -2
  30. data/lib/mongo/grid/fs_bucket.rb +26 -12
  31. data/lib/mongo/grid/stream/read.rb +36 -21
  32. data/lib/mongo/index/view.rb +11 -7
  33. data/lib/mongo/logger.rb +0 -2
  34. data/lib/mongo/monitoring.rb +31 -0
  35. data/lib/mongo/monitoring/cmap_log_subscriber.rb +53 -0
  36. data/lib/mongo/monitoring/event.rb +1 -0
  37. data/lib/mongo/monitoring/event/cmap.rb +25 -0
  38. data/lib/mongo/monitoring/event/cmap/base.rb +28 -0
  39. data/lib/mongo/monitoring/event/cmap/connection_check_out_failed.rb +78 -0
  40. data/lib/mongo/monitoring/event/cmap/connection_check_out_started.rb +56 -0
  41. data/lib/mongo/monitoring/event/cmap/connection_checked_in.rb +63 -0
  42. data/lib/mongo/monitoring/event/cmap/connection_checked_out.rb +64 -0
  43. data/lib/mongo/monitoring/event/cmap/connection_closed.rb +103 -0
  44. data/lib/mongo/monitoring/event/cmap/connection_created.rb +64 -0
  45. data/lib/mongo/monitoring/event/cmap/connection_ready.rb +64 -0
  46. data/lib/mongo/monitoring/event/cmap/pool_cleared.rb +57 -0
  47. data/lib/mongo/monitoring/event/cmap/pool_closed.rb +57 -0
  48. data/lib/mongo/monitoring/event/cmap/pool_created.rb +63 -0
  49. data/lib/mongo/monitoring/event/command_started.rb +12 -3
  50. data/lib/mongo/monitoring/publishable.rb +10 -2
  51. data/lib/mongo/operation.rb +0 -1
  52. data/lib/mongo/operation/find/legacy/result.rb +1 -0
  53. data/lib/mongo/operation/list_collections/result.rb +7 -1
  54. data/lib/mongo/operation/result.rb +10 -1
  55. data/lib/mongo/operation/shared/executable.rb +15 -0
  56. data/lib/mongo/operation/shared/result/use_legacy_error_parser.rb +29 -0
  57. data/lib/mongo/operation/shared/specifiable.rb +0 -16
  58. data/lib/mongo/operation/update/legacy/result.rb +1 -0
  59. data/lib/mongo/protocol/compressed.rb +0 -2
  60. data/lib/mongo/protocol/msg.rb +25 -2
  61. data/lib/mongo/retryable.rb +171 -33
  62. data/lib/mongo/server.rb +26 -7
  63. data/lib/mongo/server/app_metadata.rb +0 -2
  64. data/lib/mongo/server/connectable.rb +8 -2
  65. data/lib/mongo/server/connection.rb +83 -13
  66. data/lib/mongo/server/connection_base.rb +1 -1
  67. data/lib/mongo/server/connection_pool.rb +439 -43
  68. data/lib/mongo/server/monitor/connection.rb +4 -1
  69. data/lib/mongo/session.rb +37 -5
  70. data/lib/mongo/session/session_pool.rb +2 -2
  71. data/lib/mongo/socket.rb +0 -2
  72. data/lib/mongo/socket/ssl.rb +0 -2
  73. data/lib/mongo/uri.rb +127 -66
  74. data/lib/mongo/uri/srv_protocol.rb +35 -13
  75. data/lib/mongo/version.rb +1 -1
  76. data/spec/README.md +190 -63
  77. data/spec/integration/change_stream_spec.rb +64 -0
  78. data/spec/integration/command_spec.rb +0 -7
  79. data/spec/integration/error_detection_spec.rb +39 -0
  80. data/spec/integration/read_concern.rb +83 -0
  81. data/spec/integration/retryable_writes_spec.rb +6 -50
  82. data/spec/integration/sdam_error_handling_spec.rb +60 -7
  83. data/spec/integration/ssl_uri_options_spec.rb +24 -0
  84. data/spec/integration/step_down_spec.rb +197 -0
  85. data/spec/lite_spec_helper.rb +4 -0
  86. data/spec/mongo/client_construction_spec.rb +42 -17
  87. data/spec/mongo/client_spec.rb +32 -1
  88. data/spec/mongo/cluster/socket_reaper_spec.rb +2 -2
  89. data/spec/mongo/cluster_spec.rb +36 -2
  90. data/spec/mongo/collection/view/aggregation_spec.rb +2 -0
  91. data/spec/mongo/collection/view/change_stream_spec.rb +28 -28
  92. data/spec/mongo/collection/view/readable_spec.rb +1 -1
  93. data/spec/mongo/collection/view_spec.rb +3 -1
  94. data/spec/mongo/cursor_spec.rb +5 -5
  95. data/spec/mongo/error/parser_spec.rb +61 -1
  96. data/spec/mongo/grid/stream/read_spec.rb +2 -2
  97. data/spec/mongo/monitoring/event/cmap/connection_check_out_failed_spec.rb +23 -0
  98. data/spec/mongo/monitoring/event/cmap/connection_check_out_started_spec.rb +19 -0
  99. data/spec/mongo/monitoring/event/cmap/connection_checked_in_spec.rb +23 -0
  100. data/spec/mongo/monitoring/event/cmap/connection_checked_out_spec.rb +23 -0
  101. data/spec/mongo/monitoring/event/cmap/connection_closed_spec.rb +27 -0
  102. data/spec/mongo/monitoring/event/cmap/connection_created_spec.rb +24 -0
  103. data/spec/mongo/monitoring/event/cmap/connection_ready_spec.rb +24 -0
  104. data/spec/mongo/monitoring/event/cmap/pool_cleared_spec.rb +19 -0
  105. data/spec/mongo/monitoring/event/cmap/pool_closed_spec.rb +19 -0
  106. data/spec/mongo/monitoring/event/cmap/pool_created_spec.rb +26 -0
  107. data/spec/mongo/operation/delete/bulk_spec.rb +1 -6
  108. data/spec/mongo/operation/delete/command_spec.rb +1 -1
  109. data/spec/mongo/operation/delete/op_msg_spec.rb +1 -1
  110. data/spec/mongo/operation/delete_spec.rb +4 -4
  111. data/spec/mongo/operation/insert/bulk_spec.rb +1 -1
  112. data/spec/mongo/operation/insert/command_spec.rb +1 -1
  113. data/spec/mongo/operation/insert/op_msg_spec.rb +1 -1
  114. data/spec/mongo/operation/update/bulk_spec.rb +1 -1
  115. data/spec/mongo/operation/update/command_spec.rb +2 -2
  116. data/spec/mongo/operation/update/op_msg_spec.rb +2 -2
  117. data/spec/mongo/protocol/msg_spec.rb +11 -0
  118. data/spec/mongo/retryable_spec.rb +78 -25
  119. data/spec/mongo/server/connection_pool_spec.rb +661 -126
  120. data/spec/mongo/server/connection_spec.rb +55 -7
  121. data/spec/mongo/server_spec.rb +5 -0
  122. data/spec/mongo/uri/srv_protocol_spec.rb +135 -2
  123. data/spec/mongo/uri_option_parsing_spec.rb +511 -0
  124. data/spec/mongo/uri_spec.rb +42 -6
  125. data/spec/spec_helper.rb +1 -84
  126. data/spec/spec_tests/cmap_spec.rb +50 -0
  127. data/spec/spec_tests/command_monitoring_spec.rb +7 -18
  128. data/spec/spec_tests/crud_spec.rb +3 -49
  129. data/spec/spec_tests/data/cmap/connection-must-have-id.yml +21 -0
  130. data/spec/spec_tests/data/cmap/connection-must-order-ids.yml +21 -0
  131. data/spec/spec_tests/data/cmap/pool-checkin-destroy-closed.yml +24 -0
  132. data/spec/spec_tests/data/cmap/pool-checkin-destroy-stale.yml +24 -0
  133. data/spec/spec_tests/data/cmap/pool-checkin-make-available.yml +21 -0
  134. data/spec/spec_tests/data/cmap/pool-checkin.yml +18 -0
  135. data/spec/spec_tests/data/cmap/pool-checkout-connection.yml +13 -0
  136. data/spec/spec_tests/data/cmap/pool-checkout-error-closed.yml +28 -0
  137. data/spec/spec_tests/data/cmap/pool-checkout-multiple.yml +34 -0
  138. data/spec/spec_tests/data/cmap/pool-checkout-no-idle.yml +31 -0
  139. data/spec/spec_tests/data/cmap/pool-checkout-no-stale.yml +29 -0
  140. data/spec/spec_tests/data/cmap/pool-close-destroy-conns.yml +26 -0
  141. data/spec/spec_tests/data/cmap/pool-close.yml +11 -0
  142. data/spec/spec_tests/data/cmap/pool-create-max-size.yml +56 -0
  143. data/spec/spec_tests/data/cmap/pool-create-min-size.yml +27 -0
  144. data/spec/spec_tests/data/cmap/pool-create-with-options.yml +20 -0
  145. data/spec/spec_tests/data/cmap/pool-create.yml +12 -0
  146. data/spec/spec_tests/data/cmap/wait-queue-fairness.yml +94 -0
  147. data/spec/spec_tests/data/cmap/wait-queue-timeout.yml +41 -0
  148. data/spec/spec_tests/data/retryable_reads/aggregate-serverErrors.yml +157 -0
  149. data/spec/spec_tests/data/retryable_reads/aggregate.yml +87 -0
  150. data/spec/spec_tests/data/retryable_reads/changeStreams-client.watch-serverErrors.yml +149 -0
  151. data/spec/spec_tests/data/retryable_reads/changeStreams-client.watch.yml +61 -0
  152. data/spec/spec_tests/data/retryable_reads/changeStreams-db.coll.watch-serverErrors.yml +149 -0
  153. data/spec/spec_tests/data/retryable_reads/changeStreams-db.coll.watch.yml +65 -0
  154. data/spec/spec_tests/data/retryable_reads/changeStreams-db.watch-serverErrors.yml +153 -0
  155. data/spec/spec_tests/data/retryable_reads/changeStreams-db.watch.yml +61 -0
  156. data/spec/spec_tests/data/retryable_reads/count-serverErrors.yml +150 -0
  157. data/spec/spec_tests/data/retryable_reads/count.yml +64 -0
  158. data/spec/spec_tests/data/retryable_reads/countDocuments-serverErrors.yml +150 -0
  159. data/spec/spec_tests/data/retryable_reads/countDocuments.yml +64 -0
  160. data/spec/spec_tests/data/retryable_reads/distinct-serverErrors.yml +156 -0
  161. data/spec/spec_tests/data/retryable_reads/distinct.yml +71 -0
  162. data/spec/spec_tests/data/retryable_reads/estimatedDocumentCount-serverErrors.yml +148 -0
  163. data/spec/spec_tests/data/retryable_reads/estimatedDocumentCount.yml +62 -0
  164. data/spec/spec_tests/data/retryable_reads/find-serverErrors.yml +160 -0
  165. data/spec/spec_tests/data/retryable_reads/find.yml +86 -0
  166. data/spec/spec_tests/data/retryable_reads/findOne-serverErrors.yml +154 -0
  167. data/spec/spec_tests/data/retryable_reads/findOne.yml +68 -0
  168. data/spec/spec_tests/data/retryable_reads/gridfs-download-serverErrors.yml +173 -0
  169. data/spec/spec_tests/data/retryable_reads/gridfs-download.yml +79 -0
  170. data/spec/spec_tests/data/retryable_reads/gridfs-downloadByName-serverErrors.yml +174 -0
  171. data/spec/spec_tests/data/retryable_reads/gridfs-downloadByName.yml +79 -0
  172. data/spec/spec_tests/data/retryable_reads/listCollectionNames-serverErrors.yml +143 -0
  173. data/spec/spec_tests/data/retryable_reads/listCollectionNames.yml +59 -0
  174. data/spec/spec_tests/data/retryable_reads/listCollectionObjects-serverErrors.yml +144 -0
  175. data/spec/spec_tests/data/retryable_reads/listCollectionObjects.yml +59 -0
  176. data/spec/spec_tests/data/retryable_reads/listCollections-serverErrors.yml +143 -0
  177. data/spec/spec_tests/data/retryable_reads/listCollections.yml +59 -0
  178. data/spec/spec_tests/data/retryable_reads/listDatabaseNames-serverErrors.yml +143 -0
  179. data/spec/spec_tests/data/retryable_reads/listDatabaseNames.yml +59 -0
  180. data/spec/spec_tests/data/retryable_reads/listDatabaseObjects-serverErrors.yml +144 -0
  181. data/spec/spec_tests/data/retryable_reads/listDatabaseObjects.yml +59 -0
  182. data/spec/spec_tests/data/retryable_reads/listDatabases-serverErrors.yml +144 -0
  183. data/spec/spec_tests/data/retryable_reads/listDatabases.yml +59 -0
  184. data/spec/spec_tests/data/retryable_reads/listIndexNames-serverErrors.yml +144 -0
  185. data/spec/spec_tests/data/retryable_reads/listIndexNames.yml +60 -0
  186. data/spec/spec_tests/data/retryable_reads/listIndexes-serverErrors.yml +145 -0
  187. data/spec/spec_tests/data/retryable_reads/listIndexes.yml +60 -0
  188. data/spec/spec_tests/data/retryable_reads/mapReduce.yml +60 -0
  189. data/spec/spec_tests/data/retryable_writes/bulkWrite-serverErrors.yml +10 -7
  190. data/spec/spec_tests/data/retryable_writes/bulkWrite.yml +15 -22
  191. data/spec/spec_tests/data/retryable_writes/deleteMany.yml +22 -0
  192. data/spec/spec_tests/data/retryable_writes/deleteOne-serverErrors.yml +8 -7
  193. data/spec/spec_tests/data/retryable_writes/deleteOne.yml +5 -8
  194. data/spec/spec_tests/data/retryable_writes/findOneAndDelete-serverErrors.yml +8 -7
  195. data/spec/spec_tests/data/retryable_writes/findOneAndDelete.yml +5 -8
  196. data/spec/spec_tests/data/retryable_writes/findOneAndReplace-serverErrors.yml +8 -7
  197. data/spec/spec_tests/data/retryable_writes/findOneAndReplace.yml +5 -8
  198. data/spec/spec_tests/data/retryable_writes/findOneAndUpdate-serverErrors.yml +8 -7
  199. data/spec/spec_tests/data/retryable_writes/findOneAndUpdate.yml +5 -8
  200. data/spec/spec_tests/data/retryable_writes/insertMany-serverErrors.yml +8 -7
  201. data/spec/spec_tests/data/retryable_writes/insertMany.yml +5 -8
  202. data/spec/spec_tests/data/retryable_writes/insertOne-serverErrors.yml +10 -45
  203. data/spec/spec_tests/data/retryable_writes/insertOne.yml +5 -8
  204. data/spec/spec_tests/data/retryable_writes/replaceOne-serverErrors.yml +8 -7
  205. data/spec/spec_tests/data/retryable_writes/replaceOne.yml +5 -8
  206. data/spec/spec_tests/data/retryable_writes/updateMany.yml +27 -0
  207. data/spec/spec_tests/data/retryable_writes/updateOne-serverErrors.yml +8 -7
  208. data/spec/spec_tests/data/retryable_writes/updateOne.yml +5 -14
  209. data/spec/spec_tests/data/transactions/abort.yml +7 -2
  210. data/spec/spec_tests/data/transactions/bulk.yml +7 -2
  211. data/spec/spec_tests/data/transactions/causal-consistency.yml +11 -4
  212. data/spec/spec_tests/data/transactions/commit.yml +11 -4
  213. data/spec/spec_tests/data/transactions/count.yml +64 -0
  214. data/spec/spec_tests/data/transactions/delete.yml +7 -2
  215. data/spec/spec_tests/data/transactions/error-labels.yml +8 -2
  216. data/spec/spec_tests/data/transactions/errors.yml +7 -2
  217. data/spec/spec_tests/data/transactions/findOneAndDelete.yml +7 -2
  218. data/spec/spec_tests/data/transactions/findOneAndReplace.yml +7 -2
  219. data/spec/spec_tests/data/transactions/findOneAndUpdate.yml +7 -2
  220. data/spec/spec_tests/data/transactions/insert.yml +9 -2
  221. data/spec/spec_tests/data/transactions/isolation.yml +7 -2
  222. data/spec/spec_tests/data/transactions/read-concern.yml +15 -6
  223. data/spec/spec_tests/data/transactions/read-pref.yml +7 -2
  224. data/spec/spec_tests/data/transactions/reads.yml +8 -48
  225. data/spec/spec_tests/data/transactions/retryable-abort.yml +7 -2
  226. data/spec/spec_tests/data/transactions/retryable-commit.yml +7 -2
  227. data/spec/spec_tests/data/transactions/retryable-writes.yml +7 -2
  228. data/spec/spec_tests/data/transactions/run-command.yml +7 -2
  229. data/spec/spec_tests/data/transactions/transaction-options.yml +7 -2
  230. data/spec/spec_tests/data/transactions/update.yml +7 -2
  231. data/spec/spec_tests/data/transactions/write-concern.yml +7 -2
  232. data/spec/spec_tests/data/transactions_api/callback-aborts.yml +6 -1
  233. data/spec/spec_tests/data/transactions_api/callback-commits.yml +6 -1
  234. data/spec/spec_tests/data/transactions_api/callback-retry.yml +6 -1
  235. data/spec/spec_tests/data/transactions_api/commit-retry.yml +6 -1
  236. data/spec/spec_tests/data/transactions_api/commit-transienttransactionerror-4.2.yml +6 -3
  237. data/spec/spec_tests/data/transactions_api/commit-transienttransactionerror.yml +6 -1
  238. data/spec/spec_tests/data/transactions_api/commit-writeconcernerror.yml +6 -1
  239. data/spec/spec_tests/data/transactions_api/commit.yml +6 -1
  240. data/spec/spec_tests/data/transactions_api/transaction-options.yml +6 -1
  241. data/spec/spec_tests/retryable_reads_spec.rb +11 -0
  242. data/spec/spec_tests/retryable_writes_spec.rb +4 -69
  243. data/spec/spec_tests/transactions_api_spec.rb +42 -37
  244. data/spec/spec_tests/transactions_spec.rb +42 -33
  245. data/spec/support/authorization.rb +12 -0
  246. data/spec/support/change_streams/operation.rb +1 -1
  247. data/spec/support/client_registry.rb +20 -0
  248. data/spec/support/cluster_config.rb +16 -15
  249. data/spec/support/cluster_tools.rb +346 -0
  250. data/spec/support/cmap.rb +367 -0
  251. data/spec/support/cmap/verifier.rb +46 -0
  252. data/spec/support/command_monitoring.rb +4 -6
  253. data/spec/support/common_shortcuts.rb +6 -0
  254. data/spec/support/connection_string.rb +2 -2
  255. data/spec/support/crud.rb +171 -184
  256. data/spec/support/crud/operation.rb +43 -0
  257. data/spec/support/crud/outcome.rb +53 -0
  258. data/spec/support/crud/read.rb +102 -12
  259. data/spec/support/crud/requirement.rb +69 -0
  260. data/spec/support/crud/spec.rb +68 -0
  261. data/spec/support/crud/test.rb +141 -0
  262. data/spec/support/crud/verifier.rb +96 -18
  263. data/spec/support/crud/write.rb +18 -3
  264. data/spec/support/event_subscriber.rb +15 -0
  265. data/spec/support/primary_socket.rb +2 -2
  266. data/spec/support/spec_config.rb +89 -20
  267. data/spec/support/transactions.rb +2 -306
  268. data/spec/support/transactions/operation.rb +7 -7
  269. data/spec/support/transactions/spec.rb +28 -0
  270. data/spec/support/transactions/test.rb +191 -0
  271. data/spec/support/utils.rb +123 -0
  272. metadata +202 -9
  273. metadata.gz.sig +0 -0
  274. data/lib/mongo/server/connection_pool/queue.rb +0 -359
  275. data/spec/mongo/server/connection_pool/queue_spec.rb +0 -353
  276. data/spec/support/transactions/verifier.rb +0 -97
@@ -225,7 +225,7 @@ module Mongo
225
225
  # Write Options
226
226
  'journal' => [:write, 'j'],
227
227
  'w' => [:write, 'w'],
228
- 'wtimeoutms' => [:write, 'timeout'],
228
+ 'wtimeoutms' => [:write, 'wtimeout'],
229
229
 
230
230
  # Read Options
231
231
  'readpreference' => ['read', 'mode'],
@@ -252,7 +252,7 @@ module Mongo
252
252
 
253
253
  # Client Options
254
254
  'appname' => :app_name,
255
- 'readconcernlevel' => :read_concern,
255
+ 'readconcernlevel' => [:read_concern, 'level'],
256
256
  'retrywrites' => :retry_writes,
257
257
  'zlibcompressionlevel' => :zlib_compression_level,
258
258
  }
@@ -12,220 +12,207 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ require 'support/gridfs'
16
+ require 'support/crud/requirement'
17
+ require 'support/crud/spec'
18
+ require 'support/crud/test'
19
+ require 'support/crud/outcome'
20
+ require 'support/crud/operation'
15
21
  require 'support/crud/read'
16
22
  require 'support/crud/write'
17
23
  require 'support/crud/verifier'
18
24
 
19
- module Mongo
20
- module CRUD
21
-
22
- # Represents a CRUD specification test.
23
- #
24
- # @since 2.0.0
25
- class Spec
26
-
27
- # @return [ String ] description The spec description.
28
- #
29
- # @since 2.0.0
30
- attr_reader :description
31
-
32
- # Instantiate the new spec.
33
- #
34
- # @example Create the spec.
35
- # Spec.new(file)
36
- #
37
- # @param [ String ] file The name of the file.
38
- #
39
- # @since 2.0.0
40
- def initialize(file)
41
- file = File.new(file)
42
- @spec = YAML.load(ERB.new(file.read).result)
43
- file.close
44
- @description = File.basename(file)
45
- @data = @spec['data']
46
- @crud_tests = @spec['tests']
47
- @min_server_version = @spec['minServerVersion']
48
- @max_server_version = @spec['maxServerVersion']
49
- end
25
+ def crud_execute_operations(spec, test, num_ops, event_subscriber, expect_error,
26
+ client
27
+ )
28
+ cache_key = "#{test.object_id}:#{num_ops}"
29
+ $crud_result_cache ||= {}
30
+ $crud_result_cache[cache_key] ||= begin
31
+ if spec.bucket_name
32
+ client["#{spec.bucket_name}.files"].delete_many
33
+ client["#{spec.bucket_name}.chunks"].delete_many
34
+ else
35
+ client[spec.collection_name].delete_many
36
+ end
50
37
 
38
+ test.setup_test(spec, client)
51
39
 
52
- # Whether the test can be run on a given server version.
53
- #
54
- # @example Can the test run on this server version?
55
- # spec.server_version_satisfied?(client)
56
- #
57
- # @param [ Mongo::Client ] client The client to check.
58
- #
59
- # @return [ true, false ] Whether the test can be run on the given
60
- # server version.
61
- #
62
- # @since 2.4.0
63
- def server_version_satisfied?(client)
64
- lower_bound_satisfied?(client) && upper_bound_satisfied?(client)
65
- end
40
+ event_subscriber.clear_events!
66
41
 
67
- # Get a list of CRUDTests for each test definition.
68
- #
69
- # @example Get the list of CRUDTests.
70
- # spec.tests
71
- #
72
- # @return [ Array<CRUDTest> ] The list of CRUDTests.
73
- #
74
- # @since 2.0.0
75
- def tests
76
- @crud_tests.collect do |test|
77
- Mongo::CRUD::CRUDTest.new(@data, test)
78
- end
42
+ result = if expect_error.nil?
43
+ res = nil
44
+ begin
45
+ res = test.run(spec, client, num_ops)
46
+ rescue => e
47
+ res = e
79
48
  end
80
-
81
- private
82
-
83
- def upper_bound_satisfied?(client)
84
- return true unless @max_server_version
85
- client.database.command(buildInfo: 1).first['version'] <= @max_server_version
49
+ res
50
+ elsif expect_error
51
+ error = nil
52
+ begin
53
+ test.run(spec, client, num_ops)
54
+ rescue => e
55
+ error = e
86
56
  end
57
+ error
58
+ else
59
+ test.run(spec, client, num_ops)
60
+ end
87
61
 
88
- def lower_bound_satisfied?(client)
89
- return true unless @min_server_version
90
- #@min_server_version <= client.database.command(buildInfo: 1).first['version']
91
- @min_server_version <= ClusterConfig.instance.fcv_ish
92
- end
62
+ $crud_event_cache ||= {}
63
+ # It only makes sense to assert on events if all operations succeeded,
64
+ # but populate our cache in any event for simplicity
65
+ $crud_event_cache[cache_key] = event_subscriber.started_events.dup
66
+
67
+ last_op = test.operations[num_ops-1]
68
+ if last_op.outcome && last_op.outcome.collection_data?
69
+ verify_collection = client[last_op.verify_collection_name]
70
+ $crud_collection_data_cache ||= {}
71
+ $crud_collection_data_cache[cache_key] = verify_collection.find.to_a
93
72
  end
94
73
 
95
- # Represents a single CRUD test.
96
- #
97
- # @since 2.0.0
98
- class CRUDTest
99
-
100
- # The test description.
101
- #
102
- # @return [ String ] description The test description.
103
- #
104
- # @since 2.0.0
105
- attr_reader :description
106
-
107
- # Spec tests have configureFailPoint as a string, make it a string here too
108
- FAIL_POINT_BASE_COMMAND = {
109
- 'configureFailPoint' => "onPrimaryTransactionalWrite",
110
- }.freeze
111
-
112
- # Instantiate the new CRUDTest.
113
- #
114
- # @example Create the test.
115
- # CRUDTest.new(data, test)
116
- #
117
- # @param [ Array<Hash> ] data The documents the collection
118
- # must have before the test runs.
119
- # @param [ Hash ] test The test specification.
120
- #
121
- # @since 2.0.0
122
- def initialize(data, test)
123
- @data = data
124
- if test['failPoint']
125
- @fail_point_command = FAIL_POINT_BASE_COMMAND.merge(test['failPoint'])
126
- end
127
- @description = test['description']
128
- @operation = Operation.get(test['operation'])
129
- @outcome = test['outcome']
130
- end
74
+ result
75
+ ensure
76
+ test.clear_fail_point(client)
77
+ end
78
+ end
131
79
 
132
- attr_reader :outcome
133
-
134
- # Run the test.
135
- #
136
- # @example Run the test.
137
- # test.run(collection)
138
- #
139
- # @param [ Collection ] collection The collection the test
140
- # should be run on.
141
- #
142
- # @return [ Result, Array<Hash> ] The result(s) of running the test.
143
- #
144
- # @since 2.0.0
145
- def run(collection)
146
- @operation.execute(collection)
80
+ def define_crud_spec_test_examples(spec, req = nil, &block)
81
+ spec.tests.each do |test|
82
+
83
+ context(test.description) do
84
+
85
+ if test.description =~ /ListIndexNames/
86
+ before do
87
+ skip "Ruby driver does not implement list_index_names"
88
+ end
147
89
  end
148
90
 
149
- def setup_test(collection)
150
- clear_fail_point(collection)
151
- @collection = collection
152
- collection.delete_many
153
- collection.insert_many(@data)
154
- set_up_fail_point(collection)
91
+ let(:event_subscriber) do
92
+ EventSubscriber.new
155
93
  end
156
94
 
157
- def set_up_fail_point(collection)
158
- if @fail_point_command
159
- collection.client.use(:admin).command(@fail_point_command)
95
+ let(:verifier) { Mongo::CRUD::Verifier.new(test) }
96
+
97
+ let(:verify_collection) { client[verify_collection_name] }
98
+
99
+ instance_exec(spec, req, test, &block)
100
+
101
+ test.operations.each_with_index do |operation, index|
102
+
103
+ context "operation #{index+1}" do
104
+
105
+ let(:result) do
106
+ crud_execute_operations(spec, test, index+1,
107
+ event_subscriber, operation.outcome.error?, client)
108
+ end
109
+
110
+ let(:verify_collection_name) do
111
+ if operation.outcome && operation.outcome.collection_name
112
+ operation.outcome.collection_name
113
+ else
114
+ spec.collection_name
115
+ end
116
+ end
117
+
118
+ if operation.outcome.error?
119
+ it 'raises an error' do
120
+ expect(result).to be_a(Mongo::Error)
121
+ end
122
+ else
123
+ tested = false
124
+
125
+ if operation.outcome.result
126
+ tested = true
127
+ it 'returns the correct result' do
128
+ result
129
+ verifier.verify_operation_result(operation.outcome.result, result)
130
+ end
131
+ end
132
+
133
+ if operation.outcome.collection_data?
134
+ tested = true
135
+ it 'has the correct data in the collection' do
136
+ result
137
+ verifier.verify_collection_data(
138
+ operation.outcome.collection_data,
139
+ verify_collection.find.to_a)
140
+ end
141
+ end
142
+
143
+ unless tested
144
+ it 'succeeds' do
145
+ expect do
146
+ result
147
+ end.not_to raise_error
148
+ end
149
+ end
150
+ end
160
151
  end
161
152
  end
162
153
 
163
- def clear_fail_point(collection)
164
- if @fail_point_command
165
- collection.client.use(:admin).command(FAIL_POINT_BASE_COMMAND.merge(mode: "off"))
154
+ if test.expectations
155
+ let(:result) do
156
+ crud_execute_operations(spec, test, test.operations.length,
157
+ event_subscriber, nil, client)
166
158
  end
167
- end
168
159
 
169
- # The expected result of running the test.
170
- #
171
- # @example Get the expected result of running the test.
172
- # test.result
173
- #
174
- # @return [ Array<Hash> ] The expected result of running the test.
175
- #
176
- # @since 2.0.0
177
- def result
178
- @operation.has_results? ? @outcome['result'] : []
179
- end
160
+ let(:actual_events) do
161
+ result
162
+ Utils.yamlify_command_events($crud_event_cache["#{test.object_id}:#{test.operations.length}"])
163
+ end
180
164
 
181
- def error?
182
- !!@outcome['error']
183
- end
165
+ it 'has the correct number of command_started events' do
166
+ verifier.verify_command_started_event_count(test.expectations, actual_events)
167
+ end
184
168
 
185
- # The expected data in the collection as an outcome after running this test.
186
- #
187
- # @example Get the outcome collection data
188
- # test.outcome_collection_data
189
- #
190
- # @return [ Array<Hash> ] The list of documents expected to be in the collection
191
- # after running this test.
192
- #
193
- # @since 2.4.0
194
- def outcome_collection_data
195
- @outcome['collection']['data'] if @outcome['collection']
169
+ test.expectations.each_with_index do |expectation, i|
170
+ it "has the correct command_started event #{i+1}" do
171
+ verifier.verify_command_started_event(
172
+ test.expectations, actual_events, i)
173
+ end
174
+ end
196
175
  end
176
+ end
177
+ end
178
+ end
197
179
 
198
- private
199
-
200
- def actual_collection_data
201
- if @outcome['collection']
202
- collection_name = @outcome['collection']['name'] || @collection.name
203
- @collection.database[collection_name].find.to_a
180
+ def define_spec_tests_with_requirements(spec, &block)
181
+ if spec.requirements
182
+ # This block defines the same set of examples multiple times,
183
+ # once for each requirement specified in the YAML files.
184
+ # This allows detecting when any of the configurations is
185
+ # not tested by CI.
186
+ spec.requirements.each do |req|
187
+ context(req.description) do
188
+ if req.min_server_version
189
+ min_server_fcv req.short_min_server_version
204
190
  end
191
+ if req.max_server_version
192
+ max_server_version req.short_max_server_version
193
+ end
194
+ if req.topologies
195
+ require_topology *req.topologies
196
+ end
197
+
198
+ instance_exec(req, &block)
205
199
  end
206
200
  end
201
+ else
202
+ yield
203
+ end
204
+ end
205
+
206
+ def define_crud_spec_tests(description, test_paths, &block)
207
+ describe(description) do
208
+
209
+ test_paths.each do |path|
210
+
211
+ spec = Mongo::CRUD::Spec.new(path)
207
212
 
208
- # Helper module for instantiating either a Read or Write test operation.
209
- #
210
- # @since 2.0.0
211
- module Operation
212
- extend self
213
-
214
- # Get a new Operation.
215
- #
216
- # @example Get the operation.
217
- # Operation.get(spec)
218
- #
219
- # @param [ Hash ] spec The operation specification.
220
- #
221
- # @return [ Operation::Write, Operation::Read ] The Operation object.
222
- #
223
- # @since 2.0.0
224
- def get(spec)
225
- if Write::OPERATIONS.keys.include?(spec['name'])
226
- Write.new(spec)
227
- else
228
- Read.new(spec)
213
+ context(spec.description) do
214
+ define_spec_tests_with_requirements(spec) do |req|
215
+ define_crud_spec_test_examples(spec, req, &block)
229
216
  end
230
217
  end
231
218
  end
@@ -0,0 +1,43 @@
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
+
18
+ # Helper module for instantiating either a Read or Write test operation.
19
+ #
20
+ # @since 2.0.0
21
+ module Operation
22
+ extend self
23
+
24
+ # Get a new Operation.
25
+ #
26
+ # @example Get the operation.
27
+ # Operation.get(spec)
28
+ #
29
+ # @param [ Hash ] spec The operation specification.
30
+ #
31
+ # @return [ Operation::Write, Operation::Read ] The Operation object.
32
+ #
33
+ # @since 2.0.0
34
+ def get(spec, outcome_spec = nil)
35
+ if Write::OPERATIONS.keys.include?(spec['name'])
36
+ Write.new(spec, outcome_spec)
37
+ else
38
+ Read.new(spec, outcome_spec)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end