mongo 2.11.4 → 2.18.1

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 (1659) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CONTRIBUTING.md +8 -36
  4. data/LICENSE +1 -1
  5. data/README.md +65 -77
  6. data/Rakefile +58 -24
  7. data/lib/mongo/active_support.rb +4 -1
  8. data/lib/mongo/address/ipv4.rb +35 -5
  9. data/lib/mongo/address/ipv6.rb +35 -5
  10. data/lib/mongo/address/unix.rb +6 -3
  11. data/lib/mongo/address/validator.rb +4 -1
  12. data/lib/mongo/address.rb +81 -26
  13. data/lib/mongo/auth/aws/conversation.rb +128 -0
  14. data/lib/mongo/auth/aws/credentials_retriever.rb +222 -0
  15. data/lib/mongo/auth/aws/request.rb +285 -0
  16. data/lib/mongo/auth/aws.rb +40 -0
  17. data/lib/mongo/auth/base.rb +145 -0
  18. data/lib/mongo/auth/conversation_base.rb +87 -0
  19. data/lib/mongo/auth/cr/conversation.rb +21 -86
  20. data/lib/mongo/auth/cr.rb +12 -36
  21. data/lib/mongo/auth/credential_cache.rb +54 -0
  22. data/lib/mongo/auth/gssapi/conversation.rb +100 -0
  23. data/lib/mongo/auth/gssapi.rb +41 -0
  24. data/lib/mongo/auth/ldap/conversation.rb +9 -57
  25. data/lib/mongo/auth/ldap.rb +12 -34
  26. data/lib/mongo/auth/roles.rb +4 -1
  27. data/lib/mongo/auth/sasl_conversation_base.rb +102 -0
  28. data/lib/mongo/auth/scram/conversation.rb +15 -502
  29. data/lib/mongo/auth/scram.rb +42 -51
  30. data/lib/mongo/auth/scram256/conversation.rb +66 -0
  31. data/lib/mongo/auth/scram256.rb +34 -0
  32. data/lib/mongo/auth/scram_conversation_base.rb +378 -0
  33. data/lib/mongo/auth/stringprep/profiles/sasl.rb +5 -1
  34. data/lib/mongo/auth/stringprep/tables.rb +5 -1
  35. data/lib/mongo/auth/stringprep/unicode_normalize/normalize.rb +3 -2
  36. data/lib/mongo/auth/stringprep/unicode_normalize/tables.rb +2 -1
  37. data/lib/mongo/auth/stringprep.rb +9 -5
  38. data/lib/mongo/auth/user/view.rb +20 -10
  39. data/lib/mongo/auth/user.rb +5 -10
  40. data/lib/mongo/auth/x509/conversation.rb +21 -66
  41. data/lib/mongo/auth/x509.rb +17 -32
  42. data/lib/mongo/auth.rb +52 -14
  43. data/lib/mongo/background_thread.rb +27 -4
  44. data/lib/mongo/bson.rb +4 -1
  45. data/lib/mongo/bulk_write/combineable.rb +23 -8
  46. data/lib/mongo/bulk_write/ordered_combiner.rb +4 -1
  47. data/lib/mongo/bulk_write/result.rb +14 -2
  48. data/lib/mongo/bulk_write/result_combiner.rb +6 -5
  49. data/lib/mongo/bulk_write/transformable.rb +12 -10
  50. data/lib/mongo/bulk_write/unordered_combiner.rb +4 -1
  51. data/lib/mongo/bulk_write/validatable.rb +8 -1
  52. data/lib/mongo/bulk_write.rb +187 -42
  53. data/lib/mongo/caching_cursor.rb +77 -0
  54. data/lib/mongo/client.rb +669 -68
  55. data/lib/mongo/client_encryption.rb +209 -0
  56. data/lib/mongo/cluster/periodic_executor.rb +8 -4
  57. data/lib/mongo/cluster/reapers/cursor_reaper.rb +120 -46
  58. data/lib/mongo/cluster/reapers/socket_reaper.rb +4 -1
  59. data/lib/mongo/cluster/sdam_flow.rb +112 -74
  60. data/lib/mongo/cluster/topology/base.rb +17 -10
  61. data/lib/mongo/cluster/topology/load_balanced.rb +102 -0
  62. data/lib/mongo/cluster/topology/no_replica_set_options.rb +4 -1
  63. data/lib/mongo/cluster/topology/replica_set_no_primary.rb +7 -3
  64. data/lib/mongo/cluster/topology/replica_set_with_primary.rb +4 -1
  65. data/lib/mongo/cluster/topology/sharded.rb +5 -2
  66. data/lib/mongo/cluster/topology/single.rb +6 -3
  67. data/lib/mongo/cluster/topology/unknown.rb +4 -1
  68. data/lib/mongo/cluster/topology.rb +44 -4
  69. data/lib/mongo/cluster.rb +344 -155
  70. data/lib/mongo/cluster_time.rb +4 -1
  71. data/lib/mongo/collection/helpers.rb +43 -0
  72. data/lib/mongo/collection/queryable_encryption.rb +122 -0
  73. data/lib/mongo/collection/view/aggregation.rb +96 -23
  74. data/lib/mongo/collection/view/builder/aggregation.rb +20 -18
  75. data/lib/mongo/collection/view/builder/map_reduce.rb +19 -50
  76. data/lib/mongo/collection/view/builder.rb +4 -5
  77. data/lib/mongo/collection/view/change_stream/retryable.rb +4 -1
  78. data/lib/mongo/collection/view/change_stream.rb +83 -28
  79. data/lib/mongo/collection/view/explainable.rb +31 -9
  80. data/lib/mongo/collection/view/immutable.rb +4 -1
  81. data/lib/mongo/collection/view/iterable.rb +135 -23
  82. data/lib/mongo/collection/view/map_reduce.rb +78 -24
  83. data/lib/mongo/collection/view/readable.rb +162 -71
  84. data/lib/mongo/collection/view/writable.rb +356 -140
  85. data/lib/mongo/collection/view.rb +47 -42
  86. data/lib/mongo/collection.rb +244 -68
  87. data/lib/mongo/config/options.rb +62 -0
  88. data/lib/mongo/config/validators/option.rb +26 -0
  89. data/lib/mongo/config.rb +42 -0
  90. data/lib/mongo/crypt/auto_decryption_context.rb +43 -0
  91. data/lib/mongo/crypt/auto_encrypter.rb +304 -0
  92. data/lib/mongo/crypt/auto_encryption_context.rb +47 -0
  93. data/lib/mongo/crypt/binary.rb +158 -0
  94. data/lib/mongo/crypt/binding.rb +1601 -0
  95. data/lib/mongo/crypt/context.rb +141 -0
  96. data/lib/mongo/crypt/data_key_context.rb +73 -0
  97. data/lib/mongo/crypt/encryption_io.rb +343 -0
  98. data/lib/mongo/crypt/explicit_decryption_context.rb +43 -0
  99. data/lib/mongo/crypt/explicit_encrypter.rb +237 -0
  100. data/lib/mongo/crypt/explicit_encryption_context.rb +115 -0
  101. data/lib/mongo/crypt/handle.rb +392 -0
  102. data/lib/mongo/crypt/hooks.rb +116 -0
  103. data/lib/mongo/crypt/kms/aws.rb +136 -0
  104. data/lib/mongo/crypt/kms/azure.rb +144 -0
  105. data/lib/mongo/crypt/kms/credentials.rb +81 -0
  106. data/lib/mongo/crypt/kms/gcp.rb +189 -0
  107. data/lib/mongo/crypt/kms/kmip.rb +116 -0
  108. data/lib/mongo/crypt/kms/local.rb +82 -0
  109. data/lib/mongo/crypt/kms/master_key_document.rb +65 -0
  110. data/lib/mongo/crypt/kms.rb +117 -0
  111. data/lib/mongo/crypt/kms_context.rb +70 -0
  112. data/lib/mongo/crypt/rewrap_many_data_key_context.rb +46 -0
  113. data/lib/mongo/crypt/rewrap_many_data_key_result.rb +37 -0
  114. data/lib/mongo/crypt/status.rb +140 -0
  115. data/lib/mongo/crypt.rb +39 -0
  116. data/lib/mongo/cursor/kill_spec.rb +76 -0
  117. data/lib/mongo/cursor.rb +175 -70
  118. data/lib/mongo/database/view.rb +41 -9
  119. data/lib/mongo/database.rb +142 -25
  120. data/lib/mongo/dbref.rb +5 -99
  121. data/lib/mongo/distinguishing_semaphore.rb +58 -0
  122. data/lib/mongo/error/auth_error.rb +4 -1
  123. data/lib/mongo/error/bad_load_balancer_target.rb +26 -0
  124. data/lib/mongo/error/bulk_write_error.rb +60 -14
  125. data/lib/mongo/error/change_stream_resumable.rb +4 -1
  126. data/lib/mongo/error/closed_stream.rb +4 -1
  127. data/lib/mongo/error/connection_check_out_timeout.rb +4 -1
  128. data/lib/mongo/error/connection_perished.rb +26 -0
  129. data/lib/mongo/error/credential_check_error.rb +29 -0
  130. data/lib/mongo/error/crypt_error.rb +34 -0
  131. data/lib/mongo/error/extra_file_chunk.rb +4 -1
  132. data/lib/mongo/error/{failed_stringprep_validation.rb → failed_string_prep_validation.rb} +3 -0
  133. data/lib/mongo/error/file_not_found.rb +4 -1
  134. data/lib/mongo/error/handshake_error.rb +4 -1
  135. data/lib/mongo/error/insufficient_iteration_count.rb +4 -1
  136. data/lib/mongo/error/internal_driver_error.rb +25 -0
  137. data/lib/mongo/error/invalid_address.rb +4 -1
  138. data/lib/mongo/error/invalid_application_name.rb +4 -1
  139. data/lib/mongo/error/invalid_bulk_operation.rb +4 -1
  140. data/lib/mongo/error/invalid_bulk_operation_type.rb +4 -1
  141. data/lib/mongo/error/invalid_collection_name.rb +4 -1
  142. data/lib/mongo/error/invalid_config_option.rb +20 -0
  143. data/lib/mongo/error/invalid_cursor_operation.rb +30 -0
  144. data/lib/mongo/error/invalid_database_name.rb +4 -1
  145. data/lib/mongo/error/invalid_document.rb +4 -1
  146. data/lib/mongo/error/invalid_file.rb +4 -1
  147. data/lib/mongo/error/invalid_file_revision.rb +4 -1
  148. data/lib/mongo/error/invalid_min_pool_size.rb +4 -1
  149. data/lib/mongo/error/invalid_nonce.rb +5 -2
  150. data/lib/mongo/error/invalid_read_concern.rb +31 -0
  151. data/lib/mongo/error/invalid_read_option.rb +4 -1
  152. data/lib/mongo/error/invalid_replacement_document.rb +31 -10
  153. data/lib/mongo/error/invalid_server_auth_host.rb +25 -0
  154. data/lib/mongo/error/invalid_server_auth_response.rb +26 -0
  155. data/lib/mongo/error/invalid_server_preference.rb +9 -1
  156. data/lib/mongo/error/invalid_session.rb +6 -2
  157. data/lib/mongo/error/invalid_signature.rb +4 -1
  158. data/lib/mongo/error/invalid_transaction_operation.rb +4 -1
  159. data/lib/mongo/error/invalid_txt_record.rb +4 -1
  160. data/lib/mongo/error/invalid_update_document.rb +31 -8
  161. data/lib/mongo/error/invalid_uri.rb +4 -1
  162. data/lib/mongo/error/invalid_write_concern.rb +4 -1
  163. data/{spec/support/crud/context.rb → lib/mongo/error/kms_error.rb} +8 -6
  164. data/lib/mongo/error/labelable.rb +72 -0
  165. data/lib/mongo/error/lint_error.rb +4 -1
  166. data/lib/mongo/error/max_bson_size.rb +18 -4
  167. data/lib/mongo/error/max_message_size.rb +4 -1
  168. data/lib/mongo/error/mismatched_domain.rb +4 -1
  169. data/lib/mongo/error/missing_connection.rb +25 -0
  170. data/lib/mongo/error/missing_file_chunk.rb +12 -3
  171. data/lib/mongo/error/missing_password.rb +4 -1
  172. data/lib/mongo/error/missing_resume_token.rb +4 -1
  173. data/lib/mongo/error/missing_scram_server_signature.rb +30 -0
  174. data/lib/mongo/error/missing_service_id.rb +26 -0
  175. data/lib/mongo/error/mongocryptd_spawn_error.rb +25 -0
  176. data/lib/mongo/error/multi_index_drop.rb +4 -1
  177. data/lib/mongo/error/need_primary_server.rb +4 -1
  178. data/lib/mongo/error/no_server_available.rb +12 -4
  179. data/lib/mongo/error/no_service_connection_available.rb +49 -0
  180. data/lib/mongo/error/no_srv_records.rb +4 -1
  181. data/lib/mongo/error/notable.rb +34 -17
  182. data/lib/mongo/error/operation_failure.rb +107 -117
  183. data/lib/mongo/error/parser.rb +85 -18
  184. data/lib/mongo/error/pool_closed_error.rb +4 -1
  185. data/lib/mongo/error/raise_original_error.rb +32 -0
  186. data/lib/mongo/error/read_write_retryable.rb +108 -0
  187. data/lib/mongo/error/sdam_error_detection.rb +16 -5
  188. data/lib/mongo/error/server_api_conflict.rb +26 -0
  189. data/lib/mongo/error/server_api_not_supported.rb +27 -0
  190. data/lib/mongo/error/server_certificate_revoked.rb +25 -0
  191. data/lib/mongo/error/session_ended.rb +4 -1
  192. data/lib/mongo/error/session_not_materialized.rb +29 -0
  193. data/lib/mongo/error/sessions_not_supported.rb +38 -0
  194. data/lib/mongo/error/snapshot_session_invalid_server_version.rb +31 -0
  195. data/lib/mongo/error/snapshot_session_transaction_prohibited.rb +30 -0
  196. data/lib/mongo/error/socket_error.rb +4 -1
  197. data/lib/mongo/error/socket_timeout_error.rb +4 -1
  198. data/lib/mongo/error/unchangeable_collection_option.rb +4 -1
  199. data/lib/mongo/error/unexpected_chunk_length.rb +4 -1
  200. data/lib/mongo/error/unexpected_response.rb +4 -1
  201. data/lib/mongo/error/unknown_payload_type.rb +4 -1
  202. data/lib/mongo/{cursor/builder.rb → error/unmet_dependency.rb} +11 -5
  203. data/lib/mongo/error/unsupported_array_filters.rb +10 -2
  204. data/lib/mongo/error/unsupported_collation.rb +10 -2
  205. data/lib/mongo/error/unsupported_features.rb +4 -1
  206. data/lib/mongo/error/unsupported_message_type.rb +4 -1
  207. data/lib/mongo/error/unsupported_option.rb +104 -0
  208. data/lib/mongo/error/write_retryable.rb +4 -1
  209. data/lib/mongo/error.rb +50 -34
  210. data/lib/mongo/event/base.rb +10 -1
  211. data/lib/mongo/event/listeners.rb +4 -1
  212. data/lib/mongo/event/publisher.rb +4 -1
  213. data/lib/mongo/event/subscriber.rb +4 -1
  214. data/lib/mongo/event.rb +4 -1
  215. data/lib/mongo/grid/file/chunk.rb +7 -2
  216. data/lib/mongo/grid/file/info.rb +7 -3
  217. data/lib/mongo/grid/file.rb +9 -1
  218. data/lib/mongo/grid/fs_bucket.rb +108 -61
  219. data/lib/mongo/grid/stream/read.rb +29 -8
  220. data/lib/mongo/grid/stream/write.rb +13 -4
  221. data/lib/mongo/grid/stream.rb +4 -1
  222. data/lib/mongo/grid.rb +4 -1
  223. data/lib/mongo/id.rb +11 -6
  224. data/lib/mongo/index/view.rb +103 -43
  225. data/lib/mongo/index.rb +5 -1
  226. data/lib/mongo/lint.rb +14 -0
  227. data/lib/mongo/loggable.rb +4 -1
  228. data/lib/mongo/logger.rb +7 -4
  229. data/lib/mongo/monitoring/cmap_log_subscriber.rb +4 -1
  230. data/lib/mongo/monitoring/command_log_subscriber.rb +23 -5
  231. data/lib/mongo/monitoring/event/cmap/base.rb +4 -1
  232. data/lib/mongo/monitoring/event/cmap/connection_check_out_failed.rb +5 -2
  233. data/lib/mongo/monitoring/event/cmap/connection_check_out_started.rb +4 -1
  234. data/lib/mongo/monitoring/event/cmap/connection_checked_in.rb +4 -1
  235. data/lib/mongo/monitoring/event/cmap/connection_checked_out.rb +4 -1
  236. data/lib/mongo/monitoring/event/cmap/connection_closed.rb +4 -1
  237. data/lib/mongo/monitoring/event/cmap/connection_created.rb +4 -1
  238. data/lib/mongo/monitoring/event/cmap/connection_ready.rb +4 -1
  239. data/lib/mongo/monitoring/event/cmap/pool_cleared.rb +11 -5
  240. data/lib/mongo/monitoring/event/cmap/pool_closed.rb +4 -1
  241. data/lib/mongo/monitoring/event/cmap/pool_created.rb +4 -1
  242. data/lib/mongo/monitoring/event/cmap.rb +4 -1
  243. data/lib/mongo/monitoring/event/command_failed.rb +50 -6
  244. data/lib/mongo/monitoring/event/command_started.rb +70 -4
  245. data/lib/mongo/monitoring/event/command_succeeded.rb +48 -4
  246. data/lib/mongo/monitoring/event/secure.rb +44 -4
  247. data/lib/mongo/monitoring/event/server_closed.rb +5 -2
  248. data/lib/mongo/monitoring/event/server_description_changed.rb +31 -5
  249. data/lib/mongo/monitoring/event/server_heartbeat_failed.rb +39 -18
  250. data/lib/mongo/monitoring/event/server_heartbeat_started.rb +13 -3
  251. data/lib/mongo/monitoring/event/server_heartbeat_succeeded.rb +34 -13
  252. data/lib/mongo/monitoring/event/server_opening.rb +5 -2
  253. data/lib/mongo/monitoring/event/topology_changed.rb +5 -2
  254. data/lib/mongo/monitoring/event/topology_closed.rb +5 -2
  255. data/lib/mongo/monitoring/event/topology_opening.rb +5 -2
  256. data/lib/mongo/monitoring/event.rb +4 -1
  257. data/lib/mongo/monitoring/publishable.rb +43 -17
  258. data/lib/mongo/monitoring/sdam_log_subscriber.rb +4 -1
  259. data/lib/mongo/monitoring/server_closed_log_subscriber.rb +4 -1
  260. data/lib/mongo/monitoring/server_description_changed_log_subscriber.rb +13 -2
  261. data/lib/mongo/monitoring/server_opening_log_subscriber.rb +4 -1
  262. data/lib/mongo/monitoring/topology_changed_log_subscriber.rb +5 -2
  263. data/lib/mongo/monitoring/topology_closed_log_subscriber.rb +4 -1
  264. data/lib/mongo/monitoring/topology_opening_log_subscriber.rb +4 -1
  265. data/lib/mongo/monitoring/unified_sdam_log_subscriber.rb +4 -1
  266. data/lib/mongo/monitoring.rb +51 -1
  267. data/lib/mongo/operation/aggregate/command.rb +16 -5
  268. data/lib/mongo/operation/aggregate/op_msg.rb +4 -1
  269. data/lib/mongo/operation/aggregate/result.rb +13 -9
  270. data/lib/mongo/operation/aggregate.rb +4 -1
  271. data/lib/mongo/operation/{delete/legacy.rb → collections_info/command.rb} +15 -21
  272. data/lib/mongo/operation/collections_info/result.rb +25 -2
  273. data/lib/mongo/operation/collections_info.rb +18 -28
  274. data/lib/mongo/operation/command/command.rb +6 -3
  275. data/lib/mongo/operation/command/op_msg.rb +10 -1
  276. data/lib/mongo/operation/command.rb +4 -1
  277. data/lib/mongo/operation/context.rb +138 -0
  278. data/lib/mongo/operation/count/command.rb +12 -3
  279. data/lib/mongo/operation/count/op_msg.rb +13 -1
  280. data/lib/mongo/operation/count.rb +4 -1
  281. data/lib/mongo/operation/create/command.rb +13 -4
  282. data/lib/mongo/operation/create/op_msg.rb +14 -1
  283. data/lib/mongo/operation/create.rb +4 -1
  284. data/lib/mongo/operation/create_index/command.rb +24 -5
  285. data/lib/mongo/operation/create_index/op_msg.rb +23 -3
  286. data/lib/mongo/operation/create_index.rb +4 -1
  287. data/lib/mongo/operation/create_user/command.rb +7 -4
  288. data/lib/mongo/operation/create_user/op_msg.rb +5 -2
  289. data/lib/mongo/operation/create_user.rb +4 -1
  290. data/lib/mongo/operation/delete/bulk_result.rb +6 -1
  291. data/lib/mongo/operation/delete/command.rb +13 -7
  292. data/lib/mongo/operation/delete/op_msg.rb +18 -6
  293. data/lib/mongo/operation/delete/result.rb +8 -2
  294. data/lib/mongo/operation/delete.rb +4 -2
  295. data/lib/mongo/operation/distinct/command.rb +12 -3
  296. data/lib/mongo/operation/distinct/op_msg.rb +14 -1
  297. data/lib/mongo/operation/distinct.rb +4 -1
  298. data/lib/mongo/operation/drop/command.rb +6 -3
  299. data/lib/mongo/operation/drop/op_msg.rb +4 -1
  300. data/lib/mongo/operation/drop.rb +4 -1
  301. data/lib/mongo/operation/drop_database/command.rb +6 -3
  302. data/lib/mongo/operation/drop_database/op_msg.rb +4 -1
  303. data/lib/mongo/operation/drop_database.rb +4 -1
  304. data/lib/mongo/operation/drop_index/command.rb +7 -4
  305. data/lib/mongo/operation/drop_index/op_msg.rb +10 -3
  306. data/lib/mongo/operation/drop_index.rb +4 -1
  307. data/lib/mongo/operation/explain/command.rb +22 -3
  308. data/lib/mongo/operation/explain/legacy.rb +17 -3
  309. data/lib/mongo/operation/explain/op_msg.rb +18 -1
  310. data/lib/mongo/operation/explain/result.rb +7 -1
  311. data/lib/mongo/operation/explain.rb +4 -1
  312. data/lib/mongo/operation/find/builder/command.rb +111 -0
  313. data/lib/mongo/{collection/view → operation/find}/builder/flags.rb +14 -15
  314. data/lib/mongo/operation/find/builder/legacy.rb +123 -0
  315. data/lib/mongo/{collection/view → operation/find}/builder/modifiers.rb +35 -26
  316. data/lib/mongo/operation/find/builder.rb +21 -0
  317. data/lib/mongo/operation/find/command.rb +15 -3
  318. data/lib/mongo/operation/find/legacy/result.rb +6 -1
  319. data/lib/mongo/operation/find/legacy.rb +15 -3
  320. data/lib/mongo/operation/find/op_msg.rb +17 -9
  321. data/lib/mongo/operation/find/result.rb +17 -1
  322. data/lib/mongo/operation/find.rb +5 -1
  323. data/lib/mongo/operation/get_more/command.rb +7 -3
  324. data/lib/mongo/operation/get_more/command_builder.rb +42 -0
  325. data/lib/mongo/operation/get_more/legacy.rb +5 -2
  326. data/lib/mongo/operation/get_more/op_msg.rb +6 -9
  327. data/lib/mongo/operation/get_more/result.rb +7 -1
  328. data/lib/mongo/operation/get_more.rb +5 -1
  329. data/lib/mongo/operation/indexes/command.rb +6 -3
  330. data/lib/mongo/operation/indexes/legacy.rb +7 -4
  331. data/lib/mongo/operation/indexes/op_msg.rb +4 -1
  332. data/lib/mongo/operation/indexes/result.rb +9 -1
  333. data/lib/mongo/operation/indexes.rb +19 -2
  334. data/lib/mongo/operation/insert/bulk_result.rb +18 -2
  335. data/lib/mongo/operation/insert/command.rb +10 -10
  336. data/lib/mongo/operation/insert/op_msg.rb +15 -9
  337. data/lib/mongo/operation/insert/result.rb +18 -4
  338. data/lib/mongo/operation/insert.rb +6 -3
  339. data/lib/mongo/operation/kill_cursors/command.rb +14 -3
  340. data/lib/mongo/operation/kill_cursors/{legacy.rb → command_builder.rb} +9 -11
  341. data/lib/mongo/operation/kill_cursors/op_msg.rb +14 -1
  342. data/lib/mongo/operation/kill_cursors.rb +5 -2
  343. data/lib/mongo/operation/list_collections/command.rb +7 -4
  344. data/lib/mongo/operation/list_collections/op_msg.rb +9 -3
  345. data/lib/mongo/operation/list_collections/result.rb +13 -2
  346. data/lib/mongo/operation/list_collections.rb +4 -1
  347. data/lib/mongo/operation/map_reduce/command.rb +14 -3
  348. data/lib/mongo/operation/map_reduce/op_msg.rb +5 -2
  349. data/lib/mongo/operation/map_reduce/result.rb +30 -1
  350. data/lib/mongo/operation/map_reduce.rb +4 -1
  351. data/lib/mongo/operation/op_msg_base.rb +6 -3
  352. data/lib/mongo/operation/parallel_scan/command.rb +8 -6
  353. data/lib/mongo/operation/parallel_scan/op_msg.rb +5 -2
  354. data/lib/mongo/operation/parallel_scan/result.rb +8 -1
  355. data/lib/mongo/operation/parallel_scan.rb +4 -1
  356. data/lib/mongo/operation/remove_user/command.rb +7 -4
  357. data/lib/mongo/operation/remove_user/op_msg.rb +5 -2
  358. data/lib/mongo/operation/remove_user.rb +4 -1
  359. data/lib/mongo/operation/result.rb +126 -37
  360. data/lib/mongo/operation/shared/bypass_document_validation.rb +14 -4
  361. data/lib/mongo/operation/shared/causal_consistency_supported.rb +7 -3
  362. data/lib/mongo/operation/shared/executable.rb +92 -28
  363. data/lib/mongo/operation/shared/executable_no_validate.rb +6 -3
  364. data/lib/mongo/operation/shared/executable_transaction_label.rb +4 -1
  365. data/lib/mongo/operation/shared/idable.rb +6 -2
  366. data/lib/mongo/operation/shared/limited.rb +14 -2
  367. data/lib/mongo/operation/shared/object_id_generator.rb +5 -1
  368. data/lib/mongo/operation/shared/op_msg_or_command.rb +7 -8
  369. data/lib/mongo/operation/shared/op_msg_or_find_command.rb +8 -9
  370. data/lib/mongo/operation/shared/polymorphic_lookup.rb +4 -1
  371. data/lib/mongo/operation/shared/polymorphic_operation.rb +54 -0
  372. data/lib/mongo/operation/shared/polymorphic_result.rb +4 -1
  373. data/lib/mongo/operation/shared/read_preference_supported.rb +82 -23
  374. data/lib/mongo/operation/shared/response_handling.rb +97 -17
  375. data/lib/mongo/operation/shared/result/aggregatable.rb +5 -1
  376. data/lib/mongo/operation/shared/result/use_legacy_error_parser.rb +4 -1
  377. data/lib/mongo/operation/shared/sessions_supported.rb +126 -26
  378. data/lib/mongo/operation/shared/specifiable.rb +36 -38
  379. data/lib/mongo/operation/shared/validatable.rb +87 -0
  380. data/lib/mongo/operation/shared/write.rb +37 -24
  381. data/lib/mongo/operation/shared/write_concern_supported.rb +10 -6
  382. data/lib/mongo/operation/update/bulk_result.rb +4 -1
  383. data/lib/mongo/operation/update/command.rb +13 -7
  384. data/lib/mongo/operation/update/op_msg.rb +16 -8
  385. data/lib/mongo/operation/update/result.rb +13 -2
  386. data/lib/mongo/operation/update.rb +4 -2
  387. data/lib/mongo/operation/update_user/command.rb +7 -4
  388. data/lib/mongo/operation/update_user/op_msg.rb +5 -2
  389. data/lib/mongo/operation/update_user.rb +4 -1
  390. data/lib/mongo/operation/users_info/command.rb +7 -4
  391. data/lib/mongo/operation/users_info/op_msg.rb +5 -2
  392. data/lib/mongo/operation/users_info/result.rb +7 -1
  393. data/lib/mongo/operation/users_info.rb +4 -1
  394. data/lib/mongo/operation/write_command/command.rb +51 -0
  395. data/lib/mongo/operation/write_command/op_msg.rb +43 -0
  396. data/lib/mongo/operation/write_command.rb +32 -0
  397. data/lib/mongo/operation.rb +17 -1
  398. data/lib/mongo/options/mapper.rb +4 -1
  399. data/lib/mongo/options/redacted.rb +4 -1
  400. data/lib/mongo/options.rb +4 -1
  401. data/lib/mongo/protocol/bit_vector.rb +6 -2
  402. data/lib/mongo/protocol/caching_hash.rb +69 -0
  403. data/lib/mongo/protocol/compressed.rb +61 -11
  404. data/lib/mongo/protocol/delete.rb +4 -1
  405. data/lib/mongo/protocol/get_more.rb +4 -1
  406. data/lib/mongo/protocol/insert.rb +7 -2
  407. data/lib/mongo/protocol/kill_cursors.rb +4 -1
  408. data/lib/mongo/protocol/message.rb +158 -21
  409. data/lib/mongo/protocol/msg.rb +268 -41
  410. data/lib/mongo/protocol/query.rb +97 -42
  411. data/lib/mongo/protocol/registry.rb +4 -1
  412. data/lib/mongo/protocol/reply.rb +4 -1
  413. data/lib/mongo/protocol/serializers.rb +47 -16
  414. data/lib/mongo/protocol/update.rb +4 -1
  415. data/lib/mongo/protocol.rb +4 -0
  416. data/lib/mongo/query_cache.rb +300 -0
  417. data/lib/mongo/retryable.rb +114 -43
  418. data/lib/mongo/semaphore.rb +4 -1
  419. data/lib/mongo/server/app_metadata.rb +128 -35
  420. data/lib/mongo/server/connection.rb +105 -127
  421. data/lib/mongo/server/connection_base.rb +173 -32
  422. data/lib/mongo/server/connection_common.rb +208 -0
  423. data/lib/mongo/server/connection_pool/generation_manager.rb +71 -0
  424. data/lib/mongo/server/connection_pool/populator.rb +5 -2
  425. data/lib/mongo/server/connection_pool.rb +206 -42
  426. data/lib/mongo/server/description/features.rb +41 -23
  427. data/lib/mongo/{srv/warning_result.rb → server/description/load_balancer.rb} +13 -15
  428. data/lib/mongo/server/description.rb +183 -30
  429. data/lib/mongo/server/monitor/app_metadata.rb +5 -2
  430. data/lib/mongo/server/monitor/connection.rb +148 -117
  431. data/lib/mongo/server/monitor.rb +183 -79
  432. data/lib/mongo/server/pending_connection.rb +247 -1
  433. data/lib/mongo/server/push_monitor/connection.rb +31 -0
  434. data/lib/mongo/server/push_monitor.rb +207 -0
  435. data/lib/mongo/server/round_trip_time_averager.rb +18 -6
  436. data/lib/mongo/server.rb +154 -52
  437. data/lib/mongo/server_selector/{selectable.rb → base.rb} +197 -91
  438. data/lib/mongo/server_selector/nearest.rb +32 -25
  439. data/lib/mongo/server_selector/primary.rb +30 -32
  440. data/lib/mongo/server_selector/primary_preferred.rb +38 -29
  441. data/lib/mongo/server_selector/secondary.rb +32 -25
  442. data/lib/mongo/server_selector/secondary_preferred.rb +30 -38
  443. data/lib/mongo/server_selector.rb +5 -2
  444. data/lib/mongo/session/server_session.rb +4 -1
  445. data/lib/mongo/session/session_pool.rb +33 -4
  446. data/lib/mongo/session.rb +178 -39
  447. data/lib/mongo/socket/ocsp_cache.rb +99 -0
  448. data/lib/mongo/socket/ocsp_verifier.rb +344 -0
  449. data/lib/mongo/socket/ssl.rb +165 -55
  450. data/lib/mongo/socket/tcp.rb +48 -25
  451. data/lib/mongo/socket/unix.rb +17 -6
  452. data/lib/mongo/socket.rb +168 -47
  453. data/lib/mongo/srv/monitor.rb +64 -47
  454. data/lib/mongo/srv/resolver.rb +42 -14
  455. data/lib/mongo/srv/result.rb +4 -2
  456. data/lib/mongo/srv.rb +4 -1
  457. data/lib/mongo/timeout.rb +54 -0
  458. data/lib/mongo/topology_version.rb +92 -0
  459. data/lib/mongo/uri/options_mapper.rb +626 -0
  460. data/lib/mongo/uri/srv_protocol.rb +23 -13
  461. data/lib/mongo/uri.rb +103 -388
  462. data/lib/mongo/utils.rb +105 -0
  463. data/lib/mongo/version.rb +5 -2
  464. data/lib/mongo/write_concern/acknowledged.rb +4 -1
  465. data/lib/mongo/write_concern/base.rb +4 -1
  466. data/lib/mongo/write_concern/unacknowledged.rb +4 -1
  467. data/lib/mongo/write_concern.rb +4 -1
  468. data/lib/mongo.rb +67 -2
  469. data/mongo.gemspec +12 -8
  470. data/spec/NOTES.aws-auth.md +296 -0
  471. data/spec/README.aws-auth.md +318 -0
  472. data/spec/README.md +386 -15
  473. data/spec/atlas/atlas_connectivity_spec.rb +3 -0
  474. data/spec/atlas/operations_spec.rb +3 -0
  475. data/spec/integration/auth_spec.rb +130 -14
  476. data/spec/integration/awaited_ismaster_spec.rb +31 -0
  477. data/spec/integration/aws_auth_request_spec.rb +77 -0
  478. data/spec/integration/aws_credentials_retriever_spec.rb +106 -0
  479. data/spec/integration/aws_lambda_examples_spec.rb +68 -0
  480. data/spec/integration/bson_symbol_spec.rb +8 -3
  481. data/spec/integration/bulk_insert_spec.rb +3 -0
  482. data/spec/integration/bulk_write_error_message_spec.rb +73 -0
  483. data/spec/integration/bulk_write_spec.rb +86 -0
  484. data/spec/integration/change_stream_examples_spec.rb +9 -2
  485. data/spec/integration/change_stream_spec.rb +133 -57
  486. data/spec/integration/check_clean_slate_spec.rb +19 -0
  487. data/spec/integration/{client_options_spec.rb → client_authentication_options_spec.rb} +123 -46
  488. data/spec/integration/client_connectivity_spec.rb +4 -1
  489. data/spec/integration/client_construction_aws_auth_spec.rb +194 -0
  490. data/spec/integration/client_construction_spec.rb +225 -2
  491. data/spec/integration/client_side_encryption/auto_encryption_bulk_writes_spec.rb +360 -0
  492. data/spec/integration/client_side_encryption/auto_encryption_command_monitoring_spec.rb +306 -0
  493. data/spec/integration/client_side_encryption/auto_encryption_mongocryptd_spawn_spec.rb +74 -0
  494. data/spec/integration/client_side_encryption/auto_encryption_old_wire_version_spec.rb +82 -0
  495. data/spec/integration/client_side_encryption/auto_encryption_reconnect_spec.rb +255 -0
  496. data/spec/integration/client_side_encryption/auto_encryption_spec.rb +711 -0
  497. data/spec/integration/client_side_encryption/bson_size_limit_spec.rb +190 -0
  498. data/spec/integration/client_side_encryption/bypass_mongocryptd_spawn_spec.rb +81 -0
  499. data/spec/integration/client_side_encryption/client_close_spec.rb +66 -0
  500. data/spec/integration/client_side_encryption/corpus_spec.rb +265 -0
  501. data/spec/integration/client_side_encryption/custom_endpoint_spec.rb +132 -0
  502. data/spec/integration/client_side_encryption/data_key_spec.rb +258 -0
  503. data/spec/integration/client_side_encryption/decryption_events_prose_spec.rb +158 -0
  504. data/spec/integration/client_side_encryption/explicit_encryption_spec.rb +176 -0
  505. data/spec/integration/client_side_encryption/explicit_queryable_encryption_spec.rb +147 -0
  506. data/spec/integration/client_side_encryption/external_key_vault_spec.rb +144 -0
  507. data/spec/integration/client_side_encryption/kms_tls_options_spec.rb +436 -0
  508. data/spec/integration/client_side_encryption/kms_tls_spec.rb +92 -0
  509. data/spec/integration/client_side_encryption/queryable_encryption_examples_spec.rb +111 -0
  510. data/spec/integration/client_side_encryption/unique_index_on_key_alt_names_prose_spec.rb +85 -0
  511. data/spec/integration/client_side_encryption/views_spec.rb +47 -0
  512. data/spec/integration/client_spec.rb +7 -2
  513. data/spec/integration/client_update_spec.rb +157 -0
  514. data/spec/integration/collection_indexes_prose_spec.rb +58 -0
  515. data/spec/integration/command_monitoring_spec.rb +95 -31
  516. data/spec/integration/command_spec.rb +59 -20
  517. data/spec/integration/connect_single_rs_name_spec.rb +15 -7
  518. data/spec/integration/connection_pool_populator_spec.rb +7 -2
  519. data/spec/integration/connection_spec.rb +121 -38
  520. data/spec/integration/crud_spec.rb +338 -5
  521. data/spec/integration/cursor_pinning_spec.rb +121 -0
  522. data/spec/integration/cursor_reaping_spec.rb +75 -28
  523. data/spec/integration/docs_examples_spec.rb +16 -0
  524. data/spec/integration/error_detection_spec.rb +3 -0
  525. data/spec/integration/fork_reconnect_spec.rb +207 -0
  526. data/spec/integration/get_more_spec.rb +13 -3
  527. data/spec/integration/grid_fs_bucket_spec.rb +51 -0
  528. data/spec/integration/heartbeat_events_spec.rb +11 -27
  529. data/spec/integration/map_reduce_spec.rb +77 -0
  530. data/spec/integration/mmapv1_spec.rb +3 -0
  531. data/spec/integration/mongos_pinning_spec.rb +3 -0
  532. data/spec/integration/ocsp_connectivity_spec.rb +29 -0
  533. data/spec/integration/ocsp_verifier_cache_spec.rb +191 -0
  534. data/spec/integration/ocsp_verifier_spec.rb +358 -0
  535. data/spec/integration/operation_failure_code_spec.rb +4 -1
  536. data/spec/integration/operation_failure_message_spec.rb +90 -0
  537. data/spec/integration/query_cache_spec.rb +1256 -0
  538. data/spec/integration/query_cache_transactions_spec.rb +193 -0
  539. data/spec/integration/read_concern_spec.rb +5 -2
  540. data/spec/integration/read_preference_spec.rb +86 -23
  541. data/spec/integration/reconnect_spec.rb +42 -19
  542. data/spec/integration/retryable_errors_spec.rb +36 -14
  543. data/spec/integration/{retryable_writes_spec.rb → retryable_writes/retryable_writes_36_and_older_spec.rb} +60 -53
  544. data/spec/integration/retryable_writes/retryable_writes_40_and_newer_spec.rb +405 -0
  545. data/spec/integration/retryable_writes/shared/adds_diagnostics.rb +18 -0
  546. data/spec/integration/retryable_writes/shared/does_not_support_retries.rb +27 -0
  547. data/spec/integration/retryable_writes/shared/only_supports_legacy_retries.rb +28 -0
  548. data/spec/integration/retryable_writes/shared/performs_legacy_retries.rb +220 -0
  549. data/spec/integration/retryable_writes/shared/performs_modern_retries.rb +235 -0
  550. data/spec/integration/retryable_writes/shared/performs_no_retries.rb +113 -0
  551. data/spec/integration/retryable_writes/shared/supports_legacy_retries.rb +22 -0
  552. data/spec/integration/retryable_writes/shared/supports_modern_retries.rb +28 -0
  553. data/spec/integration/retryable_writes/shared/supports_retries.rb +19 -0
  554. data/spec/integration/retryable_writes_errors_spec.rb +3 -0
  555. data/spec/integration/sdam_error_handling_spec.rb +235 -25
  556. data/spec/integration/sdam_events_spec.rb +142 -7
  557. data/spec/integration/sdam_prose_spec.rb +67 -0
  558. data/spec/integration/secondary_reads_spec.rb +102 -0
  559. data/spec/integration/server_description_spec.rb +3 -0
  560. data/spec/integration/server_monitor_spec.rb +31 -2
  561. data/spec/integration/server_selection_spec.rb +39 -0
  562. data/spec/integration/server_selector_spec.rb +25 -5
  563. data/spec/integration/server_spec.rb +47 -26
  564. data/spec/integration/shell_examples_spec.rb +3 -0
  565. data/spec/integration/size_limit_spec.rb +118 -0
  566. data/spec/integration/snappy_compression_spec.rb +28 -0
  567. data/spec/integration/snapshot_query_examples_spec.rb +127 -0
  568. data/spec/integration/srv_monitoring_spec.rb +93 -9
  569. data/spec/integration/srv_spec.rb +60 -0
  570. data/spec/integration/ssl_uri_options_spec.rb +5 -2
  571. data/spec/integration/step_down_spec.rb +38 -19
  572. data/spec/integration/time_zone_querying_spec.rb +3 -0
  573. data/spec/integration/transaction_pinning_spec.rb +120 -0
  574. data/spec/integration/transactions_api_examples_spec.rb +62 -0
  575. data/spec/integration/transactions_examples_spec.rb +31 -9
  576. data/spec/integration/truncated_utf8_spec.rb +26 -0
  577. data/spec/integration/versioned_api_examples_spec.rb +120 -0
  578. data/spec/integration/x509_auth_spec.rb +112 -0
  579. data/spec/integration/zlib_compression_spec.rb +28 -0
  580. data/spec/integration/zstd_compression_spec.rb +29 -0
  581. data/spec/kerberos/kerberos_spec.rb +94 -0
  582. data/spec/lite_spec_helper.rb +88 -44
  583. data/spec/mongo/address/ipv4_spec.rb +4 -1
  584. data/spec/mongo/address/ipv6_spec.rb +10 -0
  585. data/spec/mongo/address/unix_spec.rb +4 -0
  586. data/spec/mongo/address/validator_spec.rb +3 -0
  587. data/spec/mongo/address_spec.rb +27 -13
  588. data/spec/mongo/auth/aws/request_region_spec.rb +45 -0
  589. data/spec/mongo/auth/aws/request_spec.rb +79 -0
  590. data/spec/mongo/auth/cr_spec.rb +20 -10
  591. data/spec/mongo/auth/gssapi/conversation_spec.rb +124 -0
  592. data/spec/mongo/auth/invalid_mechanism_spec.rb +4 -1
  593. data/spec/mongo/auth/ldap/conversation_spec.rb +5 -2
  594. data/spec/mongo/auth/ldap_spec.rb +18 -8
  595. data/spec/mongo/auth/scram/conversation_spec.rb +125 -338
  596. data/spec/mongo/auth/scram256/conversation_spec.rb +174 -0
  597. data/spec/mongo/auth/{scram/negotiation_spec.rb → scram_negotiation_spec.rb} +83 -75
  598. data/spec/mongo/auth/scram_spec.rb +60 -88
  599. data/spec/mongo/auth/stringprep/profiles/sasl_spec.rb +3 -0
  600. data/spec/mongo/auth/stringprep_spec.rb +3 -0
  601. data/spec/mongo/auth/user/view_spec.rb +7 -7
  602. data/spec/mongo/auth/user_spec.rb +5 -2
  603. data/spec/mongo/auth/x509/conversation_spec.rb +7 -4
  604. data/spec/mongo/auth/x509_spec.rb +18 -12
  605. data/spec/mongo/auth_spec.rb +7 -4
  606. data/spec/mongo/bson_spec.rb +3 -0
  607. data/spec/mongo/bulk_write/ordered_combiner_spec.rb +3 -0
  608. data/spec/mongo/bulk_write/result_spec.rb +29 -8
  609. data/spec/mongo/bulk_write/unordered_combiner_spec.rb +3 -0
  610. data/spec/mongo/bulk_write_spec.rb +333 -5
  611. data/spec/mongo/caching_cursor_spec.rb +73 -0
  612. data/spec/mongo/client_construction_spec.rb +1662 -284
  613. data/spec/mongo/client_encryption_spec.rb +402 -0
  614. data/spec/mongo/client_spec.rb +425 -6
  615. data/spec/mongo/cluster/cursor_reaper_spec.rb +78 -31
  616. data/spec/mongo/cluster/periodic_executor_spec.rb +6 -1
  617. data/spec/mongo/cluster/socket_reaper_spec.rb +17 -3
  618. data/spec/mongo/cluster/topology/replica_set_spec.rb +65 -19
  619. data/spec/mongo/cluster/topology/sharded_spec.rb +6 -3
  620. data/spec/mongo/cluster/topology/single_spec.rb +24 -10
  621. data/spec/mongo/cluster/topology/unknown_spec.rb +4 -1
  622. data/spec/mongo/cluster/topology_spec.rb +4 -1
  623. data/spec/mongo/cluster_spec.rb +71 -81
  624. data/spec/mongo/cluster_time_spec.rb +3 -0
  625. data/spec/mongo/collection/view/aggregation_spec.rb +186 -86
  626. data/spec/mongo/collection/view/builder/find_command_spec.rb +24 -6
  627. data/spec/mongo/collection/view/builder/op_query_spec.rb +7 -0
  628. data/spec/mongo/collection/view/change_stream_resume_spec.rb +397 -0
  629. data/spec/mongo/collection/view/change_stream_spec.rb +21 -323
  630. data/spec/mongo/collection/view/explainable_spec.rb +90 -4
  631. data/spec/mongo/collection/view/immutable_spec.rb +3 -0
  632. data/spec/mongo/collection/view/iterable_spec.rb +41 -0
  633. data/spec/mongo/collection/view/map_reduce_spec.rb +44 -6
  634. data/spec/mongo/collection/view/readable_spec.rb +745 -2
  635. data/spec/mongo/collection/view/writable_spec.rb +323 -1
  636. data/spec/mongo/collection/view_spec.rb +4 -1
  637. data/spec/mongo/collection_crud_spec.rb +4415 -0
  638. data/spec/mongo/collection_ddl_spec.rb +537 -0
  639. data/spec/mongo/collection_spec.rb +103 -4367
  640. data/spec/mongo/config/options_spec.rb +75 -0
  641. data/spec/mongo/config_spec.rb +73 -0
  642. data/spec/mongo/crypt/auto_decryption_context_spec.rb +109 -0
  643. data/spec/mongo/crypt/auto_encrypter_spec.rb +441 -0
  644. data/spec/mongo/crypt/auto_encryption_context_spec.rb +126 -0
  645. data/spec/mongo/crypt/binary_spec.rb +113 -0
  646. data/spec/mongo/crypt/binding/binary_spec.rb +54 -0
  647. data/spec/mongo/crypt/binding/context_spec.rb +305 -0
  648. data/spec/mongo/crypt/binding/helpers_spec.rb +44 -0
  649. data/spec/mongo/crypt/binding/mongocrypt_spec.rb +113 -0
  650. data/spec/mongo/crypt/binding/status_spec.rb +97 -0
  651. data/spec/mongo/crypt/binding/version_spec.rb +53 -0
  652. data/spec/mongo/crypt/binding_unloaded_spec.rb +37 -0
  653. data/spec/mongo/crypt/data_key_context_spec.rb +144 -0
  654. data/spec/mongo/crypt/encryption_io_spec.rb +141 -0
  655. data/spec/mongo/crypt/explicit_decryption_context_spec.rb +106 -0
  656. data/spec/mongo/crypt/explicit_encryption_context_spec.rb +266 -0
  657. data/spec/mongo/crypt/handle_spec.rb +251 -0
  658. data/spec/mongo/crypt/helpers/mongo_crypt_spec_helper.rb +111 -0
  659. data/spec/mongo/crypt/hooks_spec.rb +30 -0
  660. data/spec/mongo/crypt/kms/credentials_spec.rb +357 -0
  661. data/spec/mongo/crypt/kms_spec.rb +59 -0
  662. data/spec/mongo/crypt/status_spec.rb +150 -0
  663. data/spec/mongo/cursor/builder/get_more_command_spec.rb +15 -1
  664. data/spec/mongo/cursor/builder/op_get_more_spec.rb +15 -1
  665. data/spec/mongo/cursor_spec.rb +209 -17
  666. data/spec/mongo/database_spec.rb +526 -27
  667. data/spec/mongo/distinguishing_semaphore_spec.rb +66 -0
  668. data/spec/mongo/error/bulk_write_error_spec.rb +52 -0
  669. data/spec/mongo/error/crypt_error_spec.rb +29 -0
  670. data/spec/mongo/error/max_bson_size_spec.rb +38 -0
  671. data/spec/mongo/error/no_server_available_spec.rb +15 -2
  672. data/spec/mongo/error/notable_spec.rb +62 -0
  673. data/spec/mongo/error/operation_failure_heavy_spec.rb +110 -0
  674. data/spec/mongo/error/operation_failure_spec.rb +231 -70
  675. data/spec/mongo/error/parser_spec.rb +40 -6
  676. data/spec/mongo/error/unsupported_option_spec.rb +57 -0
  677. data/spec/mongo/event/publisher_spec.rb +3 -0
  678. data/spec/mongo/event/subscriber_spec.rb +3 -0
  679. data/spec/mongo/grid/file/chunk_spec.rb +7 -4
  680. data/spec/mongo/grid/file/info_spec.rb +3 -0
  681. data/spec/mongo/grid/file_spec.rb +4 -1
  682. data/spec/mongo/grid/fs_bucket_spec.rb +58 -17
  683. data/spec/mongo/grid/stream/read_spec.rb +33 -10
  684. data/spec/mongo/grid/stream/write_spec.rb +38 -9
  685. data/spec/mongo/grid/stream_spec.rb +4 -1
  686. data/spec/mongo/id_spec.rb +3 -0
  687. data/spec/mongo/index/view_spec.rb +446 -0
  688. data/spec/mongo/lint_spec.rb +3 -0
  689. data/spec/mongo/logger_spec.rb +16 -11
  690. data/spec/mongo/monitoring/command_log_subscriber_spec.rb +3 -0
  691. data/spec/mongo/monitoring/event/cmap/connection_check_out_failed_spec.rb +3 -0
  692. data/spec/mongo/monitoring/event/cmap/connection_check_out_started_spec.rb +3 -0
  693. data/spec/mongo/monitoring/event/cmap/connection_checked_in_spec.rb +3 -0
  694. data/spec/mongo/monitoring/event/cmap/connection_checked_out_spec.rb +3 -0
  695. data/spec/mongo/monitoring/event/cmap/connection_closed_spec.rb +3 -0
  696. data/spec/mongo/monitoring/event/cmap/connection_created_spec.rb +3 -0
  697. data/spec/mongo/monitoring/event/cmap/connection_ready_spec.rb +3 -0
  698. data/spec/mongo/monitoring/event/cmap/pool_cleared_spec.rb +3 -0
  699. data/spec/mongo/monitoring/event/cmap/pool_closed_spec.rb +3 -0
  700. data/spec/mongo/monitoring/event/cmap/pool_created_spec.rb +3 -0
  701. data/spec/mongo/monitoring/event/command_failed_spec.rb +59 -2
  702. data/spec/mongo/monitoring/event/command_started_spec.rb +3 -0
  703. data/spec/mongo/monitoring/event/command_succeeded_spec.rb +46 -6
  704. data/spec/mongo/monitoring/event/secure_spec.rb +28 -4
  705. data/spec/mongo/monitoring/event/server_closed_spec.rb +4 -1
  706. data/spec/mongo/monitoring/event/server_description_changed_spec.rb +4 -4
  707. data/spec/mongo/monitoring/event/server_heartbeat_failed_spec.rb +4 -1
  708. data/spec/mongo/monitoring/event/server_heartbeat_started_spec.rb +3 -0
  709. data/spec/mongo/monitoring/event/server_heartbeat_succeeded_spec.rb +4 -1
  710. data/spec/mongo/monitoring/event/server_opening_spec.rb +4 -1
  711. data/spec/mongo/monitoring/event/topology_changed_spec.rb +4 -1
  712. data/spec/mongo/monitoring/event/topology_closed_spec.rb +4 -1
  713. data/spec/mongo/monitoring/event/topology_opening_spec.rb +4 -1
  714. data/spec/mongo/monitoring_spec.rb +3 -0
  715. data/spec/mongo/operation/aggregate/result_spec.rb +11 -1
  716. data/spec/mongo/operation/aggregate_spec.rb +5 -1
  717. data/spec/mongo/operation/collections_info_spec.rb +7 -1
  718. data/spec/mongo/operation/command_spec.rb +11 -5
  719. data/spec/mongo/operation/create/op_msg_spec.rb +244 -0
  720. data/spec/mongo/operation/create_index_spec.rb +9 -3
  721. data/spec/mongo/operation/create_user_spec.rb +9 -3
  722. data/spec/mongo/operation/delete/bulk_spec.rb +24 -6
  723. data/spec/mongo/operation/delete/command_spec.rb +3 -0
  724. data/spec/mongo/operation/delete/op_msg_spec.rb +40 -25
  725. data/spec/mongo/operation/delete_spec.rb +13 -36
  726. data/spec/mongo/operation/drop_index_spec.rb +9 -2
  727. data/spec/mongo/{collection/view → operation/find}/builder/flags_spec.rb +5 -2
  728. data/spec/mongo/{collection/view → operation/find}/builder/modifiers_spec.rb +5 -2
  729. data/spec/mongo/operation/find/legacy_spec.rb +34 -7
  730. data/spec/mongo/operation/get_more_spec.rb +11 -1
  731. data/spec/mongo/operation/indexes_spec.rb +8 -1
  732. data/spec/mongo/operation/insert/bulk_spec.rb +28 -8
  733. data/spec/mongo/operation/insert/command_spec.rb +7 -0
  734. data/spec/mongo/operation/insert/op_msg_spec.rb +46 -30
  735. data/spec/mongo/operation/insert_spec.rb +17 -43
  736. data/spec/mongo/operation/limited_spec.rb +8 -3
  737. data/spec/mongo/operation/map_reduce_spec.rb +8 -2
  738. data/spec/mongo/operation/read_preference_legacy_spec.rb +360 -0
  739. data/spec/mongo/operation/read_preference_op_msg_spec.rb +332 -0
  740. data/spec/mongo/operation/remove_user_spec.rb +9 -3
  741. data/spec/mongo/operation/result_spec.rb +34 -4
  742. data/spec/mongo/operation/specifiable_spec.rb +3 -0
  743. data/spec/mongo/operation/update/bulk_spec.rb +25 -7
  744. data/spec/mongo/operation/update/command_spec.rb +7 -0
  745. data/spec/mongo/operation/update/op_msg_spec.rb +41 -24
  746. data/spec/mongo/operation/update_spec.rb +12 -35
  747. data/spec/mongo/operation/update_user_spec.rb +7 -1
  748. data/spec/mongo/options/redacted_spec.rb +3 -0
  749. data/spec/mongo/protocol/caching_hash_spec.rb +82 -0
  750. data/spec/mongo/protocol/compressed_spec.rb +29 -13
  751. data/spec/mongo/protocol/delete_spec.rb +12 -8
  752. data/spec/mongo/protocol/get_more_spec.rb +12 -8
  753. data/spec/mongo/protocol/insert_spec.rb +12 -8
  754. data/spec/mongo/protocol/kill_cursors_spec.rb +9 -5
  755. data/spec/mongo/protocol/msg_spec.rb +111 -53
  756. data/spec/mongo/protocol/query_spec.rb +18 -15
  757. data/spec/mongo/protocol/registry_spec.rb +4 -1
  758. data/spec/mongo/protocol/reply_spec.rb +4 -1
  759. data/spec/mongo/protocol/update_spec.rb +13 -9
  760. data/spec/mongo/query_cache_middleware_spec.rb +55 -0
  761. data/spec/mongo/query_cache_spec.rb +453 -0
  762. data/spec/mongo/retryable_spec.rb +109 -75
  763. data/spec/mongo/semaphore_spec.rb +54 -0
  764. data/spec/mongo/server/app_metadata_spec.rb +53 -21
  765. data/spec/mongo/server/connection_auth_spec.rb +42 -24
  766. data/spec/mongo/server/connection_common_spec.rb +87 -0
  767. data/spec/mongo/server/connection_pool/populator_spec.rb +6 -1
  768. data/spec/mongo/server/connection_pool_spec.rb +189 -80
  769. data/spec/mongo/server/connection_spec.rb +323 -246
  770. data/spec/mongo/server/description/features_spec.rb +27 -0
  771. data/spec/mongo/server/description_query_methods_spec.rb +4 -1
  772. data/spec/mongo/server/description_spec.rb +625 -594
  773. data/spec/mongo/server/monitor/app_metadata_spec.rb +10 -1
  774. data/spec/mongo/server/monitor/connection_spec.rb +60 -69
  775. data/spec/mongo/server/monitor_spec.rb +95 -24
  776. data/spec/mongo/server/push_monitor_spec.rb +95 -0
  777. data/spec/mongo/server/round_trip_time_averager_spec.rb +8 -3
  778. data/spec/mongo/server_selector/nearest_spec.rb +32 -25
  779. data/spec/mongo/server_selector/primary_preferred_spec.rb +35 -28
  780. data/spec/mongo/server_selector/primary_spec.rb +35 -11
  781. data/spec/mongo/server_selector/secondary_preferred_spec.rb +52 -29
  782. data/spec/mongo/server_selector/secondary_spec.rb +27 -20
  783. data/spec/mongo/server_selector_spec.rb +145 -21
  784. data/spec/mongo/server_spec.rb +18 -2
  785. data/spec/mongo/session/server_session_spec.rb +3 -0
  786. data/spec/mongo/session/session_pool_spec.rb +51 -12
  787. data/spec/mongo/session_spec.rb +58 -0
  788. data/spec/mongo/session_transaction_spec.rb +17 -36
  789. data/spec/mongo/socket/ssl_spec.rb +91 -69
  790. data/spec/mongo/socket/tcp_spec.rb +5 -2
  791. data/spec/mongo/socket/unix_spec.rb +6 -2
  792. data/spec/mongo/socket_spec.rb +14 -11
  793. data/spec/mongo/srv/monitor_spec.rb +91 -69
  794. data/spec/mongo/srv/result_spec.rb +3 -0
  795. data/spec/mongo/timeout_spec.rb +42 -0
  796. data/spec/mongo/tls_context_hooks_spec.rb +40 -0
  797. data/spec/mongo/uri/srv_protocol_spec.rb +171 -37
  798. data/spec/mongo/uri_option_parsing_spec.rb +52 -16
  799. data/spec/mongo/uri_spec.rb +165 -48
  800. data/spec/mongo/utils_spec.rb +42 -0
  801. data/spec/mongo/write_concern/acknowledged_spec.rb +3 -0
  802. data/spec/mongo/write_concern/unacknowledged_spec.rb +3 -0
  803. data/spec/mongo/write_concern_spec.rb +16 -1
  804. data/spec/{support → runners}/auth.rb +45 -9
  805. data/spec/runners/change_streams/outcome.rb +45 -0
  806. data/spec/runners/change_streams/spec.rb +60 -0
  807. data/spec/runners/change_streams/test.rb +232 -0
  808. data/spec/{support → runners}/cmap/verifier.rb +4 -1
  809. data/spec/{support → runners}/cmap.rb +7 -4
  810. data/spec/{support → runners}/command_monitoring.rb +8 -36
  811. data/spec/runners/connection_string.rb +283 -6
  812. data/spec/{support/transactions → runners/crud}/context.rb +12 -15
  813. data/spec/{support → runners}/crud/operation.rb +201 -61
  814. data/spec/{support → runners}/crud/outcome.rb +4 -1
  815. data/spec/runners/crud/requirement.rb +139 -0
  816. data/spec/{support → runners}/crud/spec.rb +21 -11
  817. data/spec/{support → runners}/crud/test.rb +12 -27
  818. data/spec/runners/crud/test_base.rb +53 -0
  819. data/spec/{support → runners}/crud/verifier.rb +47 -15
  820. data/spec/{support → runners}/crud.rb +34 -12
  821. data/spec/{support → runners}/gridfs.rb +5 -2
  822. data/spec/runners/read_write_concern_document.rb +4 -1
  823. data/spec/runners/sdam/verifier.rb +29 -8
  824. data/spec/{support/server_discovery_and_monitoring.rb → runners/sdam.rb} +49 -26
  825. data/spec/runners/server_selection.rb +365 -0
  826. data/spec/{support → runners}/server_selection_rtt.rb +5 -2
  827. data/spec/runners/transactions/operation.rb +328 -0
  828. data/spec/{support → runners}/transactions/spec.rb +6 -3
  829. data/spec/runners/transactions/test.rb +329 -0
  830. data/spec/{support → runners}/transactions.rb +30 -27
  831. data/spec/runners/unified/assertions.rb +362 -0
  832. data/spec/runners/unified/change_stream_operations.rb +41 -0
  833. data/spec/runners/unified/client_side_encryption_operations.rb +83 -0
  834. data/spec/runners/unified/crud_operations.rb +323 -0
  835. data/spec/runners/unified/ddl_operations.rb +179 -0
  836. data/spec/runners/unified/entity_map.rb +42 -0
  837. data/spec/runners/unified/error.rb +29 -0
  838. data/spec/runners/unified/event_subscriber.rb +104 -0
  839. data/spec/runners/unified/exceptions.rb +24 -0
  840. data/spec/runners/unified/grid_fs_operations.rb +79 -0
  841. data/spec/runners/unified/support_operations.rb +269 -0
  842. data/spec/runners/unified/test.rb +511 -0
  843. data/spec/runners/unified/test_group.rb +31 -0
  844. data/spec/runners/unified.rb +106 -0
  845. data/spec/shared/LICENSE +20 -0
  846. data/spec/shared/bin/get-mongodb-download-url +17 -0
  847. data/spec/shared/bin/s3-copy +45 -0
  848. data/spec/shared/bin/s3-upload +69 -0
  849. data/spec/shared/lib/mrss/child_process_helper.rb +80 -0
  850. data/spec/shared/lib/mrss/cluster_config.rb +231 -0
  851. data/spec/shared/lib/mrss/constraints.rb +378 -0
  852. data/spec/shared/lib/mrss/docker_runner.rb +291 -0
  853. data/spec/shared/lib/mrss/eg_config_utils.rb +51 -0
  854. data/spec/shared/lib/mrss/event_subscriber.rb +210 -0
  855. data/spec/shared/lib/mrss/lite_constraints.rb +230 -0
  856. data/spec/shared/lib/mrss/server_version_registry.rb +120 -0
  857. data/spec/shared/lib/mrss/session_registry.rb +69 -0
  858. data/spec/shared/lib/mrss/session_registry_legacy.rb +60 -0
  859. data/spec/shared/lib/mrss/spec_organizer.rb +179 -0
  860. data/spec/shared/lib/mrss/utils.rb +15 -0
  861. data/spec/shared/share/Dockerfile.erb +325 -0
  862. data/spec/shared/share/haproxy-1.conf +16 -0
  863. data/spec/shared/share/haproxy-2.conf +17 -0
  864. data/spec/shared/shlib/config.sh +27 -0
  865. data/spec/shared/shlib/distro.sh +74 -0
  866. data/spec/shared/shlib/server.sh +392 -0
  867. data/spec/shared/shlib/set_env.sh +169 -0
  868. data/spec/solo/clean_exit_spec.rb +29 -0
  869. data/spec/spec_helper.rb +10 -9
  870. data/spec/spec_tests/auth_spec.rb +33 -14
  871. data/spec/spec_tests/change_streams_unified_spec.rb +13 -0
  872. data/spec/spec_tests/client_side_encryption_spec.rb +14 -0
  873. data/spec/spec_tests/client_side_encryption_unified_spec.rb +16 -0
  874. data/spec/spec_tests/cmap_spec.rb +19 -4
  875. data/spec/spec_tests/collection_management_spec.rb +13 -0
  876. data/spec/spec_tests/command_monitoring_unified_spec.rb +13 -0
  877. data/spec/spec_tests/connection_string_spec.rb +6 -1
  878. data/spec/spec_tests/crud_spec.rb +5 -10
  879. data/spec/spec_tests/crud_unified_spec.rb +13 -0
  880. data/spec/spec_tests/data/auth/connection-string.yml +69 -0
  881. data/spec/spec_tests/data/change_streams_unified/change-streams-errors.yml +124 -0
  882. data/spec/spec_tests/data/change_streams_unified/change-streams-pre_and_post_images.yml +351 -0
  883. data/spec/spec_tests/data/change_streams_unified/change-streams-resume-allowlist.yml +1171 -0
  884. data/spec/spec_tests/data/change_streams_unified/change-streams-resume-errorLabels.yml +1071 -0
  885. data/spec/spec_tests/data/change_streams_unified/change-streams-showExpandedEvents.yml +298 -0
  886. data/spec/spec_tests/data/change_streams_unified/change-streams.yml +927 -0
  887. data/spec/spec_tests/data/client_side_encryption/aggregate.yml +120 -0
  888. data/spec/spec_tests/data/client_side_encryption/azureKMS.yml +46 -0
  889. data/spec/spec_tests/data/client_side_encryption/badQueries.yml +536 -0
  890. data/spec/spec_tests/data/client_side_encryption/badSchema.yml +73 -0
  891. data/spec/spec_tests/data/client_side_encryption/basic.yml +102 -0
  892. data/spec/spec_tests/data/client_side_encryption/bulk.yml +81 -0
  893. data/spec/spec_tests/data/client_side_encryption/bypassAutoEncryption.yml +100 -0
  894. data/spec/spec_tests/data/client_side_encryption/bypassedCommand.yml +42 -0
  895. data/spec/spec_tests/data/client_side_encryption/count.yml +54 -0
  896. data/spec/spec_tests/data/client_side_encryption/countDocuments.yml +52 -0
  897. data/spec/spec_tests/data/client_side_encryption/create-and-createIndexes.yml +58 -0
  898. data/spec/spec_tests/data/client_side_encryption/delete.yml +91 -0
  899. data/spec/spec_tests/data/client_side_encryption/distinct.yml +66 -0
  900. data/spec/spec_tests/data/client_side_encryption/explain.yml +57 -0
  901. data/spec/spec_tests/data/client_side_encryption/find.yml +105 -0
  902. data/spec/spec_tests/data/client_side_encryption/findOneAndDelete.yml +50 -0
  903. data/spec/spec_tests/data/client_side_encryption/findOneAndReplace.yml +50 -0
  904. data/spec/spec_tests/data/client_side_encryption/findOneAndUpdate.yml +50 -0
  905. data/spec/spec_tests/data/client_side_encryption/fle2-BypassQueryAnalysis.yml +101 -0
  906. data/spec/spec_tests/data/client_side_encryption/fle2-Compact.yml +80 -0
  907. data/spec/spec_tests/data/client_side_encryption/fle2-CreateCollection.yml +1263 -0
  908. data/spec/spec_tests/data/client_side_encryption/fle2-DecryptExistingData.yml +64 -0
  909. data/spec/spec_tests/data/client_side_encryption/fle2-Delete.yml +107 -0
  910. data/spec/spec_tests/data/client_side_encryption/fle2-EncryptedFields-vs-EncryptedFieldsMap.yml +80 -0
  911. data/spec/spec_tests/data/client_side_encryption/fle2-EncryptedFields-vs-jsonSchema.yml +90 -0
  912. data/spec/spec_tests/data/client_side_encryption/fle2-EncryptedFieldsMap-defaults.yml +57 -0
  913. data/spec/spec_tests/data/client_side_encryption/fle2-FindOneAndUpdate.yml +213 -0
  914. data/spec/spec_tests/data/client_side_encryption/fle2-InsertFind-Indexed.yml +86 -0
  915. data/spec/spec_tests/data/client_side_encryption/fle2-InsertFind-Unindexed.yml +83 -0
  916. data/spec/spec_tests/data/client_side_encryption/fle2-MissingKey.yml +41 -0
  917. data/spec/spec_tests/data/client_side_encryption/fle2-NoEncryption.yml +42 -0
  918. data/spec/spec_tests/data/client_side_encryption/fle2-Update.yml +221 -0
  919. data/spec/spec_tests/data/client_side_encryption/fle2-validatorAndPartialFieldExpression.yml +168 -0
  920. data/spec/spec_tests/data/client_side_encryption/gcpKMS.yml +46 -0
  921. data/spec/spec_tests/data/client_side_encryption/getMore.yml +61 -0
  922. data/spec/spec_tests/data/client_side_encryption/insert.yml +88 -0
  923. data/spec/spec_tests/data/client_side_encryption/keyAltName.yml +64 -0
  924. data/spec/spec_tests/data/client_side_encryption/localKMS.yml +47 -0
  925. data/spec/spec_tests/data/client_side_encryption/localSchema.yml +65 -0
  926. data/spec/spec_tests/data/client_side_encryption/malformedCiphertext.yml +69 -0
  927. data/spec/spec_tests/data/client_side_encryption/maxWireVersion.yml +22 -0
  928. data/spec/spec_tests/data/client_side_encryption/missingKey.yml +42 -0
  929. data/spec/spec_tests/data/client_side_encryption/noSchema.yml +39 -0
  930. data/spec/spec_tests/data/client_side_encryption/replaceOne.yml +57 -0
  931. data/spec/spec_tests/data/client_side_encryption/types.yml +501 -0
  932. data/spec/spec_tests/data/client_side_encryption/unified/addKeyAltName.yml +194 -0
  933. data/spec/spec_tests/data/client_side_encryption/unified/createDataKey-kms_providers-invalid.yml +67 -0
  934. data/spec/spec_tests/data/client_side_encryption/unified/createDataKey.yml +309 -0
  935. data/spec/spec_tests/data/client_side_encryption/unified/deleteKey.yml +159 -0
  936. data/spec/spec_tests/data/client_side_encryption/unified/getKey.yml +105 -0
  937. data/spec/spec_tests/data/client_side_encryption/unified/getKeyByAltName.yml +104 -0
  938. data/spec/spec_tests/data/client_side_encryption/unified/getKeys.yml +122 -0
  939. data/spec/spec_tests/data/client_side_encryption/unified/removeKeyAltName.yml +157 -0
  940. data/spec/spec_tests/data/client_side_encryption/unified/rewrapManyDataKey-decrypt_failure.yml +69 -0
  941. data/spec/spec_tests/data/client_side_encryption/unified/rewrapManyDataKey-encrypt_failure.yml +122 -0
  942. data/spec/spec_tests/data/client_side_encryption/unified/rewrapManyDataKey.yml +432 -0
  943. data/spec/spec_tests/data/client_side_encryption/unsupportedCommand.yml +25 -0
  944. data/spec/spec_tests/data/client_side_encryption/updateMany.yml +70 -0
  945. data/spec/spec_tests/data/client_side_encryption/updateOne.yml +164 -0
  946. data/spec/spec_tests/data/client_side_encryption/validatorAndPartialFieldExpression.yml +166 -0
  947. data/spec/spec_tests/data/cmap/pool-checkout-connection.yml +6 -2
  948. data/spec/spec_tests/data/cmap/pool-create-min-size.yml +3 -0
  949. data/spec/spec_tests/data/collection_management/clustered-indexes.yml +135 -0
  950. data/spec/spec_tests/data/collection_management/createCollection-pre_and_post_images.yml +50 -0
  951. data/spec/spec_tests/data/collection_management/modifyCollection-pre_and_post_images.yml +58 -0
  952. data/spec/spec_tests/data/collection_management/timeseries-collection.yml +129 -0
  953. data/spec/spec_tests/data/command_monitoring_unified/bulkWrite.yml +68 -0
  954. data/spec/spec_tests/data/command_monitoring_unified/command.yml +50 -0
  955. data/spec/spec_tests/data/command_monitoring_unified/deleteMany.yml +79 -0
  956. data/spec/spec_tests/data/command_monitoring_unified/deleteOne.yml +79 -0
  957. data/spec/spec_tests/data/command_monitoring_unified/find.yml +254 -0
  958. data/spec/spec_tests/data/command_monitoring_unified/insertMany.yml +79 -0
  959. data/spec/spec_tests/data/command_monitoring_unified/insertOne.yml +77 -0
  960. data/spec/spec_tests/data/command_monitoring_unified/pre-42-server-connection-id.yml +56 -0
  961. data/spec/spec_tests/data/command_monitoring_unified/redacted-commands.yml +340 -0
  962. data/spec/spec_tests/data/command_monitoring_unified/server-connection-id.yml +56 -0
  963. data/spec/spec_tests/data/command_monitoring_unified/unacknowledgedBulkWrite.yml +55 -0
  964. data/spec/spec_tests/data/command_monitoring_unified/updateMany.yml +87 -0
  965. data/spec/spec_tests/data/command_monitoring_unified/updateOne.yml +118 -0
  966. data/spec/spec_tests/data/connection_string/valid-warnings.yml +24 -0
  967. data/spec/spec_tests/data/crud/read/aggregate-collation.yml +2 -1
  968. data/spec/spec_tests/data/crud/read/aggregate-out.yml +1 -0
  969. data/spec/spec_tests/data/crud/read/count-collation.yml +2 -1
  970. data/spec/spec_tests/data/crud/read/distinct-collation.yml +2 -1
  971. data/spec/spec_tests/data/crud/read/find-collation.yml +2 -1
  972. data/spec/spec_tests/data/crud/write/bulkWrite-collation.yml +2 -1
  973. data/spec/spec_tests/data/crud/write/bulkWrite.yml +26 -22
  974. data/spec/spec_tests/data/crud/write/deleteMany-collation.yml +2 -1
  975. data/spec/spec_tests/data/crud/write/deleteOne-collation.yml +2 -1
  976. data/spec/spec_tests/data/crud/write/findOneAndDelete-collation.yml +3 -2
  977. data/spec/spec_tests/data/crud/write/findOneAndReplace-collation.yml +2 -1
  978. data/spec/spec_tests/data/crud/write/findOneAndUpdate-collation.yml +3 -2
  979. data/spec/spec_tests/data/crud/write/insertMany.yml +26 -22
  980. data/spec/spec_tests/data/crud/write/replaceOne-collation.yml +3 -2
  981. data/spec/spec_tests/data/crud/write/updateMany-collation.yml +2 -1
  982. data/spec/spec_tests/data/crud/write/updateOne-collation.yml +2 -1
  983. data/spec/spec_tests/data/crud_unified/aggregate-allowdiskuse.yml +75 -0
  984. data/spec/spec_tests/data/crud_unified/aggregate-let.yml +138 -0
  985. data/spec/spec_tests/data/crud_unified/aggregate-merge.yml +185 -0
  986. data/spec/spec_tests/data/crud_unified/aggregate-out-readConcern.yml +171 -0
  987. data/spec/spec_tests/data/crud_unified/aggregate-write-readPreference.yml +155 -0
  988. data/spec/spec_tests/data/crud_unified/aggregate.yml +215 -0
  989. data/spec/spec_tests/data/crud_unified/bulkWrite-arrayFilters-clientError.yml +98 -0
  990. data/spec/spec_tests/data/crud_unified/bulkWrite-arrayFilters.yml +174 -0
  991. data/spec/spec_tests/data/crud_unified/bulkWrite-comment.yml +189 -0
  992. data/spec/spec_tests/data/crud_unified/bulkWrite-delete-hint-clientError.yml +113 -0
  993. data/spec/spec_tests/data/crud_unified/bulkWrite-delete-hint-serverError.yml +142 -0
  994. data/spec/spec_tests/data/crud_unified/bulkWrite-delete-hint.yml +154 -0
  995. data/spec/spec_tests/data/crud_unified/bulkWrite-deleteMany-hint-unacknowledged.yml +98 -0
  996. data/spec/spec_tests/data/crud_unified/bulkWrite-deleteMany-let.yml +86 -0
  997. data/spec/spec_tests/data/crud_unified/bulkWrite-deleteOne-hint-unacknowledged.yml +97 -0
  998. data/spec/spec_tests/data/crud_unified/bulkWrite-deleteOne-let.yml +86 -0
  999. data/spec/spec_tests/data/crud_unified/bulkWrite-insertOne-dots_and_dollars.yml +138 -0
  1000. data/spec/spec_tests/data/crud_unified/bulkWrite-replaceOne-dots_and_dollars.yml +165 -0
  1001. data/spec/spec_tests/data/crud_unified/bulkWrite-replaceOne-hint-unacknowledged.yml +103 -0
  1002. data/spec/spec_tests/data/crud_unified/bulkWrite-replaceOne-let.yml +93 -0
  1003. data/spec/spec_tests/data/crud_unified/bulkWrite-update-hint-clientError.yml +148 -0
  1004. data/spec/spec_tests/data/crud_unified/bulkWrite-update-hint-serverError.yml +239 -0
  1005. data/spec/spec_tests/data/crud_unified/bulkWrite-update-hint.yml +256 -0
  1006. data/spec/spec_tests/data/crud_unified/bulkWrite-update-validation.yml +73 -0
  1007. data/spec/spec_tests/data/crud_unified/bulkWrite-updateMany-dots_and_dollars.yml +150 -0
  1008. data/spec/spec_tests/data/crud_unified/bulkWrite-updateMany-hint-unacknowledged.yml +104 -0
  1009. data/spec/spec_tests/data/crud_unified/bulkWrite-updateMany-let.yml +96 -0
  1010. data/spec/spec_tests/data/crud_unified/bulkWrite-updateOne-dots_and_dollars.yml +150 -0
  1011. data/spec/spec_tests/data/crud_unified/bulkWrite-updateOne-hint-unacknowledged.yml +103 -0
  1012. data/spec/spec_tests/data/crud_unified/bulkWrite-updateOne-let.yml +95 -0
  1013. data/spec/spec_tests/data/crud_unified/countDocuments-comment.yml +92 -0
  1014. data/spec/spec_tests/data/crud_unified/db-aggregate-write-readPreference.yml +151 -0
  1015. data/spec/spec_tests/data/crud_unified/db-aggregate.yml +73 -0
  1016. data/spec/spec_tests/data/crud_unified/deleteMany-comment.yml +97 -0
  1017. data/spec/spec_tests/data/crud_unified/deleteMany-hint-clientError.yml +87 -0
  1018. data/spec/spec_tests/data/crud_unified/deleteMany-hint-serverError.yml +107 -0
  1019. data/spec/spec_tests/data/crud_unified/deleteMany-hint-unacknowledged.yml +90 -0
  1020. data/spec/spec_tests/data/crud_unified/deleteMany-hint.yml +99 -0
  1021. data/spec/spec_tests/data/crud_unified/deleteMany-let.yml +93 -0
  1022. data/spec/spec_tests/data/crud_unified/deleteOne-comment.yml +98 -0
  1023. data/spec/spec_tests/data/crud_unified/deleteOne-hint-clientError.yml +80 -0
  1024. data/spec/spec_tests/data/crud_unified/deleteOne-hint-serverError.yml +100 -0
  1025. data/spec/spec_tests/data/crud_unified/deleteOne-hint-unacknowledged.yml +89 -0
  1026. data/spec/spec_tests/data/crud_unified/deleteOne-hint.yml +95 -0
  1027. data/spec/spec_tests/data/crud_unified/deleteOne-let.yml +91 -0
  1028. data/spec/spec_tests/data/crud_unified/distinct-comment.yml +98 -0
  1029. data/spec/spec_tests/data/crud_unified/estimatedDocumentCount-comment.yml +95 -0
  1030. data/spec/spec_tests/data/crud_unified/estimatedDocumentCount.yml +137 -0
  1031. data/spec/spec_tests/data/crud_unified/find-allowdiskuse-clientError.yml +55 -0
  1032. data/spec/spec_tests/data/crud_unified/find-allowdiskuse-serverError.yml +68 -0
  1033. data/spec/spec_tests/data/crud_unified/find-allowdiskuse.yml +79 -0
  1034. data/spec/spec_tests/data/crud_unified/find-comment.yml +166 -0
  1035. data/spec/spec_tests/data/crud_unified/find-let.yml +71 -0
  1036. data/spec/spec_tests/data/crud_unified/find.yml +68 -0
  1037. data/spec/spec_tests/data/crud_unified/findOneAndDelete-comment.yml +96 -0
  1038. data/spec/spec_tests/data/crud_unified/findOneAndDelete-hint-clientError.yml +91 -0
  1039. data/spec/spec_tests/data/crud_unified/findOneAndDelete-hint-serverError.yml +107 -0
  1040. data/spec/spec_tests/data/crud_unified/findOneAndDelete-hint-unacknowledged.yml +88 -0
  1041. data/spec/spec_tests/data/crud_unified/findOneAndDelete-hint.yml +102 -0
  1042. data/spec/spec_tests/data/crud_unified/findOneAndDelete-let.yml +86 -0
  1043. data/spec/spec_tests/data/crud_unified/findOneAndReplace-comment.yml +101 -0
  1044. data/spec/spec_tests/data/crud_unified/findOneAndReplace-dots_and_dollars.yml +140 -0
  1045. data/spec/spec_tests/data/crud_unified/findOneAndReplace-hint-clientError.yml +83 -0
  1046. data/spec/spec_tests/data/crud_unified/findOneAndReplace-hint-serverError.yml +99 -0
  1047. data/spec/spec_tests/data/crud_unified/findOneAndReplace-hint-unacknowledged.yml +96 -0
  1048. data/spec/spec_tests/data/crud_unified/findOneAndReplace-hint.yml +98 -0
  1049. data/spec/spec_tests/data/crud_unified/findOneAndReplace-let.yml +94 -0
  1050. data/spec/spec_tests/data/crud_unified/findOneAndUpdate-comment.yml +95 -0
  1051. data/spec/spec_tests/data/crud_unified/findOneAndUpdate-dots_and_dollars.yml +127 -0
  1052. data/spec/spec_tests/data/crud_unified/findOneAndUpdate-hint-clientError.yml +84 -0
  1053. data/spec/spec_tests/data/crud_unified/findOneAndUpdate-hint-serverError.yml +100 -0
  1054. data/spec/spec_tests/data/crud_unified/findOneAndUpdate-hint-unacknowledged.yml +92 -0
  1055. data/spec/spec_tests/data/crud_unified/findOneAndUpdate-hint.yml +99 -0
  1056. data/spec/spec_tests/data/crud_unified/findOneAndUpdate-let.yml +96 -0
  1057. data/spec/spec_tests/data/crud_unified/insertMany-comment.yml +93 -0
  1058. data/spec/spec_tests/data/crud_unified/insertMany-dots_and_dollars.yml +128 -0
  1059. data/spec/spec_tests/data/crud_unified/insertOne-comment.yml +91 -0
  1060. data/spec/spec_tests/data/crud_unified/insertOne-dots_and_dollars.yml +238 -0
  1061. data/spec/spec_tests/data/crud_unified/replaceOne-comment.yml +105 -0
  1062. data/spec/spec_tests/data/crud_unified/replaceOne-dots_and_dollars.yml +180 -0
  1063. data/spec/spec_tests/data/crud_unified/replaceOne-hint-unacknowledged.yml +95 -0
  1064. data/spec/spec_tests/data/crud_unified/replaceOne-hint.yml +108 -0
  1065. data/spec/spec_tests/data/crud_unified/replaceOne-let.yml +98 -0
  1066. data/spec/spec_tests/data/crud_unified/replaceOne-validation.yml +37 -0
  1067. data/spec/spec_tests/data/crud_unified/updateMany-comment.yml +104 -0
  1068. data/spec/spec_tests/data/crud_unified/updateMany-dots_and_dollars.yml +138 -0
  1069. data/spec/spec_tests/data/crud_unified/updateMany-hint-clientError.yml +91 -0
  1070. data/spec/spec_tests/data/crud_unified/updateMany-hint-serverError.yml +115 -0
  1071. data/spec/spec_tests/data/crud_unified/updateMany-hint-unacknowledged.yml +96 -0
  1072. data/spec/spec_tests/data/crud_unified/updateMany-hint.yml +115 -0
  1073. data/spec/spec_tests/data/crud_unified/updateMany-let.yml +107 -0
  1074. data/spec/spec_tests/data/crud_unified/updateMany-validation.yml +39 -0
  1075. data/spec/spec_tests/data/crud_unified/updateOne-comment.yml +104 -0
  1076. data/spec/spec_tests/data/crud_unified/updateOne-dots_and_dollars.yml +138 -0
  1077. data/spec/spec_tests/data/crud_unified/updateOne-hint-clientError.yml +85 -0
  1078. data/spec/spec_tests/data/crud_unified/updateOne-hint-serverError.yml +109 -0
  1079. data/spec/spec_tests/data/crud_unified/updateOne-hint-unacknowledged.yml +95 -0
  1080. data/spec/spec_tests/data/crud_unified/updateOne-hint.yml +109 -0
  1081. data/spec/spec_tests/data/crud_unified/updateOne-let.yml +102 -0
  1082. data/spec/spec_tests/data/crud_unified/updateOne-validation.yml +37 -0
  1083. data/spec/spec_tests/data/crud_unified/updateWithPipelines.yml +299 -0
  1084. data/spec/spec_tests/data/gridfs_unified/delete.yml +198 -0
  1085. data/spec/spec_tests/data/gridfs_unified/download.yml +241 -0
  1086. data/spec/spec_tests/data/gridfs_unified/downloadByName.yml +159 -0
  1087. data/spec/spec_tests/data/gridfs_unified/upload-disableMD5.yml +92 -0
  1088. data/spec/spec_tests/data/gridfs_unified/upload.yml +288 -0
  1089. data/spec/spec_tests/data/load_balancers/event-monitoring.yml +99 -0
  1090. data/spec/spec_tests/data/load_balancers/lb-connection-establishment.yml +36 -0
  1091. data/spec/spec_tests/data/load_balancers/non-lb-connection-establishment.yml +56 -0
  1092. data/spec/spec_tests/data/load_balancers/server-selection.yml +50 -0
  1093. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/DefaultNoMaxStaleness.yml +2 -2
  1094. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/LastUpdateTime.yml +3 -3
  1095. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/MaxStalenessTooSmall.yml +15 -0
  1096. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/Nearest.yml +3 -3
  1097. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/Nearest2.yml +3 -3
  1098. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/NoKnownServers.yml +4 -3
  1099. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/PrimaryPreferred.yml +2 -2
  1100. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/PrimaryPreferred_tags.yml +2 -2
  1101. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/Secondary.yml +4 -4
  1102. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/SecondaryPreferred.yml +2 -2
  1103. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/SecondaryPreferred_tags.yml +4 -4
  1104. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/ZeroMaxStaleness.yml +2 -2
  1105. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/DefaultNoMaxStaleness.yml +2 -2
  1106. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/LastUpdateTime.yml +3 -3
  1107. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/LongHeartbeat.yml +2 -2
  1108. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/LongHeartbeat2.yml +2 -2
  1109. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/MaxStalenessTooSmall.yml +2 -2
  1110. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/MaxStalenessWithModePrimary.yml +2 -2
  1111. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Nearest.yml +3 -3
  1112. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Nearest2.yml +3 -3
  1113. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Nearest_tags.yml +2 -2
  1114. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/PrimaryPreferred.yml +2 -2
  1115. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred.yml +2 -2
  1116. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred_tags.yml +5 -5
  1117. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred_tags2.yml +3 -3
  1118. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Secondary_tags.yml +5 -5
  1119. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Secondary_tags2.yml +3 -3
  1120. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/ZeroMaxStaleness.yml +2 -2
  1121. data/spec/spec_tests/data/max_staleness/Sharded/SmallMaxStaleness.yml +2 -2
  1122. data/spec/spec_tests/data/max_staleness/Single/SmallMaxStaleness.yml +1 -1
  1123. data/spec/spec_tests/data/max_staleness/Unknown/SmallMaxStaleness.yml +1 -0
  1124. data/spec/spec_tests/data/read_write_concern/connection-string/write-concern.yml +1 -4
  1125. data/spec/spec_tests/data/read_write_concern/operation/default-write-concern-2.6.yml +215 -0
  1126. data/spec/spec_tests/data/read_write_concern/operation/default-write-concern-3.2.yml +58 -0
  1127. data/spec/spec_tests/data/read_write_concern/operation/default-write-concern-3.4.yml +95 -0
  1128. data/spec/spec_tests/data/read_write_concern/operation/default-write-concern-4.2.yml +36 -0
  1129. data/spec/spec_tests/data/retryable_reads/{aggregate-serverErrors.yml → legacy/aggregate-serverErrors.yml} +1 -1
  1130. data/spec/spec_tests/data/retryable_reads/{changeStreams-client.watch-serverErrors.yml → legacy/changeStreams-client.watch-serverErrors.yml} +7 -6
  1131. data/spec/spec_tests/data/retryable_reads/{changeStreams-client.watch.yml → legacy/changeStreams-client.watch.yml} +2 -1
  1132. data/spec/spec_tests/data/retryable_reads/{changeStreams-db.coll.watch-serverErrors.yml → legacy/changeStreams-db.coll.watch-serverErrors.yml} +7 -6
  1133. data/spec/spec_tests/data/retryable_reads/{changeStreams-db.coll.watch.yml → legacy/changeStreams-db.coll.watch.yml} +2 -1
  1134. data/spec/spec_tests/data/retryable_reads/{changeStreams-db.watch-serverErrors.yml → legacy/changeStreams-db.watch-serverErrors.yml} +7 -6
  1135. data/spec/spec_tests/data/retryable_reads/{changeStreams-db.watch.yml → legacy/changeStreams-db.watch.yml} +2 -1
  1136. data/spec/spec_tests/data/retryable_reads/{count-serverErrors.yml → legacy/count-serverErrors.yml} +1 -1
  1137. data/spec/spec_tests/data/retryable_reads/{countDocuments-serverErrors.yml → legacy/countDocuments-serverErrors.yml} +1 -1
  1138. data/spec/spec_tests/data/retryable_reads/{distinct-serverErrors.yml → legacy/distinct-serverErrors.yml} +1 -1
  1139. data/spec/spec_tests/data/retryable_reads/{estimatedDocumentCount-serverErrors.yml → legacy/estimatedDocumentCount-serverErrors.yml} +1 -1
  1140. data/spec/spec_tests/data/retryable_reads/{find-serverErrors.yml → legacy/find-serverErrors.yml} +1 -1
  1141. data/spec/spec_tests/data/retryable_reads/{findOne-serverErrors.yml → legacy/findOne-serverErrors.yml} +1 -1
  1142. data/spec/spec_tests/data/retryable_reads/{gridfs-download-serverErrors.yml → legacy/gridfs-download-serverErrors.yml} +1 -1
  1143. data/spec/spec_tests/data/retryable_reads/{gridfs-downloadByName-serverErrors.yml → legacy/gridfs-downloadByName-serverErrors.yml} +1 -1
  1144. data/spec/spec_tests/data/retryable_reads/{listCollectionNames-serverErrors.yml → legacy/listCollectionNames-serverErrors.yml} +1 -1
  1145. data/spec/spec_tests/data/retryable_reads/{listCollectionObjects-serverErrors.yml → legacy/listCollectionObjects-serverErrors.yml} +1 -1
  1146. data/spec/spec_tests/data/retryable_reads/{listCollections-serverErrors.yml → legacy/listCollections-serverErrors.yml} +1 -1
  1147. data/spec/spec_tests/data/retryable_reads/{listDatabaseNames-serverErrors.yml → legacy/listDatabaseNames-serverErrors.yml} +1 -1
  1148. data/spec/spec_tests/data/retryable_reads/{listDatabaseObjects-serverErrors.yml → legacy/listDatabaseObjects-serverErrors.yml} +1 -1
  1149. data/spec/spec_tests/data/retryable_reads/{listDatabases-serverErrors.yml → legacy/listDatabases-serverErrors.yml} +1 -1
  1150. data/spec/spec_tests/data/retryable_reads/{listIndexNames-serverErrors.yml → legacy/listIndexNames-serverErrors.yml} +1 -1
  1151. data/spec/spec_tests/data/retryable_reads/{listIndexNames.yml → legacy/listIndexNames.yml} +1 -1
  1152. data/spec/spec_tests/data/retryable_reads/{listIndexes-serverErrors.yml → legacy/listIndexes-serverErrors.yml} +1 -1
  1153. data/spec/spec_tests/data/retryable_reads/{mapReduce.yml → legacy/mapReduce.yml} +3 -1
  1154. data/spec/spec_tests/data/retryable_reads/unified/handshakeError.yml +129 -0
  1155. data/spec/spec_tests/data/retryable_writes/legacy/bulkWrite-errorLabels.yml +77 -0
  1156. data/spec/spec_tests/data/retryable_writes/{bulkWrite-serverErrors.yml → legacy/bulkWrite-serverErrors.yml} +37 -0
  1157. data/spec/spec_tests/data/retryable_writes/{bulkWrite.yml → legacy/bulkWrite.yml} +30 -24
  1158. data/spec/spec_tests/data/retryable_writes/legacy/deleteOne-errorLabels.yml +48 -0
  1159. data/spec/spec_tests/data/retryable_writes/{deleteOne-serverErrors.yml → legacy/deleteOne-serverErrors.yml} +22 -0
  1160. data/spec/spec_tests/data/retryable_writes/legacy/findOneAndDelete-errorLabels.yml +49 -0
  1161. data/spec/spec_tests/data/retryable_writes/{findOneAndDelete-serverErrors.yml → legacy/findOneAndDelete-serverErrors.yml} +23 -0
  1162. data/spec/spec_tests/data/retryable_writes/legacy/findOneAndReplace-errorLabels.yml +52 -0
  1163. data/spec/spec_tests/data/retryable_writes/{findOneAndReplace-serverErrors.yml → legacy/findOneAndReplace-serverErrors.yml} +25 -0
  1164. data/spec/spec_tests/data/retryable_writes/legacy/findOneAndUpdate-errorLabels.yml +52 -0
  1165. data/spec/spec_tests/data/retryable_writes/{findOneAndUpdate-serverErrors.yml → legacy/findOneAndUpdate-serverErrors.yml} +24 -0
  1166. data/spec/spec_tests/data/retryable_writes/legacy/insertMany-errorLabels.yml +54 -0
  1167. data/spec/spec_tests/data/retryable_writes/{insertMany-serverErrors.yml → legacy/insertMany-serverErrors.yml} +24 -0
  1168. data/spec/spec_tests/data/retryable_writes/legacy/insertOne-errorLabels.yml +44 -0
  1169. data/spec/spec_tests/data/retryable_writes/{insertOne-serverErrors.yml → legacy/insertOne-serverErrors.yml} +94 -3
  1170. data/spec/spec_tests/data/retryable_writes/legacy/replaceOne-errorLabels.yml +53 -0
  1171. data/spec/spec_tests/data/retryable_writes/{replaceOne-serverErrors.yml → legacy/replaceOne-serverErrors.yml} +23 -0
  1172. data/spec/spec_tests/data/retryable_writes/legacy/updateOne-errorLabels.yml +53 -0
  1173. data/spec/spec_tests/data/retryable_writes/{updateOne-serverErrors.yml → legacy/updateOne-serverErrors.yml} +23 -0
  1174. data/spec/spec_tests/data/retryable_writes/unified/bulkWrite-serverErrors.yml +96 -0
  1175. data/spec/spec_tests/data/retryable_writes/unified/handshakeError.yml +137 -0
  1176. data/spec/spec_tests/data/retryable_writes/unified/insertOne-serverErrors.yml +78 -0
  1177. data/spec/spec_tests/data/sdam/errors/error_handling_handshake.yml +55 -0
  1178. data/spec/spec_tests/data/sdam/errors/non-stale-network-error.yml +47 -0
  1179. data/spec/spec_tests/data/sdam/errors/non-stale-network-timeout-error.yml +38 -0
  1180. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-greater-InterruptedAtShutdown.yml +61 -0
  1181. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-greater-InterruptedDueToReplStateChange.yml +61 -0
  1182. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-greater-LegacyNotPrimary.yml +61 -0
  1183. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-greater-NotPrimaryNoSecondaryOk.yml +61 -0
  1184. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-greater-NotPrimaryOrSecondary.yml +61 -0
  1185. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-greater-NotWritablePrimary.yml +61 -0
  1186. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-greater-PrimarySteppedDown.yml +61 -0
  1187. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-greater-ShutdownInProgress.yml +61 -0
  1188. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-missing-InterruptedAtShutdown.yml +52 -0
  1189. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-missing-InterruptedDueToReplStateChange.yml +52 -0
  1190. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-missing-LegacyNotPrimary.yml +52 -0
  1191. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-missing-NotPrimaryNoSecondaryOk.yml +52 -0
  1192. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-missing-NotPrimaryOrSecondary.yml +52 -0
  1193. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-missing-NotWritablePrimary.yml +52 -0
  1194. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-missing-PrimarySteppedDown.yml +52 -0
  1195. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-missing-ShutdownInProgress.yml +52 -0
  1196. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-proccessId-changed-InterruptedAtShutdown.yml +61 -0
  1197. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-proccessId-changed-InterruptedDueToReplStateChange.yml +61 -0
  1198. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-proccessId-changed-LegacyNotPrimary.yml +61 -0
  1199. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-proccessId-changed-NotPrimaryNoSecondaryOk.yml +61 -0
  1200. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-proccessId-changed-NotPrimaryOrSecondary.yml +61 -0
  1201. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-proccessId-changed-NotWritablePrimary.yml +61 -0
  1202. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-proccessId-changed-PrimarySteppedDown.yml +61 -0
  1203. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-proccessId-changed-ShutdownInProgress.yml +61 -0
  1204. data/spec/spec_tests/data/sdam/errors/post-42-InterruptedAtShutdown.yml +47 -0
  1205. data/spec/spec_tests/data/sdam/errors/post-42-InterruptedDueToReplStateChange.yml +47 -0
  1206. data/spec/spec_tests/data/sdam/errors/post-42-LegacyNotPrimary.yml +47 -0
  1207. data/spec/spec_tests/data/sdam/errors/post-42-NotPrimaryNoSecondaryOk.yml +47 -0
  1208. data/spec/spec_tests/data/sdam/errors/post-42-NotPrimaryOrSecondary.yml +47 -0
  1209. data/spec/spec_tests/data/sdam/errors/post-42-NotWritablePrimary.yml +47 -0
  1210. data/spec/spec_tests/data/sdam/errors/post-42-PrimarySteppedDown.yml +47 -0
  1211. data/spec/spec_tests/data/sdam/errors/post-42-ShutdownInProgress.yml +47 -0
  1212. data/spec/spec_tests/data/sdam/errors/pre-42-InterruptedAtShutdown.yml +47 -0
  1213. data/spec/spec_tests/data/sdam/errors/pre-42-InterruptedDueToReplStateChange.yml +47 -0
  1214. data/spec/spec_tests/data/sdam/errors/pre-42-LegacyNotPrimary.yml +47 -0
  1215. data/spec/spec_tests/data/sdam/errors/pre-42-NotPrimaryNoSecondaryOk.yml +47 -0
  1216. data/spec/spec_tests/data/sdam/errors/pre-42-NotPrimaryOrSecondary.yml +47 -0
  1217. data/spec/spec_tests/data/sdam/errors/pre-42-NotWritablePrimary.yml +47 -0
  1218. data/spec/spec_tests/data/sdam/errors/pre-42-PrimarySteppedDown.yml +47 -0
  1219. data/spec/spec_tests/data/sdam/errors/pre-42-ShutdownInProgress.yml +47 -0
  1220. data/spec/spec_tests/data/sdam/errors/prefer-error-code.yml +54 -0
  1221. data/spec/spec_tests/data/sdam/errors/stale-generation-InterruptedAtShutdown.yml +91 -0
  1222. data/spec/spec_tests/data/sdam/errors/stale-generation-InterruptedDueToReplStateChange.yml +91 -0
  1223. data/spec/spec_tests/data/sdam/errors/stale-generation-NotPrimaryNoSecondaryOk.yml +91 -0
  1224. data/spec/spec_tests/data/sdam/errors/stale-generation-NotPrimaryOrSecondary.yml +91 -0
  1225. data/spec/spec_tests/data/sdam/errors/stale-generation-NotWritablePrimary.yml +91 -0
  1226. data/spec/spec_tests/data/sdam/errors/stale-generation-PrimarySteppedDown.yml +91 -0
  1227. data/spec/spec_tests/data/sdam/errors/stale-generation-ShutdownInProgress.yml +91 -0
  1228. data/spec/spec_tests/data/sdam/errors/stale-generation-afterHandshakeCompletes-InterruptedAtShutdown.yml +91 -0
  1229. data/spec/spec_tests/data/sdam/errors/stale-generation-afterHandshakeCompletes-InterruptedDueToReplStateChange.yml +91 -0
  1230. data/spec/spec_tests/data/sdam/errors/stale-generation-afterHandshakeCompletes-LegacyNotPrimary.yml +91 -0
  1231. data/spec/spec_tests/data/sdam/errors/stale-generation-afterHandshakeCompletes-NotPrimaryNoSecondaryOk.yml +91 -0
  1232. data/spec/spec_tests/data/sdam/errors/stale-generation-afterHandshakeCompletes-NotPrimaryOrSecondary.yml +91 -0
  1233. data/spec/spec_tests/data/sdam/errors/stale-generation-afterHandshakeCompletes-NotWritablePrimary.yml +91 -0
  1234. data/spec/spec_tests/data/sdam/errors/stale-generation-afterHandshakeCompletes-PrimarySteppedDown.yml +91 -0
  1235. data/spec/spec_tests/data/sdam/errors/stale-generation-afterHandshakeCompletes-ShutdownInProgress.yml +91 -0
  1236. data/spec/spec_tests/data/sdam/errors/stale-generation-afterHandshakeCompletes-network.yml +82 -0
  1237. data/spec/spec_tests/data/sdam/errors/stale-generation-afterHandshakeCompletes-timeout.yml +82 -0
  1238. data/spec/spec_tests/data/sdam/errors/stale-generation-beforeHandshakeCompletes-InterruptedAtShutdown.yml +91 -0
  1239. data/spec/spec_tests/data/sdam/errors/stale-generation-beforeHandshakeCompletes-InterruptedDueToReplStateChange.yml +91 -0
  1240. data/spec/spec_tests/data/sdam/errors/stale-generation-beforeHandshakeCompletes-LegacyNotPrimary.yml +91 -0
  1241. data/spec/spec_tests/data/sdam/errors/stale-generation-beforeHandshakeCompletes-NotPrimaryNoSecondaryOk.yml +91 -0
  1242. data/spec/spec_tests/data/sdam/errors/stale-generation-beforeHandshakeCompletes-NotPrimaryOrSecondary.yml +91 -0
  1243. data/spec/spec_tests/data/sdam/errors/stale-generation-beforeHandshakeCompletes-NotWritablePrimary.yml +91 -0
  1244. data/spec/spec_tests/data/sdam/errors/stale-generation-beforeHandshakeCompletes-PrimarySteppedDown.yml +91 -0
  1245. data/spec/spec_tests/data/sdam/errors/stale-generation-beforeHandshakeCompletes-ShutdownInProgress.yml +91 -0
  1246. data/spec/spec_tests/data/sdam/errors/stale-generation-beforeHandshakeCompletes-network.yml +82 -0
  1247. data/spec/spec_tests/data/sdam/errors/stale-generation-beforeHandshakeCompletes-timeout.yml +82 -0
  1248. data/spec/spec_tests/data/sdam/errors/stale-topologyVersion-InterruptedAtShutdown.yml +65 -0
  1249. data/spec/spec_tests/data/sdam/errors/stale-topologyVersion-InterruptedDueToReplStateChange.yml +65 -0
  1250. data/spec/spec_tests/data/sdam/errors/stale-topologyVersion-LegacyNotPrimary.yml +65 -0
  1251. data/spec/spec_tests/data/sdam/errors/stale-topologyVersion-NotPrimaryNoSecondaryOk.yml +65 -0
  1252. data/spec/spec_tests/data/sdam/errors/stale-topologyVersion-NotPrimaryOrSecondary.yml +65 -0
  1253. data/spec/spec_tests/data/sdam/errors/stale-topologyVersion-NotWritablePrimary.yml +65 -0
  1254. data/spec/spec_tests/data/sdam/errors/stale-topologyVersion-PrimarySteppedDown.yml +65 -0
  1255. data/spec/spec_tests/data/sdam/errors/stale-topologyVersion-ShutdownInProgress.yml +65 -0
  1256. data/spec/spec_tests/data/sdam/errors/write_errors_ignored.yml +42 -0
  1257. data/spec/spec_tests/data/sdam/load-balanced/discover_load_balancer.yml +25 -0
  1258. data/spec/spec_tests/data/sdam/rs/compatible.yml +6 -2
  1259. data/spec/spec_tests/data/sdam/rs/compatible_unknown.yml +4 -1
  1260. data/spec/spec_tests/data/sdam/rs/discover_arbiters.yml +4 -3
  1261. data/spec/spec_tests/data/sdam/rs/discover_arbiters_replicaset.yml +44 -0
  1262. data/spec/spec_tests/data/sdam/rs/discover_ghost.yml +36 -0
  1263. data/spec/spec_tests/data/sdam/rs/{ghost_discovered.yml → discover_ghost_replicaset.yml} +3 -2
  1264. data/spec/spec_tests/data/sdam/rs/discover_hidden.yml +51 -0
  1265. data/spec/spec_tests/data/sdam/rs/discover_hidden_replicaset.yml +51 -0
  1266. data/spec/spec_tests/data/sdam/rs/discover_passives.yml +6 -4
  1267. data/spec/spec_tests/data/sdam/rs/discover_passives_replicaset.yml +83 -0
  1268. data/spec/spec_tests/data/sdam/rs/discover_primary.yml +4 -3
  1269. data/spec/spec_tests/data/sdam/rs/discover_primary_replicaset.yml +43 -0
  1270. data/spec/spec_tests/data/sdam/rs/discover_rsother.yml +50 -0
  1271. data/spec/spec_tests/data/sdam/rs/{rsother_discovered.yml → discover_rsother_replicaset.yml} +5 -3
  1272. data/spec/spec_tests/data/sdam/rs/discover_secondary.yml +4 -3
  1273. data/spec/spec_tests/data/sdam/rs/discover_secondary_replicaset.yml +44 -0
  1274. data/spec/spec_tests/data/sdam/rs/discovery.yml +8 -4
  1275. data/spec/spec_tests/data/sdam/rs/equal_electionids.yml +4 -2
  1276. data/spec/spec_tests/data/sdam/rs/hosts_differ_from_seeds.yml +2 -1
  1277. data/spec/spec_tests/data/sdam/rs/incompatible_arbiter.yml +5 -1
  1278. data/spec/spec_tests/data/sdam/rs/incompatible_ghost.yml +7 -5
  1279. data/spec/spec_tests/data/sdam/rs/incompatible_other.yml +6 -2
  1280. data/spec/spec_tests/data/sdam/rs/ls_timeout.yml +12 -6
  1281. data/spec/spec_tests/data/sdam/rs/member_reconfig.yml +4 -2
  1282. data/spec/spec_tests/data/sdam/rs/member_standalone.yml +4 -2
  1283. data/spec/spec_tests/data/sdam/rs/new_primary.yml +4 -2
  1284. data/spec/spec_tests/data/sdam/rs/new_primary_new_electionid.yml +6 -3
  1285. data/spec/spec_tests/data/sdam/rs/new_primary_new_setversion.yml +6 -3
  1286. data/spec/spec_tests/data/sdam/rs/new_primary_wrong_set_name.yml +4 -2
  1287. data/spec/spec_tests/data/sdam/rs/non_rs_member.yml +1 -0
  1288. data/spec/spec_tests/data/sdam/rs/normalize_case.yml +2 -1
  1289. data/spec/spec_tests/data/sdam/rs/normalize_case_me.yml +4 -2
  1290. data/spec/spec_tests/data/sdam/rs/null_election_id.yml +8 -4
  1291. data/spec/spec_tests/data/sdam/rs/primary_becomes_ghost.yml +4 -2
  1292. data/spec/spec_tests/data/sdam/rs/primary_becomes_mongos.yml +4 -2
  1293. data/spec/spec_tests/data/sdam/rs/primary_becomes_standalone.yml +2 -1
  1294. data/spec/spec_tests/data/sdam/rs/primary_changes_set_name.yml +4 -2
  1295. data/spec/spec_tests/data/sdam/rs/primary_disconnect.yml +2 -1
  1296. data/spec/spec_tests/data/sdam/rs/primary_disconnect_electionid.yml +10 -5
  1297. data/spec/spec_tests/data/sdam/rs/primary_disconnect_setversion.yml +10 -5
  1298. data/spec/spec_tests/data/sdam/rs/primary_hint_from_secondary_with_mismatched_me.yml +4 -2
  1299. data/spec/spec_tests/data/sdam/rs/primary_mismatched_me.yml +24 -27
  1300. data/spec/spec_tests/data/sdam/rs/primary_mismatched_me_not_removed.yml +75 -0
  1301. data/spec/spec_tests/data/sdam/rs/primary_reports_new_member.yml +8 -4
  1302. data/spec/spec_tests/data/sdam/rs/primary_to_no_primary_mismatched_me.yml +81 -56
  1303. data/spec/spec_tests/data/sdam/rs/primary_wrong_set_name.yml +2 -1
  1304. data/spec/spec_tests/data/sdam/rs/repeated.yml +105 -0
  1305. data/spec/spec_tests/data/sdam/rs/replicaset_rsnp.yml +21 -0
  1306. data/spec/spec_tests/data/sdam/rs/response_from_removed.yml +4 -2
  1307. data/spec/spec_tests/data/sdam/rs/{primary_address_change.yml → ruby_primary_address_change.yml} +2 -0
  1308. data/spec/spec_tests/data/sdam/rs/sec_not_auth.yml +4 -2
  1309. data/spec/spec_tests/data/sdam/rs/secondary_ignore_ok_0.yml +4 -2
  1310. data/spec/spec_tests/data/sdam/rs/secondary_mismatched_me.yml +5 -3
  1311. data/spec/spec_tests/data/sdam/rs/secondary_wrong_set_name.yml +2 -1
  1312. data/spec/spec_tests/data/sdam/rs/secondary_wrong_set_name_with_primary.yml +4 -2
  1313. data/spec/spec_tests/data/sdam/rs/setversion_without_electionid.yml +4 -2
  1314. data/spec/spec_tests/data/sdam/rs/stepdown_change_set_name.yml +4 -2
  1315. data/spec/spec_tests/data/sdam/rs/too_new.yml +6 -2
  1316. data/spec/spec_tests/data/sdam/rs/too_old.yml +4 -2
  1317. data/spec/spec_tests/data/sdam/rs/topology_version_equal.yml +68 -0
  1318. data/spec/spec_tests/data/sdam/rs/topology_version_greater.yml +194 -0
  1319. data/spec/spec_tests/data/sdam/rs/topology_version_less.yml +64 -0
  1320. data/spec/spec_tests/data/sdam/rs/unexpected_mongos.yml +2 -1
  1321. data/spec/spec_tests/data/sdam/rs/use_setversion_without_electionid.yml +6 -3
  1322. data/spec/spec_tests/data/sdam/rs/wrong_set_name.yml +2 -1
  1323. data/spec/spec_tests/data/sdam/sharded/compatible.yml +4 -2
  1324. data/spec/spec_tests/data/sdam/sharded/discover_single_mongos.yml +24 -0
  1325. data/spec/spec_tests/data/sdam/sharded/ls_timeout_mongos.yml +9 -5
  1326. data/spec/spec_tests/data/sdam/sharded/mongos_disconnect.yml +6 -3
  1327. data/spec/spec_tests/data/sdam/sharded/multiple_mongoses.yml +4 -2
  1328. data/spec/spec_tests/data/sdam/sharded/non_mongos_removed.yml +4 -2
  1329. data/spec/spec_tests/data/sdam/sharded/{primary_address_change.yml → ruby_primary_different_address.yml} +1 -1
  1330. data/spec/spec_tests/data/sdam/sharded/{primary_mismatched_me.yml → ruby_primary_mismatched_me.yml} +1 -1
  1331. data/spec/spec_tests/data/sdam/sharded/too_new.yml +4 -2
  1332. data/spec/spec_tests/data/sdam/sharded/too_old.yml +4 -2
  1333. data/spec/spec_tests/data/sdam/single/compatible.yml +2 -1
  1334. data/spec/spec_tests/data/sdam/single/direct_connection_external_ip.yml +3 -2
  1335. data/spec/spec_tests/data/sdam/single/direct_connection_mongos.yml +4 -3
  1336. data/spec/spec_tests/data/sdam/single/direct_connection_replicaset.yml +23 -0
  1337. data/spec/spec_tests/data/sdam/single/direct_connection_rsarbiter.yml +4 -3
  1338. data/spec/spec_tests/data/sdam/single/direct_connection_rsprimary.yml +4 -3
  1339. data/spec/spec_tests/data/sdam/single/direct_connection_rssecondary.yml +4 -3
  1340. data/spec/spec_tests/data/sdam/single/direct_connection_standalone.yml +4 -3
  1341. data/spec/spec_tests/data/sdam/single/{unavailable_seed.yml → direct_connection_unavailable_seed.yml} +2 -2
  1342. data/spec/spec_tests/data/sdam/single/direct_connection_wrong_set_name.yml +40 -0
  1343. data/spec/spec_tests/data/sdam/single/discover_standalone.yml +35 -0
  1344. data/spec/spec_tests/data/sdam/single/discover_unavailable_seed.yml +28 -0
  1345. data/spec/spec_tests/data/sdam/single/ls_timeout_standalone.yml +2 -1
  1346. data/spec/spec_tests/data/sdam/single/not_ok_response.yml +5 -3
  1347. data/spec/spec_tests/data/sdam/single/{primary_address_change.yml → ruby_primary_different_address.yml} +1 -1
  1348. data/spec/spec_tests/data/sdam/single/{primary_mismatched_me.yml → ruby_primary_mismatched_me.yml} +1 -1
  1349. data/spec/spec_tests/data/sdam/single/standalone_removed.yml +2 -1
  1350. data/spec/spec_tests/data/sdam/single/{direct_connection_slave.yml → standalone_using_legacy_hello.yml} +2 -2
  1351. data/spec/spec_tests/data/sdam/single/too_new.yml +2 -1
  1352. data/spec/spec_tests/data/sdam/single/too_old.yml +2 -1
  1353. data/spec/spec_tests/data/sdam/single/too_old_then_upgraded.yml +48 -0
  1354. data/spec/spec_tests/data/sdam_integration/cancel-server-check.yml +96 -0
  1355. data/spec/spec_tests/data/sdam_integration/connectTimeoutMS.yml +88 -0
  1356. data/spec/spec_tests/data/sdam_integration/find-network-error.yml +85 -0
  1357. data/spec/spec_tests/data/sdam_integration/find-shutdown-error.yml +118 -0
  1358. data/spec/spec_tests/data/sdam_integration/hello-command-error.yml +152 -0
  1359. data/spec/spec_tests/data/sdam_integration/hello-network-error.yml +148 -0
  1360. data/spec/spec_tests/data/sdam_integration/hello-timeout.yml +219 -0
  1361. data/spec/spec_tests/data/sdam_integration/insert-network-error.yml +88 -0
  1362. data/spec/spec_tests/data/sdam_integration/insert-shutdown-error.yml +117 -0
  1363. data/spec/spec_tests/data/sdam_integration/rediscover-quickly-after-step-down.yml +98 -0
  1364. data/spec/spec_tests/data/sdam_monitoring/discovered_standalone.yml +2 -4
  1365. data/spec/spec_tests/data/sdam_monitoring/load_balancer.yml +65 -0
  1366. data/spec/spec_tests/data/sdam_monitoring/{replica_set_with_primary_change.yml → replica_set_primary_address_change.yml} +27 -5
  1367. data/spec/spec_tests/data/sdam_monitoring/replica_set_with_me_mismatch.yml +26 -74
  1368. data/spec/spec_tests/data/sdam_monitoring/replica_set_with_no_primary.yml +2 -1
  1369. data/spec/spec_tests/data/sdam_monitoring/replica_set_with_primary.yml +2 -1
  1370. data/spec/spec_tests/data/sdam_monitoring/replica_set_with_removal.yml +21 -16
  1371. data/spec/spec_tests/data/sdam_monitoring/required_replica_set.yml +2 -1
  1372. data/spec/spec_tests/data/sdam_monitoring/standalone.yml +3 -3
  1373. data/spec/spec_tests/data/sdam_monitoring/standalone_repeated.yml +2 -2
  1374. data/spec/spec_tests/data/sdam_monitoring/standalone_suppress_equal_description_changes.yml +73 -0
  1375. data/spec/spec_tests/data/sdam_monitoring/standalone_to_rs_with_me_mismatch.yml +2 -2
  1376. data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-directConnection.yml +13 -0
  1377. data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-no-results.yml +5 -0
  1378. data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-replicaSet-errors.yml +6 -0
  1379. data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-true-multiple-hosts.yml +5 -0
  1380. data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-true-txt.yml +10 -0
  1381. data/spec/spec_tests/data/seed_list_discovery/load-balanced/srvMaxHosts-conflicts_with_loadBalanced-true-txt.yml +5 -0
  1382. data/spec/spec_tests/data/seed_list_discovery/load-balanced/srvMaxHosts-conflicts_with_loadBalanced-true.yml +5 -0
  1383. data/spec/spec_tests/data/seed_list_discovery/load-balanced/srvMaxHosts-zero-txt.yml +10 -0
  1384. data/spec/spec_tests/data/seed_list_discovery/load-balanced/srvMaxHosts-zero.yml +10 -0
  1385. data/spec/spec_tests/data/seed_list_discovery/replica-set/direct-connection-false.yml +10 -0
  1386. data/spec/spec_tests/data/seed_list_discovery/replica-set/direct-connection-true.yml +5 -0
  1387. data/spec/spec_tests/data/seed_list_discovery/replica-set/encoded-userinfo-and-db.yml +15 -0
  1388. data/spec/spec_tests/data/seed_list_discovery/replica-set/loadBalanced-false-txt.yml +10 -0
  1389. data/spec/spec_tests/data/seed_list_discovery/replica-set/srv-service-name.yml +11 -0
  1390. data/spec/spec_tests/data/seed_list_discovery/replica-set/srvMaxHosts-conflicts_with_replicaSet-txt.yml +5 -0
  1391. data/spec/spec_tests/data/seed_list_discovery/replica-set/srvMaxHosts-conflicts_with_replicaSet.yml +5 -0
  1392. data/spec/spec_tests/data/seed_list_discovery/replica-set/srvMaxHosts-equal_to_srv_records.yml +16 -0
  1393. data/spec/spec_tests/data/seed_list_discovery/replica-set/srvMaxHosts-greater_than_srv_records.yml +15 -0
  1394. data/spec/spec_tests/data/seed_list_discovery/replica-set/srvMaxHosts-less_than_srv_records.yml +15 -0
  1395. data/spec/spec_tests/data/seed_list_discovery/replica-set/srvMaxHosts-zero-txt.yml +15 -0
  1396. data/spec/spec_tests/data/seed_list_discovery/replica-set/srvMaxHosts-zero.yml +15 -0
  1397. data/spec/spec_tests/data/seed_list_discovery/replica-set/uri-with-admin-database.yml +13 -0
  1398. data/spec/spec_tests/data/seed_list_discovery/replica-set/uri-with-auth.yml +12 -0
  1399. data/spec/spec_tests/data/seed_list_discovery/sharded/srvMaxHosts-equal_to_srv_records.yml +13 -0
  1400. data/spec/spec_tests/data/seed_list_discovery/sharded/srvMaxHosts-greater_than_srv_records.yml +12 -0
  1401. data/spec/spec_tests/data/seed_list_discovery/sharded/srvMaxHosts-less_than_srv_records.yml +10 -0
  1402. data/spec/spec_tests/data/seed_list_discovery/sharded/srvMaxHosts-zero.yml +11 -0
  1403. data/spec/spec_tests/data/server_selection/Unknown/read/ghost.yml +11 -0
  1404. data/spec/spec_tests/data/server_selection/Unknown/write/ghost.yml +11 -0
  1405. data/spec/spec_tests/data/sessions_unified/driver-sessions-server-support.yml +123 -0
  1406. data/spec/spec_tests/data/sessions_unified/snapshot-sessions-not-supported-client-error.yml +75 -0
  1407. data/spec/spec_tests/data/sessions_unified/snapshot-sessions-not-supported-server-error.yml +102 -0
  1408. data/spec/spec_tests/data/sessions_unified/snapshot-sessions-unsupported-ops.yml +258 -0
  1409. data/spec/spec_tests/data/sessions_unified/snapshot-sessions.yml +482 -0
  1410. data/spec/spec_tests/data/transactions/create-collection.yml +131 -0
  1411. data/spec/spec_tests/data/transactions/create-index.yml +152 -0
  1412. data/spec/spec_tests/data/transactions/error-labels.yml +90 -21
  1413. data/spec/spec_tests/data/transactions/errors-client.yml +8 -9
  1414. data/spec/spec_tests/data/transactions/mongos-pin-auto.yml +3 -0
  1415. data/spec/spec_tests/data/transactions/mongos-recovery-token.yml +3 -0
  1416. data/spec/spec_tests/data/transactions/pin-mongos.yml +8 -6
  1417. data/spec/spec_tests/data/transactions/retryable-abort-errorLabels.yml +124 -0
  1418. data/spec/spec_tests/data/transactions/retryable-abort.yml +20 -5
  1419. data/spec/spec_tests/data/transactions/retryable-commit-errorLabels.yml +132 -0
  1420. data/spec/spec_tests/data/transactions/retryable-commit.yml +27 -12
  1421. data/spec/spec_tests/data/transactions_unified/do-not-retry-read-in-transaction.yml +64 -0
  1422. data/spec/spec_tests/data/transactions_unified/mongos-unpin.yml +172 -0
  1423. data/spec/spec_tests/data/transactions_unified/retryable-abort-handshake.yml +118 -0
  1424. data/spec/spec_tests/data/transactions_unified/retryable-commit-handshake.yml +118 -0
  1425. data/spec/spec_tests/data/unified/invalid/expectedEventsForClient-ignoreExtraEvents-type.yml +15 -0
  1426. data/spec/spec_tests/data/unified/valid-fail/operation-failure.yml +31 -0
  1427. data/spec/spec_tests/data/unified/valid-fail/operation-unsupported.yml +13 -0
  1428. data/spec/spec_tests/data/unified/valid-pass/expectedEventsForClient-ignoreExtraEvents.yml +78 -0
  1429. data/spec/spec_tests/data/unified/valid-pass/poc-change-streams.yml +223 -0
  1430. data/spec/spec_tests/data/unified/valid-pass/poc-command-monitoring.yml +102 -0
  1431. data/spec/spec_tests/data/unified/valid-pass/poc-crud.yml +184 -0
  1432. data/spec/spec_tests/data/unified/valid-pass/poc-gridfs.yml +155 -0
  1433. data/spec/spec_tests/data/unified/valid-pass/poc-retryable-reads.yml +193 -0
  1434. data/spec/spec_tests/data/unified/valid-pass/poc-retryable-writes.yml +210 -0
  1435. data/spec/spec_tests/data/unified/valid-pass/poc-sessions.yml +215 -0
  1436. data/spec/spec_tests/data/unified/valid-pass/poc-transactions-convenient-api.yml +235 -0
  1437. data/spec/spec_tests/data/unified/valid-pass/poc-transactions-mongos-pin-auto.yml +169 -0
  1438. data/spec/spec_tests/data/unified/valid-pass/poc-transactions.yml +171 -0
  1439. data/spec/spec_tests/data/uri_options/auth-options.yml +35 -0
  1440. data/spec/spec_tests/data/uri_options/compression-options.yml +7 -4
  1441. data/spec/spec_tests/data/uri_options/connection-options.yml +103 -0
  1442. data/spec/spec_tests/data/uri_options/read-preference-options.yml +24 -0
  1443. data/spec/spec_tests/data/uri_options/ruby-auth-options.yml +12 -0
  1444. data/spec/spec_tests/data/uri_options/ruby-connection-options.yml +58 -0
  1445. data/spec/spec_tests/data/uri_options/srv-options.yml +96 -0
  1446. data/spec/spec_tests/data/uri_options/tls-options.yml +233 -6
  1447. data/spec/spec_tests/data/versioned_api/crud-api-version-1-strict.yml +419 -0
  1448. data/spec/spec_tests/data/versioned_api/crud-api-version-1.yml +413 -0
  1449. data/spec/spec_tests/data/versioned_api/runcommand-helper-no-api-version-declared.yml +75 -0
  1450. data/spec/spec_tests/data/versioned_api/test-commands-deprecation-errors.yml +47 -0
  1451. data/spec/spec_tests/data/versioned_api/test-commands-strict-mode.yml +46 -0
  1452. data/spec/spec_tests/data/versioned_api/transaction-handling.yml +128 -0
  1453. data/spec/spec_tests/gridfs_spec.rb +5 -0
  1454. data/spec/spec_tests/gridfs_unified_spec.rb +13 -0
  1455. data/spec/spec_tests/load_balancers_spec.rb +15 -0
  1456. data/spec/spec_tests/max_staleness_spec.rb +7 -140
  1457. data/spec/spec_tests/read_write_concern_connection_string_spec.rb +6 -1
  1458. data/spec/spec_tests/read_write_concern_document_spec.rb +3 -0
  1459. data/spec/spec_tests/read_write_concern_operaton_spec.rb +13 -0
  1460. data/spec/spec_tests/retryable_reads_spec.rb +13 -5
  1461. data/spec/spec_tests/retryable_reads_unified_spec.rb +22 -0
  1462. data/spec/spec_tests/retryable_writes_spec.rb +16 -3
  1463. data/spec/spec_tests/retryable_writes_unified_spec.rb +21 -0
  1464. data/spec/spec_tests/sdam_integration_spec.rb +16 -0
  1465. data/spec/spec_tests/sdam_monitoring_spec.rb +16 -7
  1466. data/spec/spec_tests/sdam_spec.rb +75 -3
  1467. data/spec/spec_tests/seed_list_discovery_spec.rb +127 -0
  1468. data/spec/spec_tests/server_selection_rtt_spec.rb +5 -0
  1469. data/spec/spec_tests/server_selection_spec.rb +7 -114
  1470. data/spec/spec_tests/sessions_unified_spec.rb +13 -0
  1471. data/spec/spec_tests/transactions_api_spec.rb +8 -0
  1472. data/spec/spec_tests/transactions_spec.rb +8 -0
  1473. data/spec/spec_tests/transactions_unified_spec.rb +13 -0
  1474. data/spec/spec_tests/unified_spec.rb +23 -0
  1475. data/spec/spec_tests/uri_options_spec.rb +58 -41
  1476. data/spec/spec_tests/versioned_api_spec.rb +13 -0
  1477. data/spec/stress/cleanup_spec.rb +61 -0
  1478. data/spec/stress/connection_pool_stress_spec.rb +14 -13
  1479. data/spec/stress/connection_pool_timing_spec.rb +13 -9
  1480. data/spec/stress/fork_reconnect_stress_spec.rb +109 -0
  1481. data/spec/stress/push_monitor_close_spec.rb +44 -0
  1482. data/spec/support/authorization.rb +5 -12
  1483. data/spec/support/aws_utils/base.rb +137 -0
  1484. data/spec/support/aws_utils/inspector.rb +227 -0
  1485. data/spec/support/aws_utils/orchestrator.rb +373 -0
  1486. data/spec/support/aws_utils/provisioner.rb +363 -0
  1487. data/spec/support/aws_utils.rb +65 -0
  1488. data/spec/support/background_thread_registry.rb +12 -15
  1489. data/spec/support/certificates/README.md +7 -2
  1490. data/spec/support/certificates/atlas-ocsp-ca.crt +103 -0
  1491. data/spec/support/certificates/atlas-ocsp.crt +152 -0
  1492. data/spec/support/certificates/retrieve-atlas-cert +38 -0
  1493. data/spec/support/certificates/server-second-level-bundle.pem +77 -77
  1494. data/spec/support/certificates/server-second-level.crt +52 -52
  1495. data/spec/support/certificates/server-second-level.key +25 -25
  1496. data/spec/support/certificates/server-second-level.pem +77 -77
  1497. data/spec/support/client_registry.rb +37 -32
  1498. data/spec/support/client_registry_macros.rb +17 -5
  1499. data/spec/support/cluster_tools.rb +11 -3
  1500. data/spec/support/common_shortcuts.rb +160 -6
  1501. data/spec/support/constraints.rb +9 -217
  1502. data/spec/support/crypt/corpus/corpus-encrypted.json +9515 -0
  1503. data/spec/support/crypt/corpus/corpus-key-aws.json +33 -0
  1504. data/spec/support/crypt/corpus/corpus-key-azure.json +33 -0
  1505. data/spec/support/crypt/corpus/corpus-key-gcp.json +35 -0
  1506. data/spec/support/crypt/corpus/corpus-key-kmip.json +32 -0
  1507. data/spec/support/crypt/corpus/corpus-key-local.json +31 -0
  1508. data/spec/support/crypt/corpus/corpus-schema.json +6335 -0
  1509. data/spec/support/crypt/corpus/corpus.json +8619 -0
  1510. data/spec/support/crypt/data_keys/key_document_aws.json +34 -0
  1511. data/spec/support/crypt/data_keys/key_document_azure.json +33 -0
  1512. data/spec/support/crypt/data_keys/key_document_gcp.json +37 -0
  1513. data/spec/support/crypt/data_keys/key_document_kmip.json +32 -0
  1514. data/spec/support/crypt/data_keys/key_document_local.json +31 -0
  1515. data/spec/support/crypt/encryptedFields.json +33 -0
  1516. data/spec/support/crypt/external/external-key.json +31 -0
  1517. data/spec/support/crypt/external/external-schema.json +19 -0
  1518. data/spec/support/crypt/keys/key1-document.json +30 -0
  1519. data/spec/support/crypt/limits/limits-doc.json +102 -0
  1520. data/spec/support/crypt/limits/limits-key.json +31 -0
  1521. data/spec/support/crypt/limits/limits-schema.json +1405 -0
  1522. data/spec/support/crypt/schema_maps/schema_map_aws.json +17 -0
  1523. data/spec/support/crypt/schema_maps/schema_map_aws_key_alt_names.json +12 -0
  1524. data/spec/support/crypt/schema_maps/schema_map_azure.json +17 -0
  1525. data/spec/support/crypt/schema_maps/schema_map_azure_key_alt_names.json +12 -0
  1526. data/spec/support/crypt/schema_maps/schema_map_gcp.json +17 -0
  1527. data/spec/support/crypt/schema_maps/schema_map_gcp_key_alt_names.json +12 -0
  1528. data/spec/support/crypt/schema_maps/schema_map_kmip.json +17 -0
  1529. data/spec/support/crypt/schema_maps/schema_map_kmip_key_alt_names.json +12 -0
  1530. data/spec/support/crypt/schema_maps/schema_map_local.json +18 -0
  1531. data/spec/support/crypt/schema_maps/schema_map_local_key_alt_names.json +12 -0
  1532. data/spec/support/crypt.rb +402 -0
  1533. data/spec/support/dns.rb +3 -0
  1534. data/spec/support/json_ext_formatter.rb +3 -0
  1535. data/spec/support/keyword_struct.rb +29 -0
  1536. data/spec/support/local_resource_registry.rb +3 -0
  1537. data/spec/support/macros.rb +28 -0
  1538. data/spec/support/matchers.rb +52 -1
  1539. data/spec/support/mongos_macros.rb +17 -0
  1540. data/spec/support/monitoring_ext.rb +3 -0
  1541. data/spec/support/ocsp +1 -0
  1542. data/spec/support/primary_socket.rb +3 -0
  1543. data/spec/support/sdam_formatter_integration.rb +3 -0
  1544. data/spec/support/shared/app_metadata.rb +167 -0
  1545. data/spec/support/shared/auth_context.rb +16 -0
  1546. data/spec/support/shared/protocol.rb +5 -0
  1547. data/spec/support/shared/scram_conversation.rb +104 -0
  1548. data/spec/support/shared/server_selector.rb +99 -4
  1549. data/spec/support/shared/session.rb +47 -30
  1550. data/spec/support/spec_config.rb +339 -57
  1551. data/spec/support/spec_setup.rb +55 -38
  1552. data/spec/support/using_hash.rb +31 -0
  1553. data/spec/support/utils.rb +455 -35
  1554. data.tar.gz.sig +0 -0
  1555. metadata +2088 -838
  1556. metadata.gz.sig +0 -0
  1557. data/lib/mongo/cluster/srv_monitor.rb +0 -127
  1558. data/lib/mongo/collection/view/builder/find_command.rb +0 -142
  1559. data/lib/mongo/collection/view/builder/op_query.rb +0 -91
  1560. data/lib/mongo/cursor/builder/get_more_command.rb +0 -77
  1561. data/lib/mongo/cursor/builder/kill_cursors_command.rb +0 -108
  1562. data/lib/mongo/cursor/builder/op_get_more.rb +0 -61
  1563. data/lib/mongo/cursor/builder/op_kill_cursors.rb +0 -103
  1564. data/lib/mongo/operation/insert/legacy.rb +0 -60
  1565. data/lib/mongo/operation/shared/op_msg_or_list_indexes_command.rb +0 -45
  1566. data/lib/mongo/operation/update/legacy/result.rb +0 -102
  1567. data/lib/mongo/operation/update/legacy.rb +0 -65
  1568. data/lib/mongo/server/connectable.rb +0 -107
  1569. data/lib/mongo/server/context.rb +0 -69
  1570. data/spec/enterprise_auth/kerberos_spec.rb +0 -58
  1571. data/spec/mongo/cluster/srv_monitor_spec.rb +0 -214
  1572. data/spec/mongo/cursor/builder/op_kill_cursors_spec.rb +0 -56
  1573. data/spec/mongo/dbref_spec.rb +0 -149
  1574. data/spec/mongo/operation/kill_cursors_spec.rb +0 -41
  1575. data/spec/mongo/operation/read_preference_spec.rb +0 -245
  1576. data/spec/spec_tests/change_streams_spec.rb +0 -55
  1577. data/spec/spec_tests/command_monitoring_spec.rb +0 -53
  1578. data/spec/spec_tests/data/change_streams/change-streams-errors.yml +0 -76
  1579. data/spec/spec_tests/data/change_streams/change-streams.yml +0 -536
  1580. data/spec/spec_tests/data/command_monitoring/bulkWrite.yml +0 -49
  1581. data/spec/spec_tests/data/command_monitoring/command.yml +0 -61
  1582. data/spec/spec_tests/data/command_monitoring/deleteMany.yml +0 -55
  1583. data/spec/spec_tests/data/command_monitoring/deleteOne.yml +0 -55
  1584. data/spec/spec_tests/data/command_monitoring/find.yml +0 -266
  1585. data/spec/spec_tests/data/command_monitoring/insertMany.yml +0 -75
  1586. data/spec/spec_tests/data/command_monitoring/insertOne.yml +0 -51
  1587. data/spec/spec_tests/data/command_monitoring/unacknowledgedBulkWrite.yml +0 -34
  1588. data/spec/spec_tests/data/command_monitoring/updateMany.yml +0 -65
  1589. data/spec/spec_tests/data/command_monitoring/updateOne.yml +0 -90
  1590. data/spec/spec_tests/data/crud_v2/aggregate-merge.yml +0 -103
  1591. data/spec/spec_tests/data/crud_v2/aggregate-out-readConcern.yml +0 -110
  1592. data/spec/spec_tests/data/crud_v2/bulkWrite-arrayFilters.yml +0 -81
  1593. data/spec/spec_tests/data/crud_v2/db-aggregate.yml +0 -38
  1594. data/spec/spec_tests/data/crud_v2/updateWithPipelines.yml +0 -92
  1595. data/spec/spec_tests/data/sdam/sharded/single_mongos.yml +0 -33
  1596. data/spec/spec_tests/dns_seedlist_discovery_spec.rb +0 -66
  1597. data/spec/support/change_streams/operation.rb +0 -89
  1598. data/spec/support/change_streams.rb +0 -262
  1599. data/spec/support/cluster_config.rb +0 -194
  1600. data/spec/support/connection_string.rb +0 -354
  1601. data/spec/support/crud/requirement.rb +0 -69
  1602. data/spec/support/crud/test_base.rb +0 -22
  1603. data/spec/support/event_subscriber.rb +0 -112
  1604. data/spec/support/lite_constraints.rb +0 -76
  1605. data/spec/support/sdam_monitoring.rb +0 -89
  1606. data/spec/support/server_selection.rb +0 -148
  1607. data/spec/support/transactions/operation.rb +0 -184
  1608. data/spec/support/transactions/test.rb +0 -252
  1609. /data/spec/spec_tests/data/retryable_reads/{aggregate-merge.yml → legacy/aggregate-merge.yml} +0 -0
  1610. /data/spec/spec_tests/data/retryable_reads/{aggregate.yml → legacy/aggregate.yml} +0 -0
  1611. /data/spec/spec_tests/data/retryable_reads/{count.yml → legacy/count.yml} +0 -0
  1612. /data/spec/spec_tests/data/retryable_reads/{countDocuments.yml → legacy/countDocuments.yml} +0 -0
  1613. /data/spec/spec_tests/data/retryable_reads/{distinct.yml → legacy/distinct.yml} +0 -0
  1614. /data/spec/spec_tests/data/retryable_reads/{estimatedDocumentCount.yml → legacy/estimatedDocumentCount.yml} +0 -0
  1615. /data/spec/spec_tests/data/retryable_reads/{find.yml → legacy/find.yml} +0 -0
  1616. /data/spec/spec_tests/data/retryable_reads/{findOne.yml → legacy/findOne.yml} +0 -0
  1617. /data/spec/spec_tests/data/retryable_reads/{gridfs-download.yml → legacy/gridfs-download.yml} +0 -0
  1618. /data/spec/spec_tests/data/retryable_reads/{gridfs-downloadByName.yml → legacy/gridfs-downloadByName.yml} +0 -0
  1619. /data/spec/spec_tests/data/retryable_reads/{listCollectionNames.yml → legacy/listCollectionNames.yml} +0 -0
  1620. /data/spec/spec_tests/data/retryable_reads/{listCollectionObjects.yml → legacy/listCollectionObjects.yml} +0 -0
  1621. /data/spec/spec_tests/data/retryable_reads/{listCollections.yml → legacy/listCollections.yml} +0 -0
  1622. /data/spec/spec_tests/data/retryable_reads/{listDatabaseNames.yml → legacy/listDatabaseNames.yml} +0 -0
  1623. /data/spec/spec_tests/data/retryable_reads/{listDatabaseObjects.yml → legacy/listDatabaseObjects.yml} +0 -0
  1624. /data/spec/spec_tests/data/retryable_reads/{listDatabases.yml → legacy/listDatabases.yml} +0 -0
  1625. /data/spec/spec_tests/data/retryable_reads/{listIndexes.yml → legacy/listIndexes.yml} +0 -0
  1626. /data/spec/spec_tests/data/retryable_writes/{deleteMany.yml → legacy/deleteMany.yml} +0 -0
  1627. /data/spec/spec_tests/data/retryable_writes/{deleteOne.yml → legacy/deleteOne.yml} +0 -0
  1628. /data/spec/spec_tests/data/retryable_writes/{findOneAndDelete.yml → legacy/findOneAndDelete.yml} +0 -0
  1629. /data/spec/spec_tests/data/retryable_writes/{findOneAndReplace.yml → legacy/findOneAndReplace.yml} +0 -0
  1630. /data/spec/spec_tests/data/retryable_writes/{findOneAndUpdate.yml → legacy/findOneAndUpdate.yml} +0 -0
  1631. /data/spec/spec_tests/data/retryable_writes/{insertMany.yml → legacy/insertMany.yml} +0 -0
  1632. /data/spec/spec_tests/data/retryable_writes/{insertOne.yml → legacy/insertOne.yml} +0 -0
  1633. /data/spec/spec_tests/data/retryable_writes/{replaceOne.yml → legacy/replaceOne.yml} +0 -0
  1634. /data/spec/spec_tests/data/retryable_writes/{updateMany.yml → legacy/updateMany.yml} +0 -0
  1635. /data/spec/spec_tests/data/retryable_writes/{updateOne.yml → legacy/updateOne.yml} +0 -0
  1636. /data/spec/spec_tests/data/sdam/rs/{secondary_wrong_set_name_with_primary_second.yml → ruby_secondary_wrong_set_name_with_primary_second.yml} +0 -0
  1637. /data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/longer-parent-in-return.yml +0 -0
  1638. /data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/misformatted-option.yml +0 -0
  1639. /data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/no-results.yml +0 -0
  1640. /data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/not-enough-parts.yml +0 -0
  1641. /data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/one-result-default-port.yml +0 -0
  1642. /data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/one-txt-record-multiple-strings.yml +0 -0
  1643. /data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/one-txt-record.yml +0 -0
  1644. /data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch1.yml +0 -0
  1645. /data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch2.yml +0 -0
  1646. /data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch3.yml +0 -0
  1647. /data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch4.yml +0 -0
  1648. /data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/parent-part-mismatch5.yml +0 -0
  1649. /data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/returned-parent-too-short.yml +0 -0
  1650. /data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/returned-parent-wrong.yml +0 -0
  1651. /data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/two-results-default-port.yml +0 -0
  1652. /data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/two-results-nonstandard-port.yml +0 -0
  1653. /data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/two-txt-records.yml +0 -0
  1654. /data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/txt-record-not-allowed-option.yml +0 -0
  1655. /data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/txt-record-with-overridden-ssl-option.yml +0 -0
  1656. /data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/txt-record-with-overridden-uri-option.yml +0 -0
  1657. /data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/txt-record-with-unallowed-option.yml +0 -0
  1658. /data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/uri-with-port.yml +0 -0
  1659. /data/spec/spec_tests/data/{dns_seedlist_discovery → seed_list_discovery/replica-set}/uri-with-two-hosts.yml +0 -0
