mongo 1.8.6 → 2.15.1

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