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
@@ -0,0 +1,367 @@
1
+ require 'support/cmap/verifier'
2
+
3
+ module Mongo
4
+ module Cmap
5
+
6
+ # Represents a specification.
7
+ class Spec
8
+
9
+ # @return [ String ] description The spec description.
10
+ attr_reader :description
11
+
12
+ # @return [ Hash ] pool_options The options for the created pools.
13
+ attr_reader :pool_options
14
+
15
+ # @return [ Array<Operation> ] spec_ops The spec operations.
16
+ attr_reader :spec_ops
17
+
18
+ # @return [ Array<Operation> ] processed_ops The processed operations.
19
+ attr_reader :processed_ops
20
+
21
+ # @return [ Error | nil ] error The expected error.
22
+ attr_reader :expected_error
23
+
24
+ # @return [ Array<Event::Base> ] events The events expected to occur.
25
+ attr_reader :expected_events
26
+
27
+ # @return [ Array<String> ] events The names of events to ignore.
28
+ attr_reader :ignore_events
29
+
30
+ # @return [ Mongo::ConnectionPool ] pool The connection pool to use for operations.
31
+ attr_reader :pool
32
+
33
+ # @return [ EventSubscriber ] subscriber The subscriber receiving the CMAP events.
34
+ attr_reader :subscriber
35
+
36
+ # Instantiate the new spec.
37
+ #
38
+ # @example Create the spec.
39
+ # Spec.new(file)
40
+ #
41
+ # @param [ String ] file The name of the file.
42
+ def initialize(file)
43
+ @test = YAML.load(ERB.new(File::read(file)).result)
44
+
45
+ @description = @test['description']
46
+ @pool_options = Utils.snakeize_hash(process_options(@test['poolOptions']))
47
+ @spec_ops = @test['operations'].map { |o| Operation.new(self, o) }
48
+ @processed_ops = []
49
+ @expected_error = @test['error']
50
+ @expected_events = @test['events']
51
+ @ignore_events = @test['ignore'] || []
52
+
53
+ preprocess
54
+ end
55
+
56
+ def setup(cluster)
57
+ @subscriber = EventSubscriber.new
58
+
59
+ monitoring = Mongo::Monitoring.new(monitoring: false)
60
+ monitoring.subscribe(Mongo::Monitoring::CONNECTION_POOL, subscriber)
61
+
62
+ server = Mongo::Server.new(
63
+ Address.new(SpecConfig.instance.addresses.first),
64
+ cluster,
65
+ monitoring,
66
+ Mongo::Event::Listeners.new,
67
+ pool_options.merge(monitoring_io: false))
68
+
69
+ @pool = server.pool
70
+ @pool.populate
71
+ end
72
+
73
+ def run
74
+ state = {}
75
+
76
+ {}.tap do |result|
77
+ processed_ops.each do |op|
78
+ err = op.run(pool, state)
79
+
80
+ if err
81
+ result['error'] = err
82
+ break
83
+ end
84
+ end
85
+
86
+ result['error'] ||= nil
87
+ result['events'] = subscriber.published_events.reduce([]) do |events, event|
88
+ next events unless event.is_a?(Mongo::Monitoring::Event::Cmap::Base)
89
+
90
+ event = case event
91
+ when Mongo::Monitoring::Event::Cmap::PoolCreated
92
+ {
93
+ 'type' => 'ConnectionPoolCreated',
94
+ 'address' => event.address,
95
+ 'options' => normalize_options(event.options),
96
+ }
97
+ when Mongo::Monitoring::Event::Cmap::PoolClosed
98
+ {
99
+ 'type' => 'ConnectionPoolClosed',
100
+ 'address' => event.address,
101
+ }
102
+ when Mongo::Monitoring::Event::Cmap::ConnectionCreated
103
+ {
104
+ 'type' => 'ConnectionCreated',
105
+ 'connectionId' => event.connection_id,
106
+ }
107
+ when Mongo::Monitoring::Event::Cmap::ConnectionReady
108
+ {
109
+ 'type' => 'ConnectionReady',
110
+ 'connectionId' => event.connection_id,
111
+ }
112
+ when Mongo::Monitoring::Event::Cmap::ConnectionClosed
113
+ {
114
+ 'type' => 'ConnectionClosed',
115
+ 'connectionId' => event.connection_id,
116
+ 'reason' => event.reason,
117
+ }
118
+ when Mongo::Monitoring::Event::Cmap::ConnectionCheckOutStarted
119
+ {
120
+ 'type' => 'ConnectionCheckOutStarted',
121
+ }
122
+ when Mongo::Monitoring::Event::Cmap::ConnectionCheckOutFailed
123
+ {
124
+ 'type' => 'ConnectionCheckOutFailed',
125
+ 'reason' => event.reason,
126
+ }
127
+ when Mongo::Monitoring::Event::Cmap::ConnectionCheckedOut
128
+ {
129
+ 'type' => 'ConnectionCheckedOut',
130
+ 'connectionId' => event.connection_id,
131
+ }
132
+ when Mongo::Monitoring::Event::Cmap::ConnectionCheckedIn
133
+ {
134
+ 'type' => 'ConnectionCheckedIn',
135
+ 'connectionId' => event.connection_id,
136
+ }
137
+ when Mongo::Monitoring::Event::Cmap::PoolCleared
138
+ {
139
+ 'type' => 'ConnectionPoolCleared',
140
+ 'address' => event.address,
141
+ }
142
+ end
143
+
144
+ events << event unless @ignore_events.include?(event['type'])
145
+ events
146
+ end
147
+ end
148
+ end
149
+
150
+ private
151
+
152
+ # Converts the options used by the Ruby driver to the spec test format.
153
+ def normalize_options(options)
154
+ (options || {}).reduce({}) do |opts, kv|
155
+ case kv.first
156
+ when :max_idle_time
157
+ opts['maxIdleTimeMS'] = (kv.last * 1000.0).to_i
158
+ when :max_size
159
+ opts['maxPoolSize'] = kv.last
160
+ when :min_size
161
+ opts['minPoolSize'] = kv.last
162
+ when :wait_queue_size
163
+ opts['waitQueueSize'] = kv.last
164
+ when :wait_timeout
165
+ opts['waitQueueTimeoutMS'] = (kv.last * 1000.0).to_i
166
+ end
167
+
168
+ opts
169
+ end
170
+ end
171
+
172
+ # Converts the options given by the spec to the Ruby driver format.
173
+ def process_options(options)
174
+ (options || {}).reduce({}) do |opts, kv|
175
+ case kv.first
176
+ when 'maxIdleTimeMS'
177
+ opts[:max_idle_time] = kv.last / 1000.0
178
+ when 'maxPoolSize'
179
+ opts[:max_pool_size] = kv.last
180
+ when 'minPoolSize'
181
+ opts[:min_pool_size] = kv.last
182
+ when 'waitQueueSize'
183
+ opts[:wait_queue_size] = kv.last
184
+ when 'waitQueueTimeoutMS'
185
+ opts[:wait_queue_timeout] = kv.last / 1000.0
186
+ else
187
+ raise "Unknown option #{kv.first}"
188
+ end
189
+
190
+ opts
191
+ end
192
+ end
193
+
194
+ # Places operations run by the non-main thread in the `thread_ops` field of the corresponding
195
+ # `start` operation.
196
+ def preprocess
197
+ until spec_ops.empty?
198
+ processed_ops << spec_ops.shift
199
+
200
+ if processed_ops.last.name == "start"
201
+ spec_ops.delete_if do |op|
202
+ if op.thread == processed_ops.last.target
203
+ processed_ops.last.thread_ops << op
204
+ end
205
+ end
206
+ end
207
+ end
208
+ end
209
+ end
210
+
211
+ # Represents an operation in the spec. Operations are sequential.
212
+ class Operation
213
+
214
+ # @return [ String ] command The name of the operation to run.
215
+ attr_reader :name
216
+
217
+ # @return [ String | nil ] thread The identifier of the thread to run the operation on (`nil`
218
+ # signifying the default thread.)
219
+ attr_reader :thread
220
+
221
+ # @return [ String | nil ] target The name of the started thread.
222
+ attr_reader :target
223
+
224
+ # @return [ Array<Operation> ] thread_ops The operations to run on the thread.
225
+ attr_reader :thread_ops
226
+
227
+ # @return [ Integer | nil ] ms The number of milliseconds to sleep.
228
+ attr_reader :ms
229
+
230
+ # @return [ String | nil ] label The label for the returned connection.
231
+ attr_reader :label
232
+
233
+ # @return [ String | nil ] The binding for the connection which should run the operation.
234
+ attr_reader :connection
235
+
236
+ # @return [ Mongo::ConnectionPool ] pool The connection pool to use for the operation.
237
+ attr_reader :pool
238
+
239
+ # Create the new Operation.
240
+ #
241
+ # @param [ Spec ] spec The Spec object.
242
+ # @param [ Hash ] operation The operation hash.
243
+ def initialize(spec, operation)
244
+ @spec = spec
245
+ @name = operation['name']
246
+ @thread = operation['thread']
247
+ @thread_ops = []
248
+ @target = operation['target']
249
+ @ms = operation['ms']
250
+ @label = operation['label']
251
+ @connection = operation['connection']
252
+ @event = operation['event']
253
+ @count = operation['count']
254
+ end
255
+
256
+ def run(pool, state, main_thread = true)
257
+ @pool = pool
258
+
259
+ case name
260
+ when 'start'
261
+ run_start_op(state)
262
+ when 'wait'
263
+ run_wait_op(state)
264
+ when 'waitForThread'
265
+ run_wait_for_thread_op(state)
266
+ when 'waitForEvent'
267
+ run_wait_for_event_op(state)
268
+ when 'checkOut'
269
+ run_checkout_op(state)
270
+ when 'checkIn'
271
+ run_checkin_op(state)
272
+ when 'clear'
273
+ run_clear_op(state)
274
+ when 'close'
275
+ run_close_op(state)
276
+ else
277
+ raise "invalid operation: #{name}"
278
+ end
279
+
280
+ nil
281
+
282
+ # We hard-code the error messages because ours contain information like the address and the
283
+ # connection ID.
284
+ rescue Error::PoolClosedError
285
+ raise unless main_thread
286
+
287
+ {
288
+ 'type' => 'PoolClosedError',
289
+ 'message' => 'Attempted to check out a connection from closed connection pool',
290
+ }
291
+ rescue Error::ConnectionCheckOutTimeout
292
+ raise unless main_thread
293
+
294
+ {
295
+ 'type' => 'WaitQueueTimeoutError',
296
+ 'message' => 'Timed out while checking out a connection from connection pool',
297
+ }
298
+ end
299
+
300
+ private
301
+
302
+ def run_start_op(state)
303
+ state[target] = Thread.start do
304
+ Thread.current[:name] = @target
305
+ thread_ops.each { |op| op.run(pool, state, false) }
306
+ end
307
+
308
+ # Since we expect exceptions to occur in some cases, we disable the printing of error
309
+ # messages from the thread if the Ruby version supports it.
310
+ if state[target].respond_to?(:report_on_exception)
311
+ state[target].report_on_exception = false
312
+ end
313
+ end
314
+
315
+ def run_wait_op(_state)
316
+ sleep(ms / 1000.0)
317
+ end
318
+
319
+ def run_wait_for_thread_op(state)
320
+ state[target].join
321
+ end
322
+
323
+ def run_wait_for_event_op(state)
324
+ subscriber = @spec.subscriber
325
+ looped = 0
326
+ deadline = Time.now + 3
327
+ loop do
328
+ actual_events = @spec.subscriber.published_events.select do |e|
329
+ e.class.name.sub(/.*::/, '').sub(/^ConnectionPool/, 'Pool') == @event.sub(/^ConnectionPool/, 'Pool')
330
+ end
331
+ if actual_events.length >= @count
332
+ break
333
+ end
334
+ if looped == 1
335
+ puts("Waiting for #{@count} #{@event} events (have #{actual_events.length}): #{@spec.description}")
336
+ end
337
+ if Time.now > deadline
338
+ raise "Did not receive #{@count} #{@event} events in time (have #{actual_events.length}): #{@spec.description}"
339
+ end
340
+ looped += 1
341
+ sleep 0.1
342
+ end
343
+ end
344
+
345
+ def run_checkout_op(state)
346
+ conn = pool.check_out
347
+ state[label] = conn if label
348
+ end
349
+
350
+ def run_checkin_op(state)
351
+ until state[connection]
352
+ sleep(0.2)
353
+ end
354
+
355
+ pool.check_in(state[connection])
356
+ end
357
+
358
+ def run_clear_op(state)
359
+ pool.clear(lazy: true)
360
+ end
361
+
362
+ def run_close_op(state)
363
+ pool.close
364
+ end
365
+ end
366
+ end
367
+ end
@@ -0,0 +1,46 @@
1
+ # Copyright (C) 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 Cmap
17
+ class Verifier
18
+ include RSpec::Matchers
19
+
20
+ def initialize(test_instance)
21
+ @test_instance = test_instance
22
+ end
23
+
24
+ attr_reader :test_instance
25
+
26
+ def verify_hashes(actual, expected)
27
+ expect(expected).to be_a(Hash)
28
+ expect(actual).to be_a(Hash)
29
+
30
+ actual = actual.dup
31
+ if actual['reason']
32
+ actual['reason'] = actual['reason'].to_s.gsub(/_[a-z]/) { |m| m[1].upcase }
33
+ end
34
+
35
+ actual_modified = actual.dup
36
+ actual_modified.each do |k, v|
37
+ if expected.key?(k) && expected[k] == 42
38
+ actual_modified[k] = 42
39
+ end
40
+ end
41
+
42
+ expect(actual_modified).to eq(expected)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -230,11 +230,9 @@ module Mongo
230
230
  # @return [ Array<Expectation> ] The expectations.
