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,68 +1,14 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
1
4
  require 'spec_helper'
2
5
 
3
6
  describe Mongo::Client do
4
- before do
5
- ClientRegistry.instance.close_all_clients
6
- end
7
-
8
- describe '.new' do
9
- describe 'options' do
10
- describe 'read' do
11
- [
12
- :primary, :primary_preferred, :secondary, :secondary_preferred, :nearest
13
- ].each do |sym|
14
- it "accepts #{sym} as symbol" do
15
- client = new_local_client_nmio(['127.0.0.1:27017'],
16
- :read => {:mode => sym})
17
- # the key got converted to a string here
18
- expect(client.read_preference).to eq({'mode' => sym})
19
- end
20
-
21
- # string keys are not documented as being allowed
22
- # but the code accepts them
23
- it "accepts #{sym} as string" do
24
- client = new_local_client_nmio(['127.0.0.1:27017'],
25
- :read => {:mode => sym.to_s})
26
- # the key got converted to a string here
27
- # the value remains a string
28
- expect(client.read_preference).to eq({'mode' => sym.to_s})
29
- end
30
- end
31
-
32
- context 'when not linting' do
33
- skip_if_linting
34
-
35
- it 'rejects bogus read preference as symbol' do
36
- expect do
37
- client = new_local_client_nmio(['127.0.0.1:27017'],
38
- :read => {:mode => :bogus})
39
- end.to raise_error(Mongo::Error::InvalidReadOption, 'Invalid read option: {"mode"=>:bogus}: mode bogus is not one of recognized modes')
40
- end
41
-
42
- it 'rejects bogus read preference as string' do
43
- expect do
44
- client = new_local_client_nmio(['127.0.0.1:27017'],
45
- :read => {:mode => 'bogus'})
46
- end.to raise_error(Mongo::Error::InvalidReadOption, 'Invalid read option: {"mode"=>"bogus"}: mode bogus is not one of recognized modes')
47
- end
48
-
49
- it 'rejects read option specified as a string' do
50
- expect do
51
- client = new_local_client_nmio(['127.0.0.1:27017'],
52
- :read => 'primary')
53
- end.to raise_error(Mongo::Error::InvalidReadOption, 'Invalid read option: primary: must be a hash')
54
- end
7
+ clean_slate
55
8
 
56
- it 'rejects read option specified as a symbol' do
57
- expect do
58
- client = new_local_client_nmio(['127.0.0.1:27017'],
59
- :read => :primary)
60
- end.to raise_error(Mongo::Error::InvalidReadOption, 'Invalid read option: primary: must be a hash')
61
- end
62
- end
63
- end
64
- end
9
+ let(:subscriber) { EventSubscriber.new }
65
10
 
11
+ describe '.new' do
66
12
  context 'with scan: false' do
67
13
  it 'does not perform i/o' do
68
14
  allow_any_instance_of(Mongo::Server::Monitor).to receive(:run!)
@@ -87,37 +33,27 @@ describe Mongo::Client do
87
33
  # https://github.com/rspec/rspec-mocks/issues/1242.
88
34
  #expect_any_instance_of(Mongo::Server::Monitor).to receive(:scan!).
89
35
  # exactly(SpecConfig.instance.addresses.length).times.and_call_original
90
- c = ClientRegistry.instance.new_local_client(
36
+ c = new_local_client(
91
37
  SpecConfig.instance.addresses, SpecConfig.instance.test_options)
92
38
  expect(c.cluster.servers).not_to be_empty
93
- c.close
94
39
  end
95
40
 
96
41
  # This checks the case of all initial seeds being removed from
97
42
  # cluster during SDAM
98
43
  context 'me mismatch on the only initial seed' do
99
44
  let(:address) do
100
- address = SpecConfig.instance.addresses.first
101
- port = address.sub(/^.*:/, '').to_i
102
- address = address.sub(/:.*/, '')
103
- case address
104
- when '127.0.0.1'
105
- 'localhost'
106
- when /^(\d+\.){3}\d+$/
107
- skip 'This test requires a hostname or 127.0.0.1 as address'
108
- else
109
- # We don't know if mongod is listening on ipv4 or ipv6,
110
- # in principle.
111
- # Our tests use ipv4, so hardcode that for now.
112
- # To support both we need to try both addresses
113
- # which will make this test more complicated.
114
- resolved_address = Addrinfo.getaddrinfo(address, port, Socket::PF_INET).first.ip_address
115
- if resolved_address.include?(':')
116
- "[#{resolved_address}]"
117
- else
118
- resolved_address
119
- end + ":#{port}"
120
- end
45
+ ClusterConfig.instance.alternate_address.to_s
46
+ end
47
+
48
+ let(:logger) do
49
+ Logger.new(STDOUT, level: Logger::DEBUG)
50
+ end
51
+
52
+ let(:subscriber) do
53
+ Mongo::Monitoring::UnifiedSdamLogSubscriber.new(
54
+ logger: logger,
55
+ log_prefix: 'CCS-SDAM',
56
+ )
121
57
  end
122
58
 
123
59
  let(:client) do
@@ -125,17 +61,44 @@ describe Mongo::Client do
125
61
  [address],
126
62
  # Specify server selection timeout here because test suite sets
127
63
  # one by default and it's fairly low
128
- SpecConfig.instance.test_options.merge(server_selection_timeout: 5))
64
+ SpecConfig.instance.test_options.merge(
65
+ connect_timeout: 1,
66
+ socket_timeout: 1,
67
+ server_selection_timeout: 8,
68
+ logger: logger,
69
+ log_prefix: 'CCS-CLIENT',
70
+ sdam_proc: lambda do |client|
71
+ subscriber.subscribe(client)
72
+ end
73
+ ))
129
74
  end
130
75
 
131
76
  it 'does not wait for server selection timeout' do
132
- start_time = Time.now
133
- client
134
- time_taken = Time.now - start_time
135
- expect(time_taken < 3).to be true
77
+ time_taken = Benchmark.realtime do
78
+ # Client is created here.
79
+ client
80
+ end
81
+ puts "client_construction_spec.rb: Cluster is: #{client.cluster.summary}"
82
+
83
+ # Because the first round of sdam waits for server statuses to change
84
+ # rather than for server selection semaphore on the cluster which
85
+ # is signaled after topology is updated, the topology here could be
86
+ # old (i.e. a monitor thread was just about to update the topology
87
+ # but hasn't quite gotten to it. Add a small delay to compensate.
88
+ # This issue doesn't apply to real applications which will wait for
89
+ # server selection semaphore.
90
+ sleep 0.1
91
+
92
+ actual_class = client.cluster.topology.class
93
+ expect([
94
+ Mongo::Cluster::Topology::ReplicaSetWithPrimary,
95
+ Mongo::Cluster::Topology::Single,
96
+ Mongo::Cluster::Topology::Sharded,
97
+ ]).to include(actual_class)
98
+ expect(time_taken).to be < 5
136
99
 
137
100
  # run a command to ensure the client is a working one
138
- client.database.command(ismaster: 1)
101
+ client.database.command(ping: 1)
139
102
  end
140
103
  end
141
104
  end
@@ -152,8 +115,310 @@ describe Mongo::Client do
152
115
  end
153
116
 
154
117
  describe '#initialize' do
155
-
156
118
  context 'when providing options' do
