mongo 2.13.0.beta1 → 2.14.0

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 (339) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +1 -5
  4. data/Rakefile +50 -9
  5. data/lib/mongo.rb +13 -2
  6. data/lib/mongo/address.rb +1 -1
  7. data/lib/mongo/address/ipv4.rb +1 -1
  8. data/lib/mongo/address/ipv6.rb +1 -1
  9. data/lib/mongo/auth/aws/request.rb +31 -5
  10. data/lib/mongo/bulk_write.rb +18 -0
  11. data/lib/mongo/caching_cursor.rb +74 -0
  12. data/lib/mongo/client.rb +238 -31
  13. data/lib/mongo/cluster.rb +56 -20
  14. data/lib/mongo/cluster/sdam_flow.rb +13 -10
  15. data/lib/mongo/cluster/topology/replica_set_no_primary.rb +3 -2
  16. data/lib/mongo/cluster/topology/sharded.rb +1 -1
  17. data/lib/mongo/cluster/topology/single.rb +2 -2
  18. data/lib/mongo/collection.rb +66 -24
  19. data/lib/mongo/collection/view.rb +24 -20
  20. data/lib/mongo/collection/view/aggregation.rb +25 -4
  21. data/lib/mongo/collection/view/builder/find_command.rb +38 -18
  22. data/lib/mongo/collection/view/explainable.rb +27 -8
  23. data/lib/mongo/collection/view/iterable.rb +72 -12
  24. data/lib/mongo/collection/view/readable.rb +19 -3
  25. data/lib/mongo/collection/view/writable.rb +55 -5
  26. data/lib/mongo/crypt/encryption_io.rb +6 -6
  27. data/lib/mongo/cursor.rb +16 -3
  28. data/lib/mongo/database.rb +37 -4
  29. data/lib/mongo/database/view.rb +18 -3
  30. data/lib/mongo/distinguishing_semaphore.rb +55 -0
  31. data/lib/mongo/error.rb +5 -0
  32. data/lib/mongo/error/invalid_read_concern.rb +28 -0
  33. data/lib/mongo/error/invalid_server_auth_host.rb +22 -0
  34. data/lib/mongo/error/invalid_session.rb +2 -1
  35. data/lib/mongo/error/operation_failure.rb +11 -5
  36. data/lib/mongo/error/server_certificate_revoked.rb +22 -0
  37. data/lib/mongo/error/sessions_not_supported.rb +35 -0
  38. data/lib/mongo/error/unsupported_option.rb +14 -12
  39. data/lib/mongo/event/base.rb +6 -0
  40. data/lib/mongo/grid/file.rb +5 -0
  41. data/lib/mongo/grid/file/chunk.rb +2 -0
  42. data/lib/mongo/grid/fs_bucket.rb +15 -13
  43. data/lib/mongo/grid/stream/write.rb +9 -3
  44. data/lib/mongo/index/view.rb +3 -0
  45. data/lib/mongo/lint.rb +2 -1
  46. data/lib/mongo/logger.rb +3 -3
  47. data/lib/mongo/monitoring.rb +38 -0
  48. data/lib/mongo/monitoring/command_log_subscriber.rb +10 -2
  49. data/lib/mongo/monitoring/event/command_failed.rb +11 -0
  50. data/lib/mongo/monitoring/event/command_started.rb +37 -2
  51. data/lib/mongo/monitoring/event/command_succeeded.rb +11 -0
  52. data/lib/mongo/monitoring/event/server_closed.rb +1 -1
  53. data/lib/mongo/monitoring/event/server_description_changed.rb +27 -4
  54. data/lib/mongo/monitoring/event/server_heartbeat_failed.rb +9 -2
  55. data/lib/mongo/monitoring/event/server_heartbeat_started.rb +9 -2
  56. data/lib/mongo/monitoring/event/server_heartbeat_succeeded.rb +9 -2
  57. data/lib/mongo/monitoring/event/server_opening.rb +1 -1
  58. data/lib/mongo/monitoring/event/topology_changed.rb +1 -1
  59. data/lib/mongo/monitoring/event/topology_closed.rb +1 -1
  60. data/lib/mongo/monitoring/event/topology_opening.rb +1 -1
  61. data/lib/mongo/monitoring/publishable.rb +6 -3
  62. data/lib/mongo/monitoring/server_description_changed_log_subscriber.rb +9 -1
  63. data/lib/mongo/monitoring/topology_changed_log_subscriber.rb +1 -1
  64. data/lib/mongo/operation.rb +2 -0
  65. data/lib/mongo/operation/aggregate/result.rb +9 -8
  66. data/lib/mongo/operation/collections_info/command.rb +5 -0
  67. data/lib/mongo/operation/collections_info/result.rb +18 -1
  68. data/lib/mongo/operation/delete/bulk_result.rb +2 -0
  69. data/lib/mongo/operation/delete/result.rb +3 -0
  70. data/lib/mongo/operation/explain/command.rb +4 -0
  71. data/lib/mongo/operation/explain/legacy.rb +4 -0
  72. data/lib/mongo/operation/explain/op_msg.rb +6 -0
  73. data/lib/mongo/operation/explain/result.rb +3 -0
  74. data/lib/mongo/operation/find/legacy/result.rb +2 -0
  75. data/lib/mongo/operation/find/result.rb +13 -0
  76. data/lib/mongo/operation/get_more/result.rb +3 -0
  77. data/lib/mongo/operation/indexes/result.rb +5 -0
  78. data/lib/mongo/operation/insert/bulk_result.rb +5 -0
  79. data/lib/mongo/operation/insert/result.rb +5 -0
  80. data/lib/mongo/operation/list_collections/result.rb +5 -0
  81. data/lib/mongo/operation/map_reduce/result.rb +10 -0
  82. data/lib/mongo/operation/parallel_scan/result.rb +4 -0
  83. data/lib/mongo/operation/result.rb +35 -6
  84. data/lib/mongo/operation/shared/bypass_document_validation.rb +1 -0
  85. data/lib/mongo/operation/shared/causal_consistency_supported.rb +1 -0
  86. data/lib/mongo/operation/shared/collections_info_or_list_collections.rb +2 -0
  87. data/lib/mongo/operation/shared/executable.rb +1 -0
  88. data/lib/mongo/operation/shared/idable.rb +2 -1
  89. data/lib/mongo/operation/shared/limited.rb +1 -0
  90. data/lib/mongo/operation/shared/object_id_generator.rb +1 -0
  91. data/lib/mongo/operation/shared/result/aggregatable.rb +1 -0
  92. data/lib/mongo/operation/shared/sessions_supported.rb +1 -0
  93. data/lib/mongo/operation/shared/specifiable.rb +1 -0
  94. data/lib/mongo/operation/shared/write.rb +1 -0
  95. data/lib/mongo/operation/shared/write_concern_supported.rb +1 -0
  96. data/lib/mongo/operation/update/legacy/result.rb +7 -0
  97. data/lib/mongo/operation/update/result.rb +8 -0
  98. data/lib/mongo/operation/users_info/result.rb +3 -0
  99. data/lib/mongo/protocol/message.rb +47 -10
  100. data/lib/mongo/protocol/msg.rb +34 -1
  101. data/lib/mongo/protocol/query.rb +36 -0
  102. data/lib/mongo/protocol/serializers.rb +5 -2
  103. data/lib/mongo/query_cache.rb +242 -0
  104. data/lib/mongo/retryable.rb +8 -1
  105. data/lib/mongo/server.rb +15 -4
  106. data/lib/mongo/server/app_metadata.rb +27 -3
  107. data/lib/mongo/server/connection.rb +4 -4
  108. data/lib/mongo/server/connection_base.rb +38 -12
  109. data/lib/mongo/server/connection_common.rb +2 -2
  110. data/lib/mongo/server/connection_pool.rb +3 -0
  111. data/lib/mongo/server/description.rb +13 -1
  112. data/lib/mongo/server/monitor.rb +76 -44
  113. data/lib/mongo/server/monitor/connection.rb +57 -9
  114. data/lib/mongo/server/pending_connection.rb +14 -4
  115. data/lib/mongo/server/push_monitor.rb +173 -0
  116. data/{spec/runners/transactions/context.rb → lib/mongo/server/push_monitor/connection.rb} +9 -14
  117. data/lib/mongo/server_selector.rb +0 -1
  118. data/lib/mongo/server_selector/base.rb +583 -1
  119. data/lib/mongo/server_selector/nearest.rb +1 -6
  120. data/lib/mongo/server_selector/primary.rb +1 -6
  121. data/lib/mongo/server_selector/primary_preferred.rb +7 -10
  122. data/lib/mongo/server_selector/secondary.rb +1 -6
  123. data/lib/mongo/server_selector/secondary_preferred.rb +1 -7
  124. data/lib/mongo/session.rb +7 -1
  125. data/lib/mongo/socket.rb +26 -12
  126. data/lib/mongo/socket/ocsp_cache.rb +97 -0
  127. data/lib/mongo/socket/ocsp_verifier.rb +368 -0
  128. data/lib/mongo/socket/ssl.rb +46 -25
  129. data/lib/mongo/socket/tcp.rb +1 -1
  130. data/lib/mongo/srv/monitor.rb +7 -13
  131. data/lib/mongo/srv/resolver.rb +14 -10
  132. data/lib/mongo/timeout.rb +2 -0
  133. data/lib/mongo/topology_version.rb +9 -0
  134. data/lib/mongo/uri.rb +21 -390
  135. data/lib/mongo/uri/options_mapper.rb +582 -0
  136. data/lib/mongo/uri/srv_protocol.rb +3 -2
  137. data/lib/mongo/utils.rb +73 -0
  138. data/lib/mongo/version.rb +1 -1
  139. data/spec/NOTES.aws-auth.md +12 -7
  140. data/spec/README.aws-auth.md +2 -2
  141. data/spec/README.md +63 -1
  142. data/spec/integration/awaited_ismaster_spec.rb +28 -0
  143. data/spec/integration/bson_symbol_spec.rb +4 -2
  144. data/spec/integration/bulk_write_spec.rb +67 -0
  145. data/spec/integration/change_stream_examples_spec.rb +6 -2
  146. data/spec/integration/change_stream_spec.rb +1 -1
  147. data/spec/integration/check_clean_slate_spec.rb +16 -0
  148. data/spec/integration/client_authentication_options_spec.rb +92 -28
  149. data/spec/integration/client_construction_spec.rb +1 -0
  150. data/spec/integration/client_side_encryption/auto_encryption_bulk_writes_spec.rb +9 -5
  151. data/spec/integration/connect_single_rs_name_spec.rb +5 -2
  152. data/spec/integration/connection_pool_populator_spec.rb +4 -2
  153. data/spec/integration/connection_spec.rb +7 -4
  154. data/spec/integration/crud_spec.rb +4 -4
  155. data/spec/integration/cursor_reaping_spec.rb +54 -18
  156. data/spec/integration/docs_examples_spec.rb +6 -0
  157. data/spec/integration/fork_reconnect_spec.rb +56 -1
  158. data/spec/integration/grid_fs_bucket_spec.rb +48 -0
  159. data/spec/integration/heartbeat_events_spec.rb +4 -23
  160. data/spec/integration/ocsp_connectivity_spec.rb +26 -0
  161. data/spec/integration/ocsp_verifier_cache_spec.rb +188 -0
  162. data/spec/integration/ocsp_verifier_spec.rb +334 -0
  163. data/spec/integration/query_cache_spec.rb +1045 -0
  164. data/spec/integration/query_cache_transactions_spec.rb +190 -0
  165. data/spec/integration/read_concern_spec.rb +1 -1
  166. data/spec/integration/retryable_errors_spec.rb +1 -1
  167. data/spec/integration/retryable_writes/retryable_writes_40_and_newer_spec.rb +1 -0
  168. data/spec/integration/retryable_writes/shared/performs_legacy_retries.rb +4 -2
  169. data/spec/integration/retryable_writes/shared/performs_modern_retries.rb +3 -3
  170. data/spec/integration/retryable_writes/shared/performs_no_retries.rb +2 -2
  171. data/spec/integration/sdam_error_handling_spec.rb +122 -15
  172. data/spec/integration/sdam_events_spec.rb +80 -6
  173. data/spec/integration/sdam_prose_spec.rb +64 -0
  174. data/spec/integration/server_monitor_spec.rb +25 -1
  175. data/spec/integration/server_selection_spec.rb +36 -0
  176. data/spec/integration/size_limit_spec.rb +23 -5
  177. data/spec/integration/srv_monitoring_spec.rb +38 -3
  178. data/spec/integration/srv_spec.rb +56 -0
  179. data/spec/integration/ssl_uri_options_spec.rb +2 -2
  180. data/spec/integration/transactions_examples_spec.rb +17 -7
  181. data/spec/integration/zlib_compression_spec.rb +25 -0
  182. data/spec/lite_spec_helper.rb +20 -9
  183. data/spec/mongo/address_spec.rb +1 -1
  184. data/spec/mongo/auth/aws/request_region_spec.rb +42 -0
  185. data/spec/mongo/auth/aws/request_spec.rb +76 -0
  186. data/spec/mongo/auth/scram_spec.rb +1 -1
  187. data/spec/mongo/auth/user_spec.rb +1 -1
  188. data/spec/mongo/bulk_write_spec.rb +2 -2
  189. data/spec/mongo/caching_cursor_spec.rb +70 -0
  190. data/spec/mongo/client_construction_spec.rb +386 -3
  191. data/spec/mongo/client_encryption_spec.rb +16 -10
  192. data/spec/mongo/client_spec.rb +85 -3
  193. data/spec/mongo/cluster/topology/replica_set_spec.rb +53 -10
  194. data/spec/mongo/cluster/topology/sharded_spec.rb +1 -1
  195. data/spec/mongo/cluster/topology/single_spec.rb +19 -8
  196. data/spec/mongo/cluster/topology/unknown_spec.rb +1 -1
  197. data/spec/mongo/cluster/topology_spec.rb +1 -1
  198. data/spec/mongo/cluster_spec.rb +37 -35
  199. data/spec/mongo/collection/view/change_stream_resume_spec.rb +7 -7
  200. data/spec/mongo/collection/view/explainable_spec.rb +87 -4
  201. data/spec/mongo/collection/view/map_reduce_spec.rb +2 -0
  202. data/spec/mongo/collection/view/readable_spec.rb +36 -0
  203. data/spec/mongo/collection_spec.rb +572 -0
  204. data/spec/mongo/crypt/auto_decryption_context_spec.rb +1 -1
  205. data/spec/mongo/crypt/auto_encryption_context_spec.rb +1 -1
  206. data/spec/mongo/crypt/binary_spec.rb +1 -6
  207. data/spec/mongo/crypt/binding/binary_spec.rb +1 -6
  208. data/spec/mongo/crypt/binding/context_spec.rb +2 -7
  209. data/spec/mongo/crypt/binding/helpers_spec.rb +1 -6
  210. data/spec/mongo/crypt/binding/mongocrypt_spec.rb +2 -7
  211. data/spec/mongo/crypt/binding/status_spec.rb +1 -6
  212. data/spec/mongo/crypt/binding/version_spec.rb +1 -6
  213. data/spec/mongo/crypt/data_key_context_spec.rb +1 -1
  214. data/spec/mongo/crypt/explicit_decryption_context_spec.rb +1 -1
  215. data/spec/mongo/crypt/explicit_encryption_context_spec.rb +1 -1
  216. data/spec/mongo/crypt/status_spec.rb +1 -6
  217. data/spec/mongo/database_spec.rb +353 -8
  218. data/spec/mongo/distinguishing_semaphore_spec.rb +63 -0
  219. data/spec/mongo/error/no_server_available_spec.rb +1 -1
  220. data/spec/mongo/error/operation_failure_spec.rb +40 -0
  221. data/spec/mongo/index/view_spec.rb +148 -2
  222. data/spec/mongo/logger_spec.rb +13 -11
  223. data/spec/mongo/monitoring/event/server_closed_spec.rb +1 -1
  224. data/spec/mongo/monitoring/event/server_description_changed_spec.rb +1 -4
  225. data/spec/mongo/monitoring/event/server_opening_spec.rb +1 -1
  226. data/spec/mongo/monitoring/event/topology_changed_spec.rb +1 -1
  227. data/spec/mongo/monitoring/event/topology_closed_spec.rb +1 -1
  228. data/spec/mongo/monitoring/event/topology_opening_spec.rb +1 -1
  229. data/spec/mongo/operation/delete/op_msg_spec.rb +3 -3
  230. data/spec/mongo/operation/insert/command_spec.rb +2 -2
  231. data/spec/mongo/operation/insert/op_msg_spec.rb +3 -3
  232. data/spec/mongo/operation/read_preference_op_msg_spec.rb +1 -1
  233. data/spec/mongo/operation/update/command_spec.rb +2 -2
  234. data/spec/mongo/operation/update/op_msg_spec.rb +3 -3
  235. data/spec/mongo/protocol/msg_spec.rb +10 -0
  236. data/spec/mongo/query_cache_spec.rb +280 -0
  237. data/spec/mongo/semaphore_spec.rb +51 -0
  238. data/spec/mongo/server/app_metadata_shared.rb +82 -2
  239. data/spec/mongo/server/connection_auth_spec.rb +2 -2
  240. data/spec/mongo/server/connection_pool_spec.rb +7 -3
  241. data/spec/mongo/server/connection_spec.rb +15 -8
  242. data/spec/mongo/server/description_spec.rb +18 -0
  243. data/spec/mongo/server_selector/nearest_spec.rb +23 -23
  244. data/spec/mongo/server_selector/primary_preferred_spec.rb +26 -26
  245. data/spec/mongo/server_selector/primary_spec.rb +9 -9
  246. data/spec/mongo/server_selector/secondary_preferred_spec.rb +22 -22
  247. data/spec/mongo/server_selector/secondary_spec.rb +18 -18
  248. data/spec/mongo/server_selector_spec.rb +6 -6
  249. data/spec/mongo/session_spec.rb +35 -0
  250. data/spec/mongo/socket/ssl_spec.rb +4 -4
  251. data/spec/mongo/socket_spec.rb +1 -1
  252. data/spec/mongo/uri/srv_protocol_spec.rb +64 -33
  253. data/spec/mongo/uri_option_parsing_spec.rb +11 -11
  254. data/spec/mongo/uri_spec.rb +68 -41
  255. data/spec/mongo/utils_spec.rb +39 -0
  256. data/spec/runners/auth.rb +3 -0
  257. data/spec/runners/change_streams/test.rb +3 -3
  258. data/spec/runners/cmap.rb +1 -1
  259. data/spec/runners/command_monitoring.rb +3 -34
  260. data/spec/runners/connection_string.rb +35 -124
  261. data/spec/runners/crud/context.rb +9 -5
  262. data/spec/runners/crud/operation.rb +59 -27
  263. data/spec/runners/crud/spec.rb +0 -8
  264. data/spec/runners/crud/test.rb +1 -1
  265. data/spec/runners/crud/test_base.rb +0 -19
  266. data/spec/runners/sdam.rb +2 -2
  267. data/spec/runners/server_selection.rb +242 -28
  268. data/spec/runners/transactions.rb +12 -12
  269. data/spec/runners/transactions/operation.rb +151 -25
  270. data/spec/runners/transactions/test.rb +62 -18
  271. data/spec/shared/LICENSE +20 -0
  272. data/spec/shared/lib/mrss/child_process_helper.rb +80 -0
  273. data/spec/shared/lib/mrss/constraints.rb +303 -0
  274. data/spec/shared/lib/mrss/lite_constraints.rb +175 -0
  275. data/spec/shared/lib/mrss/spec_organizer.rb +149 -0
  276. data/spec/spec_helper.rb +3 -1
  277. data/spec/spec_tests/cmap_spec.rb +7 -3
  278. data/spec/spec_tests/command_monitoring_spec.rb +22 -12
  279. data/spec/spec_tests/crud_spec.rb +1 -1
  280. data/spec/spec_tests/data/change_streams/change-streams-errors.yml +4 -9
  281. data/spec/spec_tests/data/change_streams/change-streams-resume-whitelist.yml +66 -0
  282. data/spec/spec_tests/data/change_streams/change-streams.yml +0 -1
  283. data/spec/spec_tests/data/cmap/pool-checkout-connection.yml +6 -2
  284. data/spec/spec_tests/data/cmap/pool-create-min-size.yml +3 -0
  285. data/spec/spec_tests/data/connection_string/valid-warnings.yml +24 -0
  286. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/MaxStalenessTooSmall.yml +15 -0
  287. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/NoKnownServers.yml +4 -3
  288. data/spec/spec_tests/data/max_staleness/Unknown/SmallMaxStaleness.yml +1 -0
  289. data/spec/spec_tests/data/sdam_integration/cancel-server-check.yml +96 -0
  290. data/spec/spec_tests/data/sdam_integration/connectTimeoutMS.yml +88 -0
  291. data/spec/spec_tests/data/sdam_integration/find-network-error.yml +83 -0
  292. data/spec/spec_tests/data/sdam_integration/find-shutdown-error.yml +116 -0
  293. data/spec/spec_tests/data/sdam_integration/insert-network-error.yml +86 -0
  294. data/spec/spec_tests/data/sdam_integration/insert-shutdown-error.yml +115 -0
  295. data/spec/spec_tests/data/sdam_integration/isMaster-command-error.yml +168 -0
  296. data/spec/spec_tests/data/sdam_integration/isMaster-network-error.yml +162 -0
  297. data/spec/spec_tests/data/sdam_integration/isMaster-timeout.yml +229 -0
  298. data/spec/spec_tests/data/sdam_integration/rediscover-quickly-after-step-down.yml +87 -0
  299. data/spec/spec_tests/data/sdam_monitoring/discovered_standalone.yml +1 -3
  300. data/spec/spec_tests/data/sdam_monitoring/standalone.yml +2 -2
  301. data/spec/spec_tests/data/sdam_monitoring/standalone_repeated.yml +2 -2
  302. data/spec/spec_tests/data/sdam_monitoring/standalone_suppress_equal_description_changes.yml +2 -2
  303. data/spec/spec_tests/data/sdam_monitoring/standalone_to_rs_with_me_mismatch.yml +2 -2
  304. data/spec/spec_tests/data/uri_options/auth-options.yml +25 -0
  305. data/spec/spec_tests/data/uri_options/compression-options.yml +6 -3
  306. data/spec/spec_tests/data/uri_options/read-preference-options.yml +24 -0
  307. data/spec/spec_tests/data/uri_options/ruby-connection-options.yml +1 -0
  308. data/spec/spec_tests/data/uri_options/tls-options.yml +160 -4
  309. data/spec/spec_tests/dns_seedlist_discovery_spec.rb +9 -1
  310. data/spec/spec_tests/max_staleness_spec.rb +4 -142
  311. data/spec/spec_tests/retryable_reads_spec.rb +2 -2
  312. data/spec/spec_tests/sdam_integration_spec.rb +13 -0
  313. data/spec/spec_tests/sdam_monitoring_spec.rb +1 -2
  314. data/spec/spec_tests/server_selection_spec.rb +4 -116
  315. data/spec/spec_tests/uri_options_spec.rb +31 -33
  316. data/spec/stress/cleanup_spec.rb +17 -2
  317. data/spec/stress/connection_pool_stress_spec.rb +10 -8
  318. data/spec/stress/fork_reconnect_stress_spec.rb +1 -1
  319. data/spec/support/certificates/atlas-ocsp-ca.crt +28 -0
  320. data/spec/support/certificates/atlas-ocsp.crt +41 -0
  321. data/spec/support/client_registry.rb +1 -0
  322. data/spec/support/client_registry_macros.rb +11 -2
  323. data/spec/support/cluster_config.rb +4 -0
  324. data/spec/support/common_shortcuts.rb +45 -0
  325. data/spec/support/constraints.rb +6 -253
  326. data/spec/support/event_subscriber.rb +123 -33
  327. data/spec/support/keyword_struct.rb +26 -0
  328. data/spec/support/matchers.rb +16 -0
  329. data/spec/support/ocsp +1 -0
  330. data/spec/support/session_registry.rb +52 -0
  331. data/spec/support/shared/server_selector.rb +13 -1
  332. data/spec/support/spec_config.rb +60 -13
  333. data/spec/support/spec_setup.rb +1 -1
  334. data/spec/support/utils.rb +84 -1
  335. metadata +1027 -937
  336. metadata.gz.sig +0 -0
  337. data/lib/mongo/server_selector/selectable.rb +0 -560
  338. data/spec/runners/sdam_monitoring.rb +0 -89
  339. data/spec/support/lite_constraints.rb +0 -141
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Zlib compression' do
4
+ require_compression
5
+
6
+ before do
7
+ authorized_client['test'].drop
8
+ end
9
+
10
+ context 'when client has zlib compressor option enabled' do
11
+ it 'compresses the message to the server' do
12
+ # Double check that the client has zlib compression enabled
13
+ expect(authorized_client.options[:compressors]).to include('zlib')
14
+
15
+ expect(Mongo::Protocol::Compressed).to receive(:new).twice.and_call_original
16
+ expect(Zlib::Deflate).to receive(:deflate).twice.and_call_original
17
+ expect(Zlib::Inflate).to receive(:inflate).twice.and_call_original
18
+
19
+ authorized_client['test'].insert_one(_id: 1, text: 'hello world')
20
+ document = authorized_client['test'].find(_id: 1).first
21
+
22
+ expect(document['text']).to eq('hello world')
23
+ end
24
+ end
25
+ end
@@ -1,11 +1,11 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "shared", "lib"))
2
+
1
3
  COVERAGE_MIN = 90