231
231
  attr_reader :expectations
232
232
 
233
- # @return [ String ] The server version to ignore if greater.
234
- attr_reader :ignore_if_server_version_greater_than
233
+ attr_reader :min_server_fcv
235
234
 
236
- # @return [ String ] The server version to ignore if lower.
237
- attr_reader :ignore_if_server_version_less_than
235
+ attr_reader :max_server_version
238
236
 
239
237
  # Create the new test.
240
238
  #
@@ -248,8 +246,8 @@ module Mongo
248
246
  def initialize(data, test)
249
247
  @data = data
250
248
  @description = test['description']
251
- @ignore_if_server_version_greater_than = test['ignore_if_server_version_greater_than']
252
- @ignore_if_server_version_less_than = test['ignore_if_server_version_less_than']
249
+ @max_server_version = test['ignore_if_server_version_greater_than']
250
+ @min_server_fcv = test['ignore_if_server_version_less_than']
253
251
  @operation = Mongo::CRUD::Operation.get(test['operation'])
254
252
  @expectations = test['expectations'].map{ |e| Expectation.new(e) }
255
253
  end
@@ -89,6 +89,12 @@ module CommonShortcuts
89
89
  end
90
90
 
91
91
  def make_node_recovering_reply
92
+ make_protocol_reply(
93
+ 'ok' => 0, 'code' => 11602, 'errmsg' => 'InterruptedDueToStepDown'
94
+ )
95
+ end
96
+
97
+ def make_node_shutting_down_reply
92
98
  make_protocol_reply(
93
99
  'ok' => 0, 'code' => 91, 'errmsg' => 'shutdown in progress'
94
100
  )