mongo 2.10.5 → 2.15.1

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