2
4
  CURRENT_PATH = File.expand_path(File.dirname(__FILE__))
3
5
 
4
6
  SERVER_DISCOVERY_TESTS = Dir.glob("#{CURRENT_PATH}/spec_tests/data/sdam/**/*.yml").sort
5
7
  SDAM_MONITORING_TESTS = Dir.glob("#{CURRENT_PATH}/spec_tests/data/sdam_monitoring/*.yml").sort
6
8
  SERVER_SELECTION_RTT_TESTS = Dir.glob("#{CURRENT_PATH}/spec_tests/data/server_selection_rtt/*.yml").sort
7
- SERVER_SELECTION_TESTS = Dir.glob("#{CURRENT_PATH}/spec_tests/data/server_selection/**/*.yml").sort
8
- MAX_STALENESS_TESTS = Dir.glob("#{CURRENT_PATH}/spec_tests/data/max_staleness/**/*.yml").sort
9
9
  CRUD_TESTS = Dir.glob("#{CURRENT_PATH}/spec_tests/data/crud/**/*.yml").sort
10
10
  CRUD2_TESTS = Dir.glob("#{CURRENT_PATH}/spec_tests/data/crud_v2/**/*.yml").sort
11
11
  RETRYABLE_WRITES_TESTS = Dir.glob("#{CURRENT_PATH}/spec_tests/data/retryable_writes/**/*.yml").sort
