mongo 2.10.5 → 2.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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