mongo 2.6.2 → 2.16.0

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