@@ -22,7 +22,11 @@ CMAP_TESTS = Dir.glob("#{CURRENT_PATH}/spec_tests/data/cmap/*.yml").sort
22
22
  AUTH_TESTS = Dir.glob("#{CURRENT_PATH}/spec_tests/data/auth/*.yml").sort
23
23
  CLIENT_SIDE_ENCRYPTION_TESTS = Dir.glob("#{CURRENT_PATH}/spec_tests/data/client_side_encryption/*.yml").sort
24
24
 
25
- if ENV['CI']
25
+ # Disable output buffering: https://www.rubyguides.com/2019/02/ruby-io/
26
+ STDOUT.sync = true
27
+ STDERR.sync = true
28
+
29
+ if %w(1 true yes).include?(ENV['CI']&.downcase)
26
30
  autoload :Byebug, 'byebug'
27
31
  else
28
32
  # Load debuggers before loading the driver code, so that breakpoints
@@ -47,6 +51,7 @@ end
47
51
  autoload :Benchmark, 'benchmark'
48
52
  autoload :IceNine, 'ice_nine'
49
53
  autoload :Timecop, 'timecop'
54
+ autoload :ChildProcess, 'childprocess'
50
55
 
51
56
  if BSON::Environment.jruby?
52
57
  require 'concurrent-ruby'