119
+ context 'with auto_encryption_options' do
120
+ require_libmongocrypt
121
+
122
+ include_context 'define shared FLE helpers'
123
+
124
+ let(:client) do
125
+ new_local_client_nmio(
126
+ SpecConfig.instance.addresses,
127
+ SpecConfig.instance.test_options.merge(client_opts)
128
+ )
129
+ end
130
+
131
+ let(:client_opts) { { auto_encryption_options: auto_encryption_options } }
132
+
133
+ let(:auto_encryption_options) do
134
+ {
135
+ key_vault_client: key_vault_client,
136
+ key_vault_namespace: key_vault_namespace,
137
+ kms_providers: kms_providers,
138
+ schema_map: schema_map,
139
+ bypass_auto_encryption: bypass_auto_encryption,
140
+ extra_options: extra_options,
141
+ }
142
+ end
143
+
144
+ let(:key_vault_client) { new_local_client_nmio(SpecConfig.instance.addresses) }
145
+
146
+ let(:bypass_auto_encryption) { true }
147
+
148
+ let(:extra_options) do
149
+ {
150
+ mongocryptd_uri: mongocryptd_uri,
151
+ mongocryptd_bypass_spawn: mongocryptd_bypass_spawn,
152
+ mongocryptd_spawn_path: mongocryptd_spawn_path,
153
+ mongocryptd_spawn_args: mongocryptd_spawn_args,
154
+ }
155
+ end
156
+
157
+ let(:mongocryptd_uri) { 'mongodb://localhost:27021' }
158
+ let(:mongocryptd_bypass_spawn) { true }
159
+ let(:mongocryptd_spawn_path) { '/spawn/path' }
160
+ let(:mongocryptd_spawn_args) { ['--idleShutdownTimeoutSecs=100'] }
161
+
162
+ shared_examples 'a functioning auto encryption client' do
163
+ let(:encryption_options) { client.encrypter.options }
164
+
165
+ context 'when auto_encrypt_opts are nil' do
166
+ let(:auto_encryption_options) { nil }
167
+
168
+ it 'does not raise an exception' do
169
+ expect { client }.not_to raise_error
170
+ end
171
+ end
172
+
173
+ context 'when key_vault_namespace is nil' do
174
+ let(:key_vault_namespace) { nil }
175
+
176
+ it 'raises an exception' do
177
+ expect { client }.to raise_error(ArgumentError, /key_vault_namespace option cannot be nil/)
178
+ end
179
+ end
180
+
181
+ context 'when key_vault_namespace is incorrectly formatted' do
182
+ let(:key_vault_namespace) { 'not.good.formatting' }
183
+
184
+ it 'raises an exception' do
185
+ expect { client }.to raise_error(ArgumentError, /key_vault_namespace option must be in the format database.collection/)
186
+ end
187
+ end
188
+
189
+ context 'when kms_providers is nil' do
190
+ let(:kms_providers) { nil }
191
+
192
+ it 'raises an exception' do
193
+ expect { client }.to raise_error(ArgumentError, /kms_providers option must not be nil/)
194
+ end
195
+ end
196
+
197
+ context 'when kms_providers doesn\'t have local or aws keys' do
198
+ let(:kms_providers) { { random_key: 'hello' } }
199
+
200
+ it 'raises an exception' do
201
+ expect { client }.to raise_error(ArgumentError, /kms_providers option must have one of the following keys: :aws, :local/)
202
+ end
203
+ end
204
+
205
+ context 'when local kms_provider is incorrectly formatted' do
206
+ let(:kms_providers) { { local: { wrong_key: 'hello' } } }
207
+
208
+ it 'raises an exception' do
209
+ expect { client }.to raise_error(ArgumentError, /kms_providers with :local key must be in the format: { local: { key: 'MASTER-KEY' } }/)
210
+ end
211
+ end
212
+
213
+ context 'when aws kms_provider is incorrectly formatted' do
214
+ let(:kms_providers) { { aws: { wrong_key: 'hello' } } }
215
+
216
+ it 'raises an exception' do
217
+ expect { client }.to raise_error(ArgumentError, /kms_providers with :aws key must be in the format: { aws: { access_key_id: 'YOUR-ACCESS-KEY-ID', secret_access_key: 'SECRET-ACCESS-KEY' } }/)
218
+ end
219
+ end
220
+
221
+ context 'with an invalid schema map' do
222
+ let(:schema_map) { '' }
223
+
224
+ it 'raises an exception' do
225
+ expect { client }.to raise_error(ArgumentError, /schema_map must be a Hash or nil/)
226
+ end
227
+ end
228
+
229
+ context 'with valid options' do
230
+ it 'does not raise an exception' do
231
+ expect { client }.not_to raise_error
232
+ end
233
+
234
+ context 'with a nil schema_map' do
235
+ let(:schema_map) { nil }
236
+
237
+ it 'does not raise an exception' do
238
+ expect { client }.not_to raise_error
239
+ end
240
+ end
241
+
242
+ it 'sets options on the client' do
243
+ expect(encryption_options[:key_vault_client]).to eq(key_vault_client)
244
+ expect(encryption_options[:key_vault_namespace]).to eq(key_vault_namespace)
245
+ # Don't explicitly expect kms_providers to avoid accidentally exposing
246
+ # sensitive data in evergreen logs
247
+ expect(encryption_options[:kms_providers]).to be_a_kind_of(Hash)
248
+ expect(encryption_options[:schema_map]).to eq(schema_map)
249
+ expect(encryption_options[:bypass_auto_encryption]).to eq(bypass_auto_encryption)
250
+ expect(encryption_options[:extra_options][:mongocryptd_uri]).to eq(mongocryptd_uri)
251
+ expect(encryption_options[:extra_options][:mongocryptd_bypass_spawn]).to eq(mongocryptd_bypass_spawn)
252
+ expect(encryption_options[:extra_options][:mongocryptd_spawn_path]).to eq(mongocryptd_spawn_path)
253
+ expect(encryption_options[:extra_options][:mongocryptd_spawn_args]).to eq(mongocryptd_spawn_args)
254
+
255
+ expect(client.encrypter.mongocryptd_client.options[:monitoring_io]).to be false
256
+ end
257
+
258
+ context 'with default extra options' do
259
+ let(:auto_encryption_options) do
260
+ {
261
+ key_vault_namespace: key_vault_namespace,
262
+ kms_providers: kms_providers,
263
+ schema_map: schema_map,
264
+ }
265
+ end
266
+
267
+ it 'sets key_vault_client as a clone of self with no encryption options' do
268
+ key_vault_client = client.encrypter.key_vault_client
269
+ expect(key_vault_client).to eq(client)
270
+ end
271
+
272
+ it 'sets bypass_auto_encryption to false' do
273
+ expect(encryption_options[:bypass_auto_encryption]).to be false
274
+ end
275
+
276
+ it 'sets extra options to defaults' do
277
+ expect(encryption_options[:extra_options][:mongocryptd_uri]).to eq('mongodb://localhost:27020')
278
+ expect(encryption_options[:extra_options][:mongocryptd_bypass_spawn]).to be false
279
+ expect(encryption_options[:extra_options][:mongocryptd_spawn_path]).to eq('mongocryptd')
280
+ expect(encryption_options[:extra_options][:mongocryptd_spawn_args]).to eq(['--idleShutdownTimeoutSecs=60'])
281
+ end
282
+ end
283
+
284
+ context 'with mongocryptd_spawn_args that don\'t include idleShutdownTimeoutSecs' do
285
+ let(:mongocryptd_spawn_args) { ['--otherArgument=true'] }
286
+
287
+ it 'adds a default value to mongocryptd_spawn_args' do
288
+ expect(encryption_options[:extra_options][:mongocryptd_spawn_args]).to eq(mongocryptd_spawn_args + ['--idleShutdownTimeoutSecs=60'])
289
+ end
290
+ end
291
+
292
+ context 'with mongocryptd_spawn_args that has idleShutdownTimeoutSecs as two arguments' do
293
+ let(:mongocryptd_spawn_args) { ['--idleShutdownTimeoutSecs', 100] }
294
+
295
+ it 'does not modify mongocryptd_spawn_args' do
296
+ expect(encryption_options[:extra_options][:mongocryptd_spawn_args]).to eq(mongocryptd_spawn_args)
297
+ end
298
+ end
299
+
300
+ context 'with default key_vault_client' do
301
+ let(:key_vault_client) { nil }
302
+
303
+ it 'creates a key_vault_client' do
304
+ key_vault_client = encryption_options[:key_vault_client]
305
+
306
+ expect(key_vault_client).to be_a_kind_of(Mongo::Client)
307
+ end
308
+ end
309
+ end
310
+ end
311
+
312
+ context 'with AWS KMS providers' do
313
+ include_context 'with AWS kms_providers' do
314
+ it_behaves_like 'a functioning auto encryption client'
315
+ end
316
+ end
317
+
318
+ context 'with local KMS providers' do
319
+ include_context 'with local kms_providers' do
320
+ it_behaves_like 'a functioning auto encryption client'
321
+ end
322
+ end
323
+ end
324
+
325
+ context 'timeout options' do
326
+ let(:client) do
327
+ new_local_client(SpecConfig.instance.addresses,
328
+ SpecConfig.instance.authorized_test_options.merge(options))
329
+ end
330
+
331
+ context 'when network timeouts are zero' do
332
+ let(:options) do
333
+ { socket_timeout: 0, connect_timeout: 0 }
334
+ end
335
+
336
+ it 'sets options to zeros' do
337
+ client.options[:socket_timeout].should == 0
338
+ client.options[:connect_timeout].should == 0
339
+ end
340
+
341
+ it 'connects and performs operations successfully' do
342
+ lambda do
343
+ client.database.command(ping: 1)
344
+ end.should_not raise_error
345
+ end
346
+ end
347
+
348
+ %i(socket_timeout connect_timeout).each do |option|
349
+ context "when #{option} is negative" do
350
+ let(:options) do
351
+ { option => -1 }
352
+ end
353
+
354
+ it 'fails client creation' do
355
+ lambda do
356
+ client
357
+ end.should raise_error(ArgumentError, /#{option} must be a non-negative number/)
358
+ end
359
+ end
360
+
361
+ context "when #{option} is of the wrong type" do
362
+ let(:options) do
363
+ { option => '42' }
364
+ end
365
+
366
+ it 'fails client creation' do
367
+ lambda do
368
+ client
369
+ end.should raise_error(ArgumentError, /#{option} must be a non-negative number/)
370
+ end
371
+ end
372
+ end
373
+
374
+ context "when :connect_timeout is very small" do
375
+ # The driver reads first and checks the deadline second.
376
+ # This means the read (in a monitor) can technically take more than
377
+ # the connect timeout. Restrict to TLS configurations to make
378
+ # the network I/O take longer.
379
+ require_tls
380
+
381
+ let(:options) do
382
+ { connect_timeout: 1e-6, server_selection_timeout: 2 }
383
+ end
384
+
385
+ it 'allows client creation' do
386
+ lambda do
387
+ client
388
+ end.should_not raise_error
389
+ end
390
+
391
+ it 'fails server selection due to very small timeout' do
392
+ lambda do
393
+ client.database.command(ping: 1)
394
+ end.should raise_error(Mongo::Error::NoServerAvailable)
395
+ end
396
+ end
397
+
398
+ context "when :socket_timeout is very small" do
399
+ # The driver reads first and checks the deadline second.
400
+ # This means the read (in a monitor) can technically take more than
401
+ # the connect timeout. Restrict to TLS configurations to make
402
+ # the network I/O take longer.
403
+ require_tls
404
+
405
+ let(:options) do
406
+ { socket_timeout: 1e-6, server_selection_timeout: 2 }
407
+ end
408
+
409
+ it 'allows client creation' do
410
+ lambda do
411
+ client
412
+ end.should_not raise_error
413
+ end
414
+
415
+ it 'fails operations due to very small timeout' do
416
+ lambda do
417
+ client.database.command(ping: 1)
418
+ end.should raise_error(Mongo::Error::SocketTimeoutError)
419
+ end
420
+ end
421
+ end
157
422
 
158
423
  context 'retry_writes option' do
159
424
  let(:client) do
@@ -197,49 +462,19 @@ describe Mongo::Client do
197
462
  context 'when compressors are provided' do
198
463
 
199
464
  let(:client) do
200
- new_local_client(SpecConfig.instance.addresses, authorized_client.options.merge(options))
201
- end
202
-
203
- context 'when the compressor is supported' do
204
-
205
- let(:options) do
206
- { compressors: ['zlib'] }
207
- end
208
-
209
- it 'sets the compressor' do
210
- expect(client.options['compressors']).to eq(options[:compressors])
211
- end
212
-
213
- it 'sends the compressor in the compression key of the handshake document' do
214
- expect(client.cluster.app_metadata.send(:document)[:compression]).to eq(options[:compressors])
215
- end
216
-
217
- context 'when server supports compression' do
218
- require_compression
219
- min_server_fcv '3.6'
220
-
221
- it 'uses compression for messages' do
222
- expect(Mongo::Protocol::Compressed).to receive(:new).and_call_original
223
- client[TEST_COLL].find({}, limit: 1).first
224
- end
225
- end
226
-
227
- it 'does not use compression for authentication messages' do
228
- expect(Mongo::Protocol::Compressed).not_to receive(:new)
229
- client.cluster.next_primary.send(:with_connection) do |conn|
230
- conn.send(:authenticate!, conn)
231
- end
232
- end
465
+ new_local_client(SpecConfig.instance.addresses,
466
+ SpecConfig.instance.all_test_options.merge(options))
233
467
  end
234
468
 
235
469
  context 'when the compressor is not supported by the driver' do
470
+ require_warning_clean
236
471
 
237
472
  let(:options) do
238
473
  { compressors: ['snoopy'] }
239
474
  end
240
475
 
241
476
  it 'does not set the compressor and warns' do
242
- expect(Mongo::Logger.logger).to receive(:warn)
477
+ expect(Mongo::Logger.logger).to receive(:warn).with(/Unsupported compressor/)
243
478
  expect(client.options['compressors']).to be_nil
244
479
  end
245
480
 
@@ -278,36 +513,120 @@ describe Mongo::Client do
278
513
  expect(client.cluster.next_primary.monitor.compressor).to be_nil
279
514
  end
280
515
  end
281
- end
282
516
 
283
- context 'when compressors are not provided' do
284
- require_no_compression
517
+ context 'when zlib compression is requested' do
518
+ require_zlib_compression
285
519
 
286
- let(:client) do
287
- authorized_client
288
- end
520
+ let(:options) do
521
+ { compressors: ['zlib'] }
522
+ end
289
523
 
290
- it 'does not set the compressor' do
291
- expect(client.options['compressors']).to be_nil
292
- end
524
+ it 'sets the compressor' do
525
+ expect(client.options['compressors']).to eq(options[:compressors])
526
+ end
293
527
 
294
- it 'sets the compression key of the handshake document to an empty array' do
295
- expect(client.cluster.app_metadata.send(:document)[:compression]).to eq([])
296
- end
528
+ it 'sends the compressor in the compression key of the handshake document' do
529
+ expect(client.cluster.app_metadata.send(:document)[:compression]).to eq(options[:compressors])
530
+ end
297
531
 
298
- it 'does not use compression for messages' do
299
- client[TEST_COLL].find({}, limit: 1).first
300
- expect(Mongo::Protocol::Compressed).not_to receive(:new)
301
- end
302
- end
532
+ context 'when server supports compression' do
533
+ min_server_fcv '3.6'
303
534
 
304
- context 'when a zlib_compression_level option is provided' do
305
- require_compression
306
- min_server_fcv '3.6'
535
+ it 'uses compression for messages' do
536
+ expect(Mongo::Protocol::Compressed).to receive(:new).at_least(:once).and_call_original
537
+ client[TEST_COLL].find({}, limit: 1).first
538
+ end
539
+ end
307
540
 
308
- let(:client) do
309
- new_local_client_nmio(SpecConfig.instance.addresses, SpecConfig.instance.test_options.merge(zlib_compression_level: 1))
310
- end
541
+ it 'does not use compression for authentication messages' do
542
+ expect(Mongo::Protocol::Compressed).not_to receive(:new)
543
+ client.cluster.next_primary.send(:with_connection) do |conn|
544
+ conn.connect!
545
+ end
546
+ end
547
+ end
548
+
549
+ context 'when snappy compression is requested and supported by the server' do
550
+ min_server_version '3.6'
551
+
552
+ let(:options) do
553
+ { compressors: ['snappy'] }
554
+ end
555
+
556
+ context 'when snappy gem is installed' do
557
+ require_snappy_compression
558
+
559
+ it 'creates the client' do
560
+ expect(client.options['compressors']).to eq(['snappy'])
561
+ end
562
+ end
563
+
564
+ context 'when snappy gem is not installed' do
565
+ require_no_snappy_compression
566
+
567
+ it 'raises an exception' do
568
+ expect do
569
+ client
570
+ end.to raise_error(Mongo::Error::UnmetDependency, /Cannot enable snappy compression/)
571
+ end
572
+ end
573
+ end
574
+
575
+ context 'when zstd compression is requested and supported by the server' do
576
+ min_server_version '4.2'
577
+
578
+ let(:options) do
579
+ { compressors: ['zstd'] }
580
+ end
581
+
582
+ context 'when zstd gem is installed' do
583
+ require_zstd_compression
584
+
585
+ it 'creates the client' do
586
+ expect(client.options['compressors']).to eq(['zstd'])
587
+ end
588
+ end
589
+
590
+ context 'when zstd gem is not installed' do
591
+ require_no_zstd_compression
592
+
593
+ it 'raises an exception' do
594
+ expect do
595
+ client
596
+ end.to raise_error(Mongo::Error::UnmetDependency, /Cannot enable zstd compression/)
597
+ end
598
+ end
599
+ end
600
+ end
601
+
602
+ context 'when compressors are not provided' do
603
+ require_no_compression
604
+
605
+ let(:client) do
606
+ authorized_client
607
+ end
608
+
609
+ it 'does not set the compressor' do
610
+ expect(client.options['compressors']).to be_nil
611
+ end
612
+
613
+ it 'sets the compression key of the handshake document to an empty array' do
614
+ expect(client.cluster.app_metadata.send(:document)[:compression]).to eq([])
615
+ end
616
+
617
+ it 'does not use compression for messages' do
618
+ client[TEST_COLL].find({}, limit: 1).first
619
+ expect(Mongo::Protocol::Compressed).not_to receive(:new)
620
+ end
621
+ end
622
+
623
+ context 'when a zlib_compression_level option is provided' do
624
+ require_compression
625
+ min_server_fcv '3.6'
626
+
627
+ let(:client) do
628
+ new_local_client_nmio(SpecConfig.instance.addresses, SpecConfig.instance.test_options.merge(zlib_compression_level: 1))
629
+ end
311
630
 
312
631
  it 'sets the option on the client' do
313
632
  expect(client.options[:zlib_compression_level]).to eq(1)
@@ -411,7 +730,7 @@ describe Mongo::Client do
411
730
  context 'when providing a custom logger' do
412
731
 
413
732
  let(:logger) do
414
- Logger.new($stdout).tap do |l|
733
+ Logger.new(STDOUT).tap do |l|
415
734
  l.level = Logger::FATAL
416
735
  end
417
736
  end
@@ -580,16 +899,40 @@ describe Mongo::Client do
580
899
  new_local_client_nmio(['127.0.0.1:27017'])
581
900
  end
582
901
 
583
- let(:platform_string) do
584
- [
585
- RUBY_VERSION,
586
- RUBY_PLATFORM,
587
- RbConfig::CONFIG['build']
588
- ].join(', ')
902
+ context 'mri' do
903
+ require_mri
904
+
905
+ let(:platform_string) do
906
+ [
907
+ "Ruby #{RUBY_VERSION}",
908
+ RUBY_PLATFORM,
909
+ RbConfig::CONFIG['build'],
910
+ 'A',
911
+ ].join(', ')
912
+ end
913
+
914
+ it 'does not include the platform info in the app metadata' do
915
+ expect(app_metadata.send(:full_client_document)[:platform]).to eq(platform_string)
916
+ end
589
917
  end
590
918
 
591
- it 'does not include the platform info in the app metadata' do
592
- expect(app_metadata.send(:full_client_document)[:platform]).to eq(platform_string)
919
+ context 'jruby' do
920
+ require_jruby
921
+
922
+ let(:platform_string) do
923
+ [
924
+ "JRuby #{JRUBY_VERSION}",
925
+ "like Ruby #{RUBY_VERSION}",
926
+ RUBY_PLATFORM,
927
+ "JVM #{java.lang.System.get_property('java.version')}",
928
+ RbConfig::CONFIG['build'],
929
+ 'A',
930
+ ].join(', ')
931
+ end
932
+
933
+ it 'does not include the platform info in the app metadata' do
934
+ expect(app_metadata.send(:full_client_document)[:platform]).to eq(platform_string)
935
+ end
593
936
  end
594
937
  end
595
938
  end
@@ -642,7 +985,7 @@ describe Mongo::Client do
642
985
  end
643
986
  end
644
987
 
645
- context 'when options are provided' do
988
+ context 'when URI options are provided' do
646
989
 
647
990
  let!(:uri) do
648
991
  'mongodb://127.0.0.1:27017/testdb?w=3'
@@ -691,215 +1034,734 @@ describe Mongo::Client do
691
1034
  end
692
1035
  end
693
1036
 
694
- context 'when the min_pool_size is equal to the max_pool_size' do
1037
+ context 'when the min_pool_size is equal to the max_pool_size' do
1038
+
1039
+ let(:uri) do
1040
+ 'mongodb://127.0.0.1:27017/?minPoolSize=10&maxPoolSize=10'
1041
+ end
1042
+
1043
+ it 'sets the option' do
1044
+ expect(client.options[:min_pool_size]).to eq(10)
1045
+ expect(client.options[:max_pool_size]).to eq(10)
1046
+ end
1047
+ end
1048
+ end
1049
+
1050
+ context 'when max_pool_size is not provided' do
1051
+
1052
+ context 'when the min_pool_size is greater than the default max_pool_size' do
1053
+
1054
+ let(:uri) do
1055
+ 'mongodb://127.0.0.1:27017/?minPoolSize=10'
1056
+ end
1057
+
1058
+ it 'raises an Exception' do
1059
+ expect {
1060
+ client
1061
+ }.to raise_exception(Mongo::Error::InvalidMinPoolSize)
1062
+ end
1063
+ end
1064
+
1065
+ context 'when the min_pool_size is less than the default max_pool_size' do
1066
+
1067
+ let(:uri) do
1068
+ 'mongodb://127.0.0.1:27017/?minPoolSize=3'
1069
+ end
1070
+
1071
+ it 'sets the option' do
1072
+ expect(client.options[:min_pool_size]).to eq(3)
1073
+ end
1074
+ end
1075
+
1076
+ context 'when the min_pool_size is equal to the max_pool_size' do
1077
+
1078
+ let(:uri) do
1079
+ 'mongodb://127.0.0.1:27017/?minPoolSize=5'
1080
+ end
1081
+
1082
+ it 'sets the option' do
1083
+ expect(client.options[:min_pool_size]).to eq(5)
1084
+ end
1085
+ end
1086
+ end
1087
+ end
1088
+
1089
+ context 'when retryReads URI option is given' do
1090
+
1091
+ context 'it is false' do
1092
+ let!(:uri) do
1093
+ 'mongodb://127.0.0.1:27017/testdb?retryReads=false'
1094
+ end
1095
+
1096
+ it 'sets the option on the client' do
1097
+ expect(client.options[:retry_reads]).to be false
1098
+ end
1099
+ end
1100
+
1101
+ context 'it is true' do
1102
+ let!(:uri) do
1103
+ 'mongodb://127.0.0.1:27017/testdb?retryReads=true'
1104
+ end
1105
+
1106
+ it 'sets the option on the client' do
1107
+ expect(client.options[:retry_reads]).to be true
1108
+ end
1109
+ end
1110
+ end
1111
+
1112
+ context 'when retryWrites URI option is given' do
1113
+
1114
+ context 'it is false' do
1115
+ let!(:uri) do
1116
+ 'mongodb://127.0.0.1:27017/testdb?retryWrites=false'
1117
+ end
1118
+
1119
+ it 'sets the option on the client' do
1120
+ expect(client.options[:retry_writes]).to be false
1121
+ end
1122
+ end
1123
+
1124
+ context 'it is true' do
1125
+ let!(:uri) do
1126
+ 'mongodb://127.0.0.1:27017/testdb?retryWrites=true'
1127
+ end
1128
+
1129
+ it 'sets the option on the client' do
1130
+ expect(client.options[:retry_writes]).to be true
1131
+ end
1132
+ end
1133
+ end
1134
+ end
1135
+
1136
+ context 'when options are provided not in the string' do
1137
+
1138
+ let!(:uri) do
1139
+ 'mongodb://127.0.0.1:27017/testdb'
1140
+ end
1141
+
1142
+ let(:client) do
1143
+ new_local_client_nmio(uri, :write => { :w => 3 })
1144
+ end
1145
+
1146
+ let(:expected_options) do
1147
+ Mongo::Options::Redacted.new(:write => { :w => 3 },
1148
+ monitoring_io: false, :database => 'testdb', retry_writes: true,
1149
+ retry_reads: true)
1150
+ end
1151
+
1152
+ it 'sets the options' do
1153
+ expect(client.options).to eq(expected_options)
1154
+ end
1155
+ end
1156
+
1157
+ context 'when options are provided in the URI and as Ruby options' do
1158
+
1159
+ let!(:uri) do
1160
+ 'mongodb://127.0.0.1:27017/testdb?w=3'
1161
+ end
1162
+
1163
+ let(:client) do
1164
+ new_local_client_nmio(uri, option_name => { :w => 4 })
1165
+ end
1166
+
1167
+ let(:expected_options) do
1168
+ Mongo::Options::Redacted.new(option_name => { :w => 4 },
1169
+ monitoring_io: false, :database => 'testdb', retry_writes: true,
1170
+ retry_reads: true)
1171
+ end
1172
+
1173
+ shared_examples_for 'allows explicit options to take preference' do
1174
+ it 'allows explicit options to take preference' do
1175
+ expect(client.options).to eq(expected_options)
1176
+ end
1177
+ end
1178
+
1179
+ context 'when using :write' do
1180
+ let(:option_name) { :write }
1181
+
1182
+ it_behaves_like 'allows explicit options to take preference'
1183
+ end
1184
+
1185
+ context 'when using :write_concern' do
1186
+ let(:option_name) { :write_concern }
1187
+
1188
+ it_behaves_like 'allows explicit options to take preference'
1189
+ end
1190
+ end
1191
+
1192
+ context 'when a replica set name is provided' do
1193
+
1194
+ let!(:uri) do
1195
+ 'mongodb://127.0.0.1:27017/testdb?replicaSet=testing'
1196
+ end
1197
+
1198
+ let(:client) do
1199
+ new_local_client_nmio(uri)
1200
+ end
1201
+
1202
+ it 'sets the correct cluster topology' do
1203
+ expect(client.cluster.topology).to be_a(Mongo::Cluster::Topology::ReplicaSetNoPrimary)
1204
+ end
1205
+ end
1206
+ end
1207
+
1208
+ context 'when Ruby options are provided' do
1209
+ let(:client) do
1210
+ new_local_client_nmio(['127.0.0.1:27017'], options)
1211
+ end
1212
+
1213
+ describe 'connection option conflicts' do
1214
+ context 'direct_connection: true and multiple seeds' do
1215
+ let(:client) do
1216
+ new_local_client_nmio(['127.0.0.1:27017', '127.0.0.2:27017'],
1217
+ direct_connection: true)
1218
+ end
1219
+
1220
+ it 'is rejected' do
1221
+ lambda do
1222
+ client
1223
+ end.should raise_error(ArgumentError, /direct_connection=true cannot be used with multiple seeds/)
1224
+ end
1225
+ end
1226
+
1227
+ context 'direct_connection: true and connect: :direct' do
1228
+ let(:options) do
1229
+ {direct_connection: true, connect: :direct}
1230
+ end
1231
+
1232
+ it 'is accepted' do
1233
+ client.options[:direct_connection].should be true
1234
+ client.options[:connect].should be :direct
1235
+ end
1236
+ end
1237
+
1238
+ context 'direct_connection: true and connect: :replica_set' do
1239
+ let(:options) do
1240
+ {direct_connection: true, connect: :replica_set}
1241
+ end
1242
+
1243
+ it 'is rejected' do
1244
+ lambda do
1245
+ client
1246
+ end.should raise_error(ArgumentError, /Conflicting client options: direct_connection=true and connect=replica_set/)
1247
+ end
1248
+ end
1249
+
1250
+ context 'direct_connection: true and connect: :sharded' do
1251
+ let(:options) do
1252
+ {direct_connection: true, connect: :sharded}
1253
+ end
1254
+
1255
+ it 'is rejected' do
1256
+ lambda do
1257
+ client
1258
+ end.should raise_error(ArgumentError, /Conflicting client options: direct_connection=true and connect=sharded/)
1259
+ end
1260
+ end
1261
+
1262
+ context 'direct_connection: false and connect: :direct' do
1263
+ let(:options) do
1264
+ {direct_connection: false, connect: :direct}
1265
+ end
1266
+
1267
+ it 'is rejected' do
1268
+ lambda do
1269
+ client
1270
+ end.should raise_error(ArgumentError, /Conflicting client options: direct_connection=false and connect=direct/)
1271
+ end
1272
+ end
1273
+
1274
+ context 'direct_connection: false and connect: :replica_set' do
1275
+ let(:options) do
1276
+ {direct_connection: false, connect: :replica_set, replica_set: 'foo'}
1277
+ end
1278
+
1279
+ it 'is accepted' do
1280
+ client.options[:direct_connection].should be false
1281
+ client.options[:connect].should be :replica_set
1282
+ end
1283
+ end
1284
+
1285
+ context 'direct_connection: false and connect: :sharded' do
1286
+ let(:options) do
1287
+ {direct_connection: false, connect: :sharded}
1288
+ end
1289
+
1290
+ it 'is accepted' do
1291
+ client.options[:direct_connection].should be false
1292
+ client.options[:connect].should be :sharded
1293
+ end
1294
+ end
1295
+ end
1296
+
1297
+ context ':bg_error_backtrace option' do
1298
+ [true, false, nil, 42].each do |valid_value|
1299
+ context "valid value: #{valid_value.inspect}" do
1300
+ let(:options) do
1301
+ {bg_error_backtrace: valid_value}
1302
+ end
1303
+
1304
+ it 'is accepted' do
1305
+ client.options[:bg_error_backtrace].should == valid_value
1306
+ end
1307
+ end
1308
+ end
1309
+
1310
+ context 'invalid value type' do
1311
+ let(:options) do
1312
+ {bg_error_backtrace: 'yes'}
1313
+ end
1314
+
1315
+ it 'is rejected' do
1316
+ lambda do
1317
+ client
1318
+ end.should raise_error(ArgumentError, /:bg_error_backtrace option value must be true, false, nil or a positive integer/)
1319
+ end
1320
+ end
1321
+
1322
+ context 'invalid value' do
1323
+ [0, -1, 42.0].each do |invalid_value|
1324
+ context "invalid value: #{invalid_value.inspect}" do
1325
+ let(:options) do
1326
+ {bg_error_backtrace: invalid_value}
1327
+ end
1328
+
1329
+ it 'is rejected' do
1330
+ lambda do
1331
+ client
1332
+ end.should raise_error(ArgumentError, /:bg_error_backtrace option value must be true, false, nil or a positive integer/)
1333
+ end
1334
+ end
1335
+ end
1336
+ end
1337
+ end
1338
+
1339
+ describe ':read option' do
1340
+ [
1341
+ :primary, :primary_preferred, :secondary, :secondary_preferred, :nearest
1342
+ ].each do |sym|
1343
+ describe "#{sym}" do
1344
+ context 'when given as symbol' do
1345
+ let(:options) do
1346
+ {read: {mode: sym}}
1347
+ end
1348
+
1349
+ it "is accepted" do
1350
+ # the key got converted to a string here
1351
+ expect(client.read_preference).to eq({'mode' => sym})
1352
+ end
1353
+ end
1354
+
1355
+ context 'when given as string' do
1356
+ let(:options) do
1357
+ {read: {mode: sym.to_s}}
1358
+ end
1359
+
1360
+ # string keys are not documented as being allowed
1361
+ # but the code accepts them
1362
+ it "is accepted" do
1363
+ # the key got converted to a string here
1364
+ # the value remains a string
1365
+ expect(client.read_preference).to eq({'mode' => sym.to_s})
1366
+ end
1367
+ end
1368
+ end
1369
+ end
1370
+
1371
+ context 'when not linting' do
1372
+ require_no_linting
1373
+
1374
+ it 'rejects bogus read preference as symbol' do
1375
+ expect do
1376
+ client = new_local_client_nmio(['127.0.0.1:27017'],
1377
+ :read => {:mode => :bogus})
1378
+ end.to raise_error(Mongo::Error::InvalidReadOption, 'Invalid read option: {"mode"=>:bogus}: mode bogus is not one of recognized modes')
1379
+ end
1380
+
1381
+ it 'rejects bogus read preference as string' do
1382
+ expect do
1383
+ client = new_local_client_nmio(['127.0.0.1:27017'],
1384
+ :read => {:mode => 'bogus'})
1385
+ end.to raise_error(Mongo::Error::InvalidReadOption, 'Invalid read option: {"mode"=>"bogus"}: mode bogus is not one of recognized modes')
1386
+ end
1387
+
1388
+ it 'rejects read option specified as a string' do
1389
+ expect do
1390
+ client = new_local_client_nmio(['127.0.0.1:27017'],
1391
+ :read => 'primary')
1392
+ end.to raise_error(Mongo::Error::InvalidReadOption, 'Invalid read option: primary: must be a hash')
1393
+ end
1394
+
1395
+ it 'rejects read option specified as a symbol' do
1396
+ expect do
1397
+ client = new_local_client_nmio(['127.0.0.1:27017'],
1398
+ :read => :primary)
1399
+ end.to raise_error(Mongo::Error::InvalidReadOption, 'Invalid read option: primary: must be a hash')
1400
+ end
1401
+ end
1402
+ end
1403
+
1404
+ context 'when setting read concern options' do
1405
+ min_server_fcv '3.2'
1406
+
1407
+ context 'when read concern is valid' do
1408
+ let(:options) do
1409
+ { read_concern: { level: :local } }
1410
+ end
1411
+
1412
+ it 'does not warn' do
1413
+ expect(Mongo::Logger.logger).to_not receive(:warn)
1414
+ new_local_client_nmio(SpecConfig.instance.addresses, options)
1415
+ end
1416
+ end
1417
+
1418
+ context 'when read concern has an invalid key' do
1419
+ require_no_linting
1420
+
1421
+ let(:options) do
1422
+ { read_concern: { hello: :local } }
1423
+ end
1424
+
1425
+ it 'logs a warning' do
1426
+ expect(Mongo::Logger.logger).to receive(:warn).with(/Read concern has invalid keys: hello/)
1427
+ new_local_client_nmio(SpecConfig.instance.addresses, options)
1428
+ end
1429
+ end
1430
+
1431
+ context 'when read concern has a non-user-settable key' do
1432
+ let(:options) do
1433
+ { read_concern: { after_cluster_time: 100 } }
1434
+ end
1435
+
1436
+ it 'raises an exception' do
1437
+ expect do
1438
+ new_local_client_nmio(SpecConfig.instance.addresses, options)
1439
+ end.to raise_error(Mongo::Error::InvalidReadConcern, 'The after_cluster_time read_concern option cannot be specified by the user')
1440
+ end
1441
+ end
1442
+ end
1443
+
1444
+ context 'when an invalid option is provided' do
1445
+
1446
+ let(:options) do
1447
+ {ssl: false, invalid: :test}
1448
+ end
1449
+
1450
+ it 'does not set the option' do
1451
+ expect(client.options.keys).not_to include('invalid')
1452
+ end
1453
+
1454
+ it 'sets the valid options' do
1455
+ expect(client.options.keys).to include('ssl')
1456
+ end
1457
+
1458
+ it 'warns that an invalid option has been specified' do
1459
+ expect(Mongo::Logger.logger).to receive(:warn)
1460
+ expect(client.options.keys).not_to include('invalid')
1461
+ end
1462
+ end
1463
+
1464
+ =begin WriteConcern object support
1465
+ context 'when write concern is provided via a WriteConcern object' do
1466
+
1467
+ let(:options) do
1468
+ {write_concern: wc}
1469
+ end
1470
+
1471
+ let(:wc) { Mongo::WriteConcern.get(w: 2) }
1472
+
1473
+ it 'stores write concern options in client options' do
1474
+ expect(client.options[:write_concern]).to eq(
1475
+ Mongo::Options::Redacted.new(w: 2))
1476
+ end
1477
+
1478
+ it 'caches write concern object' do
1479
+ expect(client.write_concern).to be wc
1480
+ end
1481
+ end
1482
+ =end
1483
+
1484
+ context ':wrapping_libraries option' do
1485
+ let(:options) do
1486
+ {wrapping_libraries: wrapping_libraries}
1487
+ end
695
1488
 
696
- let(:uri) do
697
- 'mongodb://127.0.0.1:27017/?minPoolSize=10&maxPoolSize=10'
698
- end
1489
+ context 'valid input' do
1490
+ context 'symbol keys' do
1491
+ let(:wrapping_libraries) do
1492
+ [name: 'Mongoid', version: '7.1.2'].freeze
1493
+ end
699
1494
 
700
- it 'sets the option' do
701
- expect(client.options[:min_pool_size]).to eq(10)
702
- expect(client.options[:max_pool_size]).to eq(10)
703
- end
1495
+ it 'works' do
1496
+ client.options[:wrapping_libraries].should == ['name' => 'Mongoid', 'version' => '7.1.2']
704
1497
  end
705
1498
  end
706
1499
 
707
- context 'when max_pool_size is not provided' do
708
-
709
- context 'when the min_pool_size is greater than the default max_pool_size' do
710
-
711
- let(:uri) do
712
- 'mongodb://127.0.0.1:27017/?minPoolSize=10'
713
- end
714
-
715
- it 'raises an Exception' do
716
- expect {
717
- client
718
- }.to raise_exception(Mongo::Error::InvalidMinPoolSize)
719
- end
1500
+ context 'string keys' do
1501
+ let(:wrapping_libraries) do
1502
+ ['name' => 'Mongoid', 'version' => '7.1.2'].freeze
720
1503
  end
721
1504
 
722
- context 'when the min_pool_size is less than the default max_pool_size' do
723
-
724
- let(:uri) do
725
- 'mongodb://127.0.0.1:27017/?minPoolSize=3'
726
- end
1505
+ it 'works' do
1506
+ client.options[:wrapping_libraries].should == ['name' => 'Mongoid', 'version' => '7.1.2']
1507
+ end
1508
+ end
727
1509
 
728
- it 'sets the option' do
729
- expect(client.options[:min_pool_size]).to eq(3)
730
- end
1510
+ context 'Redacted keys' do
1511
+ let(:wrapping_libraries) do
1512
+ [Mongo::Options::Redacted.new(name: 'Mongoid', version: '7.1.2')].freeze
731
1513
  end
732
1514
 
733
- context 'when the min_pool_size is equal to the max_pool_size' do
1515
+ it 'works' do
1516
+ client.options[:wrapping_libraries].should == ['name' => 'Mongoid', 'version' => '7.1.2']
1517
+ end
1518
+ end
734
1519
 
735
- let(:uri) do
736
- 'mongodb://127.0.0.1:27017/?minPoolSize=5'
737
- end
1520
+ context 'two libraries' do
1521
+ let(:wrapping_libraries) do
1522
+ [
1523
+ {name: 'Mongoid', version: '7.1.2'},
1524
+ {name: 'Rails', version: '4.0', platform: 'Foobar'},
1525
+ ].freeze
1526
+ end
738
1527
 
739
- it 'sets the option' do
740
- expect(client.options[:min_pool_size]).to eq(5)
741
- end
1528
+ it 'works' do
1529
+ client.options[:wrapping_libraries].should == [
1530
+ {'name' => 'Mongoid', 'version' => '7.1.2'},
1531
+ {'name' => 'Rails', 'version' => '4.0', 'platform' => 'Foobar'},
1532
+ ]
742
1533
  end
743
1534
  end
744
- end
745
-
746
- context 'when retryReads URI option is given' do
747
1535
 
748
- context 'it is false' do
749
- let!(:uri) do
750
- 'mongodb://127.0.0.1:27017/testdb?retryReads=false'
1536
+ context 'empty array' do
1537
+ let(:wrapping_libraries) do
1538
+ []
751
1539
  end
752
1540
 
753
- it 'sets the option on the client' do
754
- expect(client.options[:retry_reads]).to be false
1541
+ it 'works' do
1542
+ client.options[:wrapping_libraries].should == []
755
1543
  end
756
1544
  end
757
1545
 
758
- context 'it is true' do
759
- let!(:uri) do
760
- 'mongodb://127.0.0.1:27017/testdb?retryReads=true'
1546
+ context 'empty array' do
1547
+ let(:wrapping_libraries) do
1548
+ nil
761
1549
  end
762
1550
 
763
- it 'sets the option on the client' do
764
- expect(client.options[:retry_reads]).to be true
1551
+ it 'works' do
1552
+ client.options[:wrapping_libraries].should be nil
765
1553
  end
766
1554
  end
767
1555
  end
768
1556
 
769
- context 'when retryWrites URI option is given' do
1557
+ context 'valid input' do
1558
+ context 'hash given instead of an array' do
1559
+ let(:wrapping_libraries) do
1560
+ {name: 'Mongoid', version: '7.1.2'}.freeze
1561
+ end
770
1562
 
771
- context 'it is false' do
772
- let!(:uri) do
773
- 'mongodb://127.0.0.1:27017/testdb?retryWrites=false'
1563
+ it 'is rejected' do
1564
+ lambda do
1565
+ client
1566
+ end.should raise_error(ArgumentError, /:wrapping_libraries must be an array of hashes/)
1567
+ end
1568
+ end
1569
+
1570
+ context 'invalid keys' do
1571
+ let(:wrapping_libraries) do
1572
+ [name: 'Mongoid', invalid: '7.1.2'].freeze
774
1573
  end
775
1574
 
776
- it 'sets the option on the client' do
777
- expect(client.options[:retry_writes]).to be false
1575
+ it 'is rejected' do
1576
+ lambda do
1577
+ client
1578
+ end.should raise_error(ArgumentError, /:wrapping_libraries element has invalid keys/)
778
1579
  end
779
1580
  end
780
1581
 
781
- context 'it is true' do
782
- let!(:uri) do
783
- 'mongodb://127.0.0.1:27017/testdb?retryWrites=true'
1582
+ context 'value includes |' do
1583
+ let(:wrapping_libraries) do
1584
+ [name: 'Mongoid|on|Rails', version: '7.1.2'].freeze
784
1585
  end
785
1586
 
786
- it 'sets the option on the client' do
787
- expect(client.options[:retry_writes]).to be true
1587
+ it 'is rejected' do
1588
+ lambda do
1589
+ client
1590
+ end.should raise_error(ArgumentError, /:wrapping_libraries element value cannot include '|'/)
788
1591
  end
789
1592
  end
790
1593
  end
791
1594
  end
792
1595
 
793
- context 'when options are provided not in the string' do
1596
+ context ':auth_mech_properties option' do
1597
+ context 'is nil' do
1598
+ let(:options) do
1599
+ {auth_mech_properties: nil}
1600
+ end
794
1601
 
795
- let!(:uri) do
796
- 'mongodb://127.0.0.1:27017/testdb'
1602
+ it 'creates the client without the option' do
1603
+ client.options.should_not have_key(:auth_mech_properties)
1604
+ end
797
1605
  end
1606
+ end
798
1607
 
799
- let(:client) do
800
- new_local_client_nmio(uri, :write => { :w => 3 })
801
- end
1608
+ context ':server_api parameter' do
1609
+ context 'is a hash with symbol keys' do
1610
+ context 'using known keys' do
1611
+ let(:options) do
1612
+ {server_api: {
1613
+ version: '1',
1614
+ strict: true,
1615
+ deprecation_errors: false,
1616
+ }}
1617
+ end
802
1618
 
803
- let(:expected_options) do
804
- Mongo::Options::Redacted.new(:write => { :w => 3 },
805
- monitoring_io: false, :database => 'testdb', retry_writes: true,
806
- retry_reads: true)
807
- end
1619
+ it 'is accepted' do
1620
+ client.options[:server_api].should == {
1621
+ 'version' => '1',
1622
+ 'strict' => true,
1623
+ 'deprecation_errors' => false,
1624
+ }
1625
+ end
1626
+ end
808
1627
 
809
- it 'sets the options' do
810
- expect(client.options).to eq(expected_options)
811
- end
812
- end
1628
+ context 'using an unknown version' do
1629
+ let(:options) do
1630
+ {server_api: {
1631
+ version: '42',
1632
+ }}
1633
+ end
813
1634
 
814
- context 'when options are provided in the URI and as Ruby options' do
1635
+ it 'is rejected' do
1636
+ lambda do
1637
+ client
1638
+ end.should raise_error(ArgumentError, 'Unknown server API version: 42')
1639
+ end
1640
+ end
815
1641
 
816
- let!(:uri) do
817
- 'mongodb://127.0.0.1:27017/testdb?w=3'
818
- end
1642
+ context 'using an unknown option' do
1643
+ let(:options) do
1644
+ {server_api: {
1645
+ vversion: '1',
1646
+ }}
1647
+ end
819
1648
 
820
- let(:client) do
821
- new_local_client_nmio(uri, option_name => { :w => 4 })
822
- end
1649
+ it 'is rejected' do
1650
+ lambda do
1651
+ client
1652
+ end.should raise_error(ArgumentError, 'Unknown keys under :server_api: "vversion"')
1653
+ end
1654
+ end
823
1655
 
824
- let(:expected_options) do
825
- Mongo::Options::Redacted.new(option_name => { :w => 4 },
826
- monitoring_io: false, :database => 'testdb', retry_writes: true,
827
- retry_reads: true)
828
- end
1656
+ context 'using a value which is not a hash' do
1657
+ let(:options) do
1658
+ {server_api: 42}
1659
+ end
829
1660
 
830
- shared_examples_for 'allows explicit options to take preference' do
831
- it 'allows explicit options to take preference' do
832
- expect(client.options).to eq(expected_options)
1661
+ it 'is rejected' do
1662
+ lambda do
1663
+ client
1664
+ end.should raise_error(ArgumentError, ':server_api value must be a hash: 42')
1665
+ end
833
1666
  end
834
1667
  end
835
1668
 
836
- context 'when using :write' do
837
- let(:option_name) { :write }
1669
+ context 'when connected to a pre-OP_MSG server' do
1670
+ max_server_version '3.4'
838
1671
 
839
- it_behaves_like 'allows explicit options to take preference'
840
- end
1672
+ let(:options) do
1673
+ {server_api: {version: 1}}
1674
+ end
841
1675
 
842
- context 'when using :write_concern' do
843
- let(:option_name) { :write_concern }
1676
+ let(:client) do
1677
+ new_local_client(SpecConfig.instance.addresses,
1678
+ SpecConfig.instance.all_test_options.merge(options))
1679
+ end
844
1680
 
845
- it_behaves_like 'allows explicit options to take preference'
846
- end
847
- end
1681
+ it 'constructs the client' do
1682
+ client.should be_a(Mongo::Client)
1683
+ end
848
1684
 
849
- context 'when a replica set name is provided' do
1685
+ it 'does not discover servers' do
1686
+ client.cluster.servers_list.each do |s|
1687
+ expect(s.status).to eq('UNKNOWN')
1688
+ end
1689
+ end
850
1690
 
851
- let!(:uri) do
852
- 'mongodb://127.0.0.1:27017/testdb?replicaSet=testing'
1691
+ it 'fails operations' do
1692
+ lambda do
1693
+ client.command(ping: 1)
1694
+ end.should raise_error(Mongo::Error::NoServerAvailable)
1695
+ end
853
1696
  end
1697
+ end
1698
+ end
854
1699
 
855
- let(:client) do
856
- new_local_client_nmio(uri)
1700
+ context 'when making a block client' do
1701
+ context 'when the block doesn\'t raise an error' do
1702
+ let(:block_client) do
1703
+ c = nil
1704
+ Mongo::Client.new(
1705
+ SpecConfig.instance.addresses,
1706
+ SpecConfig.instance.test_options.merge(database: SpecConfig.instance.test_db),
1707
+ ) do |client|
1708
+ c = client
1709
+ end
1710
+ c
857
1711
  end
858
1712
 
859
- it 'sets the correct cluster topology' do
860
- expect(client.cluster.topology).to be_a(Mongo::Cluster::Topology::ReplicaSetNoPrimary)
1713
+ it 'is closed after block' do
1714
+ expect(block_client.cluster.connected?).to eq(false)
861
1715
  end
862
1716
  end
863
1717
 
864
- context 'when an invalid option is provided' do
865
-
866
- let(:client) do
867
- new_local_client_nmio(['127.0.0.1:27017'], :ssl => false, :invalid => :test)
868
- end
869
-
870
- it 'does not set the option' do
871
- expect(client.options.keys).not_to include('invalid')
1718
+ context 'when the block raises an error' do
1719
+ it 'it is closed after the block' do
1720
+ block_client_raise = nil
1721
+ expect do
1722
+ Mongo::Client.new(
1723
+ SpecConfig.instance.addresses,
1724
+ SpecConfig.instance.test_options.merge(database: SpecConfig.instance.test_db),
1725
+ ) do |client|
1726
+ block_client_raise = client
1727
+ raise "This is an error!"
1728
+ end
1729
+ end.to raise_error(StandardError, "This is an error!")
1730
+ expect(block_client_raise.cluster.connected?).to eq(false)
872
1731
  end
1732
+ end
873
1733
 
874
- it 'sets the valid options' do
875
- expect(client.options.keys).to include('ssl')
1734
+ context 'when the hosts given include the protocol' do
1735
+ it 'raises an error on mongodb://' do
1736
+ expect do
1737
+ Mongo::Client.new(['mongodb://127.0.0.1:27017/test'])
1738
+ end.to raise_error(ArgumentError, "Host 'mongodb://127.0.0.1:27017/test' should not contain protocol. Did you mean to not use an array?")
876
1739
  end
877
1740
 
878
- it 'warns that an invalid option has been specified' do
879
- expect(Mongo::Logger.logger).to receive(:warn)
880
- expect(client.options.keys).not_to include('invalid')
1741
+ it 'raises an error on mongodb+srv://' do
1742
+ expect do
1743
+ Mongo::Client.new(['mongodb+srv://127.0.0.1:27017/test'])
1744
+ end.to raise_error(ArgumentError, "Host 'mongodb+srv://127.0.0.1:27017/test' should not contain protocol. Did you mean to not use an array?")
881
1745
  end
882
- end
883
-
884
- =begin WriteConcern object support
885
- context 'when write concern is provided via a WriteConcern object' do
886
1746
 
887
- let(:client) do
888
- new_local_client_nmio(['127.0.0.1:27017'], write_concern: wc)
1747
+ it 'raises an error on multiple items' do
1748
+ expect do
1749
+ Mongo::Client.new(['127.0.0.1:27017', 'mongodb+srv://127.0.0.1:27017/test'])
1750
+ end.to raise_error(ArgumentError, "Host 'mongodb+srv://127.0.0.1:27017/test' should not contain protocol. Did you mean to not use an array?")
889
1751
  end
890
1752
 
891
- let(:wc) { Mongo::WriteConcern.get(w: 2) }
892
-
893
- it 'stores write concern options in client options' do
894
- expect(client.options[:write_concern]).to eq(
895
- Mongo::Options::Redacted.new(w: 2))
1753
+ it 'raises an error only at beginning of string' do
1754
+ expect do
1755
+ Mongo::Client.new(['somethingmongodb://127.0.0.1:27017/test', 'mongodb+srv://127.0.0.1:27017/test'])
1756
+ end.to raise_error(ArgumentError, "Host 'mongodb+srv://127.0.0.1:27017/test' should not contain protocol. Did you mean to not use an array?")
896
1757
  end
897
1758
 
898
- it 'caches write concern object' do
899
- expect(client.write_concern).to be wc
1759
+ it 'raises an error with different case' do
1760
+ expect do
1761
+ Mongo::Client.new(['MongOdB://127.0.0.1:27017/test'])
1762
+ end.to raise_error(ArgumentError, "Host 'MongOdB://127.0.0.1:27017/test' should not contain protocol. Did you mean to not use an array?")
900
1763
  end
901
1764
  end
902
- =end
903
1765
  end
904
1766
  end
905
1767
 
@@ -913,7 +1775,7 @@ describe Mongo::Client do
913
1775
 
914
1776
  it 'copies monitoring subscribers' do
915
1777
  monitoring.subscribers.clear
916
- client.subscribe(Mongo::Monitoring::SERVER_HEARTBEAT, EventSubscriber.new)
1778
+ client.subscribe(Mongo::Monitoring::SERVER_HEARTBEAT, subscriber)
917
1779
  expect(monitoring.present_subscribers.length).to eq(1)
918
1780
  expect(monitoring.subscribers[Mongo::Monitoring::SERVER_HEARTBEAT].length).to eq(1)
919
1781
 
@@ -924,12 +1786,12 @@ describe Mongo::Client do
924
1786
 
925
1787
  it 'does not change subscribers on original client' do
926
1788
  monitoring.subscribers.clear
927
- client.subscribe(Mongo::Monitoring::SERVER_HEARTBEAT, EventSubscriber.new)
1789
+ client.subscribe(Mongo::Monitoring::SERVER_HEARTBEAT, subscriber)
928
1790
  expect(monitoring.present_subscribers.length).to eq(1)
929
1791
  expect(monitoring.subscribers[Mongo::Monitoring::SERVER_HEARTBEAT].length).to eq(1)
930
1792
 
931
- new_client.subscribe(Mongo::Monitoring::SERVER_HEARTBEAT, EventSubscriber.new)
932
- new_client.subscribe(Mongo::Monitoring::SERVER_HEARTBEAT, EventSubscriber.new)
1793
+ new_client.subscribe(Mongo::Monitoring::SERVER_HEARTBEAT, subscriber)
1794
+ new_client.subscribe(Mongo::Monitoring::SERVER_HEARTBEAT, subscriber)
933
1795
  expect(new_monitoring.present_subscribers.length).to eq(1)
934
1796
  expect(new_monitoring.subscribers[Mongo::Monitoring::SERVER_HEARTBEAT].length).to eq(3)
935
1797
  # original client should not have gotten any of the new subscribers
@@ -957,7 +1819,7 @@ describe Mongo::Client do
957
1819
 
958
1820
  it 'resets monitoring subscribers' do
959
1821
  monitoring.subscribers.clear
960
- client.subscribe(Mongo::Monitoring::SERVER_HEARTBEAT, EventSubscriber.new)
1822
+ client.subscribe(Mongo::Monitoring::SERVER_HEARTBEAT, subscriber)
961
1823
  expect(monitoring.present_subscribers.length).to eq(1)
962
1824
  expect(monitoring.subscribers[Mongo::Monitoring::SERVER_HEARTBEAT].length).to eq(1)
963
1825
 
@@ -970,12 +1832,12 @@ describe Mongo::Client do
970
1832
 
971
1833
  it 'does not change subscribers on original client' do
972
1834
  monitoring.subscribers.clear
973
- client.subscribe(Mongo::Monitoring::SERVER_HEARTBEAT, EventSubscriber.new)
1835
+ client.subscribe(Mongo::Monitoring::SERVER_HEARTBEAT, subscriber)
974
1836
  expect(monitoring.present_subscribers.length).to eq(1)
975
1837
  expect(monitoring.subscribers[Mongo::Monitoring::SERVER_HEARTBEAT].length).to eq(1)
976
1838
 
977
- new_client.subscribe(Mongo::Monitoring::SERVER_HEARTBEAT, EventSubscriber.new)
978
- new_client.subscribe(Mongo::Monitoring::SERVER_HEARTBEAT, EventSubscriber.new)
1839
+ new_client.subscribe(Mongo::Monitoring::SERVER_HEARTBEAT, subscriber)
1840
+ new_client.subscribe(Mongo::Monitoring::SERVER_HEARTBEAT, subscriber)
979
1841
  # 7 default subscribers + heartbeat
980
1842
  expect(new_monitoring.present_subscribers.length).to eq(8)
981
1843
  # the heartbeat subscriber on the original client is not inherited
@@ -1079,6 +1941,73 @@ describe Mongo::Client do
1079
1941
  end
1080
1942
  end
1081
1943
 
1944
+ context 'when direct_connection option is given' do
1945
+ let(:client) do
1946
+ options = SpecConfig.instance.test_options
1947
+ options.delete(:connect)
1948
+ new_local_client(SpecConfig.instance.addresses, options)
1949
+ end
1950
+
1951
+ before do
1952
+ client.options[:direct_connection].should be nil
1953
+ end
1954
+
1955
+ let(:new_client) do
1956
+ client.with(new_options)
1957
+ end
1958
+
1959
+ context 'direct_connection set to false' do
1960
+
1961
+ let(:new_options) do
1962
+ { direct_connection: false }
1963
+ end
1964
+
1965
+ it 'is accepted' do
1966
+ new_client.options[:direct_connection].should be false
1967
+ end
1968
+ end
1969
+
1970
+ context 'direct_connection set to true' do
1971
+
1972
+ let(:new_options) do
1973
+ { direct_connection: true }
1974
+ end
1975
+
1976
+ context 'in single topology' do
1977
+ require_topology :single
1978
+
1979
+
1980
+ it 'is accepted' do
1981
+ new_client.options[:direct_connection].should be true
1982
+ new_client.cluster.topology.should be_a(Mongo::Cluster::Topology::Single)
1983
+ end
1984
+ end
1985
+
1986
+ context 'in replica set or sharded cluster topology' do
1987
+ require_topology :replica_set, :sharded
1988
+
1989
+ it 'is rejected' do
1990
+ lambda do
1991
+ new_client
1992
+ end.should raise_error(ArgumentError, /direct_connection=true cannot be used with topologies other than Single/)
1993
+ end
1994
+
1995
+ context 'when a new cluster is created' do
1996
+
1997
+ let(:new_options) do
1998
+ { direct_connection: true, app_name: 'new-client' }
1999
+ end
2000
+
2001
+ it 'is rejected' do
2002
+ lambda do
2003
+ new_client
2004
+ end.should raise_error(ArgumentError, /direct_connection=true cannot be used with topologies other than Single/)
2005
+ end
2006
+ end
2007
+ end
2008
+ end
2009
+ end
2010
+
1082
2011
  context 'when the write concern is not changed' do
1083
2012
 
1084
2013
  let(:client) do
@@ -1323,7 +2252,10 @@ describe Mongo::Client do
1323
2252
 
1324
2253
  context 'when new client has a new cluster' do
1325
2254
  let(:client) do
1326
- new_local_client(['127.0.0.1:27017'], :database => SpecConfig.instance.test_db)
2255
+ new_local_client(['127.0.0.1:27017'],
2256
+ database: SpecConfig.instance.test_db,
2257
+ server_selection_timeout: 0.5,
2258
+ socket_timeout: 0.1, connect_timeout: 0.1)
1327
2259
  end
1328
2260
  let(:new_client) do
1329
2261
  client.with(app_name: 'client_construction_spec').tap do |new_client|
@@ -1348,7 +2280,6 @@ describe Mongo::Client do
1348
2280
  # in #with, the consistent behavior is to never transfer sdam_proc to
1349
2281
  # the new client.
1350
2282
  context 'when sdam_proc is given on original client' do
1351
- let(:subscriber) { EventSubscriber.new }
1352
2283
 
1353
2284
  let(:sdam_proc) do
1354
2285
  Proc.new do |client|
@@ -1356,31 +2287,91 @@ describe Mongo::Client do
1356
2287
  end
1357
2288
  end
1358
2289
 
1359
- let(:new_client) { client.with(database: 'foo') }
2290
+ let(:client) do
2291
+ new_local_client(SpecConfig.instance.addresses,
2292
+ SpecConfig.instance.test_options.merge(
2293
+ sdam_proc: sdam_proc,
2294
+ connect_timeout: 3.08, socket_timeout: 3.09,
2295
+ server_selection_timeout: 2.92,
2296
+ heartbeat_frequency: 100,
2297
+ database: SpecConfig.instance.test_db))
2298
+ end
2299
+
2300
+ let(:new_client) do
2301
+ client.with(app_name: 'foo').tap do |new_client|
2302
+ new_client.cluster.should_not == client.cluster
2303
+ end
2304
+ end
2305
+
2306
+ before do
2307
+ client.cluster.next_primary
2308
+ events = subscriber.select_started_events(Mongo::Monitoring::Event::ServerHeartbeatStarted)
2309
+ events.length.should > 0
2310
+ end
1360
2311
 
1361
2312
  it 'does not copy sdam_proc option to new client' do
1362
- client = new_local_client(['a'], sdam_proc: sdam_proc)
1363
2313
  expect(new_client.options[:sdam_proc]).to be nil
1364
2314
  end
1365
2315
 
1366
2316
  it 'does not notify subscribers set up by sdam_proc' do
1367
- client = new_local_client(['a'], sdam_proc: sdam_proc)
2317
+ # On 4.4, the push monitor also is receiving heartbeats.
2318
+ # Give those some time to be processed.
2319
+ sleep 2
2320
+
1368
2321
  expect(subscriber.started_events.length).to be > 0
1369
2322
  subscriber.started_events.clear
1370
2323
 
1371
2324
  # If this test takes longer than heartbeat interval,
1372
2325
  # subscriber may receive events from the original client.
1373
2326
 
1374
- new_client
2327
+ new_client.cluster.next_primary
2328
+
2329
+ # Diagnostics
2330
+ unless subscriber.started_events.empty?
2331
+ p subscriber.started_events
2332
+ end
2333
+
1375
2334
  expect(subscriber.started_events.length).to eq 0
2335
+ new_client.cluster.topology.class.should_not be Mongo::Cluster::Topology::Unknown
2336
+ end
2337
+ end
2338
+
2339
+ context 'when :server_api is changed' do
2340
+
2341
+ let(:client) do
2342
+ new_local_client_nmio(['127.0.0.1:27017'])
2343
+ end
2344
+
2345
+ let(:new_client) do
2346
+ client.with(server_api: {version: '1'})
2347
+ end
2348
+
2349
+ it 'changes :server_api' do
2350
+ new_client.options[:server_api].should == {'version' => '1'}
2351
+ end
2352
+ end
2353
+
2354
+ context 'when :server_api is cleared' do
2355
+
2356
+ let(:client) do
2357
+ new_local_client_nmio(['127.0.0.1:27017'], server_api: {version: '1'})
2358
+ end
2359
+
2360
+ let(:new_client) do
2361
+ client.with(server_api: nil)
2362
+ end
2363
+
2364
+ it 'clears :server_api' do
2365
+ new_client.options[:server_api].should be nil
1376
2366
  end
1377
2367
  end
2368
+
1378
2369
  end
1379
2370
 
1380
2371
  describe '#dup' do
1381
2372
 
1382
2373
  let(:client) do
1383
- new_local_client(
2374
+ new_local_client_nmio(
1384
2375
  ['127.0.0.1:27017'],
1385
2376
  :read => { :mode => :primary },
1386
2377
  :database => SpecConfig.instance.test_db