@@ -0,0 +1,4415 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ require 'spec_helper'
5
+
6
+ describe Mongo::Collection do
7
+
8
+ let(:subscriber) { Mrss::EventSubscriber.new }
9
+
10
+ let(:client) do
11
+ authorized_client.tap do |client|
12
+ client.subscribe(Mongo::Monitoring::COMMAND, subscriber)
13
+ end
14
+ end
15
+
16
+ let(:authorized_collection) { client['collection_spec'] }
17
+
18
+ before do
19
+ authorized_client['collection_spec'].drop
20
+ end
21
+
22
+ let(:collection_invalid_write_concern) do
23
+ authorized_collection.client.with(write: INVALID_WRITE_CONCERN)[authorized_collection.name]
24
+ end
25
+
26
+ let(:collection_with_validator) do
27
+ authorized_client[:validating]
28
+ end
29
+
30
+ describe '#find' do
31
+
32
+ describe 'updating cluster time' do
33
+
34
+ let(:operation) do
35
+ client[TEST_COLL].find.first
36
+ end
37
+
38
+ let(:operation_with_session) do
39
+ client[TEST_COLL].find({}, session: session).first
40
+ end
41
+
42
+ let(:second_operation) do
43
+ client[TEST_COLL].find({}, session: session).first
44
+ end
45
+
46
+ it_behaves_like 'an operation updating cluster time'
47
+ end
48
+
49
+ context 'when provided a filter' do
50
+
51
+ let(:view) do
52
+ authorized_collection.find(name: 1)
53
+ end
54
+
55
+ it 'returns a authorized_collection view for the filter' do
56
+ expect(view.filter).to eq('name' => 1)
57
+ end
58
+ end
59
+
60
+ context 'when provided no filter' do
61
+
62
+ let(:view) do
63
+ authorized_collection.find
64
+ end
65
+
66
+ it 'returns a authorized_collection view with an empty filter' do
67
+ expect(view.filter).to be_empty
68
+ end
69
+ end
70
+
71
+ context 'when providing a bad filter' do
72
+
73
+ let(:view) do
74
+ authorized_collection.find('$or' => [])
75
+ end
76
+
77
+ it 'raises an exception when iterating' do
78
+ expect {
79
+ view.to_a
80
+ }.to raise_exception(Mongo::Error::OperationFailure)
81
+ end
82
+ end
83
+
84
+ context 'when iterating the authorized_collection view' do
85
+
86
+ before do
87
+ authorized_collection.insert_many([{ field: 'test1' }, { field: 'test2' }])
88
+ end
89
+
90
+ let(:view) do
91
+ authorized_collection.find
92
+ end
93
+
94
+ it 'iterates over the documents' do
95
+ view.each do |document|
96
+ expect(document).to_not be_nil
97
+ end
98
+ end
99
+ end
100
+
101
+ context 'when the user is not authorized' do
102
+ require_auth
103
+
104
+ let(:view) do
105
+ unauthorized_collection.find
106
+ end
107
+
108
+ it 'iterates over the documents' do
109
+ expect {
110
+ view.each{ |document| document }
111
+ }.to raise_error(Mongo::Error::OperationFailure)
112
+ end
113
+ end
114
+
115
+ context 'when documents contain potential error message fields' do
116
+
117
+ [ 'errmsg', 'error', Mongo::Operation::Result::OK ].each do |field|
118
+
119
+ context "when the document contains a '#{field}' field" do
120
+
121
+ let(:value) do
122
+ 'testing'
123
+ end
124
+
125
+ let(:view) do
126
+ authorized_collection.find
127
+ end
128
+
129
+ before do
130
+ authorized_collection.insert_one({ field => value })
131
+ end
132
+
133
+ it 'iterates over the documents' do
134
+ view.each do |document|
135
+ expect(document[field]).to eq(value)
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
141
+
142
+ context 'when provided options' do
143
+
144
+ context 'when a session is provided' do
145
+ require_wired_tiger
146
+
147
+ let(:operation) do
148
+ authorized_collection.find({}, session: session).to_a
149
+ end
150
+
151
+ let(:session) do
152
+ authorized_client.start_session
153
+ end
154
+
155
+ let(:failed_operation) do
156
+ client[authorized_collection.name].find({ '$._id' => 1 }, session: session).to_a
157
+ end
158
+
159
+ let(:client) do
160
+ authorized_client
161
+ end
162
+
163
+ it_behaves_like 'an operation using a session'
164
+ it_behaves_like 'a failed operation using a session'
165
+ end
166
+
167
+ context 'session id' do
168
+ min_server_fcv '3.6'
169
+ require_topology :replica_set, :sharded
170
+ require_wired_tiger
171
+
172
+ let(:options) do
173
+ { session: session }
174
+ end
175
+
176
+ let(:session) do
177
+ client.start_session
178
+ end
179
+
180
+ let(:view) do
181
+ Mongo::Collection::View.new(client[TEST_COLL], selector, view_options)
182
+ end
183
+
184
+ let(:command) do
185
+ client[TEST_COLL].find({}, session: session).explain
186
+ subscriber.started_events.find { |c| c.command_name == 'explain' }.command
187
+ end
188
+
189
+ it 'sends the session id' do
190
+ expect(command['lsid']).to eq(session.session_id)
191
+ end
192
+ end
193
+
194
+ context 'when a session supporting causal consistency is used' do
195
+ require_wired_tiger
196
+
197
+ let(:operation) do
198
+ collection.find({}, session: session).to_a
199
+ end
200
+
201
+ let(:command) do
202
+ operation
203
+ subscriber.started_events.find { |cmd| cmd.command_name == 'find' }.command
204
+ end
205
+
206
+ it_behaves_like 'an operation supporting causally consistent reads'
207
+ end
208
+
209
+ let(:view) do
210
+ authorized_collection.find({}, options)
211
+ end
212
+
213
+ context 'when provided :allow_partial_results' do
214
+
215
+ let(:options) do
216
+ { allow_partial_results: true }
217
+ end
218
+
219
+ it 'returns a view with :allow_partial_results set' do
220
+ expect(view.options[:allow_partial_results]).to be(options[:allow_partial_results])
221
+ end
222
+ end
223
+
224
+ context 'when provided :batch_size' do
225
+
226
+ let(:options) do
227
+ { batch_size: 100 }
228
+ end
229
+
230
+ it 'returns a view with :batch_size set' do
231
+ expect(view.options[:batch_size]).to eq(options[:batch_size])
232
+ end
233
+ end
234
+
235
+ context 'when provided :comment' do
236
+
237
+ let(:options) do
238
+ { comment: 'slow query' }
239
+ end
240
+
241
+ it 'returns a view with :comment set' do
242
+ expect(view.modifiers[:$comment]).to eq(options[:comment])
243
+ end
244
+ end
245
+
246
+ context 'when provided :cursor_type' do
247
+
248
+ let(:options) do
249
+ { cursor_type: :tailable }
250
+ end
251
+
252
+ it 'returns a view with :cursor_type set' do
253
+ expect(view.options[:cursor_type]).to eq(options[:cursor_type])
254
+ end
255
+ end
256
+
257
+ context 'when provided :max_time_ms' do
258
+
259
+ let(:options) do
260
+ { max_time_ms: 500 }
261
+ end
262
+
263
+ it 'returns a view with :max_time_ms set' do
264
+ expect(view.modifiers[:$maxTimeMS]).to eq(options[:max_time_ms])
265
+ end
266
+ end
267
+
268
+ context 'when provided :modifiers' do
269
+
270
+ let(:options) do
271
+ { modifiers: { '$orderby' => Mongo::Index::ASCENDING } }
272
+ end
273
+
274
+ it 'returns a view with modifiers set' do
275
+ expect(view.modifiers).to eq(options[:modifiers])
276
+ end
277
+
278
+ it 'dups the modifiers hash' do
279
+ expect(view.modifiers).not_to be(options[:modifiers])
280
+ end
281
+ end
282
+
283
+ context 'when provided :no_cursor_timeout' do
284
+
285
+ let(:options) do
286
+ { no_cursor_timeout: true }
287
+ end
288
+
289
+ it 'returns a view with :no_cursor_timeout set' do
290
+ expect(view.options[:no_cursor_timeout]).to eq(options[:no_cursor_timeout])
291
+ end
292
+ end
293
+
294
+ context 'when provided :oplog_replay' do
295
+
296
+ let(:options) do
297
+ { oplog_replay: false }
298
+ end
299
+
300
+ it 'returns a view with :oplog_replay set' do
301
+ expect(view.options[:oplog_replay]).to eq(options[:oplog_replay])
302
+ end
303
+ end
304
+
305
+ context 'when provided :projection' do
306
+
307
+ let(:options) do
308
+ { projection: { 'x' => 1 } }
309
+ end
310
+
311
+ it 'returns a view with :projection set' do
312
+ expect(view.options[:projection]).to eq(options[:projection])
313
+ end
314
+ end
315
+
316
+ context 'when provided :skip' do
317
+
318
+ let(:options) do
319
+ { skip: 5 }
320
+ end
321
+
322
+ it 'returns a view with :skip set' do
323
+ expect(view.options[:skip]).to eq(options[:skip])
324
+ end
325
+ end
326
+
327
+ context 'when provided :sort' do
328
+
329
+ let(:options) do
330
+ { sort: { 'x' => Mongo::Index::ASCENDING } }
331
+ end
332
+
333
+ it 'returns a view with :sort set' do
334
+ expect(view.modifiers[:$orderby]).to eq(options[:sort])
335
+ end
336
+ end
337
+
338
+ context 'when provided :collation' do
339
+
340
+ let(:options) do
341
+ { collation: { 'locale' => 'en_US' } }
342
+ end
343
+
344
+ it 'returns a view with :collation set' do
345
+ expect(view.options[:collation]).to eq(options[:collation])
346
+ end
347
+ end
348
+ end
349
+ end
350
+
351
+ describe '#insert_many' do
352
+
353
+ let(:result) do
354
+ authorized_collection.insert_many([{ name: 'test1' }, { name: 'test2' }])
355
+ end
356
+
357
+ it 'inserts the documents into the collection' do
358
+ expect(result.inserted_count).to eq(2)
359
+ end
360
+
361
+ it 'contains the ids in the result' do
362
+ expect(result.inserted_ids.size).to eq(2)
363
+ end
364
+
365
+ context 'when a session is provided' do
366
+
367
+ let(:session) do
368
+ authorized_client.start_session
369
+ end
370
+
371
+ let(:operation) do
372
+ authorized_collection.insert_many([{ name: 'test1' }, { name: 'test2' }], session: session)
373
+ end
374
+
375
+ let(:failed_operation) do
376
+ authorized_collection.insert_many([{ _id: 'test1' }, { _id: 'test1' }], session: session)
377
+ end
378
+
379
+ let(:client) do
380
+ authorized_client
381
+ end
382
+
383
+ it_behaves_like 'an operation using a session'
384
+ it_behaves_like 'a failed operation using a session'
385
+ end
386
+
387
+ context 'when unacknowledged writes is used with an explicit session' do
388
+
389
+ let(:collection_with_unacknowledged_write_concern) do
390
+ authorized_collection.with(write: { w: 0 })
391
+ end
392
+
393
+ let(:operation) do
394
+ collection_with_unacknowledged_write_concern.insert_many([{ name: 'test1' }, { name: 'test2' }], session: session)
395
+ end
396
+
397
+ it_behaves_like 'an explicit session with an unacknowledged write'
398
+ end
399
+
400
+ context 'when unacknowledged writes is used with an implicit session' do
401
+
402
+ let(:collection_with_unacknowledged_write_concern) do
403
+ client.with(write: { w: 0 })[TEST_COLL]
404
+ end
405
+
406
+ let(:operation) do
407
+ collection_with_unacknowledged_write_concern.insert_many([{ name: 'test1' }, { name: 'test2' }])
408
+ end
409
+
410
+ it_behaves_like 'an implicit session with an unacknowledged write'
411
+ end
412
+
413
+ context 'when a document contains dotted keys' do
414
+
415
+ let(:docs) do
416
+ [ { 'first.name' => 'test1' }, { name: 'test2' } ]
417
+ end
418
+
419
+ let(:view) { authorized_collection.find({}, { sort: { name: 1 } }) }
420
+
421
+ it 'inserts the documents correctly' do
422
+ expect {
423
+ authorized_collection.insert_many(docs)
424
+ }.to_not raise_error
425
+
426
+ expect(view.count).to eq(2)
427
+ expect(view.first['first.name']).to eq('test1')
428
+ expect(view.to_a[1]['name']).to eq('test2')
429
+ end
430
+ end
431
+
432
+ context 'when the client has a custom id generator' do
433
+
434
+ let(:generator) do
435
+ Class.new do
436
+ def generate
437
+ 1
438
+ end
439
+ end.new
440
+ end
441
+
442
+ let(:custom_client) do
443
+ authorized_client.with(id_generator: generator)
444
+ end
445
+
446
+ let(:custom_collection) do
447
+ custom_client['custom_id_generator_test_collection']
448
+ end
449
+
450
+ before do
451
+ custom_collection.delete_many
452
+ custom_collection.insert_many([{ name: 'testing' }])
453
+ expect(custom_collection.count).to eq(1)
454
+ end
455
+
456
+ it 'inserts with the custom id' do
457
+ expect(custom_collection.count).to eq(1)
458
+ expect(custom_collection.find.first[:_id]).to eq(1)
459
+ end
460
+ end
461
+
462
+ context 'when the inserts fail' do
463
+
464
+ let(:result) do
465
+ authorized_collection.insert_many([{ _id: 1 }, { _id: 1 }])
466
+ end
467
+
468
+ it 'raises an BulkWriteError' do
469
+ expect {
470
+ result
471
+ }.to raise_exception(Mongo::Error::BulkWriteError)
472
+ end
473
+ end
474
+
475
+ context "when the documents exceed the max bson size" do
476
+
477
+ let(:documents) do
478
+ [{ '_id' => 1, 'name' => '1'*17000000 }]
479
+ end
480
+
481
+ it 'raises a MaxBSONSize error' do
482
+ expect {
483
+ authorized_collection.insert_many(documents)
484
+ }.to raise_error(Mongo::Error::MaxBSONSize)
485
+ end
486
+ end
487
+
488
+ context 'when the documents are sent with OP_MSG' do
489
+ min_server_fcv '3.6'
490
+
491
+ let(:documents) do
492
+ [{ '_id' => 1, 'name' => '1'*16777191 }, { '_id' => 'y' }]
493
+ end
494
+
495
+ before do
496
+ authorized_collection.insert_many(documents)
497
+ end
498
+
499
+ let(:insert_events) do
500
+ subscriber.started_events.select { |e| e.command_name == 'insert' }
501
+ end
502
+
503
+ it 'sends the documents in one OP_MSG' do
504
+ expect(insert_events.size).to eq(1)
505
+ expect(insert_events[0].command['documents']).to eq(documents)
506
+ end
507
+ end
508
+
509
+ context 'when collection has a validator' do
510
+ min_server_fcv '3.2'
511
+
512
+ around(:each) do |spec|
513
+ authorized_client[:validating].drop
514
+ authorized_client[:validating,
515
+ :validator => { :a => { '$exists' => true } }].tap do |c|
516
+ c.create
517
+ end
518
+ spec.run
519
+ collection_with_validator.drop
520
+ end
521
+
522
+ context 'when the document is valid' do
523
+
524
+ let(:result) do
525
+ collection_with_validator.insert_many([{ a: 1 }, { a: 2 }])
526
+ end
527
+
528
+ it 'inserts successfully' do
529
+ expect(result.inserted_count).to eq(2)
530
+ end
531
+ end
532
+
533
+ context 'when the document is invalid' do
534
+
535
+ context 'when bypass_document_validation is not set' do
536
+
537
+ let(:result2) do
538
+ collection_with_validator.insert_many([{ x: 1 }, { x: 2 }])
539
+ end
540
+
541
+ it 'raises a BulkWriteError' do
542
+ expect {
543
+ result2
544
+ }.to raise_exception(Mongo::Error::BulkWriteError)
545
+ end
546
+ end
547
+
548
+ context 'when bypass_document_validation is true' do
549
+
550
+ let(:result3) do
551
+ collection_with_validator.insert_many(
552
+ [{ x: 1 }, { x: 2 }], :bypass_document_validation => true)
553
+ end
554
+
555
+ it 'inserts successfully' do
556
+ expect(result3.inserted_count).to eq(2)
557
+ end
558
+ end
559
+ end
560
+ end
561
+
562
+ context 'when unacknowledged writes is used' do
563
+
564
+ let(:collection_with_unacknowledged_write_concern) do
565
+ authorized_collection.with(write: { w: 0 })
566
+ end
567
+
568
+ let(:result) do
569
+ collection_with_unacknowledged_write_concern.insert_many([{ _id: 1 }, { _id: 1 }])
570
+ end
571
+
572
+ it 'does not raise an exception' do
573
+ expect(result.inserted_count).to be(0)
574
+ end
575
+ end
576
+
577
+ context 'when various options passed in' do
578
+ # w: 2 requires a replica set
579
+ require_topology :replica_set
580
+
581
+ # https://jira.mongodb.org/browse/RUBY-2306
582
+ min_server_fcv '3.6'
583
+
584
+ let(:session) do
585
+ authorized_client.start_session
586
+ end
587
+
588
+ let(:events) do
589
+ subscriber.command_started_events('insert')
590
+ end
591
+
592
+ let(:collection) do
593
+ authorized_collection.with(write_concern: {w: 2})
594
+ end
595
+
596
+ let!(:command) do
597
+ Utils.get_command_event(authorized_client, 'insert') do |client|
598
+ collection.insert_many([{ name: 'test1' }, { name: 'test2' }], session: session,
599
+ write_concern: {w: 1}, bypass_document_validation: true)
600
+ end.command
601
+ end
602
+
603
+ it 'inserts many successfully with correct options sent to server' do
604
+ expect(events.length).to eq(1)
605
+ expect(command[:writeConcern]).to_not be_nil
606
+ expect(command[:writeConcern][:w]).to eq(1)
607
+ expect(command[:bypassDocumentValidation]).to be(true)
608
+ end
609
+ end
610
+ end
611
+
612
+ describe '#insert_one' do
613
+
614
+ describe 'updating cluster time' do
615
+
616
+ let(:operation) do
617
+ client[TEST_COLL].insert_one({ name: 'testing' })
618
+ end
619
+
620
+ let(:operation_with_session) do
621
+ client[TEST_COLL].insert_one({ name: 'testing' }, session: session)
622
+ end
623
+
624
+ let(:second_operation) do
625
+ client[TEST_COLL].insert_one({ name: 'testing' }, session: session)
626
+ end
627
+
628
+ it_behaves_like 'an operation updating cluster time'
629
+ end
630
+
631
+ let(:result) do
632
+ authorized_collection.insert_one({ name: 'testing' })
633
+ end
634
+
635
+ it 'inserts the document into the collection'do
636
+ expect(result.written_count).to eq(1)
637
+ end
638
+
639
+ it 'contains the id in the result' do
640
+ expect(result.inserted_id).to_not be_nil
641
+ end
642
+
643
+ context 'when a session is provided' do
644
+
645
+ let(:session) do
646
+ authorized_client.start_session
647
+ end
648
+
649
+ let(:operation) do
650
+ authorized_collection.insert_one({ name: 'testing' }, session: session)
651
+ end
652
+
653
+ let(:failed_operation) do
654
+ authorized_collection.insert_one({ _id: 'testing' })
655
+ authorized_collection.insert_one({ _id: 'testing' }, session: session)
656
+ end
657
+
658
+ let(:client) do
659
+ authorized_client
660
+ end
661
+
662
+ it_behaves_like 'an operation using a session'
663
+ it_behaves_like 'a failed operation using a session'
664
+ end
665
+
666
+ context 'when unacknowledged writes is used with an explicit session' do
667
+
668
+ let(:collection_with_unacknowledged_write_concern) do
669
+ authorized_collection.with(write: { w: 0 })
670
+ end
671
+
672
+ let(:operation) do
673
+ collection_with_unacknowledged_write_concern.insert_one({ name: 'testing' }, session: session)
674
+ end
675
+
676
+ it_behaves_like 'an explicit session with an unacknowledged write'
677
+ end
678
+
679
+ context 'when unacknowledged writes is used with an implicit session' do
680
+
681
+ let(:collection_with_unacknowledged_write_concern) do
682
+ client.with(write: { w: 0 })[TEST_COLL]
683
+ end
684
+
685
+ let(:operation) do
686
+ collection_with_unacknowledged_write_concern.insert_one({ name: 'testing' })
687
+ end
688
+
689
+ it_behaves_like 'an implicit session with an unacknowledged write'
690
+ end
691
+
692
+ context 'when various options passed in' do
693
+ # https://jira.mongodb.org/browse/RUBY-2306
694
+ min_server_fcv '3.6'
695
+
696
+ let(:session) do
697
+ authorized_client.start_session
698
+ end
699
+
700
+ let(:events) do
701
+ subscriber.command_started_events('insert')
702
+ end
703
+
704
+ let(:collection) do
705
+ authorized_collection.with(write_concern: {w: 3})
706
+ end
707
+
708
+ let!(:command) do
709
+ Utils.get_command_event(authorized_client, 'insert') do |client|
710
+ collection.insert_one({name: 'test1'}, session: session, write_concern: {w: 1},
711
+ bypass_document_validation: true)
712
+ end.command
713
+ end
714
+
715
+ it 'inserts one successfully with correct options sent to server' do
716
+ expect(events.length).to eq(1)
717
+ expect(command[:writeConcern]).to_not be_nil
718
+ expect(command[:writeConcern][:w]).to eq(1)
719
+ expect(command[:bypassDocumentValidation]).to be(true)
720
+ end
721
+ end
722
+
723
+ context 'when the document contains dotted keys' do
724
+
725
+ let(:doc) do
726
+ { 'testing.test' => 'value' }
727
+ end
728
+
729
+ it 'inserts the document correctly' do
730
+ expect {
731
+ authorized_collection.insert_one(doc)
732
+ }.to_not raise_error
733
+
734
+ expect(authorized_collection.count).to eq(1)
735
+ expect(authorized_collection.find.first['testing.test']).to eq('value')
736
+ end
737
+ end
738
+
739
+ context 'when the document is nil' do
740
+ let(:result) do
741
+ authorized_collection.insert_one(nil)
742
+ end
743
+
744
+ it 'raises an ArgumentError' do
745
+ expect {
746
+ result
747
+ }.to raise_error(ArgumentError, "Document to be inserted cannot be nil")
748
+ end
749
+ end
750
+
751
+ context 'when the insert fails' do
752
+
753
+ let(:result) do
754
+ authorized_collection.insert_one(_id: 1)
755
+ authorized_collection.insert_one(_id: 1)
756
+ end
757
+
758
+ it 'raises an OperationFailure' do
759
+ expect {
760
+ result
761
+ }.to raise_exception(Mongo::Error::OperationFailure)
762
+ end
763
+ end
764
+
765
+ context 'when the client has a custom id generator' do
766
+
767
+ let(:generator) do
768
+ Class.new do
769
+ def generate
770
+ 1
771
+ end
772
+ end.new
773
+ end
774
+
775
+ let(:custom_client) do
776
+ authorized_client.with(id_generator: generator)
777
+ end
778
+
779
+ let(:custom_collection) do
780
+ custom_client[TEST_COLL]
781
+ end
782
+
783
+ before do
784
+ custom_collection.delete_many
785
+ custom_collection.insert_one({ name: 'testing' })
786
+ end
787
+
788
+ it 'inserts with the custom id' do
789
+ expect(custom_collection.find.first[:_id]).to eq(1)
790
+ end
791
+ end
792
+
793
+ context 'when collection has a validator' do
794
+ min_server_fcv '3.2'
795
+
796
+ around(:each) do |spec|
797
+ authorized_client[:validating,
798
+ :validator => { :a => { '$exists' => true } }].tap do |c|
799
+ c.create
800
+ end
801
+ spec.run
802
+ collection_with_validator.drop
803
+ end
804
+
805
+ context 'when the document is valid' do
806
+
807
+ let(:result) do
808
+ collection_with_validator.insert_one({ a: 1 })
809
+ end
810
+
811
+ it 'inserts successfully' do
812
+ expect(result.written_count).to eq(1)
813
+ end
814
+ end
815
+
816
+ context 'when the document is invalid' do
817
+
818
+ context 'when bypass_document_validation is not set' do
819
+
820
+ let(:result2) do
821
+ collection_with_validator.insert_one({ x: 1 })
822
+ end
823
+
824
+ it 'raises a OperationFailure' do
825
+ expect {
826
+ result2
827
+ }.to raise_exception(Mongo::Error::OperationFailure)
828
+ end
829
+ end
830
+
831
+ context 'when bypass_document_validation is true' do
832
+
833
+ let(:result3) do
834
+ collection_with_validator.insert_one(
835
+ { x: 1 }, :bypass_document_validation => true)
836
+ end
837
+
838
+ it 'inserts successfully' do
839
+ expect(result3.written_count).to eq(1)
840
+ end
841
+ end
842
+ end
843
+ end
844
+ end
845
+
846
+ describe '#bulk_write' do
847
+
848
+ context 'when various options passed in' do
849
+ min_server_fcv '3.2'
850
+ require_topology :replica_set
851
+
852
+ # https://jira.mongodb.org/browse/RUBY-2306
853
+ min_server_fcv '3.6'
854
+
855
+ let(:requests) do
856
+ [
857
+ { insert_one: { name: "anne" }},
858
+ { insert_one: { name: "bob" }},
859
+ { insert_one: { name: "charlie" }}
860
+ ]
861
+ end
862
+
863
+ let(:session) do
864
+ authorized_client.start_session
865
+ end
866
+
867
+ let!(:command) do
868
+ Utils.get_command_event(authorized_client, 'insert') do |client|
869
+ collection.bulk_write(requests, session: session, write_concern: {w: 1},
870
+ bypass_document_validation: true)
871
+ end.command
872
+ end
873
+
874
+ let(:events) do
875
+ subscriber.command_started_events('insert')
876
+ end
877
+
878
+ let(:collection) do
879
+ authorized_collection.with(write_concern: {w: 2})
880
+ end
881
+
882
+ it 'inserts successfully with correct options sent to server' do
883
+ expect(collection.count).to eq(3)
884
+ expect(events.length).to eq(1)
885
+ expect(command[:writeConcern]).to_not be_nil
886
+ expect(command[:writeConcern][:w]).to eq(1)
887
+ expect(command[:bypassDocumentValidation]).to eq(true)
888
+ end
889
+ end
890
+ end
891
+
892
+ describe '#aggregate' do
893
+
894
+ describe 'updating cluster time' do
895
+
896
+ let(:operation) do
897
+ client[TEST_COLL].aggregate([]).first
898
+ end
899
+
900
+ let(:operation_with_session) do
901
+ client[TEST_COLL].aggregate([], session: session).first
902
+ end
903
+
904
+ let(:second_operation) do
905
+ client[TEST_COLL].aggregate([], session: session).first
906
+ end
907
+
908
+ it_behaves_like 'an operation updating cluster time'
909
+ end
910
+
911
+ context 'when a session supporting causal consistency is used' do
912
+ require_wired_tiger
913
+
914
+ let(:operation) do
915
+ collection.aggregate([], session: session).first
916
+ end
917
+
918
+ let(:command) do
919
+ operation
920
+ subscriber.started_events.find { |cmd| cmd.command_name == 'aggregate' }.command
921
+ end
922
+
923
+ it_behaves_like 'an operation supporting causally consistent reads'
924
+ end
925
+
926
+ it 'returns an Aggregation object' do
927
+ expect(authorized_collection.aggregate([])).to be_a(Mongo::Collection::View::Aggregation)
928
+ end
929
+
930
+ context 'when options are provided' do
931
+
932
+ let(:options) do
933
+ { :allow_disk_use => true, :bypass_document_validation => true }
934
+ end
935
+
936
+ it 'sets the options on the Aggregation object' do
937
+ expect(authorized_collection.aggregate([], options).options).to eq(BSON::Document.new(options))
938
+ end
939
+
940
+ context 'when the :comment option is provided' do
941
+
942
+ let(:options) do
943
+ { :comment => 'testing' }
944
+ end
945
+
946
+ it 'sets the options on the Aggregation object' do
947
+ expect(authorized_collection.aggregate([], options).options).to eq(BSON::Document.new(options))
948
+ end
949
+ end
950
+
951
+ context 'when a session is provided' do
952
+
953
+ let(:session) do
954
+ authorized_client.start_session
955
+ end
956
+
957
+ let(:operation) do
958
+ authorized_collection.aggregate([], session: session).to_a
959
+ end
960
+
961
+ let(:failed_operation) do
962
+ authorized_collection.aggregate([ { '$invalid' => 1 }], session: session).to_a
963
+ end
964
+
965
+ let(:client) do
966
+ authorized_client
967
+ end
968
+
969
+ it_behaves_like 'an operation using a session'
970
+ it_behaves_like 'a failed operation using a session'
971
+ end
972
+
973
+ context 'when a hint is provided' do
974
+
975
+ let(:options) do
976
+ { 'hint' => { 'y' => 1 } }
977
+ end
978
+
979
+ it 'sets the options on the Aggregation object' do
980
+ expect(authorized_collection.aggregate([], options).options).to eq(options)
981
+ end
982
+ end
983
+
984
+ context 'when collation is provided' do
985
+
986
+ before do
987
+ authorized_collection.insert_many([ { name: 'bang' }, { name: 'bang' }])
988
+ end
989
+
990
+ let(:pipeline) do
991
+ [{ "$match" => { "name" => "BANG" } }]
992
+ end
993
+
994
+ let(:options) do
995
+ { collation: { locale: 'en_US', strength: 2 } }
996
+ end
997
+
998
+ let(:result) do
999
+ authorized_collection.aggregate(pipeline, options).collect { |doc| doc['name']}
1000
+ end
1001
+
1002
+ context 'when the server selected supports collations' do
1003
+ min_server_fcv '3.4'
1004
+
1005
+ it 'applies the collation' do
1006
+ expect(result).to eq(['bang', 'bang'])
1007
+ end
1008
+ end
1009
+
1010
+ context 'when the server selected does not support collations' do
1011
+ max_server_version '3.2'
1012
+
1013
+ it 'raises an exception' do
1014
+ expect {
1015
+ result
1016
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
1017
+ end
1018
+
1019
+ context 'when a String key is used' do
1020
+
1021
+ let(:options) do
1022
+ { 'collation' => { locale: 'en_US', strength: 2 } }
1023
+ end
1024
+
1025
+ it 'raises an exception' do
1026
+ expect {
1027
+ result
1028
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
1029
+ end
1030
+ end
1031
+ end
1032
+ end
1033
+ end
1034
+ end
1035
+
1036
+ describe '#count_documents' do
1037
+
1038
+ before do
1039
+ authorized_collection.delete_many
1040
+ end
1041
+
1042
+ context 'no argument provided' do
1043
+
1044
+ context 'when collection is empty' do
1045
+ it 'returns 0 matching documents' do
1046
+ expect(authorized_collection.count_documents).to eq(0)
1047
+ end
1048
+ end
1049
+
1050
+ context 'when collection is not empty' do
1051
+
1052
+ let(:documents) do
1053
+ documents = []
1054
+ 1.upto(10) do |index|
1055
+ documents << { key: 'a', _id: "in#{index}" }
1056
+ end
1057
+ documents
1058
+ end
1059
+
1060
+ before do
1061
+ authorized_collection.insert_many(documents)
1062
+ end
1063
+
1064
+ it 'returns 10 matching documents' do
1065
+ expect(authorized_collection.count_documents).to eq(10)
1066
+ end
1067
+ end
1068
+ end
1069
+
1070
+ context 'when transactions are enabled' do
1071
+ require_wired_tiger
1072
+ require_transaction_support
1073
+
1074
+ before do
1075
+ # Ensure that the collection is created
1076
+ authorized_collection.insert_one(x: 1)
1077
+ authorized_collection.delete_many({})
1078
+ end
1079
+
1080
+ let(:session) do
1081
+ authorized_client.start_session
1082
+ end
1083
+
1084
+ it 'successfully starts a transaction and executes a transaction' do
1085
+ session.start_transaction
1086
+ expect(
1087
+ session.instance_variable_get(:@state)
1088
+ ).to eq(Mongo::Session::STARTING_TRANSACTION_STATE)
1089
+
1090
+ expect(authorized_collection.count_documents({}, { session: session })).to eq(0)
1091
+ expect(
1092
+ session.instance_variable_get(:@state)
1093
+ ).to eq(Mongo::Session::TRANSACTION_IN_PROGRESS_STATE)
1094
+
1095
+ authorized_collection.insert_one({ x: 1 }, { session: session })
1096
+ expect(authorized_collection.count_documents({}, { session: session })).to eq(1)
1097
+
1098
+ session.commit_transaction
1099
+ expect(
1100
+ session.instance_variable_get(:@state)
1101
+ ).to eq(Mongo::Session::TRANSACTION_COMMITTED_STATE)
1102
+ end
1103
+ end
1104
+ end
1105
+
1106
+ describe '#count' do
1107
+
1108
+ let(:documents) do
1109
+ (1..10).map{ |i| { field: "test#{i}" }}
1110
+ end
1111
+
1112
+ before do
1113
+ authorized_collection.insert_many(documents)
1114
+ end
1115
+
1116
+ it 'returns an integer count' do
1117
+ expect(authorized_collection.count).to eq(10)
1118
+ end
1119
+
1120
+ context 'when options are provided' do
1121
+
1122
+ it 'passes the options to the count' do
1123
+ expect(authorized_collection.count({}, limit: 5)).to eq(5)
1124
+ end
1125
+
1126
+ context 'when a session is provided' do
1127
+ require_wired_tiger
1128
+
1129
+ let(:session) do
1130
+ authorized_client.start_session
1131
+ end
1132
+
1133
+ let(:operation) do
1134
+ authorized_collection.count({}, session: session)
1135
+ end
1136
+
1137
+ let(:failed_operation) do
1138
+ authorized_collection.count({ '$._id' => 1 }, session: session)
1139
+ end
1140
+
1141
+ let(:client) do
1142
+ authorized_client
1143
+ end
1144
+
1145
+ it_behaves_like 'an operation using a session'
1146
+ it_behaves_like 'a failed operation using a session'
1147
+ end
1148
+
1149
+ context 'when a session supporting causal consistency is used' do
1150
+ require_wired_tiger
1151
+
1152
+ let(:operation) do
1153
+ collection.count({}, session: session)
1154
+ end
1155
+
1156
+ let(:command) do
1157
+ operation
1158
+ subscriber.started_events.find { |cmd| cmd.command_name == 'count' }.command
1159
+ end
1160
+
1161
+ it_behaves_like 'an operation supporting causally consistent reads'
1162
+ end
1163
+
1164
+ context 'when a collation is specified' do
1165
+
1166
+ let(:selector) do
1167
+ { name: 'BANG' }
1168
+ end
1169
+
1170
+ let(:result) do
1171
+ authorized_collection.count(selector, options)
1172
+ end
1173
+
1174
+ before do
1175
+ authorized_collection.insert_one(name: 'bang')
1176
+ end
1177
+
1178
+ let(:options) do
1179
+ { collation: { locale: 'en_US', strength: 2 } }
1180
+ end
1181
+
1182
+ context 'when the server selected supports collations' do
1183
+ min_server_fcv '3.4'
1184
+
1185
+ it 'applies the collation to the count' do
1186
+ expect(result).to eq(1)
1187
+ end
1188
+ end
1189
+
1190
+ context 'when the server selected does not support collations' do
1191
+ max_server_version '3.2'
1192
+
1193
+ it 'raises an exception' do
1194
+ expect {
1195
+ result
1196
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
1197
+ end
1198
+
1199
+ context 'when a String key is used' do
1200
+
1201
+ let(:options) do
1202
+ { 'collation' => { locale: 'en_US', strength: 2 } }
1203
+ end
1204
+
1205
+ it 'raises an exception' do
1206
+ expect {
1207
+ result
1208
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
1209
+ end
1210
+ end
1211
+ end
1212
+ end
1213
+ end
1214
+ end
1215
+
1216
+ describe '#distinct' do
1217
+
1218
+ let(:documents) do
1219
+ (1..3).map{ |i| { field: "test#{i}" }}
1220
+ end
1221
+
1222
+ before do
1223
+ authorized_collection.insert_many(documents)
1224
+ end
1225
+
1226
+ it 'returns the distinct values' do
1227
+ expect(authorized_collection.distinct(:field).sort).to eq([ 'test1', 'test2', 'test3' ])
1228
+ end
1229
+
1230
+ context 'when a selector is provided' do
1231
+
1232
+ it 'returns the distinct values' do
1233
+ expect(authorized_collection.distinct(:field, field: 'test1')).to eq([ 'test1' ])
1234
+ end
1235
+ end
1236
+
1237
+ context 'when options are provided' do
1238
+
1239
+ it 'passes the options to the distinct command' do
1240
+ expect(authorized_collection.distinct(:field, {}, max_time_ms: 100).sort).to eq([ 'test1', 'test2', 'test3' ])
1241
+ end
1242
+
1243
+ context 'when a session is provided' do
1244
+ require_wired_tiger
1245
+
1246
+ let(:session) do
1247
+ authorized_client.start_session
1248
+ end
1249
+
1250
+ let(:operation) do
1251
+ authorized_collection.distinct(:field, {}, session: session)
1252
+ end
1253
+
1254
+ let(:failed_operation) do
1255
+ authorized_collection.distinct(:field, { '$._id' => 1 }, session: session)
1256
+ end
1257
+
1258
+ let(:client) do
1259
+ authorized_client
1260
+ end
1261
+
1262
+ it_behaves_like 'an operation using a session'
1263
+ it_behaves_like 'a failed operation using a session'
1264
+ end
1265
+ end
1266
+
1267
+ context 'when a session supporting causal consistency is used' do
1268
+ require_wired_tiger
1269
+
1270
+ let(:operation) do
1271
+ collection.distinct(:field, {}, session: session)
1272
+ end
1273
+
1274
+ let(:command) do
1275
+ operation
1276
+ subscriber.started_events.find { |cmd| cmd.command_name == 'distinct' }.command
1277
+ end
1278
+
1279
+ it_behaves_like 'an operation supporting causally consistent reads'
1280
+ end
1281
+
1282
+ context 'when a collation is specified' do
1283
+
1284
+ let(:result) do
1285
+ authorized_collection.distinct(:name, {}, options)
1286
+ end
1287
+
1288
+ before do
1289
+ authorized_collection.insert_one(name: 'bang')
1290
+ authorized_collection.insert_one(name: 'BANG')
1291
+ end
1292
+
1293
+ let(:options) do
1294
+ { collation: { locale: 'en_US', strength: 2 } }
1295
+ end
1296
+
1297
+ context 'when the server selected supports collations' do
1298
+ min_server_fcv '3.4'
1299
+
1300
+ it 'applies the collation to the distinct' do
1301
+ expect(result).to eq(['bang'])
1302
+ end
1303
+ end
1304
+
1305
+ context 'when the server selected does not support collations' do
1306
+ max_server_version '3.2'
1307
+
1308
+ it 'raises an exception' do
1309
+ expect {
1310
+ result
1311
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
1312
+ end
1313
+
1314
+ context 'when a String key is used' do
1315
+
1316
+ let(:options) do
1317
+ { 'collation' => { locale: 'en_US', strength: 2 } }
1318
+ end
1319
+
1320
+ it 'raises an exception' do
1321
+ expect {
1322
+ result
1323
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
1324
+ end
1325
+ end
1326
+ end
1327
+ end
1328
+
1329
+ context 'when a collation is not specified' do
1330
+
1331
+ let(:result) do
1332
+ authorized_collection.distinct(:name)
1333
+ end
1334
+
1335
+ before do
1336
+ authorized_collection.insert_one(name: 'bang')
1337
+ authorized_collection.insert_one(name: 'BANG')
1338
+ end
1339
+
1340
+ it 'does not apply the collation to the distinct' do
1341
+ expect(result).to match_array(['bang', 'BANG'])
1342
+ end
1343
+ end
1344
+ end
1345
+
1346
+ describe '#delete_one' do
1347
+
1348
+ context 'when a selector was provided' do
1349
+
1350
+ let(:selector) do
1351
+ { field: 'test1' }
1352
+ end
1353
+
1354
+ before do
1355
+ authorized_collection.insert_many([
1356
+ { field: 'test1' },
1357
+ { field: 'test1' },
1358
+ { field: 'test1' }
1359
+ ])
1360
+ end
1361
+
1362
+ let(:response) do
1363
+ authorized_collection.delete_one(selector)
1364
+ end
1365
+
1366
+ it 'deletes the first matching document in the collection' do
1367
+ expect(response.deleted_count).to eq(1)
1368
+ end
1369
+ end
1370
+
1371
+ context 'when no selector was provided' do
1372
+
1373
+ before do
1374
+ authorized_collection.insert_many([{ field: 'test1' }, { field: 'test2' }])
1375
+ end
1376
+
1377
+ let(:response) do
1378
+ authorized_collection.delete_one
1379
+ end
1380
+
1381
+ it 'deletes the first document in the collection' do
1382
+ expect(response.deleted_count).to eq(1)
1383
+ end
1384
+ end
1385
+
1386
+ context 'when the delete fails' do
1387
+ require_topology :single
1388
+
1389
+ let(:result) do
1390
+ collection_invalid_write_concern.delete_one
1391
+ end
1392
+
1393
+ it 'raises an OperationFailure' do
1394
+ expect {
1395
+ result
1396
+ }.to raise_exception(Mongo::Error::OperationFailure)
1397
+ end
1398
+ end
1399
+
1400
+ context 'when a session is provided' do
1401
+
1402
+ let(:session) do
1403
+ authorized_client.start_session
1404
+ end
1405
+
1406
+ let(:operation) do
1407
+ authorized_collection.delete_one({}, session: session)
1408
+ end
1409
+
1410
+ let(:failed_operation) do
1411
+ authorized_collection.delete_one({ '$._id' => 1}, session: session)
1412
+ end
1413
+
1414
+ let(:client) do
1415
+ authorized_client
1416
+ end
1417
+
1418
+ it_behaves_like 'an operation using a session'
1419
+ it_behaves_like 'a failed operation using a session'
1420
+ end
1421
+
1422
+ context 'when unacknowledged writes is used' do
1423
+
1424
+ let(:collection_with_unacknowledged_write_concern) do
1425
+ authorized_collection.with(write: { w: 0 })
1426
+ end
1427
+
1428
+ let(:operation) do
1429
+ collection_with_unacknowledged_write_concern.delete_one({}, session: session)
1430
+ end
1431
+
1432
+ it_behaves_like 'an explicit session with an unacknowledged write'
1433
+ end
1434
+
1435
+ context 'when unacknowledged writes is used with an implicit session' do
1436
+
1437
+ let(:collection_with_unacknowledged_write_concern) do
1438
+ client.with(write: { w: 0 })[TEST_COLL]
1439
+ end
1440
+
1441
+ let(:operation) do
1442
+ collection_with_unacknowledged_write_concern.delete_one
1443
+ end
1444
+
1445
+ it_behaves_like 'an implicit session with an unacknowledged write'
1446
+ end
1447
+
1448
+ context 'when a collation is provided' do
1449
+
1450
+ let(:selector) do
1451
+ { name: 'BANG' }
1452
+ end
1453
+
1454
+ let(:result) do
1455
+ authorized_collection.delete_one(selector, options)
1456
+ end
1457
+
1458
+ before do
1459
+ authorized_collection.insert_one(name: 'bang')
1460
+ end
1461
+
1462
+ let(:options) do
1463
+ { collation: { locale: 'en_US', strength: 2 } }
1464
+ end
1465
+
1466
+ context 'when the server selected supports collations' do
1467
+ min_server_fcv '3.4'
1468
+
1469
+ it 'applies the collation' do
1470
+ expect(result.written_count).to eq(1)
1471
+ expect(authorized_collection.find(name: 'bang').count).to eq(0)
1472
+ end
1473
+
1474
+ context 'when unacknowledged writes is used' do
1475
+
1476
+ let(:collection_with_unacknowledged_write_concern) do
1477
+ authorized_collection.with(write: { w: 0 })
1478
+ end
1479
+
1480
+ let(:result) do
1481
+ collection_with_unacknowledged_write_concern.delete_one(selector, options)
1482
+ end
1483
+
1484
+ it 'raises an exception' do
1485
+ expect {
1486
+ result
1487
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
1488
+ end
1489
+
1490
+ context 'when a String key is used' do
1491
+
1492
+ let(:options) do
1493
+ { 'collation' => { locale: 'en_US', strength: 2 } }
1494
+ end
1495
+
1496
+ it 'raises an exception' do
1497
+ expect {
1498
+ result
1499
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
1500
+ end
1501
+ end
1502
+ end
1503
+ end
1504
+
1505
+ context 'when the server selected does not support collations' do
1506
+ max_server_version '3.2'
1507
+
1508
+ it 'raises an exception' do
1509
+ expect {
1510
+ result
1511
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
1512
+ end
1513
+
1514
+ context 'when a String key is used' do
1515
+
1516
+ let(:options) do
1517
+ { 'collation' => { locale: 'en_US', strength: 2 } }
1518
+ end
1519
+
1520
+ it 'raises an exception' do
1521
+ expect {
1522
+ result
1523
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
1524
+ end
1525
+ end
1526
+ end
1527
+ end
1528
+
1529
+ context 'when collation is not specified' do
1530
+
1531
+ let(:selector) do
1532
+ { name: 'BANG' }
1533
+ end
1534
+
1535
+ let(:result) do
1536
+ authorized_collection.delete_one(selector)
1537
+ end
1538
+
1539
+ before do
1540
+ authorized_collection.insert_one(name: 'bang')
1541
+ end
1542
+
1543
+ it 'does not apply the collation' do
1544
+ expect(result.written_count).to eq(0)
1545
+ expect(authorized_collection.find(name: 'bang').count).to eq(1)
1546
+ end
1547
+ end
1548
+
1549
+ context 'when various options passed in' do
1550
+ # w: 2 requires a replica set
1551
+ require_topology :replica_set
1552
+
1553
+ # https://jira.mongodb.org/browse/RUBY-2306
1554
+ min_server_fcv '3.6'
1555
+
1556
+ before do
1557
+ authorized_collection.insert_many([{ name: 'test1' }, { name: 'test2' }])
1558
+ end
1559
+
1560
+ let(:selector) do
1561
+ {name: 'test2'}
1562
+ end
1563
+
1564
+ let(:session) do
1565
+ authorized_client.start_session
1566
+ end
1567
+
1568
+ let(:events) do
1569
+ subscriber.command_started_events('delete')
1570
+ end
1571
+
1572
+ let(:collection) do
1573
+ authorized_collection.with(write_concern: {w: 2})
1574
+ end
1575
+
1576
+ let!(:command) do
1577
+ Utils.get_command_event(authorized_client, 'delete') do |client|
1578
+ collection.delete_one(selector, session: session, write_concern: {w: 1},
1579
+ bypass_document_validation: true)
1580
+ end.command
1581
+ end
1582
+
1583
+ it 'deletes one successfully with correct options sent to server' do
1584
+ expect(events.length).to eq(1)
1585
+ expect(command[:writeConcern]).to_not be_nil
1586
+ expect(command[:writeConcern][:w]).to eq(1)
1587
+ expect(command[:bypassDocumentValidation]).to eq(true)
1588
+ end
1589
+ end
1590
+ end
1591
+
1592
+ describe '#delete_many' do
1593
+
1594
+ before do
1595
+ authorized_collection.insert_many([{ field: 'test1' }, { field: 'test2' }])
1596
+ end
1597
+
1598
+ context 'when a selector was provided' do
1599
+
1600
+ let(:selector) do
1601
+ { field: 'test1' }
1602
+ end
1603
+
1604
+ it 'deletes the matching documents in the collection' do
1605
+ expect(authorized_collection.delete_many(selector).deleted_count).to eq(1)
1606
+ end
1607
+ end
1608
+
1609
+ context 'when no selector was provided' do
1610
+
1611
+ it 'deletes all the documents in the collection' do
1612
+ expect(authorized_collection.delete_many.deleted_count).to eq(2)
1613
+ end
1614
+ end
1615
+
1616
+ context 'when the deletes fail' do
1617
+ require_topology :single
1618
+
1619
+ let(:result) do
1620
+ collection_invalid_write_concern.delete_many
1621
+ end
1622
+
1623
+ it 'raises an OperationFailure' do
1624
+ expect {
1625
+ result
1626
+ }.to raise_exception(Mongo::Error::OperationFailure)
1627
+ end
1628
+ end
1629
+
1630
+ context 'when a session is provided' do
1631
+
1632
+ let(:session) do
1633
+ authorized_client.start_session
1634
+ end
1635
+
1636
+ let(:operation) do
1637
+ authorized_collection.delete_many({}, session: session)
1638
+ end
1639
+
1640
+ let(:failed_operation) do
1641
+ authorized_collection.delete_many({ '$._id' => 1}, session: session)
1642
+ end
1643
+
1644
+ let(:client) do
1645
+ authorized_client
1646
+ end
1647
+
1648
+ it_behaves_like 'an operation using a session'
1649
+ it_behaves_like 'a failed operation using a session'
1650
+ end
1651
+
1652
+ context 'when unacknowledged writes are used with an explicit session' do
1653
+
1654
+ let(:collection_with_unacknowledged_write_concern) do
1655
+ authorized_collection.with(write: { w: 0 })
1656
+ end
1657
+
1658
+ let(:operation) do
1659
+ collection_with_unacknowledged_write_concern.delete_many({ '$._id' => 1}, session: session)
1660
+ end
1661
+
1662
+ it_behaves_like 'an explicit session with an unacknowledged write'
1663
+ end
1664
+
1665
+ context 'when unacknowledged writes are used with an implicit session' do
1666
+
1667
+ let(:collection_with_unacknowledged_write_concern) do
1668
+ client.with(write: { w: 0 })[TEST_COLL]
1669
+ end
1670
+
1671
+ let(:operation) do
1672
+ collection_with_unacknowledged_write_concern.delete_many({ '$._id' => 1 })
1673
+ end
1674
+
1675
+ it_behaves_like 'an implicit session with an unacknowledged write'
1676
+ end
1677
+
1678
+ context 'when a collation is specified' do
1679
+
1680
+ let(:selector) do
1681
+ { name: 'BANG' }
1682
+ end
1683
+
1684
+ let(:result) do
1685
+ authorized_collection.delete_many(selector, options)
1686
+ end
1687
+
1688
+ before do
1689
+ authorized_collection.insert_one(name: 'bang')
1690
+ authorized_collection.insert_one(name: 'bang')
1691
+ end
1692
+
1693
+ let(:options) do
1694
+ { collation: { locale: 'en_US', strength: 2 } }
1695
+ end
1696
+
1697
+ context 'when the server selected supports collations' do
1698
+ min_server_fcv '3.4'
1699
+
1700
+ it 'applies the collation' do
1701
+ expect(result.written_count).to eq(2)
1702
+ expect(authorized_collection.find(name: 'bang').count).to eq(0)
1703
+ end
1704
+
1705
+ context 'when unacknowledged writes is used' do
1706
+
1707
+ let(:collection_with_unacknowledged_write_concern) do
1708
+ authorized_collection.with(write: { w: 0 })
1709
+ end
1710
+
1711
+ let(:result) do
1712
+ collection_with_unacknowledged_write_concern.delete_many(selector, options)
1713
+ end
1714
+
1715
+ it 'raises an exception' do
1716
+ expect {
1717
+ result
1718
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
1719
+ end
1720
+
1721
+ context 'when a String key is used' do
1722
+
1723
+ let(:options) do
1724
+ { 'collation' => { locale: 'en_US', strength: 2 } }
1725
+ end
1726
+
1727
+ it 'raises an exception' do
1728
+ expect {
1729
+ result
1730
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
1731
+ end
1732
+ end
1733
+ end
1734
+ end
1735
+
1736
+ context 'when the server selected does not support collations' do
1737
+ max_server_version '3.2'
1738
+
1739
+ it 'raises an exception' do
1740
+ expect {
1741
+ result
1742
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
1743
+ end
1744
+
1745
+ context 'when a String key is used' do
1746
+
1747
+ let(:options) do
1748
+ { 'collation' => { locale: 'en_US', strength: 2 } }
1749
+ end
1750
+
1751
+ it 'raises an exception' do
1752
+ expect {
1753
+ result
1754
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
1755
+ end
1756
+ end
1757
+ end
1758
+ end
1759
+
1760
+ context 'when a collation is not specified' do
1761
+
1762
+ let(:selector) do
1763
+ { name: 'BANG' }
1764
+ end
1765
+
1766
+ let(:result) do
1767
+ authorized_collection.delete_many(selector)
1768
+ end
1769
+
1770
+ before do
1771
+ authorized_collection.insert_one(name: 'bang')
1772
+ authorized_collection.insert_one(name: 'bang')
1773
+ end
1774
+
1775
+ it 'does not apply the collation' do
1776
+ expect(result.written_count).to eq(0)
1777
+ expect(authorized_collection.find(name: 'bang').count).to eq(2)
1778
+ end
1779
+ end
1780
+
1781
+ context 'when various options passed in' do
1782
+ # w: 2 requires a replica set
1783
+ require_topology :replica_set
1784
+
1785
+ # https://jira.mongodb.org/browse/RUBY-2306
1786
+ min_server_fcv '3.6'
1787
+
1788
+ before do
1789
+ collection.insert_many([{ name: 'test1' }, { name: 'test2' }, { name: 'test3'}])
1790
+ end
1791
+
1792
+ let(:selector) do
1793
+ {name: 'test1'}
1794
+ end
1795
+
1796
+ let(:session) do
1797
+ authorized_client.start_session
1798
+ end
1799
+
1800
+ let(:events) do
1801
+ subscriber.command_started_events('delete')
1802
+ end
1803
+
1804
+ let(:collection) do
1805
+ authorized_collection.with(write_concern: {w: 1})
1806
+ end
1807
+
1808
+ let!(:command) do
1809
+ Utils.get_command_event(authorized_client, 'delete') do |client|
1810
+ collection.delete_many(selector, session: session, write_concern: {w: 2},
1811
+ bypass_document_validation: true)
1812
+ end.command
1813
+ end
1814
+
1815
+ it 'deletes many successfully with correct options sent to server' do
1816
+ expect(events.length).to eq(1)
1817
+ expect(command[:writeConcern]).to_not be_nil
1818
+ expect(command[:writeConcern][:w]).to eq(2)
1819
+ expect(command[:bypassDocumentValidation]).to be(true)
1820
+ end
1821
+ end
1822
+ end
1823
+
1824
+ describe '#parallel_scan' do
1825
+ max_server_version '4.0'
1826
+ require_topology :single, :replica_set
1827
+
1828
+ let(:documents) do
1829
+ (1..200).map do |i|
1830
+ { name: "testing-scan-#{i}" }
1831
+ end
1832
+ end
1833
+
1834
+ before do
1835
+ authorized_collection.insert_many(documents)
1836
+ end
1837
+
1838
+ let(:cursors) do
1839
+ authorized_collection.parallel_scan(2)
1840
+ end
1841
+
1842
+ it 'returns an array of cursors' do
1843
+ cursors.each do |cursor|
1844
+ expect(cursor.class).to be(Mongo::Cursor)
1845
+ end
1846
+ end
1847
+
1848
+ it 'returns the correct number of documents' do
1849
+ expect(
1850
+ cursors.reduce(0) { |total, cursor| total + cursor.to_a.size }
1851
+ ).to eq(200)
1852
+ end
1853
+
1854
+ context 'when a session is provided' do
1855
+ require_wired_tiger
1856
+
1857
+ let(:cursors) do
1858
+ authorized_collection.parallel_scan(2, session: session)
1859
+ end
1860
+
1861
+ let(:operation) do
1862
+ cursors.reduce(0) { |total, cursor| total + cursor.to_a.size }
1863
+ end
1864
+
1865
+ let(:failed_operation) do
1866
+ authorized_collection.parallel_scan(-2, session: session)
1867
+ end
1868
+
1869
+ let(:client) do
1870
+ authorized_client
1871
+ end
1872
+
1873
+ it_behaves_like 'an operation using a session'
1874
+ it_behaves_like 'a failed operation using a session'
1875
+ end
1876
+
1877
+ context 'when a session is not provided' do
1878
+ let(:collection) { client['test'] }
1879
+
1880
+ let(:cursors) do
1881
+ collection.parallel_scan(2)
1882
+ end
1883
+
1884
+ let(:operation) do
1885
+ cursors.reduce(0) { |total, cursor| total + cursor.to_a.size }
1886
+ end
1887
+
1888
+ let(:failed_operation) do
1889
+ collection.parallel_scan(-2)
1890
+ end
1891
+
1892
+ let(:command) do
1893
+ operation
1894
+ event = subscriber.started_events.find { |cmd| cmd.command_name == 'parallelCollectionScan' }
1895
+ expect(event).not_to be_nil
1896
+ event.command
1897
+ end
1898
+
1899
+ it_behaves_like 'an operation not using a session'
1900
+ it_behaves_like 'a failed operation not using a session'
1901
+ end
1902
+
1903
+ context 'when a session supporting causal consistency is used' do
1904
+ require_wired_tiger
1905
+
1906
+ before do
1907
+ collection.drop
1908
+ collection.create
1909
+ end
1910
+
1911
+ let(:cursors) do
1912
+ collection.parallel_scan(2, session: session)
1913
+ end
1914
+
1915
+ let(:operation) do
1916
+ cursors.reduce(0) { |total, cursor| total + cursor.to_a.size }
1917
+ end
1918
+
1919
+ let(:command) do
1920
+ operation
1921
+ event = subscriber.started_events.find { |cmd| cmd.command_name == 'parallelCollectionScan' }
1922
+ expect(event).not_to be_nil
1923
+ event.command
1924
+ end
1925
+
1926
+ it_behaves_like 'an operation supporting causally consistent reads'
1927
+ end
1928
+
1929
+ context 'when a read concern is provided' do
1930
+ require_wired_tiger
1931
+ min_server_fcv '3.2'
1932
+
1933
+ let(:result) do
1934
+ authorized_collection.with(options).parallel_scan(2)
1935
+ end
1936
+
1937
+ context 'when the read concern is valid' do
1938
+
1939
+ let(:options) do
1940
+ { read_concern: { level: 'local' }}
1941
+ end
1942
+
1943
+ it 'sends the read concern' do
1944
+ expect { result }.to_not raise_error
1945
+ end
1946
+ end
1947
+
1948
+ context 'when the read concern is not valid' do
1949
+
1950
+ let(:options) do
1951
+ { read_concern: { level: 'idontknow' }}
1952
+ end
1953
+
1954
+ it 'raises an exception' do
1955
+ expect {
1956
+ result
1957
+ }.to raise_error(Mongo::Error::OperationFailure)
1958
+ end
1959
+ end
1960
+ end
1961
+
1962
+ context 'when the collection has a read preference' do
1963
+ require_topology :single, :replica_set
1964
+
1965
+ before do
1966
+ allow(collection.client.cluster).to receive(:single?).and_return(false)
1967
+ end
1968
+
1969
+ let(:client) do
1970
+ authorized_client.with(server_selection_timeout: 0.2)
1971
+ end
1972
+
1973
+ let(:collection) do
1974
+ client[authorized_collection.name,
1975
+ read: { :mode => :secondary, :tag_sets => [{ 'non' => 'existent' }] }]
1976
+ end
1977
+
1978
+ let(:result) do
1979
+ collection.parallel_scan(2)
1980
+ end
1981
+
1982
+ it 'uses that read preference' do
1983
+ expect {
1984
+ result
1985
+ }.to raise_exception(Mongo::Error::NoServerAvailable)
1986
+ end
1987
+ end
1988
+
1989
+ context 'when a max time ms value is provided' do
1990
+ require_topology :single, :replica_set
1991
+
1992
+ let(:result) do
1993
+ authorized_collection.parallel_scan(2, options)
1994
+ end
1995
+
1996
+ context 'when the read concern is valid' do
1997
+
1998
+ let(:options) do
1999
+ { max_time_ms: 5 }
2000
+ end
2001
+
2002
+ it 'sends the max time ms value' do
2003
+ expect { result }.to_not raise_error
2004
+ end
2005
+ end
2006
+
2007
+ context 'when the max time ms is not valid' do
2008
+
2009
+ let(:options) do
2010
+ { max_time_ms: 0.1 }
2011
+ end
2012
+
2013
+ it 'raises an exception' do
2014
+ expect {
2015
+ result
2016
+ }.to raise_error(Mongo::Error::OperationFailure)
2017
+ end
2018
+ end
2019
+ end
2020
+ end
2021
+
2022
+ describe '#replace_one' do
2023
+
2024
+ let(:selector) do
2025
+ { field: 'test1' }
2026
+ end
2027
+
2028
+ context 'when a selector was provided' do
2029
+
2030
+ before do
2031
+ authorized_collection.insert_many([{ field: 'test1' }, { field: 'test1' }])
2032
+ end
2033
+
2034
+ let!(:response) do
2035
+ authorized_collection.replace_one(selector, { field: 'testing' })
2036
+ end
2037
+
2038
+ let(:updated) do
2039
+ authorized_collection.find(field: 'testing').first
2040
+ end
2041
+
2042
+ it 'updates the first matching document in the collection' do
2043
+ expect(response.modified_count).to eq(1)
2044
+ end
2045
+
2046
+ it 'updates the documents in the collection' do
2047
+ expect(updated[:field]).to eq('testing')
2048
+ end
2049
+ end
2050
+
2051
+ context 'when upsert is false' do
2052
+
2053
+ let!(:response) do
2054
+ authorized_collection.replace_one(selector, { field: 'test1' }, upsert: false)
2055
+ end
2056
+
2057
+ let(:updated) do
2058
+ authorized_collection.find(field: 'test1').to_a
2059
+ end
2060
+
2061
+ it 'reports that no documents were written' do
2062
+ expect(response.modified_count).to eq(0)
2063
+ end
2064
+
2065
+ it 'does not insert the document' do
2066
+ expect(updated).to be_empty
2067
+ end
2068
+ end
2069
+
2070
+ context 'when upsert is true' do
2071
+
2072
+ let!(:response) do
2073
+ authorized_collection.replace_one(selector, { field: 'test1' }, upsert: true)
2074
+ end
2075
+
2076
+ let(:updated) do
2077
+ authorized_collection.find(field: 'test1').first
2078
+ end
2079
+
2080
+ it 'reports that a document was written' do
2081
+ expect(response.written_count).to eq(1)
2082
+ end
2083
+
2084
+ it 'inserts the document' do
2085
+ expect(updated[:field]).to eq('test1')
2086
+ end
2087
+ end
2088
+
2089
+ context 'when upsert is not specified' do
2090
+
2091
+ let!(:response) do
2092
+ authorized_collection.replace_one(selector, { field: 'test1' })
2093
+ end
2094
+
2095
+ let(:updated) do
2096
+ authorized_collection.find(field: 'test1').to_a
2097
+ end
2098
+
2099
+ it 'reports that no documents were written' do
2100
+ expect(response.modified_count).to eq(0)
2101
+ end
2102
+
2103
+ it 'does not insert the document' do
2104
+ expect(updated).to be_empty
2105
+ end
2106
+ end
2107
+
2108
+ context 'when the replace has an invalid key' do
2109
+
2110
+ context "when validate_update_replace is true" do
2111
+
2112
+ config_override :validate_update_replace, true
2113
+
2114
+ let(:result) do
2115
+ authorized_collection.replace_one(selector, { '$s' => 'test1' })
2116
+ end
2117
+
2118
+ it 'raises an InvalidReplacementDocument error' do
2119
+ expect {
2120
+ result
2121
+ }.to raise_exception(Mongo::Error::InvalidReplacementDocument)
2122
+ end
2123
+ end
2124
+
2125
+ context "when validate_update_replace is false" do
2126
+
2127
+ config_override :validate_update_replace, false
2128
+
2129
+ let(:result) do
2130
+ authorized_collection.replace_one(selector, { '$set' => { 'test1' => 1 } })
2131
+ end
2132
+
2133
+ it 'does not raise an error' do
2134
+ expect {
2135
+ result
2136
+ }.to_not raise_exception
2137
+ end
2138
+ end
2139
+ end
2140
+
2141
+ context 'when collection has a validator' do
2142
+ min_server_fcv '3.2'
2143
+
2144
+ around(:each) do |spec|
2145
+ collection_with_validator.drop
2146
+ authorized_client[:validating,
2147
+ :validator => { :a => { '$exists' => true } }].tap do |c|
2148
+ c.create
2149
+ end
2150
+ spec.run
2151
+ collection_with_validator.drop
2152
+ end
2153
+
2154
+ before do
2155
+ collection_with_validator.insert_one({ a: 1 })
2156
+ end
2157
+
2158
+ context 'when the document is valid' do
2159
+
2160
+ let(:result) do
2161
+ collection_with_validator.replace_one({ a: 1 }, { a: 5 })
2162
+ end
2163
+
2164
+ it 'replaces successfully' do
2165
+ expect(result.modified_count).to eq(1)
2166
+ end
2167
+ end
2168
+
2169
+ context 'when the document is invalid' do
2170
+
2171
+ context 'when bypass_document_validation is not set' do
2172
+
2173
+ let(:result2) do
2174
+ collection_with_validator.replace_one({ a: 1 }, { x: 5 })
2175
+ end
2176
+
2177
+ it 'raises OperationFailure' do
2178
+ expect {
2179
+ result2
2180
+ }.to raise_exception(Mongo::Error::OperationFailure)
2181
+ end
2182
+ end
2183
+
2184
+ context 'when bypass_document_validation is true' do
2185
+
2186
+ let(:result3) do
2187
+ collection_with_validator.replace_one(
2188
+ { a: 1 }, { x: 1 }, :bypass_document_validation => true)
2189
+ end
2190
+
2191
+ it 'replaces successfully' do
2192
+ expect(result3.written_count).to eq(1)
2193
+ end
2194
+ end
2195
+ end
2196
+ end
2197
+
2198
+ context 'when a collation is specified' do
2199
+
2200
+ let(:selector) do
2201
+ { name: 'BANG' }
2202
+ end
2203
+
2204
+ let(:result) do
2205
+ authorized_collection.replace_one(selector, { name: 'doink' }, options)
2206
+ end
2207
+
2208
+ before do
2209
+ authorized_collection.insert_one(name: 'bang')
2210
+ end
2211
+
2212
+ let(:options) do
2213
+ { collation: { locale: 'en_US', strength: 2 } }
2214
+ end
2215
+
2216
+ context 'when the server selected supports collations' do
2217
+ min_server_fcv '3.4'
2218
+
2219
+ it 'applies the collation' do
2220
+ expect(result.written_count).to eq(1)
2221
+ expect(authorized_collection.find(name: 'doink').count).to eq(1)
2222
+ end
2223
+
2224
+ context 'when unacknowledged writes is used' do
2225
+
2226
+ let(:collection_with_unacknowledged_write_concern) do
2227
+ authorized_collection.with(write: { w: 0 })
2228
+ end
2229
+
2230
+ let(:result) do
2231
+ collection_with_unacknowledged_write_concern.replace_one(selector, { name: 'doink' }, options)
2232
+ end
2233
+
2234
+ it 'raises an exception' do
2235
+ expect {
2236
+ result
2237
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
2238
+ end
2239
+
2240
+ context 'when a String key is used' do
2241
+
2242
+ let(:options) do
2243
+ { 'collation' => { locale: 'en_US', strength: 2 } }
2244
+ end
2245
+
2246
+ it 'raises an exception' do
2247
+ expect {
2248
+ result
2249
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
2250
+ end
2251
+ end
2252
+ end
2253
+ end
2254
+
2255
+ context 'when the server selected does not support collations' do
2256
+ max_server_version '3.2'
2257
+
2258
+ it 'raises an exception' do
2259
+ expect {
2260
+ result
2261
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
2262
+ end
2263
+
2264
+ context 'when a String key is used' do
2265
+
2266
+ let(:options) do
2267
+ { 'collation' => { locale: 'en_US', strength: 2 } }
2268
+ end
2269
+
2270
+ it 'raises an exception' do
2271
+ expect {
2272
+ result
2273
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
2274
+ end
2275
+ end
2276
+ end
2277
+ end
2278
+
2279
+ context 'when a collation is not specified' do
2280
+
2281
+ let(:selector) do
2282
+ { name: 'BANG' }
2283
+ end
2284
+
2285
+ let(:result) do
2286
+ authorized_collection.replace_one(selector, { name: 'doink' })
2287
+ end
2288
+
2289
+ before do
2290
+ authorized_collection.insert_one(name: 'bang')
2291
+ end
2292
+
2293
+ it 'does not apply the collation' do
2294
+ expect(result.written_count).to eq(0)
2295
+ expect(authorized_collection.find(name: 'bang').count).to eq(1)
2296
+ end
2297
+ end
2298
+
2299
+ context 'when a session is provided' do
2300
+
2301
+ let(:selector) do
2302
+ { name: 'BANG' }
2303
+ end
2304
+
2305
+ before do
2306
+ authorized_collection.insert_one(name: 'bang')
2307
+ end
2308
+
2309
+ let(:session) do
2310
+ authorized_client.start_session
2311
+ end
2312
+
2313
+ let(:operation) do
2314
+ authorized_collection.replace_one(selector, { name: 'doink' }, session: session)
2315
+ end
2316
+
2317
+ let(:failed_operation) do
2318
+ authorized_collection.replace_one({ '$._id' => 1 }, { name: 'doink' }, session: session)
2319
+ end
2320
+
2321
+ let(:client) do
2322
+ authorized_client
2323
+ end
2324
+
2325
+ it_behaves_like 'an operation using a session'
2326
+ it_behaves_like 'a failed operation using a session'
2327
+ end
2328
+
2329
+ context 'when unacknowledged writes is used with an explicit session' do
2330
+
2331
+ let(:collection_with_unacknowledged_write_concern) do
2332
+ authorized_collection.with(write: { w: 0 })
2333
+ end
2334
+
2335
+ let(:operation) do
2336
+ collection_with_unacknowledged_write_concern.replace_one({ a: 1 }, { x: 5 }, session: session)
2337
+ end
2338
+
2339
+ it_behaves_like 'an explicit session with an unacknowledged write'
2340
+ end
2341
+
2342
+ context 'when unacknowledged writes is used with an implicit session' do
2343
+
2344
+ let(:collection_with_unacknowledged_write_concern) do
2345
+ client.with(write: { w: 0 })[TEST_COLL]
2346
+ end
2347
+
2348
+ let(:operation) do
2349
+ collection_with_unacknowledged_write_concern.replace_one({ a: 1 }, { x: 5 })
2350
+ end
2351
+
2352
+ it_behaves_like 'an implicit session with an unacknowledged write'
2353
+ end
2354
+
2355
+ context 'when various options passed in' do
2356
+ # w: 2 requires a replica set
2357
+ require_topology :replica_set
2358
+
2359
+ # https://jira.mongodb.org/browse/RUBY-2306
2360
+ min_server_fcv '3.6'
2361
+
2362
+ before do
2363
+ authorized_collection.insert_one({field: 'test1'})
2364
+ end
2365
+
2366
+ let(:session) do
2367
+ authorized_client.start_session
2368
+ end
2369
+
2370
+ let(:events) do
2371
+ subscriber.command_started_events('update')
2372
+ end
2373
+
2374
+ let(:collection) do
2375
+ authorized_collection.with(write_concern: {w: 3})
2376
+ end
2377
+
2378
+ let(:updated) do
2379
+ collection.find(field: 'test4').first
2380
+ end
2381
+
2382
+ let!(:command) do
2383
+ Utils.get_command_event(authorized_client, 'update') do |client|
2384
+ collection.replace_one(selector, { field: 'test4'},
2385
+ session: session, :return_document => :after, write_concern: {w: 2},
2386
+ upsert: true, bypass_document_validation: true)
2387
+ end.command
2388
+ end
2389
+
2390
+ it 'replaced one successfully with correct options sent to server' do
2391
+ expect(updated[:field]).to eq('test4')
2392
+ expect(events.length).to eq(1)
2393
+ expect(command[:writeConcern]).to_not be_nil
2394
+ expect(command[:writeConcern][:w]).to eq(2)
2395
+ expect(command[:bypassDocumentValidation]).to be(true)
2396
+ expect(command[:updates][0][:upsert]).to be(true)
2397
+ end
2398
+ end
2399
+ end
2400
+
2401
+ describe '#update_many' do
2402
+
2403
+ let(:selector) do
2404
+ { field: 'test' }
2405
+ end
2406
+
2407
+ context 'when a selector was provided' do
2408
+
2409
+ before do
2410
+ authorized_collection.insert_many([{ field: 'test' }, { field: 'test' }])
2411
+ end
2412
+
2413
+ let!(:response) do
2414
+ authorized_collection.update_many(selector, '$set'=> { field: 'testing' })
2415
+ end
2416
+
2417
+ let(:updated) do
2418
+ authorized_collection.find(field: 'testing').to_a.last
2419
+ end
2420
+
2421
+ it 'returns the number updated' do
2422
+ expect(response.modified_count).to eq(2)
2423
+ end
2424
+
2425
+ it 'updates the documents in the collection' do
2426
+ expect(updated[:field]).to eq('testing')
2427
+ end
2428
+ end
2429
+
2430
+ context 'when upsert is false' do
2431
+
2432
+ let(:response) do
2433
+ authorized_collection.update_many(selector, { '$set'=> { field: 'testing' } },
2434
+ upsert: false)
2435
+ end
2436
+
2437
+ let(:updated) do
2438
+ authorized_collection.find.to_a
2439
+ end
2440
+
2441
+ it 'reports that no documents were updated' do
2442
+ expect(response.modified_count).to eq(0)
2443
+ end
2444
+
2445
+ it 'updates no documents in the collection' do
2446
+ expect(updated).to be_empty
2447
+ end
2448
+ end
2449
+
2450
+ context 'when upsert is true' do
2451
+
2452
+ let!(:response) do
2453
+ authorized_collection.update_many(selector, { '$set'=> { field: 'testing' } },
2454
+ upsert: true)
2455
+ end
2456
+
2457
+ let(:updated) do
2458
+ authorized_collection.find.to_a.last
2459
+ end
2460
+
2461
+ it 'reports that a document was written' do
2462
+ expect(response.written_count).to eq(1)
2463
+ end
2464
+
2465
+ it 'inserts a document into the collection' do
2466
+ expect(updated[:field]).to eq('testing')
2467
+ end
2468
+ end
2469
+
2470
+ context 'when upsert is not specified' do
2471
+
2472
+ let(:response) do
2473
+ authorized_collection.update_many(selector, { '$set'=> { field: 'testing' } })
2474
+ end
2475
+
2476
+ let(:updated) do
2477
+ authorized_collection.find.to_a
2478
+ end
2479
+
2480
+ it 'reports that no documents were updated' do
2481
+ expect(response.modified_count).to eq(0)
2482
+ end
2483
+
2484
+ it 'updates no documents in the collection' do
2485
+ expect(updated).to be_empty
2486
+ end
2487
+ end
2488
+
2489
+ context 'when arrayFilters is provided' do
2490
+
2491
+ let(:selector) do
2492
+ { '$or' => [{ _id: 0 }, { _id: 1 }]}
2493
+ end
2494
+
2495
+ context 'when the server supports arrayFilters' do
2496
+ min_server_fcv '3.6'
2497
+
2498
+ before do
2499
+ authorized_collection.insert_many([{
2500
+ _id: 0, x: [
2501
+ { y: 1 },
2502
+ { y: 2 },
2503
+ { y: 3 }
2504
+ ]
2505
+ },
2506
+ {
2507
+ _id: 1,
2508
+ x: [
2509
+ { y: 3 },
2510
+ { y: 2 },
2511
+ { y: 1 }
2512
+ ]
2513
+ }])
2514
+ end
2515
+
2516
+ let(:result) do
2517
+ authorized_collection.update_many(selector,
2518
+ { '$set' => { 'x.$[i].y' => 5 } },
2519
+ options)
2520
+ end
2521
+
2522
+ context 'when a Symbol key is used' do
2523
+
2524
+ let(:options) do
2525
+ { array_filters: [{ 'i.y' => 3 }] }
2526
+ end
2527
+
2528
+ it 'applies the arrayFilters' do
2529
+ expect(result.matched_count).to eq(2)
2530
+ expect(result.modified_count).to eq(2)
2531
+
2532
+ docs = authorized_collection.find(selector, sort: { _id: 1 }).to_a
2533
+ expect(docs[0]['x']).to eq ([{ 'y' => 1 }, { 'y' => 2 }, { 'y' => 5 }])
2534
+ expect(docs[1]['x']).to eq ([{ 'y' => 5 }, { 'y' => 2 }, { 'y' => 1 }])
2535
+ end
2536
+ end
2537
+
2538
+ context 'when a String key is used' do
2539
+ let(:options) do
2540
+ { 'array_filters' => [{ 'i.y' => 3 }] }
2541
+ end
2542
+
2543
+ it 'applies the arrayFilters' do
2544
+ expect(result.matched_count).to eq(2)
2545
+ expect(result.modified_count).to eq(2)
2546
+
2547
+ docs = authorized_collection.find({}, sort: { _id: 1 }).to_a
2548
+ expect(docs[0]['x']).to eq ([{ 'y' => 1 }, { 'y' => 2 }, { 'y' => 5 }])
2549
+ expect(docs[1]['x']).to eq ([{ 'y' => 5 }, { 'y' => 2 }, { 'y' => 1 }])
2550
+ end
2551
+ end
2552
+ end
2553
+
2554
+ context 'when the server does not support arrayFilters' do
2555
+ max_server_version '3.4'
2556
+
2557
+ let(:result) do
2558
+ authorized_collection.update_many(selector,
2559
+ { '$set' => { 'x.$[i].y' => 5 } },
2560
+ options)
2561
+ end
2562
+
2563
+ context 'when a Symbol key is used' do
2564
+
2565
+ let(:options) do
2566
+ { array_filters: [{ 'i.y' => 3 }] }
2567
+ end
2568
+
2569
+ it 'raises an exception' do
2570
+ expect {
2571
+ result
2572
+ }.to raise_exception(Mongo::Error::UnsupportedArrayFilters)
2573
+ end
2574
+ end
2575
+
2576
+ context 'when a String key is used' do
2577
+
2578
+ let(:options) do
2579
+ { 'array_filters' => [{ 'i.y' => 3 }] }
2580
+ end
2581
+
2582
+ it 'raises an exception' do
2583
+ expect {
2584
+ result
2585
+ }.to raise_exception(Mongo::Error::UnsupportedArrayFilters)
2586
+ end
2587
+ end
2588
+ end
2589
+ end
2590
+
2591
+ context 'when the updates fail' do
2592
+
2593
+ let(:result) do
2594
+ authorized_collection.update_many(selector, { '$s'=> { field: 'testing' } })
2595
+ end
2596
+
2597
+ it 'raises an OperationFailure' do
2598
+ expect {
2599
+ result
2600
+ }.to raise_exception(Mongo::Error::OperationFailure)
2601
+ end
2602
+ end
2603
+
2604
+ context 'when collection has a validator' do
2605
+ min_server_fcv '3.2'
2606
+
2607
+ around(:each) do |spec|
2608
+ authorized_client[:validating,
2609
+ :validator => { :a => { '$exists' => true } }].tap do |c|
2610
+ c.create
2611
+ end
2612
+ spec.run
2613
+ collection_with_validator.drop
2614
+ end
2615
+
2616
+ before do
2617
+ collection_with_validator.insert_many([{ a: 1 }, { a: 2 }])
2618
+ end
2619
+
2620
+ context 'when the document is valid' do
2621
+
2622
+ let(:result) do
2623
+ collection_with_validator.update_many(
2624
+ { :a => { '$gt' => 0 } }, '$inc' => { :a => 1 } )
2625
+ end
2626
+
2627
+ it 'updates successfully' do
2628
+ expect(result.modified_count).to eq(2)
2629
+ end
2630
+ end
2631
+
2632
+ context 'when the document is invalid' do
2633
+
2634
+ context 'when bypass_document_validation is not set' do
2635
+
2636
+ let(:result2) do
2637
+ collection_with_validator.update_many(
2638
+ { :a => { '$gt' => 0 } }, '$unset' => { :a => '' })
2639
+ end
2640
+
2641
+ it 'raises OperationFailure' do
2642
+ expect {
2643
+ result2
2644
+ }.to raise_exception(Mongo::Error::OperationFailure)
2645
+ end
2646
+ end
2647
+
2648
+ context 'when bypass_document_validation is true' do
2649
+
2650
+ let(:result3) do
2651
+ collection_with_validator.update_many(
2652
+ { :a => { '$gt' => 0 } }, { '$unset' => { :a => '' } },
2653
+ :bypass_document_validation => true)
2654
+ end
2655
+
2656
+ it 'updates successfully' do
2657
+ expect(result3.written_count).to eq(2)
2658
+ end
2659
+ end
2660
+ end
2661
+ end
2662
+
2663
+ context 'when a collation is specified' do
2664
+
2665
+ let(:selector) do
2666
+ { name: 'BANG' }
2667
+ end
2668
+
2669
+ let(:result) do
2670
+ authorized_collection.update_many(selector, { '$set' => { other: 'doink' } }, options)
2671
+ end
2672
+
2673
+ before do
2674
+ authorized_collection.insert_one(name: 'bang')
2675
+ authorized_collection.insert_one(name: 'baNG')
2676
+ end
2677
+
2678
+ let(:options) do
2679
+ { collation: { locale: 'en_US', strength: 2 } }
2680
+ end
2681
+
2682
+ context 'when the server selected supports collations' do
2683
+ min_server_fcv '3.4'
2684
+
2685
+ it 'applies the collation' do
2686
+ expect(result.written_count).to eq(2)
2687
+ expect(authorized_collection.find(other: 'doink').count).to eq(2)
2688
+ end
2689
+
2690
+ context 'when unacknowledged writes is used' do
2691
+
2692
+ let(:collection_with_unacknowledged_write_concern) do
2693
+ authorized_collection.with(write: { w: 0 })
2694
+ end
2695
+
2696
+ let(:result) do
2697
+ collection_with_unacknowledged_write_concern.update_many(selector, { '$set' => { other: 'doink' } }, options)
2698
+ end
2699
+
2700
+ it 'raises an exception' do
2701
+ expect {
2702
+ result
2703
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
2704
+ end
2705
+
2706
+ context 'when a String key is used' do
2707
+
2708
+ let(:options) do
2709
+ { 'collation' => { locale: 'en_US', strength: 2 } }
2710
+ end
2711
+
2712
+ it 'raises an exception' do
2713
+ expect {
2714
+ result
2715
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
2716
+ end
2717
+ end
2718
+ end
2719
+ end
2720
+
2721
+ context 'when the server selected does not support collations' do
2722
+ max_server_version '3.2'
2723
+
2724
+ it 'raises an exception' do
2725
+ expect {
2726
+ result
2727
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
2728
+ end
2729
+
2730
+ context 'when a String key is used' do
2731
+
2732
+ let(:options) do
2733
+ { 'collation' => { locale: 'en_US', strength: 2 } }
2734
+ end
2735
+
2736
+ it 'raises an exception' do
2737
+ expect {
2738
+ result
2739
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
2740
+ end
2741
+ end
2742
+ end
2743
+ end
2744
+
2745
+ context 'when collation is not specified' do
2746
+
2747
+ let(:selector) do
2748
+ {name: 'BANG'}
2749
+ end
2750
+
2751
+ let(:result) do
2752
+ authorized_collection.update_many(selector, { '$set' => {other: 'doink'} })
2753
+ end
2754
+
2755
+ before do
2756
+ authorized_collection.insert_one(name: 'bang')
2757
+ authorized_collection.insert_one(name: 'baNG')
2758
+ end
2759
+
2760
+ it 'does not apply the collation' do
2761
+ expect(result.written_count).to eq(0)
2762
+ end
2763
+ end
2764
+
2765
+ context 'when a session is provided' do
2766
+
2767
+ let(:selector) do
2768
+ { name: 'BANG' }
2769
+ end
2770
+
2771
+ let(:operation) do
2772
+ authorized_collection.update_many(selector, { '$set' => {other: 'doink'} }, session: session)
2773
+ end
2774
+
2775
+ before do
2776
+ authorized_collection.insert_one(name: 'bang')
2777
+ authorized_collection.insert_one(name: 'baNG')
2778
+ end
2779
+
2780
+ let(:session) do
2781
+ authorized_client.start_session
2782
+ end
2783
+
2784
+ let(:failed_operation) do
2785
+ authorized_collection.update_many({ '$._id' => 1 }, { '$set' => {other: 'doink'} }, session: session)
2786
+ end
2787
+
2788
+ let(:client) do
2789
+ authorized_client
2790
+ end
2791
+
2792
+ it_behaves_like 'an operation using a session'
2793
+ it_behaves_like 'a failed operation using a session'
2794
+ end
2795
+
2796
+ context 'when unacknowledged writes is used with an explicit session' do
2797
+
2798
+ let(:collection_with_unacknowledged_write_concern) do
2799
+ authorized_collection.with(write: { w: 0 })
2800
+ end
2801
+
2802
+ let(:operation) do
2803
+ collection_with_unacknowledged_write_concern.update_many({a: 1}, { '$set' => {x: 1} }, session: session)
2804
+ end
2805
+
2806
+ it_behaves_like 'an explicit session with an unacknowledged write'
2807
+ end
2808
+
2809
+ context 'when unacknowledged writes is used with an implicit session' do
2810
+
2811
+ let(:collection_with_unacknowledged_write_concern) do
2812
+ client.with(write: { w: 0 })[TEST_COLL]
2813
+ end
2814
+
2815
+ let(:operation) do
2816
+ collection_with_unacknowledged_write_concern.update_many({a: 1}, {'$set' => {x: 1}})
2817
+ end
2818
+
2819
+ it_behaves_like 'an implicit session with an unacknowledged write'
2820
+ end
2821
+
2822
+ context 'when various options passed in' do
2823
+ # w: 2 requires a replica set
2824
+ require_topology :replica_set
2825
+
2826
+ # https://jira.mongodb.org/browse/RUBY-2306
2827
+ min_server_fcv '3.6'
2828
+
2829
+ before do
2830
+ collection.insert_many([{ field: 'test' }, { field: 'test2' }], session: session)
2831
+ end
2832
+
2833
+ let(:session) do
2834
+ authorized_client.start_session
2835
+ end
2836
+
2837
+ let(:collection) do
2838
+ authorized_collection.with(write_concern: {w: 1})
2839
+ end
2840
+
2841
+ let(:events) do
2842
+ subscriber.command_started_events('update')
2843
+ end
2844
+
2845
+ let!(:command) do
2846
+ Utils.get_command_event(authorized_client, 'update') do |client|
2847
+ collection.update_many(selector, {'$set'=> { field: 'testing' }}, session: session,
2848
+ write_concern: {w: 2}, bypass_document_validation: true, upsert: true)
2849
+ end.command
2850
+ end
2851
+
2852
+ it 'updates many successfully with correct options sent to server' do
2853
+ expect(events.length).to eq(1)
2854
+ expect(collection.options[:write_concern]).to eq(w: 1)
2855
+ expect(command[:writeConcern][:w]).to eq(2)
2856
+ expect(command[:bypassDocumentValidation]).to be(true)
2857
+ expect(command[:updates][0][:upsert]).to be(true)
2858
+ end
2859
+ end
2860
+ end
2861
+
2862
+ describe '#update_one' do
2863
+
2864
+ let(:selector) do
2865
+ { field: 'test1' }
2866
+ end
2867
+
2868
+ context 'when a selector was provided' do
2869
+
2870
+ before do
2871
+ authorized_collection.insert_many([{ field: 'test1' }, { field: 'test1' }])
2872
+ end
2873
+
2874
+ let!(:response) do
2875
+ authorized_collection.update_one(selector, '$set'=> { field: 'testing' })
2876
+ end
2877
+
2878
+ let(:updated) do
2879
+ authorized_collection.find(field: 'testing').first
2880
+ end
2881
+
2882
+ it 'updates the first matching document in the collection' do
2883
+ expect(response.modified_count).to eq(1)
2884
+ end
2885
+
2886
+ it 'updates the documents in the collection' do
2887
+ expect(updated[:field]).to eq('testing')
2888
+ end
2889
+ end
2890
+
2891
+ context 'when upsert is false' do
2892
+
2893
+ let(:response) do
2894
+ authorized_collection.update_one(selector, { '$set'=> { field: 'testing' } },
2895
+ upsert: false)
2896
+ end
2897
+
2898
+ let(:updated) do
2899
+ authorized_collection.find.to_a
2900
+ end
2901
+
2902
+ it 'reports that no documents were updated' do
2903
+ expect(response.modified_count).to eq(0)
2904
+ end
2905
+
2906
+ it 'updates no documents in the collection' do
2907
+ expect(updated).to be_empty
2908
+ end
2909
+ end
2910
+
2911
+ context 'when upsert is true' do
2912
+
2913
+ let!(:response) do
2914
+ authorized_collection.update_one(selector, { '$set'=> { field: 'testing' } },
2915
+ upsert: true)
2916
+ end
2917
+
2918
+ let(:updated) do
2919
+ authorized_collection.find.first
2920
+ end
2921
+
2922
+ it 'reports that a document was written' do
2923
+ expect(response.written_count).to eq(1)
2924
+ end
2925
+
2926
+ it 'inserts a document into the collection' do
2927
+ expect(updated[:field]).to eq('testing')
2928
+ end
2929
+ end
2930
+
2931
+ context 'when upsert is not specified' do
2932
+
2933
+ let(:response) do
2934
+ authorized_collection.update_one(selector, { '$set'=> { field: 'testing' } })
2935
+ end
2936
+
2937
+ let(:updated) do
2938
+ authorized_collection.find.to_a
2939
+ end
2940
+
2941
+ it 'reports that no documents were updated' do
2942
+ expect(response.modified_count).to eq(0)
2943
+ end
2944
+
2945
+ it 'updates no documents in the collection' do
2946
+ expect(updated).to be_empty
2947
+ end
2948
+ end
2949
+
2950
+ context 'when the update fails' do
2951
+
2952
+ let(:result) do
2953
+ authorized_collection.update_one(selector, { '$s'=> { field: 'testing' } })
2954
+ end
2955
+
2956
+ it 'raises an OperationFailure' do
2957
+ expect {
2958
+ result
2959
+ }.to raise_exception(Mongo::Error::OperationFailure)
2960
+ end
2961
+ end
2962
+
2963
+ context 'when collection has a validator' do
2964
+ min_server_fcv '3.2'
2965
+
2966
+ around(:each) do |spec|
2967
+ authorized_client[:validating,
2968
+ :validator => { :a => { '$exists' => true } }].tap do |c|
2969
+ c.create
2970
+ end
2971
+ spec.run
2972
+ collection_with_validator.drop
2973
+ end
2974
+
2975
+ before do
2976
+ collection_with_validator.insert_one({ a: 1 })
2977
+ end
2978
+
2979
+ context 'when the document is valid' do
2980
+
2981
+ let(:result) do
2982
+ collection_with_validator.update_one(
2983
+ { :a => { '$gt' => 0 } }, '$inc' => { :a => 1 } )
2984
+ end
2985
+
2986
+ it 'updates successfully' do
2987
+ expect(result.modified_count).to eq(1)
2988
+ end
2989
+ end
2990
+
2991
+ context 'when the document is invalid' do
2992
+
2993
+ context 'when bypass_document_validation is not set' do
2994
+
2995
+ let(:result2) do
2996
+ collection_with_validator.update_one(
2997
+ { :a => { '$gt' => 0 } }, '$unset' => { :a => '' })
2998
+ end
2999
+
3000
+ it 'raises OperationFailure' do
3001
+ expect {
3002
+ result2
3003
+ }.to raise_exception(Mongo::Error::OperationFailure)
3004
+ end
3005
+ end
3006
+
3007
+ context 'when bypass_document_validation is true' do
3008
+
3009
+ let(:result3) do
3010
+ collection_with_validator.update_one(
3011
+ { :a => { '$gt' => 0 } }, { '$unset' => { :a => '' } },
3012
+ :bypass_document_validation => true)
3013
+ end
3014
+
3015
+ it 'updates successfully' do
3016
+ expect(result3.written_count).to eq(1)
3017
+ end
3018
+ end
3019
+ end
3020
+ end
3021
+
3022
+ context 'when there is a collation specified' do
3023
+
3024
+ let(:selector) do
3025
+ { name: 'BANG' }
3026
+ end
3027
+
3028
+ let(:result) do
3029
+ authorized_collection.update_one(selector, { '$set' => { other: 'doink' } }, options)
3030
+ end
3031
+
3032
+ before do
3033
+ authorized_collection.insert_one(name: 'bang')
3034
+ end
3035
+
3036
+ let(:options) do
3037
+ { collation: { locale: 'en_US', strength: 2 } }
3038
+ end
3039
+
3040
+ context 'when the server selected supports collations' do
3041
+ min_server_fcv '3.4'
3042
+
3043
+ it 'applies the collation' do
3044
+ expect(result.written_count).to eq(1)
3045
+ expect(authorized_collection.find(other: 'doink').count).to eq(1)
3046
+ end
3047
+
3048
+ context 'when unacknowledged writes is used' do
3049
+
3050
+ let(:collection_with_unacknowledged_write_concern) do
3051
+ authorized_collection.with(write: { w: 0 })
3052
+ end
3053
+
3054
+ let(:result) do
3055
+ collection_with_unacknowledged_write_concern.update_one(selector, { '$set' => { other: 'doink' } }, options)
3056
+ end
3057
+
3058
+ it 'raises an exception' do
3059
+ expect {
3060
+ result
3061
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
3062
+ end
3063
+
3064
+ context 'when a String key is used' do
3065
+
3066
+ let(:options) do
3067
+ { 'collation' => { locale: 'en_US', strength: 2 } }
3068
+ end
3069
+
3070
+ it 'raises an exception' do
3071
+ expect {
3072
+ result
3073
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
3074
+ end
3075
+ end
3076
+ end
3077
+ end
3078
+
3079
+ context 'when the server selected does not support collations' do
3080
+ max_server_version '3.2'
3081
+
3082
+ it 'raises an exception' do
3083
+ expect {
3084
+ result
3085
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
3086
+ end
3087
+
3088
+ context 'when a String key is used' do
3089
+
3090
+ let(:options) do
3091
+ { 'collation' => { locale: 'en_US', strength: 2 } }
3092
+ end
3093
+
3094
+ it 'raises an exception' do
3095
+ expect {
3096
+ result
3097
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
3098
+ end
3099
+ end
3100
+ end
3101
+ end
3102
+
3103
+ context 'when a collation is not specified' do
3104
+
3105
+ let(:selector) do
3106
+ { name: 'BANG' }
3107
+ end
3108
+
3109
+ let(:result) do
3110
+ authorized_collection.update_one(selector, { '$set' => { other: 'doink' } })
3111
+ end
3112
+
3113
+ before do
3114
+ authorized_collection.insert_one(name: 'bang')
3115
+ end
3116
+
3117
+ it 'does not apply the collation' do
3118
+ expect(result.written_count).to eq(0)
3119
+ end
3120
+ end
3121
+
3122
+
3123
+ context 'when arrayFilters is provided' do
3124
+
3125
+ let(:selector) do
3126
+ { _id: 0}
3127
+ end
3128
+
3129
+ context 'when the server supports arrayFilters' do
3130
+ min_server_fcv '3.6'
3131
+
3132
+ before do
3133
+ authorized_collection.insert_one(_id: 0, x: [{ y: 1 }, { y: 2 }, {y: 3 }])
3134
+ end
3135
+
3136
+ let(:result) do
3137
+ authorized_collection.update_one(selector,
3138
+ { '$set' => { 'x.$[i].y' => 5 } },
3139
+ options)
3140
+ end
3141
+
3142
+ context 'when a Symbol key is used' do
3143
+
3144
+ let(:options) do
3145
+ { array_filters: [{ 'i.y' => 3 }] }
3146
+ end
3147
+
3148
+ it 'applies the arrayFilters' do
3149
+ expect(result.matched_count).to eq(1)
3150
+ expect(result.modified_count).to eq(1)
3151
+ expect(authorized_collection.find(selector).first['x'].last['y']).to eq(5)
3152
+ end
3153
+ end
3154
+
3155
+ context 'when a String key is used' do
3156
+
3157
+ let(:options) do
3158
+ { 'array_filters' => [{ 'i.y' => 3 }] }
3159
+ end
3160
+
3161
+ it 'applies the arrayFilters' do
3162
+ expect(result.matched_count).to eq(1)
3163
+ expect(result.modified_count).to eq(1)
3164
+ expect(authorized_collection.find(selector).first['x'].last['y']).to eq(5)
3165
+ end
3166
+ end
3167
+ end
3168
+
3169
+ context 'when the server does not support arrayFilters' do
3170
+ max_server_version '3.4'
3171
+
3172
+ let(:result) do
3173
+ authorized_collection.update_one(selector,
3174
+ { '$set' => { 'x.$[i].y' => 5 } },
3175
+ options)
3176
+ end
3177
+
3178
+ context 'when a Symbol key is used' do
3179
+
3180
+ let(:options) do
3181
+ { array_filters: [{ 'i.y' => 3 }] }
3182
+ end
3183
+
3184
+ it 'raises an exception' do
3185
+ expect {
3186
+ result
3187
+ }.to raise_exception(Mongo::Error::UnsupportedArrayFilters)
3188
+ end
3189
+ end
3190
+
3191
+ context 'when a String key is used' do
3192
+
3193
+ let(:options) do
3194
+ { 'array_filters' => [{ 'i.y' => 3 }] }
3195
+ end
3196
+
3197
+ it 'raises an exception' do
3198
+ expect {
3199
+ result
3200
+ }.to raise_exception(Mongo::Error::UnsupportedArrayFilters)
3201
+ end
3202
+ end
3203
+ end
3204
+ end
3205
+
3206
+ context 'when the documents are sent with OP_MSG' do
3207
+ min_server_fcv '3.6'
3208
+
3209
+ let(:documents) do
3210
+ [{ '_id' => 1, 'name' => '1'*16777191 }, { '_id' => 'y' }]
3211
+ end
3212
+
3213
+ before do
3214
+ authorized_collection.insert_many([{ field: 'test1' }, { field: 'test1' }])
3215
+ client[TEST_COLL].update_one({ a: 1 }, {'$set' => { 'name' => '1'*16777149 }})
3216
+ end
3217
+
3218
+ let(:update_events) do
3219
+ subscriber.started_events.select { |e| e.command_name == 'update' }
3220
+ end
3221
+
3222
+ it 'sends the documents in one OP_MSG' do
3223
+ expect(update_events.size).to eq(1)
3224
+ end
3225
+ end
3226
+
3227
+ context 'when a session is provided' do
3228
+
3229
+ before do
3230
+ authorized_collection.insert_many([{ field: 'test1' }, { field: 'test1' }])
3231
+ end
3232
+
3233
+ let(:session) do
3234
+ authorized_client.start_session
3235
+ end
3236
+
3237
+ let(:operation) do
3238
+ authorized_collection.update_one({ field: 'test' }, { '$set'=> { field: 'testing' } }, session: session)
3239
+ end
3240
+
3241
+ let(:failed_operation) do
3242
+ authorized_collection.update_one({ '$._id' => 1 }, { '$set'=> { field: 'testing' } }, session: session)
3243
+ end
3244
+
3245
+ let(:client) do
3246
+ authorized_client
3247
+ end
3248
+
3249
+ it_behaves_like 'an operation using a session'
3250
+ it_behaves_like 'a failed operation using a session'
3251
+ end
3252
+
3253
+ context 'when unacknowledged writes is used with an explicit session' do
3254
+
3255
+ let(:collection_with_unacknowledged_write_concern) do
3256
+ authorized_collection.with(write: { w: 0 })
3257
+ end
3258
+
3259
+ let(:operation) do
3260
+ collection_with_unacknowledged_write_concern.update_one({ a: 1 }, { '$set' => { x: 1 } }, session: session)
3261
+ end
3262
+
3263
+ it_behaves_like 'an explicit session with an unacknowledged write'
3264
+ end
3265
+
3266
+ context 'when unacknowledged writes is used with an implicit session' do
3267
+
3268
+ let(:collection_with_unacknowledged_write_concern) do
3269
+ client.with(write: { w: 0 })[TEST_COLL]
3270
+ end
3271
+
3272
+ let(:operation) do
3273
+ collection_with_unacknowledged_write_concern.update_one({ a: 1 }, { '$set' => { x: 1 }})
3274
+ end
3275
+
3276
+ it_behaves_like 'an implicit session with an unacknowledged write'
3277
+ end
3278
+
3279
+ context 'when various options passed in' do
3280
+ # w: 2 requires a replica set
3281
+ require_topology :replica_set
3282
+
3283
+ # https://jira.mongodb.org/browse/RUBY-2306
3284
+ min_server_fcv '3.6'
3285
+
3286
+ before do
3287
+ collection.insert_many([{ field: 'test1' }, { field: 'test2' }], session: session)
3288
+ end
3289
+
3290
+ let(:session) do
3291
+ authorized_client.start_session
3292
+ end
3293
+
3294
+ let(:collection) do
3295
+ authorized_collection.with(write_concern: {w: 1})
3296
+ end
3297
+
3298
+ let(:events) do
3299
+ subscriber.command_started_events('update')
3300
+ end
3301
+
3302
+ let!(:command) do
3303
+ Utils.get_command_event(authorized_client, 'update') do |client|
3304
+ collection.update_one(selector, { '$set'=> { field: 'testing' } }, session: session,
3305
+ write_concern: {w: 2}, bypass_document_validation: true, :return_document => :after,
3306
+ upsert: true)
3307
+ end.command
3308
+ end
3309
+
3310
+ it 'updates one successfully with correct options sent to server' do
3311
+ expect(events.length).to eq(1)
3312
+ expect(command[:writeConcern]).to_not be_nil
3313
+ expect(command[:writeConcern][:w]).to eq(2)
3314
+ expect(collection.options[:write_concern]).to eq(w:1)
3315
+ expect(command[:bypassDocumentValidation]).to be(true)
3316
+ expect(command[:updates][0][:upsert]).to be(true)
3317
+ end
3318
+ end
3319
+ end
3320
+
3321
+ describe '#find_one_and_delete' do
3322
+
3323
+ before do
3324
+ authorized_collection.insert_many([{ field: 'test1' }])
3325
+ end
3326
+
3327
+ let(:selector) do
3328
+ { field: 'test1' }
3329
+ end
3330
+
3331
+ context 'when a matching document is found' do
3332
+
3333
+ context 'when a session is provided' do
3334
+
3335
+ let(:operation) do
3336
+ authorized_collection.find_one_and_delete(selector, session: session)
3337
+ end
3338
+
3339
+ let(:failed_operation) do
3340
+ authorized_collection.find_one_and_delete({ '$._id' => 1 }, session: session)
3341
+ end
3342
+
3343
+ let(:session) do
3344
+ authorized_client.start_session
3345
+ end
3346
+
3347
+ let(:client) do
3348
+ authorized_client
3349
+ end
3350
+
3351
+ it_behaves_like 'an operation using a session'
3352
+ it_behaves_like 'a failed operation using a session'
3353
+ end
3354
+
3355
+ context 'when no options are provided' do
3356
+
3357
+ let!(:document) do
3358
+ authorized_collection.find_one_and_delete(selector)
3359
+ end
3360
+
3361
+ it 'deletes the document from the database' do
3362
+ expect(authorized_collection.find.to_a).to be_empty
3363
+ end
3364
+
3365
+ it 'returns the document' do
3366
+ expect(document['field']).to eq('test1')
3367
+ end
3368
+ end
3369
+
3370
+ context 'when a projection is provided' do
3371
+
3372
+ let!(:document) do
3373
+ authorized_collection.find_one_and_delete(selector, projection: { _id: 1 })
3374
+ end
3375
+
3376
+ it 'deletes the document from the database' do
3377
+ expect(authorized_collection.find.to_a).to be_empty
3378
+ end
3379
+
3380
+ it 'returns the document with limited fields' do
3381
+ expect(document['field']).to be_nil
3382
+ expect(document['_id']).to_not be_nil
3383
+ end
3384
+ end
3385
+
3386
+ context 'when a sort is provided' do
3387
+
3388
+ let!(:document) do
3389
+ authorized_collection.find_one_and_delete(selector, sort: { field: 1 })
3390
+ end
3391
+
3392
+ it 'deletes the document from the database' do
3393
+ expect(authorized_collection.find.to_a).to be_empty
3394
+ end
3395
+
3396
+ it 'returns the document with limited fields' do
3397
+ expect(document['field']).to eq('test1')
3398
+ end
3399
+ end
3400
+
3401
+ context 'when max_time_ms is provided' do
3402
+
3403
+ it 'includes the max_time_ms value in the command' do
3404
+ expect {
3405
+ authorized_collection.find_one_and_delete(selector, max_time_ms: 0.1)
3406
+ }.to raise_error(Mongo::Error::OperationFailure)
3407
+ end
3408
+ end
3409
+ end
3410
+
3411
+ context 'when no matching document is found' do
3412
+
3413
+ let(:selector) do
3414
+ { field: 'test5' }
3415
+ end
3416
+
3417
+ let!(:document) do
3418
+ authorized_collection.find_one_and_delete(selector)
3419
+ end
3420
+
3421
+ it 'returns nil' do
3422
+ expect(document).to be_nil
3423
+ end
3424
+ end
3425
+
3426
+ context 'when the operation fails' do
3427
+
3428
+ let(:result) do
3429
+ authorized_collection.find_one_and_delete(selector, max_time_ms: 0.1)
3430
+ end
3431
+
3432
+ it 'raises an OperationFailure' do
3433
+ expect {
3434
+ result
3435
+ }.to raise_exception(Mongo::Error::OperationFailure)
3436
+ end
3437
+ end
3438
+
3439
+ context 'when write_concern is provided' do
3440
+ min_server_fcv '3.2'
3441
+ require_topology :single
3442
+
3443
+ it 'uses the write concern' do
3444
+ expect {
3445
+ authorized_collection.find_one_and_delete(selector,
3446
+ write_concern: { w: 2 })
3447
+ }.to raise_error(Mongo::Error::OperationFailure)
3448
+ end
3449
+ end
3450
+
3451
+ context 'when the collection has a write concern' do
3452
+ min_server_fcv '3.2'
3453
+ require_topology :single
3454
+
3455
+ let(:collection) do
3456
+ authorized_collection.with(write: { w: 2 })
3457
+ end
3458
+
3459
+ it 'uses the write concern' do
3460
+ expect {
3461
+ collection.find_one_and_delete(selector,
3462
+ write_concern: { w: 2 })
3463
+ }.to raise_error(Mongo::Error::OperationFailure)
3464
+ end
3465
+ end
3466
+
3467
+ context 'when collation is specified' do
3468
+
3469
+ let(:selector) do
3470
+ { name: 'BANG' }
3471
+ end
3472
+
3473
+ let(:result) do
3474
+ authorized_collection.find_one_and_delete(selector, options)
3475
+ end
3476
+
3477
+ before do
3478
+ authorized_collection.insert_one(name: 'bang')
3479
+ end
3480
+
3481
+ let(:options) do
3482
+ { collation: { locale: 'en_US', strength: 2 } }
3483
+ end
3484
+
3485
+ context 'when the server selected supports collations' do
3486
+ min_server_fcv '3.4'
3487
+
3488
+ it 'applies the collation' do
3489
+ expect(result['name']).to eq('bang')
3490
+ expect(authorized_collection.find(name: 'bang').count).to eq(0)
3491
+ end
3492
+ end
3493
+
3494
+ context 'when the server selected does not support collations' do
3495
+ max_server_version '3.2'
3496
+
3497
+ it 'raises an exception' do
3498
+ expect {
3499
+ result
3500
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
3501
+ end
3502
+
3503
+ context 'when a String key is used' do
3504
+
3505
+ let(:options) do
3506
+ { 'collation' => { locale: 'en_US', strength: 2 } }
3507
+ end
3508
+
3509
+ it 'raises an exception' do
3510
+ expect {
3511
+ result
3512
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
3513
+ end
3514
+ end
3515
+ end
3516
+ end
3517
+
3518
+ context 'when collation is not specified' do
3519
+
3520
+ let(:selector) do
3521
+ { name: 'BANG' }
3522
+ end
3523
+
3524
+ let(:result) do
3525
+ authorized_collection.find_one_and_delete(selector)
3526
+ end
3527
+
3528
+ before do
3529
+ authorized_collection.insert_one(name: 'bang')
3530
+ end
3531
+
3532
+ it 'does not apply the collation' do
3533
+ expect(result).to be_nil
3534
+ end
3535
+ end
3536
+
3537
+ context 'when various options passed in' do
3538
+ # w: 2 requires a replica set
3539
+ require_topology :replica_set
3540
+
3541
+ # https://jira.mongodb.org/browse/RUBY-2306
3542
+ min_server_fcv '3.6'
3543
+
3544
+ before do
3545
+ authorized_collection.delete_many
3546
+ authorized_collection.insert_many([{ name: 'test1' }, { name: 'test2' }])
3547
+ end
3548
+
3549
+ let(:collection) do
3550
+ authorized_collection.with(write_concern: {w: 2})
3551
+ end
3552
+
3553
+ let(:session) do
3554
+ authorized_client.start_session
3555
+ end
3556
+
3557
+ let!(:command) do
3558
+ Utils.get_command_event(authorized_client, 'findAndModify') do |client|
3559
+ collection.find_one_and_delete(selector, session: session, write_concern: {w: 2},
3560
+ bypass_document_validation: true, max_time_ms: 300)
3561
+ end.command
3562
+ end
3563
+
3564
+ let(:events) do
3565
+ subscriber.command_started_events('findAndModify')
3566
+ end
3567
+
3568
+ it 'finds and deletes successfully with correct options sent to server' do
3569
+ expect(events.length).to eq(1)
3570
+ expect(command[:writeConcern]).to_not be_nil
3571
+ expect(command[:writeConcern][:w]).to eq(2)
3572
+ expect(command[:bypassDocumentValidation]).to eq(true)
3573
+ expect(command[:maxTimeMS]).to eq(300)
3574
+ end
3575
+ end
3576
+ end
3577
+
3578
+ describe '#find_one_and_update' do
3579
+
3580
+ let(:selector) do
3581
+ { field: 'test1' }
3582
+ end
3583
+
3584
+ before do
3585
+ authorized_collection.insert_many([{ field: 'test1' }])
3586
+ end
3587
+
3588
+ context 'when a matching document is found' do
3589
+
3590
+ context 'when no options are provided' do
3591
+
3592
+ let(:document) do
3593
+ authorized_collection.find_one_and_update(selector, { '$set' => { field: 'testing' }})
3594
+ end
3595
+
3596
+ it 'returns the original document' do
3597
+ expect(document['field']).to eq('test1')
3598
+ end
3599
+ end
3600
+
3601
+ context 'when a session is provided' do
3602
+
3603
+ let(:operation) do
3604
+ authorized_collection.find_one_and_update(selector, { '$set' => { field: 'testing' }}, session: session)
3605
+ end
3606
+
3607
+ let(:failed_operation) do
3608
+ authorized_collection.find_one_and_update({ '$._id' => 1 }, { '$set' => { field: 'testing' }}, session: session)
3609
+ end
3610
+
3611
+ let(:session) do
3612
+ authorized_client.start_session
3613
+ end
3614
+
3615
+ let(:client) do
3616
+ authorized_client
3617
+ end
3618
+
3619
+ it_behaves_like 'an operation using a session'
3620
+ it_behaves_like 'a failed operation using a session'
3621
+ end
3622
+
3623
+ context 'when no options are provided' do
3624
+
3625
+ let(:document) do
3626
+ authorized_collection.find_one_and_update(selector, { '$set' => { field: 'testing' }})
3627
+ end
3628
+
3629
+ it 'returns the original document' do
3630
+ expect(document['field']).to eq('test1')
3631
+ end
3632
+ end
3633
+
3634
+ context 'when return_document options are provided' do
3635
+
3636
+ context 'when return_document is :after' do
3637
+
3638
+ let(:document) do
3639
+ authorized_collection.find_one_and_update(selector, { '$set' => { field: 'testing' }}, :return_document => :after)
3640
+ end
3641
+
3642
+ it 'returns the new document' do
3643
+ expect(document['field']).to eq('testing')
3644
+ end
3645
+ end
3646
+
3647
+ context 'when return_document is :before' do
3648
+
3649
+ let(:document) do
3650
+ authorized_collection.find_one_and_update(selector, { '$set' => { field: 'testing' }}, :return_document => :before)
3651
+ end
3652
+
3653
+ it 'returns the original document' do
3654
+ expect(document['field']).to eq('test1')
3655
+ end
3656
+ end
3657
+ end
3658
+
3659
+ context 'when a projection is provided' do
3660
+
3661
+ let(:document) do
3662
+ authorized_collection.find_one_and_update(selector, { '$set' => { field: 'testing' }}, projection: { _id: 1 })
3663
+ end
3664
+
3665
+ it 'returns the document with limited fields' do
3666
+ expect(document['field']).to be_nil
3667
+ expect(document['_id']).to_not be_nil
3668
+ end
3669
+ end
3670
+
3671
+ context 'when a sort is provided' do
3672
+
3673
+ let(:document) do
3674
+ authorized_collection.find_one_and_update(selector, { '$set' => { field: 'testing' }}, sort: { field: 1 })
3675
+ end
3676
+
3677
+ it 'returns the original document' do
3678
+ expect(document['field']).to eq('test1')
3679
+ end
3680
+ end
3681
+ end
3682
+
3683
+ context 'when max_time_ms is provided' do
3684
+
3685
+ it 'includes the max_time_ms value in the command' do
3686
+ expect {
3687
+ authorized_collection.find_one_and_update(selector, { '$set' => { field: 'testing' }}, max_time_ms: 0.1)
3688
+ }.to raise_error(Mongo::Error::OperationFailure)
3689
+ end
3690
+ end
3691
+
3692
+ context 'when no matching document is found' do
3693
+
3694
+ let(:selector) do
3695
+ { field: 'test5' }
3696
+ end
3697
+
3698
+ let(:document) do
3699
+ authorized_collection.find_one_and_update(selector, { '$set' => { field: 'testing' }})
3700
+ end
3701
+
3702
+ it 'returns nil' do
3703
+ expect(document).to be_nil
3704
+ end
3705
+ end
3706
+
3707
+ context 'when no matching document is found' do
3708
+
3709
+ context 'when no upsert options are provided' do
3710
+
3711
+ let(:selector) do
3712
+ { field: 'test5' }
3713
+ end
3714
+
3715
+ let(:document) do
3716
+ authorized_collection.find_one_and_update(selector, { '$set' => { field: 'testing' }})
3717
+ end
3718
+
3719
+ it 'returns nil' do
3720
+ expect(document).to be_nil
3721
+ end
3722
+ end
3723
+
3724
+ context 'when upsert options are provided' do
3725
+
3726
+ let(:selector) do
3727
+ { field: 'test5' }
3728
+ end
3729
+
3730
+ let(:document) do
3731
+ authorized_collection.find_one_and_update(selector, { '$set' => { field: 'testing' }}, :upsert => true, :return_document => :after)
3732
+ end
3733
+
3734
+ it 'returns the new document' do
3735
+ expect(document['field']).to eq('testing')
3736
+ end
3737
+ end
3738
+ end
3739
+
3740
+ context 'when the operation fails' do
3741
+
3742
+ let(:result) do
3743
+ authorized_collection.find_one_and_update(selector, { '$set' => { field: 'testing' }}, max_time_ms: 0.1)
3744
+ end
3745
+
3746
+ it 'raises an OperationFailure' do
3747
+ expect {
3748
+ result
3749
+ }.to raise_exception(Mongo::Error::OperationFailure)
3750
+ end
3751
+ end
3752
+
3753
+ context 'when collection has a validator' do
3754
+ min_server_fcv '3.2'
3755
+
3756
+ around(:each) do |spec|
3757
+ authorized_client[:validating].drop
3758
+ authorized_client[:validating,
3759
+ :validator => { :a => { '$exists' => true } }].tap do |c|
3760
+ c.create
3761
+ end
3762
+ spec.run
3763
+ collection_with_validator.drop
3764
+ end
3765
+
3766
+ before do
3767
+ collection_with_validator.insert_one({ a: 1 })
3768
+ end
3769
+
3770
+ context 'when the document is valid' do
3771
+
3772
+ let(:result) do
3773
+ collection_with_validator.find_one_and_update(
3774
+ { a: 1 }, { '$inc' => { :a => 1 } }, :return_document => :after)
3775
+ end
3776
+
3777
+ it 'updates successfully' do
3778
+ expect(result['a']).to eq(2)
3779
+ end
3780
+ end
3781
+
3782
+ context 'when the document is invalid' do
3783
+
3784
+ context 'when bypass_document_validation is not set' do
3785
+
3786
+ let(:result2) do
3787
+ collection_with_validator.find_one_and_update(
3788
+ { a: 1 }, { '$unset' => { :a => '' } }, :return_document => :after)
3789
+ end
3790
+
3791
+ it 'raises OperationFailure' do
3792
+ expect {
3793
+ result2
3794
+ }.to raise_exception(Mongo::Error::OperationFailure)
3795
+ end
3796
+ end
3797
+
3798
+ context 'when bypass_document_validation is true' do
3799
+
3800
+ let(:result3) do
3801
+ collection_with_validator.find_one_and_update(
3802
+ { a: 1 }, { '$unset' => { :a => '' } },
3803
+ :bypass_document_validation => true,
3804
+ :return_document => :after)
3805
+ end
3806
+
3807
+ it 'updates successfully' do
3808
+ expect(result3['a']).to be_nil
3809
+ end
3810
+ end
3811
+ end
3812
+ end
3813
+
3814
+ context 'when write_concern is provided' do
3815
+ min_server_fcv '3.2'
3816
+ require_topology :single
3817
+
3818
+ it 'uses the write concern' do
3819
+ expect {
3820
+ authorized_collection.find_one_and_update(selector,
3821
+ { '$set' => { field: 'testing' }},
3822
+ write_concern: { w: 2 })
3823
+ }.to raise_error(Mongo::Error::OperationFailure)
3824
+ end
3825
+ end
3826
+
3827
+ context 'when the collection has a write concern' do
3828
+ min_server_fcv '3.2'
3829
+ require_topology :single
3830
+
3831
+ let(:collection) do
3832
+ authorized_collection.with(write: { w: 2 })
3833
+ end
3834
+
3835
+ it 'uses the write concern' do
3836
+ expect {
3837
+ collection.find_one_and_update(selector,
3838
+ { '$set' => { field: 'testing' }},
3839
+ write_concern: { w: 2 })
3840
+ }.to raise_error(Mongo::Error::OperationFailure)
3841
+ end
3842
+ end
3843
+
3844
+ context 'when a collation is specified' do
3845
+
3846
+ let(:selector) do
3847
+ { name: 'BANG' }
3848
+ end
3849
+
3850
+ let(:result) do
3851
+ authorized_collection.find_one_and_update(selector,
3852
+ { '$set' => { other: 'doink' } },
3853
+ options)
3854
+ end
3855
+
3856
+ before do
3857
+ authorized_collection.insert_one(name: 'bang')
3858
+ end
3859
+
3860
+ let(:options) do
3861
+ { collation: { locale: 'en_US', strength: 2 } }
3862
+ end
3863
+
3864
+ context 'when the server selected supports collations' do
3865
+ min_server_fcv '3.4'
3866
+
3867
+ it 'applies the collation' do
3868
+ expect(result['name']).to eq('bang')
3869
+ expect(authorized_collection.find({ name: 'bang' }, limit: -1).first['other']).to eq('doink')
3870
+ end
3871
+ end
3872
+
3873
+ context 'when the server selected does not support collations' do
3874
+ max_server_version '3.2'
3875
+
3876
+ it 'raises an exception' do
3877
+ expect {
3878
+ result
3879
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
3880
+ end
3881
+
3882
+ context 'when a String key is used' do
3883
+
3884
+ let(:options) do
3885
+ { 'collation' => { locale: 'en_US', strength: 2 } }
3886
+ end
3887
+
3888
+ it 'raises an exception' do
3889
+ expect {
3890
+ result
3891
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
3892
+ end
3893
+ end
3894
+ end
3895
+ end
3896
+
3897
+ context 'when there is no collation specified' do
3898
+
3899
+ let(:selector) do
3900
+ { name: 'BANG' }
3901
+ end
3902
+
3903
+ let(:result) do
3904
+ authorized_collection.find_one_and_update(selector, { '$set' => { other: 'doink' } })
3905
+ end
3906
+
3907
+ before do
3908
+ authorized_collection.insert_one(name: 'bang')
3909
+ end
3910
+
3911
+ it 'does not apply the collation' do
3912
+ expect(result).to be_nil
3913
+ end
3914
+ end
3915
+
3916
+ context 'when arrayFilters is provided' do
3917
+
3918
+ let(:selector) do
3919
+ { _id: 0 }
3920
+ end
3921
+
3922
+ context 'when the server supports arrayFilters' do
3923
+ min_server_fcv '3.6'
3924
+
3925
+ before do
3926
+ authorized_collection.insert_one(_id: 0, x: [{ y: 1 }, { y: 2 }, { y: 3 }])
3927
+ end
3928
+
3929
+ let(:result) do
3930
+ authorized_collection.find_one_and_update(selector,
3931
+ { '$set' => { 'x.$[i].y' => 5 } },
3932
+ options)
3933
+ end
3934
+
3935
+ context 'when a Symbol key is used' do
3936
+
3937
+ let(:options) do
3938
+ { array_filters: [{ 'i.y' => 3 }] }
3939
+ end
3940
+
3941
+
3942
+ it 'applies the arrayFilters' do
3943
+ expect(result['x']).to eq([{ 'y' => 1 }, { 'y' => 2 }, { 'y' => 3 }])
3944
+ expect(authorized_collection.find(selector).first['x'].last['y']).to eq(5)
3945
+ end
3946
+ end
3947
+
3948
+ context 'when a String key is used' do
3949
+
3950
+ let(:options) do
3951
+ { 'array_filters' => [{ 'i.y' => 3 }] }
3952
+ end
3953
+
3954
+ it 'applies the arrayFilters' do
3955
+ expect(result['x']).to eq([{ 'y' => 1 }, { 'y' => 2 }, { 'y' => 3 }])
3956
+ expect(authorized_collection.find(selector).first['x'].last['y']).to eq(5)
3957
+ end
3958
+ end
3959
+ end
3960
+
3961
+ context 'when the server selected does not support arrayFilters' do
3962
+ max_server_version '3.4'
3963
+
3964
+ let(:result) do
3965
+ authorized_collection.find_one_and_update(selector,
3966
+ { '$set' => { 'x.$[i].y' => 5 } },
3967
+ options)
3968
+ end
3969
+
3970
+ context 'when a Symbol key is used' do
3971
+
3972
+ let(:options) do
3973
+ { array_filters: [{ 'i.y' => 3 }] }
3974
+ end
3975
+
3976
+ it 'raises an exception' do
3977
+ expect {
3978
+ result
3979
+ }.to raise_exception(Mongo::Error::UnsupportedArrayFilters)
3980
+ end
3981
+ end
3982
+
3983
+ context 'when a String key is used' do
3984
+
3985
+ let(:options) do
3986
+ { 'array_filters' => [{ 'i.y' => 3 }] }
3987
+ end
3988
+
3989
+ it 'raises an exception' do
3990
+ expect {
3991
+ result
3992
+ }.to raise_exception(Mongo::Error::UnsupportedArrayFilters)
3993
+ end
3994
+ end
3995
+ end
3996
+ end
3997
+
3998
+ context 'when various options passed in' do
3999
+ # w: 2 requires a replica set
4000
+ require_topology :replica_set
4001
+
4002
+ # https://jira.mongodb.org/browse/RUBY-2306
4003
+ min_server_fcv '3.6'
4004
+
4005
+ let(:session) do
4006
+ authorized_client.start_session
4007
+ end
4008
+
4009
+ let(:events) do
4010
+ subscriber.command_started_events('findAndModify')
4011
+ end
4012
+
4013
+ let(:collection) do
4014
+ authorized_collection.with(write_concern: {w: 2})
4015
+ end
4016
+
4017
+ let(:selector) do
4018
+ {field: 'test1'}
4019
+ end
4020
+
4021
+ before do
4022
+ collection.insert_one({field: 'test1'}, session: session)
4023
+ end
4024
+
4025
+ let!(:command) do
4026
+ Utils.get_command_event(authorized_client, 'findAndModify') do |client|
4027
+ collection.find_one_and_update(selector, { '$set' => {field: 'testing'}},
4028
+ :return_document => :after, write_concern: {w: 1}, upsert: true,
4029
+ bypass_document_validation: true, max_time_ms: 100, session: session)
4030
+ end.command
4031
+ end
4032
+
4033
+ it 'find and updates successfully with correct options sent to server' do
4034
+ expect(events.length).to eq(1)
4035
+ expect(command[:writeConcern]).to_not be_nil
4036
+ expect(command[:writeConcern][:w]).to eq(1)
4037
+ expect(command[:upsert]).to eq(true)
4038
+ expect(command[:bypassDocumentValidation]).to be(true)
4039
+ expect(command[:maxTimeMS]).to eq(100)
4040
+ end
4041
+ end
4042
+ end
4043
+
4044
+ describe '#find_one_and_replace' do
4045
+
4046
+ before do
4047
+ authorized_collection.insert_many([{ field: 'test1', other: 'sth' }])
4048
+ end
4049
+
4050
+ let(:selector) do
4051
+ { field: 'test1' }
4052
+ end
4053
+
4054
+ context 'when a matching document is found' do
4055
+
4056
+ context 'when no options are provided' do
4057
+
4058
+ let(:document) do
4059
+ authorized_collection.find_one_and_replace(selector, { field: 'testing' })
4060
+ end
4061
+
4062
+ it 'returns the original document' do
4063
+ expect(document['field']).to eq('test1')
4064
+ end
4065
+ end
4066
+
4067
+ context 'when a session is provided' do
4068
+
4069
+ let(:operation) do
4070
+ authorized_collection.find_one_and_replace(selector, { field: 'testing' }, session: session)
4071
+ end
4072
+
4073
+ let(:failed_operation) do
4074
+ authorized_collection.find_one_and_replace({ '$._id' => 1}, { field: 'testing' }, session: session)
4075
+ end
4076
+
4077
+ let(:session) do
4078
+ authorized_client.start_session
4079
+ end
4080
+
4081
+ let(:client) do
4082
+ authorized_client
4083
+ end
4084
+
4085
+ it_behaves_like 'an operation using a session'
4086
+ it_behaves_like 'a failed operation using a session'
4087
+ end
4088
+
4089
+ context 'when return_document options are provided' do
4090
+
4091
+ context 'when return_document is :after' do
4092
+
4093
+ let(:document) do
4094
+ authorized_collection.find_one_and_replace(selector, { field: 'testing' }, :return_document => :after)
4095
+ end
4096
+
4097
+ it 'returns the new document' do
4098
+ expect(document['field']).to eq('testing')
4099
+ end
4100
+ end
4101
+
4102
+ context 'when return_document is :before' do
4103
+
4104
+ let(:document) do
4105
+ authorized_collection.find_one_and_replace(selector, { field: 'testing' }, :return_document => :before)
4106
+ end
4107
+
4108
+ it 'returns the original document' do
4109
+ expect(document['field']).to eq('test1')
4110
+ end
4111
+ end
4112
+ end
4113
+
4114
+ context 'when a projection is provided' do
4115
+
4116
+ let(:document) do
4117
+ authorized_collection.find_one_and_replace(selector, { field: 'testing' }, projection: { _id: 1 })
4118
+ end
4119
+
4120
+ it 'returns the document with limited fields' do
4121
+ expect(document['field']).to be_nil
4122
+ expect(document['_id']).to_not be_nil
4123
+ end
4124
+ end
4125
+
4126
+ context 'when a sort is provided' do
4127
+
4128
+ let(:document) do
4129
+ authorized_collection.find_one_and_replace(selector, { field: 'testing' }, :sort => { field: 1 })
4130
+ end
4131
+
4132
+ it 'returns the original document' do
4133
+ expect(document['field']).to eq('test1')
4134
+ end
4135
+ end
4136
+ end
4137
+
4138
+ context 'when no matching document is found' do
4139
+
4140
+ context 'when no upsert options are provided' do
4141
+
4142
+ let(:selector) do
4143
+ { field: 'test5' }
4144
+ end
4145
+
4146
+ let(:document) do
4147
+ authorized_collection.find_one_and_replace(selector, { field: 'testing' })
4148
+ end
4149
+
4150
+ it 'returns nil' do
4151
+ expect(document).to be_nil
4152
+ end
4153
+ end
4154
+
4155
+ context 'when upsert options are provided' do
4156
+
4157
+ let(:selector) do
4158
+ { field: 'test5' }
4159
+ end
4160
+
4161
+ let(:document) do
4162
+ authorized_collection.find_one_and_replace(selector, { field: 'testing' }, :upsert => true, :return_document => :after)
4163
+ end
4164
+
4165
+ it 'returns the new document' do
4166
+ expect(document['field']).to eq('testing')
4167
+ end
4168
+ end
4169
+ end
4170
+
4171
+ context 'when max_time_ms is provided' do
4172
+
4173
+ it 'includes the max_time_ms value in the command' do
4174
+ expect {
4175
+ authorized_collection.find_one_and_replace(selector, { field: 'testing' }, max_time_ms: 0.1)
4176
+ }.to raise_error(Mongo::Error::OperationFailure)
4177
+ end
4178
+ end
4179
+
4180
+ context 'when the operation fails' do
4181
+
4182
+ let(:result) do
4183
+ authorized_collection.find_one_and_replace(selector, { field: 'testing' }, max_time_ms: 0.1)
4184
+ end
4185
+
4186
+ it 'raises an OperationFailure' do
4187
+ expect {
4188
+ result
4189
+ }.to raise_exception(Mongo::Error::OperationFailure)
4190
+ end
4191
+ end
4192
+
4193
+ context 'when collection has a validator' do
4194
+ min_server_fcv '3.2'
4195
+
4196
+ around(:each) do |spec|
4197
+ authorized_client[:validating].drop
4198
+ authorized_client[:validating,
4199
+ :validator => { :a => { '$exists' => true } }].tap do |c|
4200
+ c.create
4201
+ end
4202
+ spec.run
4203
+ collection_with_validator.drop
4204
+ end
4205
+
4206
+ before do
4207
+ collection_with_validator.insert_one({ a: 1 })
4208
+ end
4209
+
4210
+ context 'when the document is valid' do
4211
+
4212
+ let(:result) do
4213
+ collection_with_validator.find_one_and_replace(
4214
+ { a: 1 }, { a: 5 }, :return_document => :after)
4215
+ end
4216
+
4217
+ it 'replaces successfully when document is valid' do
4218
+ expect(result[:a]).to eq(5)
4219
+ end
4220
+ end
4221
+
4222
+ context 'when the document is invalid' do
4223
+
4224
+ context 'when bypass_document_validation is not set' do
4225
+
4226
+ let(:result2) do
4227
+ collection_with_validator.find_one_and_replace(
4228
+ { a: 1 }, { x: 5 }, :return_document => :after)
4229
+ end
4230
+
4231
+ it 'raises OperationFailure' do
4232
+ expect {
4233
+ result2
4234
+ }.to raise_exception(Mongo::Error::OperationFailure)
4235
+ end
4236
+ end
4237
+
4238
+ context 'when bypass_document_validation is true' do
4239
+
4240
+ let(:result3) do
4241
+ collection_with_validator.find_one_and_replace(
4242
+ { a: 1 }, { x: 1 }, :bypass_document_validation => true,
4243
+ :return_document => :after)
4244
+ end
4245
+
4246
+ it 'replaces successfully' do
4247
+ expect(result3[:x]).to eq(1)
4248
+ expect(result3[:a]).to be_nil
4249
+ end
4250
+ end
4251
+ end
4252
+ end
4253
+
4254
+ context 'when write_concern is provided' do
4255
+ min_server_fcv '3.2'
4256
+ require_topology :single
4257
+
4258
+ it 'uses the write concern' do
4259
+ expect {
4260
+ authorized_collection.find_one_and_replace(selector,
4261
+ { field: 'testing' },
4262
+ write_concern: { w: 2 })
4263
+ }.to raise_error(Mongo::Error::OperationFailure)
4264
+ end
4265
+ end
4266
+
4267
+ context 'when the collection has a write concern' do
4268
+ min_server_fcv '3.2'
4269
+ require_topology :single
4270
+
4271
+ let(:collection) do
4272
+ authorized_collection.with(write: { w: 2 })
4273
+ end
4274
+
4275
+ it 'uses the write concern' do
4276
+ expect {
4277
+ collection.find_one_and_replace(selector,
4278
+ { field: 'testing' },
4279
+ write_concern: { w: 2 })
4280
+ }.to raise_error(Mongo::Error::OperationFailure)
4281
+ end
4282
+ end
4283
+
4284
+ context 'when collation is provided' do
4285
+
4286
+ let(:selector) do
4287
+ { name: 'BANG' }
4288
+ end
4289
+
4290
+ let(:result) do
4291
+ authorized_collection.find_one_and_replace(selector,
4292
+ { name: 'doink' },
4293
+ options)
4294
+ end
4295
+
4296
+ before do
4297
+ authorized_collection.insert_one(name: 'bang')
4298
+ end
4299
+
4300
+ let(:options) do
4301
+ { collation: { locale: 'en_US', strength: 2 } }
4302
+ end
4303
+
4304
+ context 'when the server selected supports collations' do
4305
+ min_server_fcv '3.4'
4306
+
4307
+ it 'applies the collation' do
4308
+ expect(result['name']).to eq('bang')
4309
+ expect(authorized_collection.find(name: 'doink').count).to eq(1)
4310
+ end
4311
+ end
4312
+
4313
+ context 'when the server selected does not support collations' do
4314
+ max_server_version '3.2'
4315
+
4316
+ it 'raises an exception' do
4317
+ expect {
4318
+ result
4319
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
4320
+ end
4321
+
4322
+ context 'when a String key is used' do
4323
+
4324
+ let(:options) do
4325
+ { 'collation' => { locale: 'en_US', strength: 2 } }
4326
+ end
4327
+
4328
+ it 'raises an exception' do
4329
+ expect {
4330
+ result
4331
+ }.to raise_exception(Mongo::Error::UnsupportedCollation)
4332
+ end
4333
+ end
4334
+ end
4335
+ end
4336
+
4337
+ context 'when collation is not specified' do
4338
+
4339
+ let(:selector) do
4340
+ { name: 'BANG' }
4341
+ end
4342
+
4343
+ let(:result) do
4344
+ authorized_collection.find_one_and_replace(selector, { name: 'doink' })
4345
+ end
4346
+
4347
+ before do
4348
+ authorized_collection.insert_one(name: 'bang')
4349
+ end
4350
+
4351
+ it 'does not apply the collation' do
4352
+ expect(result).to be_nil
4353
+ end
4354
+ end
4355
+
4356
+ context 'when various options passed in' do
4357
+ # https://jira.mongodb.org/browse/RUBY-2306
4358
+ min_server_fcv '3.6'
4359
+
4360
+ before do
4361
+ authorized_collection.insert_one({field: 'test1'})
4362
+ end
4363
+
4364
+ let(:session) do
4365
+ authorized_client.start_session
4366
+ end
4367
+
4368
+ let(:events) do
4369
+ subscriber.command_started_events('findAndModify')
4370
+ end
4371
+
4372
+ let(:collection) do
4373
+ authorized_collection.with(write_concern: { w: 2 })
4374
+ end
4375
+
4376
+ let!(:command) do
4377
+ Utils.get_command_event(authorized_client, 'findAndModify') do |client|
4378
+ collection.find_one_and_replace(selector, { '$set' => {field: 'test5'}},
4379
+ :return_document => :after, write_concern: {w: 1}, session: session,
4380
+ upsert: true, bypass_document_validation: false, max_time_ms: 200)
4381
+ end.command
4382
+ end
4383
+
4384
+ it 'find and replaces successfully with correct options sent to server' do
4385
+ expect(events.length).to eq(1)
4386
+ expect(command[:writeConcern]).to_not be_nil
4387
+ expect(command[:writeConcern][:w]).to eq(1)
4388
+ expect(command[:upsert]).to be(true)
4389
+ expect(command[:bypassDocumentValidation]).to be false
4390
+ expect(command[:maxTimeMS]).to eq(200)
4391
+ end
4392
+ end
4393
+ end
4394
+
4395
+ context 'when unacknowledged writes is used on find_one_and_update' do
4396
+
4397
+ let(:selector) do
4398
+ { name: 'BANG' }
4399
+ end
4400
+
4401
+ let(:collection_with_unacknowledged_write_concern) do
4402
+ authorized_collection.with(write: { w: 0 })
4403
+ end
4404
+
4405
+ let(:result) do
4406
+ collection_with_unacknowledged_write_concern.find_one_and_update(selector,
4407
+ { '$set' => { field: 'testing' }},
4408
+ write_concern: { w: 0 })
4409
+ end
4410
+
4411
+ it 'does not raise an exception' do
4412
+ expect(result).to be_nil
4413
+ end
4414
+ end
4415
+ end