@@ -58,14 +63,14 @@ end
58
63
  require 'support/utils'
59
64
  require 'support/spec_config'
60
65
 
61
- Mongo::Logger.logger = Logger.new($stdout)
66
+ Mongo::Logger.logger = Logger.new(STDOUT)
62
67
  unless SpecConfig.instance.client_debug?
63
68
  Mongo::Logger.logger.level = Logger::INFO
64
69
  end
65
70
  Encoding.default_external = Encoding::UTF_8
66
71
 
72
+ require 'mrss/lite_constraints'
67
73
  require 'support/matchers'
68
- require 'support/lite_constraints'
69
74
  require 'support/event_subscriber'
70
75
  require 'support/common_shortcuts'
71
76
  require 'support/client_registry'
@@ -74,6 +79,7 @@ require 'support/crypt'
74
79
  require 'support/json_ext_formatter'
75
80
  require 'support/sdam_formatter_integration'
76
81
  require 'support/background_thread_registry'
82
+ require 'support/session_registry'
77
83
 
78
84
  if SpecConfig.instance.mri?
79
85
  require 'timeout_interrupt'
@@ -85,7 +91,7 @@ end
85
91
  RSpec.configure do |config|
86
92
  config.extend(CommonShortcuts::ClassMethods)
87
93
  config.include(CommonShortcuts::InstanceMethods)
88
- config.extend(LiteConstraints)
94
+ config.extend(Mrss::LiteConstraints)
89
95
  config.include(ClientRegistryMacros)
90
96
 
91
97
  if SpecConfig.instance.ci?
@@ -102,19 +108,24 @@ RSpec.configure do |config|
102
108
  end
103
109
  end
104
110
 
105
- if SpecConfig.instance.ci?
111
+ if SpecConfig.instance.ci? && !%w(1 true yes).include?(ENV['INTERACTIVE']&.downcase)
106
112
  # Allow a max of 30 seconds per test.
107
113
  # Tests should take under 10 seconds ideally but it seems
108
114
  # we have some that run for more than 10 seconds in CI.
109
115
  config.around(:each) do |example|
110
- TimeoutInterrupt.timeout(45) do
116
+ timeout = if %w(1 true yes).include?(ENV['STRESS']&.downcase)
117
+ 210
118
+ else
119
+ 45
120
+ end
121
+ TimeoutInterrupt.timeout(timeout) do
111
122
  example.run
112
123
  end
113
124
  end
114
125
  end
115
126
 
116
127
  if SpecConfig.instance.ci?
117
- if defined?(Rfc)
128
+ if defined?(Rfc::Rif)
118
129
  unless BSON::Environment.jruby?
119
130
  Rfc::Rif.output_object_space_stats = true
120
131
  end
@@ -234,7 +234,7 @@ describe Mongo::Address do
234
234
  end
235
235
 
236
236
  let(:address) do
237
- Mongo::Address.new(custom_hostname)
237
+ Mongo::Address.new("#{custom_hostname}:#{SpecConfig.instance.any_port}")
238
238
  end
239
239
 
240
240
  before do
@@ -0,0 +1,42 @@
1
+ require 'lite_spec_helper'
2
+
3
+ AWS_REGION_TEST_CASES = {
4
+ 'sts.amazonaws.com' => 'us-east-1',
5
+ 'sts.us-west-2.amazonaws.com' => 'us-west-2',
6
+ 'sts.us-west-2.amazonaws.com.ch' => 'us-west-2',
7
+ 'example.com' => 'com',
8
+ 'localhost' => 'us-east-1',
9
+ 'sts..com' => Mongo::Error::InvalidServerAuthHost,
10
+ '.amazonaws.com' => Mongo::Error::InvalidServerAuthHost,
11
+ 'sts.amazonaws.' => Mongo::Error::InvalidServerAuthHost,
12
+ '' => Mongo::Error::InvalidServerAuthResponse,
13
+ 'x' * 256 => Mongo::Error::InvalidServerAuthHost,
14
+ }
15
+
16
+ describe 'AWS auth region tests' do
17
+
18
+ AWS_REGION_TEST_CASES.each do |host, expected_region|
19
+ context "host '#{host}'" do
20
+ let(:request) do
21
+ Mongo::Auth::Aws::Request.new(access_key_id: 'access_key_id',
22
+ secret_access_key: 'secret_access_key',
23
+ session_token: 'session_token',
24
+ host: host,
25
+ server_nonce: 'server_nonce',
26
+ )
27
+ end
28
+
29
+ if expected_region.is_a?(String)
30
+ it 'derives expected region' do
31
+ request.region.should == expected_region
32
+ end
33
+ else
34
+ it 'fails with an error' do
35
+ lambda do
36
+ request.region
37
+ end.should raise_error(expected_region)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,76 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongo::Auth::Aws::Request do
4
+
5
+ describe "#formatted_time" do
6
+ context "when time is provided and frozen" do
7
+ let(:original_time) { Time.at(1592399523).freeze }
8
+ let(:request) do
9
+ described_class.new(access_key_id: 'access_key_id',
10
+ secret_access_key: 'secret_access_key',
11
+ session_token: 'session_token',
12
+ host: 'host',
13
+ server_nonce: 'server_nonce',
14
+ time: original_time
15
+ )
16
+ end
17
+
18
+ it 'doesn\'t modify the time instance variable' do
19
+ expect { request.formatted_time }.to_not raise_error
20
+ end
21
+
22
+ it 'returns the correct formatted time' do
23
+ expect(request.formatted_time).to eq('20200617T131203Z')
24
+ end
25
+ end
26
+
27
+ context "when time is not provided" do
28
+ let(:request) do
29
+ described_class.new(access_key_id: 'access_key_id',
30
+ secret_access_key: 'secret_access_key',
31
+ session_token: 'session_token',
32
+ host: 'host',
33
+ server_nonce: 'server_nonce'
34
+ )
35
+ end
36
+
37
+ it 'doesn\'t raise an error on formatted_time' do
38
+ expect { request.formatted_time }.to_not raise_error
39
+ end
40
+ end
41
+ end
42
+
43
+ describe "#signature" do
44
+ context "when time is provided and frozen" do
45
+ let(:original_time) { Time.at(1592399523).freeze }
46
+ let(:request) do
47
+ described_class.new(access_key_id: 'access_key_id',
48
+ secret_access_key: 'secret_access_key',
49
+ session_token: 'session_token',
50
+ host: 'host',
51
+ server_nonce: 'server_nonce',
52
+ time: original_time
53
+ )
54
+ end
55
+
56
+ it 'doesn\'t raise error on signature' do
57
+ expect { request.signature }.to_not raise_error
58
+ end
59
+ end
60
+
61
+ context "when time is not provided" do
62
+ let(:request) do
63
+ described_class.new(access_key_id: 'access_key_id',
64
+ secret_access_key: 'secret_access_key',
65
+ session_token: 'session_token',
66
+ host: 'host',
67
+ server_nonce: 'server_nonce'
68
+ )
69
+ end
70
+
71
+ it 'doesn\'t raise error on signature' do
72
+ expect { request.signature }.to_not raise_error
73
+ end
74
+ end
75
+ end
76
+ end
@@ -65,7 +65,7 @@ describe Mongo::Auth::Scram do
65
65
  it 'does not compress the message' do
66
66
  expect(Mongo::Protocol::Compressed).not_to receive(:new)
67
67
  expect {
68
- authenticator.login(connection)
68
+ authenticator.login
69
69
  }.to raise_error(Mongo::Auth::Unauthorized)
70
70
  end
71
71
  end
@@ -55,7 +55,7 @@ describe Mongo::Auth::User do
55
55
  let(:options) { {auth_mech: 'scram'} }
56
56
 
57
57
  context 'not linting' do
58
- skip_if_linting
58
+ require_no_linting
59
59
 
60
60
  it 'warns' do
61
61
  expect(Mongo::Logger.logger).to receive(:warn)
@@ -1335,7 +1335,7 @@ describe Mongo::BulkWrite do
1335
1335
  context 'when the number of updates exceeds the max batch size' do
1336
1336
  # Test uses doubles for server descriptions, doubles are
1337
1337
  # incompatible with freezing which linting does for descriptions
1338
- skip_if_linting
1338
+ require_no_linting
1339
1339
 
1340
1340
  let(:batch_size) do
1341
1341
  11
@@ -2012,7 +2012,7 @@ describe Mongo::BulkWrite do
2012
2012
  context 'when the operations need to be split' do
2013
2013
  # Test uses doubles for server descriptions, doubles are
2014
2014
  # incompatible with freezing which linting does for descriptions
2015
- skip_if_linting
2015
+ require_no_linting
2016
2016
 
2017
2017
  let(:batch_size) do
2018
2018
  11
@@ -0,0 +1,70 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongo::CachingCursor do
4
+
5
+ around do |spec|
6
+ Mongo::QueryCache.clear
7
+ Mongo::QueryCache.cache { spec.run }
8
+ end
9
+
10
+ let(:authorized_collection) do
11
+ authorized_client['caching_cursor']
12
+ end
13
+
14
+ before do
15
+ authorized_collection.drop
16
+ end
17
+
18
+ let(:server) do
19
+ view.send(:server_selector).select_server(authorized_client.cluster)
20
+ end
21
+
22
+ let(:reply) do
23
+ view.send(:send_initial_query, server)
24
+ end
25
+
26
+ let(:cursor) do
27
+ described_class.new(view, reply, server)
28
+ end
29
+
30
+ let(:view) do
31
+ Mongo::Collection::View.new(authorized_collection)
32
+ end
33
+
34
+ before do
35
+ authorized_collection.delete_many
36
+ 3.times { |i| authorized_collection.insert_one(_id: i) }
37
+ end
38
+
39
+ describe '#cached_docs' do
40
+ context 'when no query has been performed' do
41
+ it 'returns nil' do
42
+ expect(cursor.cached_docs).to be_nil
43
+ end
44
+ end
45
+
46
+ context 'when a query has been performed' do
47
+ it 'returns the number of documents' do
48
+ cursor.to_a
49
+ expect(cursor.cached_docs.length).to eq(3)
50
+ expect(cursor.cached_docs).to eq([{ '_id' => 0 }, { '_id' => 1 }, { '_id' => 2 }])
51
+ end
52
+ end
53
+ end
54
+
55
+ describe '#try_next' do
56
+ it 'fetches the next document' do
57
+ expect(cursor.try_next).to eq('_id' => 0)
58
+ expect(cursor.try_next).to eq('_id' => 1)
59
+ expect(cursor.try_next).to eq('_id' => 2)
60
+ end
61
+ end
62
+
63
+ describe '#each' do
64
+ it 'iterates the cursor' do
65
+ result = cursor.each.to_a
66
+ expect(result.length).to eq(3)
67
+ expect(result).to eq([{ '_id' => 0 }, { '_id' => 1 }, { '_id' => 2 }])
68
+ end
69
+ end
70
+ end
@@ -319,6 +319,104 @@ describe Mongo::Client do
319
319
  end
320
320
  end
321
321
 
322
+ context 'timeout options' do
323
+ let(:client) do
324
+ new_local_client(SpecConfig.instance.addresses,
325
+ SpecConfig.instance.authorized_test_options.merge(options))
326
+ end
327
+
328
+ context 'when network timeouts are zero' do
329
+ let(:options) do
330
+ { socket_timeout: 0, connect_timeout: 0 }
331
+ end
332
+
333
+ it 'sets options to zeros' do
334
+ client.options[:socket_timeout].should == 0
335
+ client.options[:connect_timeout].should == 0
336
+ end
337
+
338
+ it 'connects and performs operations successfully' do
339
+ lambda do
340
+ client.database.command(ping: 1)
341
+ end.should_not raise_error
342
+ end
343
+ end
344
+
345
+ %i(socket_timeout connect_timeout).each do |option|
346
+ context "when #{option} is negative" do
347
+ let(:options) do
348
+ { option => -1 }
349
+ end
350
+
351
+ it 'fails client creation' do
352
+ lambda do
353
+ client
354
+ end.should raise_error(ArgumentError, /#{option} must be a non-negative number/)
355
+ end
356
+ end
357
+
358
+ context "when #{option} is of the wrong type" do
359
+ let(:options) do
360
+ { option => '42' }
361
+ end
362
+
363
+ it 'fails client creation' do
364
+ lambda do
365
+ client
366
+ end.should raise_error(ArgumentError, /#{option} must be a non-negative number/)
367
+ end
368
+ end
369
+ end
370
+
371
+ context "when :connect_timeout is very small" do
372
+ # The driver reads first and checks the deadline second.
373
+ # This means the read (in a monitor) can technically take more than
374
+ # the connect timeout. Restrict to TLS configurations to make
375
+ # the network I/O take longer.
376
+ require_tls
377
+
378
+ let(:options) do
379
+ { connect_timeout: 1e-6, server_selection_timeout: 2 }
380
+ end
381
+
382
+ it 'allows client creation' do
383
+ lambda do
384
+ client
385
+ end.should_not raise_error
386
+ end
387
+
388
+ it 'fails server selection due to very small timeout' do
389
+ lambda do
390
+ client.database.command(ping: 1)
391
+ end.should raise_error(Mongo::Error::NoServerAvailable)
392
+ end
393
+ end
394
+
395
+ context "when :socket_timeout is very small" do
396
+ # The driver reads first and checks the deadline second.
397
+ # This means the read (in a monitor) can technically take more than
398
+ # the connect timeout. Restrict to TLS configurations to make
399
+ # the network I/O take longer.
400
+ require_tls
401
+
402
+ let(:options) do
403
+ { socket_timeout: 1e-6, server_selection_timeout: 2 }
404
+ end
405
+
406
+ it 'allows client creation' do
407
+ lambda do
408
+ client
409
+ end.should_not raise_error
410
+ end
411
+
412
+ it 'fails operations due to very small timeout' do
413
+ lambda do
414
+ client.database.command(ping: 1)
415
+ end.should raise_error(Mongo::Error::SocketTimeoutError)
416
+ end
417
+ end
418
+ end
419
+
322
420
  context 'retry_writes option' do
323
421
  let(:client) do
324
422
  new_local_client_nmio(SpecConfig.instance.addresses, options)
@@ -398,6 +496,7 @@ describe Mongo::Client do
398
496
  end
399
497
 
400
498
  context 'when the compressor is not supported by the driver' do
499
+ require_warning_clean
401
500
 
402
501
  let(:options) do
403
502
  { compressors: ['snoopy'] }
@@ -576,7 +675,7 @@ describe Mongo::Client do
576
675
  context 'when providing a custom logger' do
577
676
 
578
677
  let(:logger) do
579
- Logger.new($stdout).tap do |l|
678
+ Logger.new(STDOUT).tap do |l|
580
679
  l.level = Logger::FATAL
581
680
  end
582
681
  end
@@ -746,7 +845,7 @@ describe Mongo::Client do
746
845
  end
747
846
 
748
847
  context 'mri' do
749
- only_mri
848
+ require_mri
750
849
 
751
850
  let(:platform_string) do
752
851
  [
@@ -1138,6 +1237,48 @@ describe Mongo::Client do
1138
1237
  end
1139
1238
  end
1140
1239
 
1240
+ context ':bg_error_backtrace option' do
1241
+ [true, false, nil, 42].each do |valid_value|
1242
+ context "valid value: #{valid_value.inspect}" do
1243
+ let(:options) do
1244
+ {bg_error_backtrace: valid_value}
1245
+ end
1246
+
1247
+ it 'is accepted' do
1248
+ client.options[:bg_error_backtrace].should == valid_value
1249
+ end
1250
+ end
1251
+ end
1252
+
1253
+ context 'invalid value type' do
1254
+ let(:options) do
1255
+ {bg_error_backtrace: 'yes'}
1256
+ end
1257
+
1258
+ it 'is rejected' do
1259
+ lambda do
1260
+ client
1261
+ end.should raise_error(ArgumentError, /:bg_error_backtrace option value must be true, false, nil or a positive integer/)
1262
+ end
1263
+ end
1264
+
1265
+ context 'invalid value' do
1266
+ [0, -1, 42.0].each do |invalid_value|
1267
+ context "invalid value: #{invalid_value.inspect}" do
1268
+ let(:options) do
1269
+ {bg_error_backtrace: invalid_value}
1270
+ end
1271
+
1272
+ it 'is rejected' do
1273
+ lambda do
1274
+ client
1275
+ end.should raise_error(ArgumentError, /:bg_error_backtrace option value must be true, false, nil or a positive integer/)
1276
+ end
1277
+ end
1278
+ end
1279
+ end
1280
+ end
1281
+
1141
1282
  describe ':read option' do
1142
1283
  [
1143
1284
  :primary, :primary_preferred, :secondary, :secondary_preferred, :nearest
@@ -1171,7 +1312,7 @@ describe Mongo::Client do
1171
1312
  end
1172
1313
 
1173
1314
  context 'when not linting' do
1174
- skip_if_linting
1315
+ require_no_linting
1175
1316
 
1176
1317
  it 'rejects bogus read preference as symbol' do
1177
1318
  expect do
@@ -1203,6 +1344,46 @@ describe Mongo::Client do
1203
1344
  end
1204
1345
  end
1205
1346
 
1347
+ context 'when setting read concern options' do
1348
+ min_server_fcv '3.2'
1349
+
1350
+ context 'when read concern is valid' do
1351
+ let(:options) do
1352
+ { read_concern: { level: :local } }
1353
+ end
1354
+
1355
+ it 'does not warn' do
1356
+ expect(Mongo::Logger.logger).to_not receive(:warn)
1357
+ new_local_client_nmio(SpecConfig.instance.addresses, options)
1358
+ end
1359
+ end
1360
+
1361
+ context 'when read concern has an invalid key' do
1362
+ require_no_linting
1363
+
1364
+ let(:options) do
1365
+ { read_concern: { hello: :local } }
1366
+ end
1367
+
1368
+ it 'logs a warning' do
1369
+ expect(Mongo::Logger.logger).to receive(:warn).with(/Read concern has invalid keys: hello/)
1370
+ new_local_client_nmio(SpecConfig.instance.addresses, options)
1371
+ end
1372
+ end
1373
+
1374
+ context 'when read concern has a non-user-settable key' do
1375
+ let(:options) do
1376
+ { read_concern: { after_cluster_time: 100 } }
1377
+ end
1378
+
1379
+ it 'raises an exception' do
1380
+ expect do
1381
+ new_local_client_nmio(SpecConfig.instance.addresses, options)
1382
+ end.to raise_error(Mongo::Error::InvalidReadConcern, 'The after_cluster_time read_concern option cannot be specified by the user')
1383
+ end
1384
+ end
1385
+ end
1386
+
1206
1387
  context 'when an invalid option is provided' do
1207
1388
 
1208
1389
  let(:options) do
@@ -1242,6 +1423,197 @@ describe Mongo::Client do
1242
1423
  end
1243
1424
  end
1244
1425
  =end
1426
+
1427
+ context ':wrapping_libraries option' do
1428
+ let(:options) do
1429
+ {wrapping_libraries: wrapping_libraries}
1430
+ end
1431
+
1432
+ context 'valid input' do
1433
+ context 'symbol keys' do
1434
+ let(:wrapping_libraries) do
1435
+ [name: 'Mongoid', version: '7.1.2'].freeze
1436
+ end
1437
+
1438
+ it 'works' do
1439
+ client.options[:wrapping_libraries].should == ['name' => 'Mongoid', 'version' => '7.1.2']
1440
+ end
1441
+ end
1442
+
1443
+ context 'string keys' do
1444
+ let(:wrapping_libraries) do
1445
+ ['name' => 'Mongoid', 'version' => '7.1.2'].freeze
1446
+ end
1447
+
1448
+ it 'works' do
1449
+ client.options[:wrapping_libraries].should == ['name' => 'Mongoid', 'version' => '7.1.2']
1450
+ end
1451
+ end
1452
+
1453
+ context 'Redacted keys' do
1454
+ let(:wrapping_libraries) do
1455
+ [Mongo::Options::Redacted.new(name: 'Mongoid', version: '7.1.2')].freeze
1456
+ end
1457
+
1458
+ it 'works' do
1459
+ client.options[:wrapping_libraries].should == ['name' => 'Mongoid', 'version' => '7.1.2']
1460
+ end
1461
+ end
1462
+
1463
+ context 'two libraries' do
1464
+ let(:wrapping_libraries) do
1465
+ [
1466
+ {name: 'Mongoid', version: '7.1.2'},
1467
+ {name: 'Rails', version: '4.0', platform: 'Foobar'},
1468
+ ].freeze
1469
+ end
1470
+
1471
+ it 'works' do
1472
+ client.options[:wrapping_libraries].should == [
1473
+ {'name' => 'Mongoid', 'version' => '7.1.2'},
1474
+ {'name' => 'Rails', 'version' => '4.0', 'platform' => 'Foobar'},
1475
+ ]
1476
+ end
1477
+ end
1478
+
1479
+ context 'empty array' do
1480
+ let(:wrapping_libraries) do
1481
+ []
1482
+ end
1483
+
1484
+ it 'works' do
1485
+ client.options[:wrapping_libraries].should == []
1486
+ end
1487
+ end
1488
+
1489
+ context 'empty array' do
1490
+ let(:wrapping_libraries) do
1491
+ nil
1492
+ end
1493
+
1494
+ it 'works' do
1495
+ client.options[:wrapping_libraries].should be nil
1496
+ end
1497
+ end
1498
+ end
1499
+
1500
+ context 'valid input' do
1501
+ context 'hash given instead of an array' do
1502
+ let(:wrapping_libraries) do
1503
+ {name: 'Mongoid', version: '7.1.2'}.freeze
1504
+ end
1505
+
1506
+ it 'is rejected' do
1507
+ lambda do
1508
+ client
1509
+ end.should raise_error(ArgumentError, /:wrapping_libraries must be an array of hashes/)
1510
+ end
1511
+ end
1512
+
1513
+ context 'invalid keys' do
1514
+ let(:wrapping_libraries) do
1515
+ [name: 'Mongoid', invalid: '7.1.2'].freeze
1516
+ end
1517
+
1518
+ it 'is rejected' do
1519
+ lambda do
1520
+ client
1521
+ end.should raise_error(ArgumentError, /:wrapping_libraries element has invalid keys/)
1522
+ end
1523
+ end
1524
+
1525
+ context 'value includes |' do
1526
+ let(:wrapping_libraries) do
1527
+ [name: 'Mongoid|on|Rails', version: '7.1.2'].freeze
1528
+ end
1529
+
1530
+ it 'is rejected' do
1531
+ lambda do
1532
+ client
1533
+ end.should raise_error(ArgumentError, /:wrapping_libraries element value cannot include '|'/)
1534
+ end
1535
+ end
1536
+ end
1537
+ end
1538
+
1539
+ context ':auth_mech_properties option' do
1540
+ context 'is nil' do
1541
+ let(:options) do
1542
+ {auth_mech_properties: nil}
1543
+ end
1544
+
1545
+ it 'creates the client without the option' do
1546
+ client.options.should_not have_key(:auth_mech_properties)
1547
+ end
1548
+ end
1549
+ end
1550
+ end
1551
+
1552
+ context 'when making a block client' do
1553
+ context 'when the block doesn\'t raise an error' do
1554
+ let(:block_client) do
1555
+ c = nil
1556
+ Mongo::Client.new(
1557
+ SpecConfig.instance.addresses,
1558
+ SpecConfig.instance.test_options.merge(database: SpecConfig.instance.test_db),
1559
+ ) do |client|
1560
+ c = client
1561
+ end
1562
+ c
1563
+ end
1564
+
1565
+ it 'is closed after block' do
1566
+ expect(block_client.cluster.connected?).to eq(false)
1567
+ end
1568
+ end
1569
+
1570
+ context 'when the block raises an error' do
1571
+ it 'it is closed after the block' do
1572
+ block_client_raise = nil
1573
+ expect do
1574
+ Mongo::Client.new(
1575
+ SpecConfig.instance.addresses,
1576
+ SpecConfig.instance.test_options.merge(database: SpecConfig.instance.test_db),
1577
+ ) do |client|
1578
+ block_client_raise = client
1579
+ raise "This is an error!"
1580
+ end
1581
+ end.to raise_error(StandardError, "This is an error!")
1582
+ expect(block_client_raise.cluster.connected?).to eq(false)
1583
+ end
1584
+ end
1585
+
1586
+ context 'when the hosts given include the protocol' do
1587
+ it 'raises an error on mongodb://' do
1588
+ expect do
1589
+ Mongo::Client.new(['mongodb://127.0.0.1:27017/test'])
1590
+ 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?")
1591
+ end
1592
+
1593
+ it 'raises an error on mongodb+srv://' do
1594
+ expect do
1595
+ Mongo::Client.new(['mongodb+srv://127.0.0.1:27017/test'])
1596
+ 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?")
1597
+ end
1598
+
1599
+ it 'raises an error on multiple items' do
1600
+ expect do
1601
+ Mongo::Client.new(['127.0.0.1:27017', 'mongodb+srv://127.0.0.1:27017/test'])
1602
+ 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?")
1603
+ end
1604
+
1605
+ it 'raises an error only at beginning of string' do
1606
+ expect do
1607
+ Mongo::Client.new(['somethingmongodb://127.0.0.1:27017/test', 'mongodb+srv://127.0.0.1:27017/test'])
1608
+ 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?")
1609
+ end
1610
+
1611
+ it 'raises an error with different case' do
1612
+ expect do
1613
+ Mongo::Client.new(['MongOdB://127.0.0.1:27017/test'])
1614
+ 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?")
1615
+ end
1616
+ end
1245
1617
  end
1246
1618
  end
1247
1619
 
@@ -1773,6 +2145,7 @@ describe Mongo::Client do
1773
2145
  sdam_proc: sdam_proc,
1774
2146
  connect_timeout: 3.08, socket_timeout: 3.09,
1775
2147
  server_selection_timeout: 2.92,
2148
+ heartbeat_frequency: 100,
1776
2149
  database: SpecConfig.instance.test_db))
1777
2150
  end
1778
2151
 
@@ -1793,6 +2166,10 @@ describe Mongo::Client do
1793
2166
  end
1794
2167
 
1795
2168
  it 'does not notify subscribers set up by sdam_proc' do
2169
+ # On 4.4, the push monitor also is receiving heartbeats.
2170
+ # Give those some time to be processed.
2171
+ sleep 2
2172
+
1796
2173
  expect(subscriber.started_events.length).to be > 0
1797
2174
  subscriber.started_events.clear
1798
2175
 
@@ -1800,6 +2177,12 @@ describe Mongo::Client do
1800
2177
  # subscriber may receive events from the original client.
1801
2178
 
1802
2179
  new_client.cluster.next_primary
2180
+
2181
+ # Diagnostics
2182
+ unless subscriber.started_events.empty?
2183
+ p subscriber.started_events
2184
+ end
2185
+
1803
2186
  expect(subscriber.started_events.length).to eq 0
1804
2187
  new_client.cluster.topology.class.should_not be Mongo::Cluster::Topology::Unknown
1805
2188
  end