mongo 2.5.3 → 2.6.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 (394) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/LICENSE +1 -1
  5. data/README.md +3 -2
  6. data/lib/mongo.rb +2 -2
  7. data/lib/mongo/address.rb +10 -2
  8. data/lib/mongo/address/ipv4.rb +1 -1
  9. data/lib/mongo/address/ipv6.rb +26 -5
  10. data/lib/mongo/address/unix.rb +1 -1
  11. data/lib/mongo/auth.rb +10 -3
  12. data/lib/mongo/auth/cr.rb +4 -1
  13. data/lib/mongo/auth/cr/conversation.rb +4 -1
  14. data/lib/mongo/auth/ldap.rb +1 -1
  15. data/lib/mongo/auth/ldap/conversation.rb +1 -1
  16. data/lib/mongo/auth/roles.rb +1 -1
  17. data/lib/mongo/auth/scram.rb +24 -7
  18. data/lib/mongo/auth/scram/conversation.rb +52 -19
  19. data/lib/mongo/auth/stringprep.rb +114 -0
  20. data/lib/mongo/auth/stringprep/profiles/sasl.rb +73 -0
  21. data/lib/mongo/auth/stringprep/tables.rb +3232 -0
  22. data/lib/mongo/auth/stringprep/unicode_normalize/normalize.rb +174 -0
  23. data/lib/mongo/auth/stringprep/unicode_normalize/tables.rb +1170 -0
  24. data/lib/mongo/auth/user.rb +14 -3
  25. data/lib/mongo/auth/user/view.rb +1 -1
  26. data/lib/mongo/auth/x509.rb +1 -1
  27. data/lib/mongo/auth/x509/conversation.rb +1 -1
  28. data/lib/mongo/bson.rb +1 -1
  29. data/lib/mongo/bulk_write.rb +8 -8
  30. data/lib/mongo/bulk_write/combineable.rb +1 -1
  31. data/lib/mongo/bulk_write/ordered_combiner.rb +1 -1
  32. data/lib/mongo/bulk_write/result.rb +1 -1
  33. data/lib/mongo/bulk_write/result_combiner.rb +4 -4
  34. data/lib/mongo/bulk_write/transformable.rb +1 -1
  35. data/lib/mongo/bulk_write/unordered_combiner.rb +1 -1
  36. data/lib/mongo/bulk_write/validatable.rb +1 -1
  37. data/lib/mongo/client.rb +115 -24
  38. data/lib/mongo/cluster.rb +17 -10
  39. data/lib/mongo/cluster/app_metadata.rb +7 -1
  40. data/lib/mongo/cluster/periodic_executor.rb +1 -1
  41. data/lib/mongo/cluster/reapers/socket_reaper.rb +1 -1
  42. data/lib/mongo/cluster/topology.rb +12 -2
  43. data/lib/mongo/cluster/topology/replica_set.rb +9 -1
  44. data/lib/mongo/cluster/topology/sharded.rb +1 -1
  45. data/lib/mongo/cluster/topology/single.rb +1 -1
  46. data/lib/mongo/cluster/topology/unknown.rb +1 -1
  47. data/lib/mongo/collection.rb +75 -19
  48. data/lib/mongo/collection/view.rb +1 -1
  49. data/lib/mongo/collection/view/aggregation.rb +1 -1
  50. data/lib/mongo/collection/view/builder.rb +1 -1
  51. data/lib/mongo/collection/view/builder/aggregation.rb +3 -3
  52. data/lib/mongo/collection/view/builder/find_command.rb +1 -1
  53. data/lib/mongo/collection/view/builder/flags.rb +1 -1
  54. data/lib/mongo/collection/view/builder/map_reduce.rb +1 -1
  55. data/lib/mongo/collection/view/builder/modifiers.rb +1 -1
  56. data/lib/mongo/collection/view/builder/op_query.rb +1 -1
  57. data/lib/mongo/collection/view/change_stream.rb +193 -17
  58. data/lib/mongo/collection/view/change_stream/retryable.rb +3 -20
  59. data/lib/mongo/collection/view/explainable.rb +1 -1
  60. data/lib/mongo/collection/view/immutable.rb +1 -1
  61. data/lib/mongo/collection/view/iterable.rb +2 -2
  62. data/lib/mongo/collection/view/map_reduce.rb +1 -1
  63. data/lib/mongo/collection/view/readable.rb +108 -29
  64. data/lib/mongo/collection/view/writable.rb +3 -3
  65. data/lib/mongo/cursor.rb +44 -4
  66. data/lib/mongo/cursor/builder.rb +1 -1
  67. data/lib/mongo/cursor/builder/get_more_command.rb +1 -1
  68. data/lib/mongo/cursor/builder/kill_cursors_command.rb +1 -1
  69. data/lib/mongo/cursor/builder/op_get_more.rb +1 -1
  70. data/lib/mongo/cursor/builder/op_kill_cursors.rb +1 -1
  71. data/lib/mongo/database.rb +46 -3
  72. data/lib/mongo/database/view.rb +11 -11
  73. data/lib/mongo/dbref.rb +1 -1
  74. data/lib/mongo/error.rb +57 -1
  75. data/lib/mongo/error/bulk_write_error.rb +2 -2
  76. data/lib/mongo/error/change_stream_resumable.rb +37 -0
  77. data/lib/mongo/error/closed_stream.rb +1 -1
  78. data/lib/mongo/error/extra_file_chunk.rb +1 -1
  79. data/lib/mongo/error/failed_stringprep_validation.rb +38 -0
  80. data/lib/mongo/error/file_not_found.rb +1 -1
  81. data/lib/mongo/error/insufficient_iteration_count.rb +38 -0
  82. data/lib/mongo/error/invalid_application_name.rb +1 -1
  83. data/lib/mongo/error/invalid_bulk_operation.rb +1 -1
  84. data/lib/mongo/error/invalid_bulk_operation_type.rb +1 -1
  85. data/lib/mongo/error/invalid_collection_name.rb +1 -1
  86. data/lib/mongo/error/invalid_database_name.rb +1 -1
  87. data/lib/mongo/error/invalid_document.rb +1 -1
  88. data/lib/mongo/error/invalid_file.rb +1 -1
  89. data/lib/mongo/error/invalid_file_revision.rb +1 -1
  90. data/lib/mongo/error/invalid_min_pool_size.rb +1 -1
  91. data/lib/mongo/error/invalid_nonce.rb +1 -1
  92. data/lib/mongo/error/invalid_read_option.rb +35 -0
  93. data/lib/mongo/error/invalid_replacement_document.rb +1 -1
  94. data/lib/mongo/error/invalid_server_preference.rb +1 -1
  95. data/lib/mongo/error/invalid_session.rb +1 -1
  96. data/lib/mongo/error/invalid_signature.rb +1 -1
  97. data/lib/mongo/error/invalid_transaction_operation.rb +82 -0
  98. data/lib/mongo/error/invalid_txt_record.rb +1 -1
  99. data/lib/mongo/error/invalid_update_document.rb +1 -1
  100. data/lib/mongo/error/invalid_uri.rb +1 -1
  101. data/lib/mongo/error/invalid_write_concern.rb +1 -1
  102. data/lib/mongo/error/max_bson_size.rb +1 -1
  103. data/lib/mongo/error/max_message_size.rb +1 -1
  104. data/lib/mongo/error/mismatched_domain.rb +1 -1
  105. data/lib/mongo/error/missing_file_chunk.rb +1 -1
  106. data/lib/mongo/error/missing_resume_token.rb +1 -1
  107. data/lib/mongo/error/multi_index_drop.rb +1 -1
  108. data/lib/mongo/error/need_primary_server.rb +1 -1
  109. data/lib/mongo/error/no_server_available.rb +1 -1
  110. data/lib/mongo/error/no_srv_records.rb +1 -1
  111. data/lib/mongo/error/operation_failure.rb +108 -14
  112. data/lib/mongo/error/parser.rb +50 -1
  113. data/lib/mongo/error/socket_error.rb +5 -2
  114. data/lib/mongo/error/socket_timeout_error.rb +5 -2
  115. data/lib/mongo/error/unchangeable_collection_option.rb +1 -1
  116. data/lib/mongo/error/unexpected_chunk_length.rb +1 -1
  117. data/lib/mongo/error/unexpected_response.rb +1 -1
  118. data/lib/mongo/error/unknown_payload_type.rb +1 -1
  119. data/lib/mongo/error/unsupported_array_filters.rb +1 -1
  120. data/lib/mongo/error/unsupported_collation.rb +1 -1
  121. data/lib/mongo/error/unsupported_features.rb +1 -1
  122. data/lib/mongo/error/unsupported_message_type.rb +1 -1
  123. data/lib/mongo/error/write_retryable.rb +27 -0
  124. data/lib/mongo/event.rb +10 -9
  125. data/lib/mongo/event/base.rb +33 -0
  126. data/lib/mongo/event/description_changed.rb +2 -2
  127. data/lib/mongo/event/listeners.rb +1 -1
  128. data/lib/mongo/event/member_discovered.rb +4 -2
  129. data/lib/mongo/event/primary_elected.rb +2 -2
  130. data/lib/mongo/event/publisher.rb +1 -1
  131. data/lib/mongo/event/standalone_discovered.rb +2 -2
  132. data/lib/mongo/event/subscriber.rb +1 -1
  133. data/lib/mongo/grid.rb +1 -1
  134. data/lib/mongo/grid/file.rb +1 -1
  135. data/lib/mongo/grid/file/chunk.rb +3 -3
  136. data/lib/mongo/grid/file/info.rb +26 -3
  137. data/lib/mongo/grid/fs_bucket.rb +1 -1
  138. data/lib/mongo/grid/stream.rb +1 -1
  139. data/lib/mongo/grid/stream/read.rb +1 -1
  140. data/lib/mongo/grid/stream/write.rb +1 -1
  141. data/lib/mongo/index.rb +1 -1
  142. data/lib/mongo/index/view.rb +1 -1
  143. data/lib/mongo/loggable.rb +1 -1
  144. data/lib/mongo/logger.rb +1 -1
  145. data/lib/mongo/monitoring.rb +99 -62
  146. data/lib/mongo/monitoring/command_log_subscriber.rb +2 -2
  147. data/lib/mongo/monitoring/event.rb +2 -1
  148. data/lib/mongo/monitoring/event/command_failed.rb +19 -6
  149. data/lib/mongo/monitoring/event/command_started.rb +14 -3
  150. data/lib/mongo/monitoring/event/command_succeeded.rb +5 -3
  151. data/lib/mongo/monitoring/event/secure.rb +1 -1
  152. data/lib/mongo/monitoring/event/server_closed.rb +2 -2
  153. data/lib/mongo/monitoring/event/server_description_changed.rb +2 -2
  154. data/lib/mongo/monitoring/event/server_opening.rb +11 -2
  155. data/lib/mongo/monitoring/event/topology_changed.rb +13 -2
  156. data/lib/mongo/monitoring/event/topology_closed.rb +2 -2
  157. data/lib/mongo/monitoring/event/topology_opening.rb +11 -2
  158. data/lib/mongo/monitoring/publishable.rb +10 -6
  159. data/lib/mongo/monitoring/sdam_log_subscriber.rb +1 -1
  160. data/lib/mongo/monitoring/server_closed_log_subscriber.rb +1 -1
  161. data/lib/mongo/monitoring/server_description_changed_log_subscriber.rb +1 -1
  162. data/lib/mongo/monitoring/server_opening_log_subscriber.rb +1 -1
  163. data/lib/mongo/monitoring/topology_changed_log_subscriber.rb +1 -1
  164. data/lib/mongo/monitoring/topology_opening_log_subscriber.rb +1 -1
  165. data/lib/mongo/operation/aggregate/op_msg.rb +3 -0
  166. data/lib/mongo/operation/create/op_msg.rb +9 -0
  167. data/lib/mongo/operation/create_index/op_msg.rb +9 -0
  168. data/lib/mongo/operation/create_user/command.rb +1 -1
  169. data/lib/mongo/operation/create_user/op_msg.rb +10 -1
  170. data/lib/mongo/operation/delete/op_msg.rb +3 -0
  171. data/lib/mongo/operation/distinct/op_msg.rb +9 -0
  172. data/lib/mongo/operation/drop/op_msg.rb +9 -0
  173. data/lib/mongo/operation/drop_database/op_msg.rb +9 -0
  174. data/lib/mongo/operation/drop_index/op_msg.rb +9 -0
  175. data/lib/mongo/operation/explain/op_msg.rb +3 -0
  176. data/lib/mongo/operation/find/op_msg.rb +3 -0
  177. data/lib/mongo/operation/get_more.rb +1 -1
  178. data/lib/mongo/operation/get_more/command.rb +1 -1
  179. data/lib/mongo/operation/get_more/legacy.rb +1 -1
  180. data/lib/mongo/operation/get_more/op_msg.rb +3 -0
  181. data/lib/mongo/operation/indexes/op_msg.rb +3 -0
  182. data/lib/mongo/operation/indexes/result.rb +1 -1
  183. data/lib/mongo/operation/insert/bulk_result.rb +32 -2
  184. data/lib/mongo/operation/insert/op_msg.rb +3 -0
  185. data/lib/mongo/operation/insert/result.rb +1 -1
  186. data/lib/mongo/operation/kill_cursors/op_msg.rb +9 -0
  187. data/lib/mongo/operation/list_collections/op_msg.rb +3 -0
  188. data/lib/mongo/operation/list_collections/result.rb +5 -1
  189. data/lib/mongo/operation/map_reduce/op_msg.rb +3 -0
  190. data/lib/mongo/operation/map_reduce/result.rb +1 -1
  191. data/lib/mongo/operation/parallel_scan/op_msg.rb +3 -0
  192. data/lib/mongo/operation/remove_user/op_msg.rb +9 -0
  193. data/lib/mongo/operation/result.rb +27 -14
  194. data/lib/mongo/operation/shared/executable.rb +1 -0
  195. data/lib/mongo/operation/shared/sessions_supported.rb +78 -7
  196. data/lib/mongo/operation/shared/specifiable.rb +18 -2
  197. data/lib/mongo/operation/shared/write_concern_supported.rb +1 -1
  198. data/lib/mongo/operation/update/op_msg.rb +3 -0
  199. data/lib/mongo/operation/update_user/command.rb +1 -1
  200. data/lib/mongo/operation/update_user/op_msg.rb +10 -1
  201. data/lib/mongo/operation/users_info/op_msg.rb +3 -0
  202. data/lib/mongo/options.rb +1 -1
  203. data/lib/mongo/options/mapper.rb +1 -1
  204. data/lib/mongo/options/redacted.rb +1 -1
  205. data/lib/mongo/protocol/bit_vector.rb +1 -1
  206. data/lib/mongo/protocol/compressed.rb +1 -1
  207. data/lib/mongo/protocol/delete.rb +1 -1
  208. data/lib/mongo/protocol/get_more.rb +7 -7
  209. data/lib/mongo/protocol/insert.rb +1 -1
  210. data/lib/mongo/protocol/kill_cursors.rb +1 -1
  211. data/lib/mongo/protocol/message.rb +5 -5
  212. data/lib/mongo/protocol/msg.rb +9 -7
  213. data/lib/mongo/protocol/query.rb +1 -1
  214. data/lib/mongo/protocol/registry.rb +1 -1
  215. data/lib/mongo/protocol/reply.rb +10 -10
  216. data/lib/mongo/protocol/serializers.rb +1 -1
  217. data/lib/mongo/protocol/update.rb +1 -1
  218. data/lib/mongo/retryable.rb +22 -14
  219. data/lib/mongo/server.rb +1 -1
  220. data/lib/mongo/server/connectable.rb +1 -1
  221. data/lib/mongo/server/connection.rb +16 -4
  222. data/lib/mongo/server/connection_pool.rb +1 -1
  223. data/lib/mongo/server/connection_pool/queue.rb +1 -1
  224. data/lib/mongo/server/context.rb +1 -1
  225. data/lib/mongo/server/description.rb +14 -2
  226. data/lib/mongo/server/description/features.rb +10 -9
  227. data/lib/mongo/server/description/inspector.rb +1 -1
  228. data/lib/mongo/server/description/inspector/description_changed.rb +1 -1
  229. data/lib/mongo/server/description/inspector/member_discovered.rb +1 -1
  230. data/lib/mongo/server/description/inspector/primary_elected.rb +1 -1
  231. data/lib/mongo/server/description/inspector/standalone_discovered.rb +1 -1
  232. data/lib/mongo/server/monitor.rb +15 -3
  233. data/lib/mongo/server/monitor/connection.rb +1 -1
  234. data/lib/mongo/server_selector.rb +1 -1
  235. data/lib/mongo/server_selector/nearest.rb +1 -1
  236. data/lib/mongo/server_selector/primary.rb +1 -1
  237. data/lib/mongo/server_selector/primary_preferred.rb +1 -1
  238. data/lib/mongo/server_selector/secondary.rb +1 -1
  239. data/lib/mongo/server_selector/secondary_preferred.rb +1 -1
  240. data/lib/mongo/server_selector/selectable.rb +7 -2
  241. data/lib/mongo/session.rb +389 -12
  242. data/lib/mongo/session/server_session.rb +7 -2
  243. data/lib/mongo/session/session_pool.rb +1 -1
  244. data/lib/mongo/socket.rb +1 -1
  245. data/lib/mongo/socket/ssl.rb +1 -1
  246. data/lib/mongo/socket/tcp.rb +1 -1
  247. data/lib/mongo/socket/unix.rb +1 -1
  248. data/lib/mongo/uri.rb +6 -4
  249. data/lib/mongo/uri/srv_protocol.rb +1 -1
  250. data/lib/mongo/version.rb +2 -2
  251. data/lib/mongo/write_concern.rb +1 -1
  252. data/lib/mongo/write_concern/acknowledged.rb +1 -1
  253. data/lib/mongo/write_concern/normalizable.rb +1 -1
  254. data/lib/mongo/write_concern/unacknowledged.rb +1 -1
  255. data/mongo.gemspec +4 -1
  256. data/spec/atlas/atlas_connectivity_spec.rb +54 -0
  257. data/spec/integration/bulk_insert_spec.rb +78 -0
  258. data/spec/integration/change_stream_spec.rb +365 -0
  259. data/spec/integration/command_monitoring_spec.rb +92 -0
  260. data/spec/lite_spec_helper.rb +63 -0
  261. data/spec/mongo/address/ipv6_spec.rb +29 -1
  262. data/spec/mongo/address_spec.rb +34 -0
  263. data/spec/mongo/auth/scram/conversation_spec.rb +326 -120
  264. data/spec/mongo/auth/scram/negotiation_spec.rb +574 -0
  265. data/spec/mongo/auth/scram_spec.rb +107 -38
  266. data/spec/mongo/auth/stringprep/profiles/sasl_spec.rb +113 -0
  267. data/spec/mongo/auth/stringprep_spec.rb +188 -0
  268. data/spec/mongo/auth/user/view_spec.rb +5 -2
  269. data/spec/mongo/auth/user_spec.rb +1 -1
  270. data/spec/mongo/bulk_write/result_spec.rb +120 -0
  271. data/spec/mongo/bulk_write_spec.rb +42 -2
  272. data/spec/mongo/client_spec.rb +121 -9
  273. data/spec/mongo/cluster/app_metadata_spec.rb +14 -1
  274. data/spec/mongo/cluster/topology_spec.rb +1 -23
  275. data/spec/mongo/collection/view/change_stream_spec.rb +62 -180
  276. data/spec/mongo/collection_spec.rb +45 -12
  277. data/spec/mongo/cursor/builder/get_more_command_spec.rb +7 -7
  278. data/spec/mongo/cursor_spec.rb +2 -2
  279. data/spec/mongo/database_spec.rb +3 -3
  280. data/spec/mongo/docs_examples_spec.rb +194 -0
  281. data/spec/mongo/error/operation_failure_spec.rb +152 -0
  282. data/spec/mongo/error/parser_spec.rb +127 -0
  283. data/spec/mongo/grid/fs_bucket_spec.rb +32 -0
  284. data/spec/mongo/grid/stream/write_spec.rb +40 -1
  285. data/spec/mongo/monitoring/event/command_failed_spec.rb +30 -0
  286. data/spec/mongo/monitoring/event/command_started_spec.rb +26 -4
  287. data/spec/mongo/monitoring/event/command_succeeded_spec.rb +29 -7
  288. data/spec/mongo/monitoring_spec.rb +28 -3
  289. data/spec/mongo/protocol/get_more_spec.rb +2 -2
  290. data/spec/mongo/retryable_spec.rb +252 -34
  291. data/spec/mongo/retryable_writes_spec.rb +468 -544
  292. data/spec/mongo/server/connection_spec.rb +5 -5
  293. data/spec/mongo/server/description_spec.rb +23 -6
  294. data/spec/mongo/session/server_session_spec.rb +2 -2
  295. data/spec/mongo/session/session_pool_spec.rb +2 -2
  296. data/spec/mongo/transactions_examples_spec.rb +227 -0
  297. data/spec/mongo/transactions_spec.rb +44 -0
  298. data/spec/spec_helper.rb +135 -49
  299. data/spec/spec_tests/change_streams_spec.rb +42 -0
  300. data/spec/{mongo → spec_tests}/command_monitoring_spec.rb +8 -2
  301. data/spec/{mongo → spec_tests}/connection_string_spec.rb +1 -1
  302. data/spec/{mongo → spec_tests}/crud_spec.rb +5 -7
  303. data/spec/{mongo → spec_tests}/dns_seedlist_discovery_spec.rb +1 -1
  304. data/spec/{mongo → spec_tests}/gridfs_spec.rb +0 -0
  305. data/spec/{mongo → spec_tests}/max_staleness_spec.rb +0 -0
  306. data/spec/spec_tests/retryable_writes_spec.rb +78 -0
  307. data/spec/{mongo → spec_tests}/sdam_monitoring_spec.rb +4 -3
  308. data/spec/{mongo → spec_tests}/sdam_spec.rb +7 -7
  309. data/spec/{mongo → spec_tests}/server_selection_rtt_spec.rb +0 -0
  310. data/spec/{mongo → spec_tests}/server_selection_spec.rb +0 -0
  311. data/spec/support/authorization.rb +18 -6
  312. data/spec/support/change_streams.rb +265 -0
  313. data/spec/support/change_streams/operation.rb +62 -0
  314. data/spec/support/change_streams_tests/change-streams-errors.yml +53 -0
  315. data/spec/support/change_streams_tests/change-streams.yml +299 -0
  316. data/spec/support/command_monitoring.rb +1 -1
  317. data/spec/support/command_monitoring/bulkWrite.yml +4 -28
  318. data/spec/support/command_monitoring/command.yml +19 -0
  319. data/spec/support/command_monitoring/find.yml +17 -19
  320. data/spec/support/command_monitoring/insertMany.yml +2 -8
  321. data/spec/support/command_monitoring/unacknowledgedBulkWrite.yml +34 -0
  322. data/spec/support/connection_string.rb +1 -1
  323. data/spec/support/constraints.rb +56 -0
  324. data/spec/support/crud.rb +9 -4
  325. data/spec/support/crud/read.rb +24 -3
  326. data/spec/support/crud/write.rb +7 -2
  327. data/spec/support/crud_tests/read/count-collation.yml +12 -2
  328. data/spec/support/crud_tests/read/count.yml +43 -5
  329. data/spec/support/gridfs.rb +1 -1
  330. data/spec/support/primary_socket.rb +21 -0
  331. data/spec/support/retryable_writes_tests/bulkWrite-serverErrors.yml +90 -0
  332. data/spec/support/retryable_writes_tests/bulkWrite.yml +99 -1
  333. data/spec/support/retryable_writes_tests/deleteOne-serverErrors.yml +50 -0
  334. data/spec/support/retryable_writes_tests/deleteOne.yml +10 -1
  335. data/spec/support/retryable_writes_tests/findOneAndDelete-serverErrors.yml +50 -0
  336. data/spec/support/retryable_writes_tests/findOneAndDelete.yml +39 -30
  337. data/spec/support/retryable_writes_tests/findOneAndReplace-serverErrors.yml +54 -0
  338. data/spec/support/retryable_writes_tests/findOneAndReplace.yml +9 -0
  339. data/spec/support/retryable_writes_tests/findOneAndUpdate-serverErrors.yml +54 -0
  340. data/spec/support/retryable_writes_tests/findOneAndUpdate.yml +9 -0
  341. data/spec/support/retryable_writes_tests/insertMany-serverErrors.yml +59 -0
  342. data/spec/support/retryable_writes_tests/insertMany.yml +11 -6
  343. data/spec/support/retryable_writes_tests/insertOne-serverErrors.yml +471 -0
  344. data/spec/support/retryable_writes_tests/insertOne.yml +9 -0
  345. data/spec/support/retryable_writes_tests/replaceOne-serverErrors.yml +58 -0
  346. data/spec/support/retryable_writes_tests/replaceOne.yml +9 -0
  347. data/spec/support/retryable_writes_tests/updateOne-serverErrors.yml +58 -0
  348. data/spec/support/retryable_writes_tests/updateOne.yml +71 -53
  349. data/spec/support/sdam/rs/normalize_case_me.yml +100 -0
  350. data/spec/support/sdam/sharded/compatible.yml +38 -0
  351. data/spec/support/sdam/sharded/mongos_disconnect.yml +9 -3
  352. data/spec/support/sdam/sharded/multiple_mongoses.yml +6 -2
  353. data/spec/support/sdam/sharded/non_mongos_removed.yml +6 -2
  354. data/spec/support/sdam/sharded/too_new.yml +36 -0
  355. data/spec/support/sdam/sharded/too_old.yml +36 -0
  356. data/spec/support/sdam/single/compatible.yml +26 -0
  357. data/spec/support/sdam/single/direct_connection_external_ip.yml +3 -1
  358. data/spec/support/sdam/single/direct_connection_mongos.yml +3 -1
  359. data/spec/support/sdam/single/direct_connection_rsarbiter.yml +3 -1
  360. data/spec/support/sdam/single/direct_connection_rsprimary.yml +3 -1
  361. data/spec/support/sdam/single/direct_connection_rssecondary.yml +3 -1
  362. data/spec/support/sdam/single/direct_connection_slave.yml +3 -1
  363. data/spec/support/sdam/single/direct_connection_standalone.yml +3 -1
  364. data/spec/support/sdam/single/not_ok_response.yml +6 -2
  365. data/spec/support/sdam/single/standalone_removed.yml +3 -1
  366. data/spec/support/sdam/single/too_new.yml +26 -0
  367. data/spec/support/sdam/single/too_old.yml +24 -0
  368. data/spec/support/shared/session.rb +107 -0
  369. data/spec/support/transactions.rb +391 -0
  370. data/spec/support/transactions/operation.rb +373 -0
  371. data/spec/support/transactions_tests/abort.yml +403 -0
  372. data/spec/support/transactions_tests/bulk.yml +267 -0
  373. data/spec/support/transactions_tests/causal-consistency.yml +173 -0
  374. data/spec/support/transactions_tests/commit.yml +593 -0
  375. data/spec/support/transactions_tests/delete.yml +184 -0
  376. data/spec/support/transactions_tests/error-labels.yml +948 -0
  377. data/spec/support/transactions_tests/errors.yml +125 -0
  378. data/spec/support/transactions_tests/findOneAndDelete.yml +126 -0
  379. data/spec/support/transactions_tests/findOneAndReplace.yml +140 -0
  380. data/spec/support/transactions_tests/findOneAndUpdate.yml +228 -0
  381. data/spec/support/transactions_tests/insert.yml +264 -0
  382. data/spec/support/transactions_tests/isolation.yml +125 -0
  383. data/spec/support/transactions_tests/read-pref.yml +340 -0
  384. data/spec/support/transactions_tests/reads.yml +298 -0
  385. data/spec/support/transactions_tests/retryable-abort.yml +1292 -0
  386. data/spec/support/transactions_tests/retryable-commit.yml +1332 -0
  387. data/spec/support/transactions_tests/retryable-writes.yml +208 -0
  388. data/spec/support/transactions_tests/run-command.yml +189 -0
  389. data/spec/support/transactions_tests/transaction-options.yml +877 -0
  390. data/spec/support/transactions_tests/update.yml +246 -0
  391. data/spec/support/transactions_tests/write-concern.yml +236 -0
  392. metadata +494 -359
  393. metadata.gz.sig +0 -0
  394. data/lib/csasl/csasl.bundle +0 -0
@@ -134,7 +134,7 @@ describe Mongo::Server::Connection do
134
134
  TEST_OPTIONS.merge(
135
135
  :user => TEST_USER.name,
136
136
  :password => TEST_USER.password,
137
- :database => TEST_DB )
137
+ :database => TEST_USER.database )
138
138
  )
139
139
  end
140
140
 
@@ -187,7 +187,7 @@ describe Mongo::Server::Connection do
187
187
  TEST_OPTIONS.merge(
188
188
  :user => TEST_USER.name,
189
189
  :password => TEST_USER.password,
190
- :database => TEST_DB )
190
+ :database => TEST_USER.database )
191
191
  )
192
192
  end
193
193
 
@@ -608,10 +608,10 @@ describe Mongo::Server::Connection do
608
608
  context 'when the ismaster response indicates the auth mechanism is :scram' do
609
609
 
610
610
  let(:features) do
611
- Mongo::Server::Description::Features.new(0..3)
611
+ Mongo::Server::Description::Features.new(0..7)
612
612
  end
613
613
 
614
- context 'when the server auth mechanism is scram', if: scram_sha_1_enabled? do
614
+ context 'when the server auth mechanism is scram', if: scram_sha_1_enabled? && !scram_sha_256_enabled? do
615
615
 
616
616
  it 'uses scram' do
617
617
  allow(Mongo::Server::Description::Features).to receive(:new).and_return(features)
@@ -636,7 +636,7 @@ describe Mongo::Server::Connection do
636
636
  Mongo::Server::Description::Features.new(0..2)
637
637
  end
638
638
 
639
- context 'when the server auth mechanism is scram', if: scram_sha_1_enabled? do
639
+ context 'when the server auth mechanism is scram', if: scram_sha_1_enabled? && !scram_sha_256_enabled? do
640
640
 
641
641
  it 'uses scram' do
642
642
  allow(Mongo::Server::Description::Features).to receive(:new).and_return(features)
@@ -42,7 +42,7 @@ describe Mongo::Server::Description do
42
42
  let(:topology) do
43
43
  double('topology')
44
44
  end
45
-
45
+
46
46
  let(:cluster) do
47
47
  double('cluster').tap do |cl|
48
48
  allow(cl).to receive(:topology).and_return(topology)
@@ -431,19 +431,36 @@ describe Mongo::Server::Description do
431
431
  described_class.new(address, { 'ismaster' => false })
432
432
  end
433
433
 
434
- it 'returns true' do
434
+ it 'returns false' do
435
435
  expect(description).to_not be_primary
436
436
  end
437
437
  end
438
438
 
439
439
  context 'when the server is a primary' do
440
440
 
441
- let(:description) do
442
- described_class.new(address, replica)
441
+ context 'when the hostname contains no capital letters' do
442
+
443
+ let(:description) do
444
+ described_class.new(address, replica)
445
+ end
446
+
447
+ it 'returns true' do
448
+ expect(description).to be_primary
449
+ end
443
450
  end
444
451
 
445
- it 'returns false' do
446
- expect(description).to be_primary
452
+ context 'when the hostname contains capital letters' do
453
+
454
+ let(:description) do
455
+ described_class.new('localhost:27017',
456
+ { 'ismaster' => true,
457
+ 'primary' => 'LOCALHOST:27017',
458
+ 'setName' => 'itsASet!'})
459
+ end
460
+
461
+ it 'returns true' do
462
+ expect(description).to be_primary
463
+ end
447
464
  end
448
465
  end
449
466
  end
@@ -18,7 +18,7 @@ describe Mongo::Session::ServerSession do
18
18
  describe '#next_txn_number' do
19
19
 
20
20
  it 'advances and returns the next transaction number' do
21
- expect(described_class.new.next_txn_num).to be(0)
21
+ expect(described_class.new.next_txn_num).to be(1)
22
22
  end
23
23
 
24
24
  context 'when the method is called multiple times' do
@@ -33,7 +33,7 @@ describe Mongo::Session::ServerSession do
33
33
  end
34
34
 
35
35
  it 'advances and returns the next transaction number' do
36
- expect(server_session.next_txn_num).to be(2)
36
+ expect(server_session.next_txn_num).to be(3)
37
37
  end
38
38
  end
39
39
  end
@@ -171,7 +171,7 @@ describe Mongo::Session::SessionPool, if: test_sessions? do
171
171
 
172
172
  let(:end_sessions_command) do
173
173
  pool.end_sessions
174
- EventSubscriber.started_events.find { |c| c.command_name == :endSessions}
174
+ EventSubscriber.started_events.find { |c| c.command_name == 'endSessions'}
175
175
  end
176
176
 
177
177
  it 'sends the endSessions command with all the session ids' do
@@ -210,7 +210,7 @@ describe Mongo::Session::SessionPool, if: test_sessions? do
210
210
  end
211
211
 
212
212
  let(:end_sessions_commands) do
213
- EventSubscriber.started_events.select { |c| c.command_name == :endSessions}
213
+ EventSubscriber.started_events.select { |c| c.command_name == 'endSessions'}
214
214
  end
215
215
 
216
216
  it 'sends the command more than once' do
@@ -0,0 +1,227 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'transactions examples in Ruby', if: test_transactions? do
4
+
5
+ let(:hr) do
6
+ authorized_client.use(:hr).database
7
+ end
8
+
9
+ let(:reporting) do
10
+ authorized_client.use(:reporting).database
11
+ end
12
+
13
+ before(:each) do
14
+ hr[:employees].insert_one(employee: 3, status: 'Active')
15
+ reporting[:events].insert_one(employee: 3, status: { new: 'Active', old: nil})
16
+ end
17
+
18
+ after(:each) do
19
+ hr.drop
20
+ reporting.drop
21
+ end
22
+
23
+ context 'individual examples' do
24
+
25
+ let(:session) do
26
+ authorized_client.start_session
27
+ end
28
+
29
+ # Start Transactions Intro Example 1
30
+
31
+ def update_employee_info(session)
32
+ employees_coll = session.client.use(:hr)[:employees]
33
+ events_coll = session.client.use(:reporting)[:events]
34
+
35
+ session.start_transaction(read_concern: { level: :snapshot },
36
+ write_concern: { w: :majority })
37
+ employees_coll.update_one({ employee: 3 }, { '$set' => { status: 'Inactive'} },
38
+ session: session)
39
+ events_coll.insert_one({ employee: 3, status: { new: 'Inactive', old: 'Active' } },
40
+ session: session)
41
+
42
+ loop do
43
+ begin
44
+ session.commit_transaction
45
+ puts 'Transaction committed.'
46
+ break
47
+ rescue Mongo::Error => e
48
+ if e.label?(Mongo::Error::UNKNOWN_TRANSACTION_COMMIT_RESULT_LABEL)
49
+ puts "#{Mongo::Error::UNKNOWN_TRANSACTION_COMMIT_RESULT_LABEL}, retrying commit operation..."
50
+ next
51
+ else
52
+ puts 'Error during commit ...'
53
+ raise
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ # End Transactions Intro Example 1
60
+
61
+ context 'Transactions Intro Example 1' do
62
+
63
+ let(:run_transaction) do
64
+ update_employee_info(session)
65
+ end
66
+
67
+ it 'makes the changes to the database' do
68
+ run_transaction
69
+ employee = hr[:employees].find({ employee: 3 }, limit: 1).first
70
+ expect(employee).to_not be_nil
71
+ expect(employee['status']).to eq('Inactive')
72
+ end
73
+ end
74
+
75
+ context 'Transactions Retry Example 1' do
76
+
77
+ # Start Transactions Retry Example 1
78
+
79
+ def run_transaction_with_retry(session)
80
+ loop do
81
+ begin
82
+ yield session # performs transaction
83
+ break
84
+ rescue Mongo::Error => e
85
+
86
+ puts 'Transaction aborted. Caught exception during transaction.'
87
+ raise unless e.label?(Mongo::Error::TRANSIENT_TRANSACTION_ERROR_LABEL)
88
+
89
+ puts "#{Mongo::Error::TRANSIENT_TRANSACTION_ERROR_LABEL}, retrying transaction ..."
90
+ next
91
+ end
92
+ end
93
+ end
94
+
95
+ # End Transactions Retry Example 1
96
+
97
+ let(:run_transaction) do
98
+ run_transaction_with_retry(session) { |s| update_employee_info(s) }
99
+ end
100
+
101
+ it 'makes the changes to the database' do
102
+ run_transaction
103
+ employee = hr[:employees].find({ employee: 3 }, limit: 1).first
104
+ expect(employee).to_not be_nil
105
+ expect(employee['status']).to eq('Inactive')
106
+ end
107
+ end
108
+
109
+ context 'Transactions Retry Example 2' do
110
+
111
+ # Start Transactions Retry Example 2
112
+
113
+ def commit_with_retry(session)
114
+ loop do
115
+ begin
116
+ session.commit_transaction
117
+ puts 'Transaction committed.'
118
+ break
119
+ rescue Mongo::Error=> e
120
+ if e.label?(Mongo::Error::UNKNOWN_TRANSACTION_COMMIT_RESULT_LABEL)
121
+ puts "#{Mongo::Error::UNKNOWN_TRANSACTION_COMMIT_RESULT_LABEL}, retrying commit operation..."
122
+ next
123
+ else
124
+ puts 'Error during commit ...'
125
+ raise
126
+ end
127
+ end
128
+ end
129
+ end
130
+
131
+ # End Transactions Retry Example 2
132
+
133
+ let(:run_transaction) do
134
+ session.start_transaction
135
+ hr[:employees].insert_one({ employee: 4, status: 'Active' }, session: session)
136
+ reporting[:events].insert_one({ employee: 4, status: { new: 'Active', old: nil } },
137
+ session: session)
138
+ commit_with_retry(session)
139
+ end
140
+
141
+ it 'makes the changes to the database' do
142
+ run_transaction
143
+ employee = hr[:employees].find({ employee: 4 }, limit: 1).first
144
+ expect(employee).to_not be_nil
145
+ expect(employee['status']).to eq('Active')
146
+ end
147
+ end
148
+ end
149
+
150
+ context 'Transactions Retry Example 3 (combined example)' do
151
+
152
+ let(:client) do
153
+ authorized_client
154
+ end
155
+
156
+ let(:run_transaction) do
157
+
158
+ # Start Transactions Retry Example 3
159
+
160
+ def run_transaction_with_retry(session)
161
+ loop do
162
+ begin
163
+ yield session # performs transaction
164
+ break
165
+ rescue Mongo::Error=> e
166
+ puts 'Transaction aborted. Caught exception during transaction.'
167
+ raise unless e.label?(Mongo::Error::TRANSIENT_TRANSACTION_ERROR_LABEL)
168
+
169
+ puts "#{Mongo::Error::TRANSIENT_TRANSACTION_ERROR_LABEL}, retrying transaction ..."
170
+ next
171
+ end
172
+ end
173
+ end
174
+
175
+ def commit_with_retry(session)
176
+ loop do
177
+ begin
178
+ session.commit_transaction
179
+ puts 'Transaction committed.'
180
+ break
181
+ rescue Mongo::Error => e
182
+ if e.label?(Mongo::Error::UNKNOWN_TRANSACTION_COMMIT_RESULT_LABEL)
183
+ puts "#{Mongo::Error::UNKNOWN_TRANSACTION_COMMIT_RESULT_LABEL}, retrying commit operation ..."
184
+ next
185
+ else
186
+ puts 'Error during commit ...'
187
+ raise
188
+ end
189
+ end
190
+ end
191
+ end
192
+
193
+ # updates two collections in a transaction
194
+
195
+ def update_employee_info(session)
196
+ employees_coll = session.client.use(:hr)[:employees]
197
+ events_coll = session.client.use(:reporting)[:events]
198
+
199
+ session.start_transaction(read_concern: { level: :snapshot },
200
+ write_concern: { w: :majority })
201
+ employees_coll.update_one({ employee: 3 }, { '$set' => { status: 'Inactive'} },
202
+ session: session)
203
+ events_coll.insert_one({ employee: 3, status: { new: 'Inactive', old: 'Active' } },
204
+ session: session)
205
+ commit_with_retry(session)
206
+ end
207
+
208
+ session = client.start_session
209
+
210
+ begin
211
+ run_transaction_with_retry(session) { |s| update_employee_info(s) }
212
+ rescue StandardError => e
213
+ # Do something with error
214
+ raise
215
+ end
216
+
217
+ # End Transactions Retry Example 3
218
+ end
219
+
220
+ it 'makes the changes to the database' do
221
+ run_transaction
222
+ employee = hr[:employees].find({ employee: 3 }, limit: 1).first
223
+ expect(employee).to_not be_nil
224
+ expect(employee['status']).to eq('Inactive')
225
+ end
226
+ end
227
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Transactions' do
4
+
5
+ TRANSACTIONS_TESTS.sort.each do |file|
6
+
7
+ spec = Mongo::Transactions::Spec.new(file)
8
+
9
+ context(spec.description) do
10
+ spec.tests.each do |test|
11
+ context(test.description) do
12
+
13
+ before(:each) do
14
+ test.setup_test
15
+ end
16
+
17
+ let(:results) do
18
+ test.run
19
+ end
20
+
21
+ it 'returns the correct result', if: test_transactions? do
22
+ expect(results[:results]).to match_operation_result(test)
23
+ end
24
+
25
+ it 'has the correct data in the collection', if: test_transactions? && test.outcome_collection_data do
26
+ expect(results[:contents]).to match_collection_data(test)
27
+ end
28
+
29
+ it 'has the correct command_started events', if: test_transactions? && test.expectations do
30
+ test.expectations.each do |expectation|
31
+ # We convert the hashes to sorted arrays to ensure that asserting equality between
32
+ # the expected and actual event descriptions don't fail due to the same entries being
33
+ # in a different order.
34
+ expectation['command_started_event']['command'] = expectation['command_started_event']['command'].to_a.sort
35
+ expectation['command_started_event']['command'].delete_if { |_, v| v == nil }
36
+ end
37
+
38
+ expect(results[:events]).to eq(test.expectations)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,59 +1,93 @@
1
- TEST_SET = 'ruby-driver-rs'
2
- COVERAGE_MIN = 90
3
- CURRENT_PATH = File.expand_path(File.dirname(__FILE__))
4
- SERVER_DISCOVERY_TESTS = Dir.glob("#{CURRENT_PATH}/support/sdam/**/*.yml")
5
- SDAM_MONITORING_TESTS = Dir.glob("#{CURRENT_PATH}/support/sdam_monitoring/*.yml")
6
- SERVER_SELECTION_RTT_TESTS = Dir.glob("#{CURRENT_PATH}/support/server_selection/rtt/*.yml")
7
- SERVER_SELECTION_TESTS = Dir.glob("#{CURRENT_PATH}/support/server_selection/selection/**/*.yml")
8
- MAX_STALENESS_TESTS = Dir.glob("#{CURRENT_PATH}/support/max_staleness/**/*.yml")
9
- CRUD_TESTS = Dir.glob("#{CURRENT_PATH}/support/crud_tests/**/*.yml")
10
- RETRYABLE_WRITES_TESTS = Dir.glob("#{CURRENT_PATH}/support/retryable_writes_tests/**/*.yml")
11
- COMMAND_MONITORING_TESTS = Dir.glob("#{CURRENT_PATH}/support/command_monitoring/**/*.yml")
12
- CONNECTION_STRING_TESTS = Dir.glob("#{CURRENT_PATH}/support/connection_string_tests/*.yml")
13
- DNS_SEEDLIST_DISCOVERY_TESTS = Dir.glob("#{CURRENT_PATH}/support/dns_seedlist_discovery_tests/*.yml")
14
- GRIDFS_TESTS = Dir.glob("#{CURRENT_PATH}/support/gridfs_tests/*.yml")
15
-
16
- if ENV['DRIVERS_TOOLS']
17
- CLIENT_CERT_PEM = ENV['DRIVER_TOOLS_CLIENT_CERT_PEM']
18
- CLIENT_KEY_PEM = ENV['DRIVER_TOOLS_CLIENT_KEY_PEM']
19
- CA_PEM = ENV['DRIVER_TOOLS_CA_PEM']
20
- CLIENT_KEY_ENCRYPTED_PEM = ENV['DRIVER_TOOLS_CLIENT_KEY_ENCRYPTED_PEM']
21
- else
22
- SSL_CERTS_DIR = "#{CURRENT_PATH}/support/certificates"
23
- CLIENT_PEM = "#{SSL_CERTS_DIR}/client.pem"
24
- CLIENT_PASSWORD_PEM = "#{SSL_CERTS_DIR}/password_protected.pem"
25
- CA_PEM = "#{SSL_CERTS_DIR}/ca.pem"
26
- CRL_PEM = "#{SSL_CERTS_DIR}/crl.pem"
27
- CLIENT_KEY_PEM = "#{SSL_CERTS_DIR}/client_key.pem"
28
- CLIENT_CERT_PEM = "#{SSL_CERTS_DIR}/client_cert.pem"
29
- CLIENT_KEY_ENCRYPTED_PEM = "#{SSL_CERTS_DIR}/client_key_encrypted.pem"
30
- CLIENT_KEY_PASSPHRASE = "passphrase"
31
- end
1
+ # The tests run against a MongoDB cluster which is
2
+ # configured and started externally to the test suite. This allows
3
+ # running the entire test suite against, for example, a standalone
4
+ # mongod as well as a replica set. The flip side to this is the
5
+ # test suite will not work without a running mongo cluster, and
6
+ # tests which are not applicable to or cannot be performed on the
7
+ # running mongo cluster are skipped.
8
+ #
9
+ # Not only does the test suite require an externally launched cluster,
10
+ # the test suite must also be told how the cluster is configured
11
+ # via MONGODB_URI, TOPOLOGY, MONGODB_ADDRESSES, RS_ENABLED, RS_NAME and
12
+ # SHARDED_ENABLED environment variables.
13
+ #
14
+ # The test suite does not validate that it is able to successfully connect
15
+ # to the cluster prior to running the tests. If a connection fails entirely,
16
+ # the clue is generally failures to invoke methods on nil.
17
+ # However, it is also possible to establish a connection to a cluster which
18
+ # is not quite correctly configured. The result is usually a mass of test
19
+ # failures that are indistinguishable from legitimate failures.
20
+ #
21
+ # Additionally some of the tests assume that the seed list (given in
22
+ # MONGODB_URI or MONGODB_ADDRESSES) encompasses all servers in the cluster,
23
+ # and will fail when MONGODB_URI includes only one host of a replica set.
24
+ # It is best to include all hosts of the cluster in MONGODB_URI and
25
+ # MONGODB_ADDRESSES.
26
+ #
27
+ # The test suite seems to have issues connecting to a replica set
28
+ # via IP addresses if the replica set hosts are defined with hostnames
29
+ # (i.e., 127.0.0.1 vs localhost). Try to exactly match the contents of
30
+ # MONGODB_URI and `rs.isMaster()` output, either by adjusting MONGODB_URI
31
+ # or by reconfiguring the replica set.
32
+ #
33
+ # In order to run spec tests, the mongo cluster needs to have failpoints
34
+ # enabled. This is accomplished by starting mongod with the following option:
35
+ # --setParameter enableTestCommands=1
36
+ #
37
+ # Use the following environment variables to configure the tests:
38
+ #
39
+ # CLIENT_DEBUG: Show debug messages from the client.
40
+ # CLIENT_DEBUG=1
41
+ #
42
+ # MONGODB_URI: Connection string to use. This must be a valid MongoDB URI;
43
+ # mongodb:// and mongodb+srv:// are both supported.
44
+ # RS_ENABLED and SHARDED_ENABLED are NOT honored if using MONGODB_URI -
45
+ # specify replica set name in the URI and to specify a sharded topology
46
+ # set TOPOLOGY=sharded_cluster environment variable.
47
+ # MONGODB_URI=mongodb://127.0.0.1:27001/?replicaSet=test
48
+ # MONGODB_URI=mongodb://127.0.0.1:27001,127.0.0.1:27002/ TOPOLOGY=sharded_cluster
49
+ #
50
+ # MONGODB_ADDRESSES: Specify addresses to connect to. Use RS_ENABLED,
51
+ # RS_NAME and SHARDED_ENABLED to configure the topology.
52
+ # MONGODB_ADDRESSES=127.0.0.1:27017,127.0.0.1:27018
53
+ # MONGODB_ADDRESSES=127.0.0.1:27017,127.0.0.1:27018 RS_ENABLED=1
54
+ # MONGODB_ADDRESSES=127.0.0.1:27017,127.0.0.1:27018 RS_ENABLED=1 RS_NAME=test
55
+ # MONGODB_ADDRESSES=127.0.0.1:27017,127.0.0.1:27018 SHARDED_ENABLED=1
56
+ #
57
+ # RS_ENABLED: Instruct the test suite to connect to a replica set.
58
+ # RS_ENABLED is only honored when not using MONGODB_URI; to connect to a
59
+ # replica set with MONGODB_URI, specify the replica set name in the URI
60
+ # (despite the Ruby driver performing topology discovery by default, it
61
+ # doesn't do so in the test suite).
62
+ # RS_NAME can be given to specify the replica set name; the default is
63
+ # ruby-driver-rs.
64
+ # RS_ENABLED=1
65
+ # RS_ENABLED=1 RS_NAME=test
66
+ #
67
+ # SHARDED_ENABLED: Instruct the test suite to connect to the sharded cluster.
68
+ # Set MONGODB_URI appropriately as well.
69
+ # SHARDED_ENABLED=1
32
70
 
33
- require 'mongo'
71
+ require 'lite_spec_helper'
34
72
 
35
- Mongo::Logger.logger = Logger.new($stdout)
36
- Mongo::Logger.logger.level = Logger::INFO
37
- Encoding.default_external = Encoding::UTF_8
73
+ if RUBY_PLATFORM !~ /\bjava\b/
74
+ require 'timeout_interrupt'
75
+ end
76
+
77
+ # Replica set name can be overridden via replicaSet parameter in MONGODB_URI
78
+ # environment variable or by specifying RS_NAME environment variable when
79
+ # not using MONGODB_URI.
80
+ TEST_SET = 'ruby-driver-rs'
38
81
 
39
82
  require 'support/travis'
40
- require 'support/matchers'
41
- require 'support/event_subscriber'
42
83
  require 'support/authorization'
43
- require 'support/server_discovery_and_monitoring'
44
- require 'support/server_selection_rtt'
45
- require 'support/server_selection'
46
- require 'support/sdam_monitoring'
47
- require 'support/crud'
48
- require 'support/command_monitoring'
49
- require 'support/connection_string'
50
- require 'support/gridfs'
84
+ require 'support/primary_socket'
85
+ require 'support/constraints'
86
+ require 'rspec/retry'
51
87
 
52
88
  RSpec.configure do |config|
53
- config.color = true
54
- config.fail_fast = true unless ENV['CI']
55
- config.formatter = 'documentation'
56
89
  config.include(Authorization)
90
+ config.extend(Constraints)
57
91
 
58
92
  config.before(:suite) do
59
93
  begin
@@ -157,6 +191,14 @@ def test_change_streams?
157
191
  !BSON::Environment.jruby? && change_stream_enabled? & replica_set?
158
192
  end
159
193
 
194
+ # Whether transactions can be tested. Transactions are available on server versions 4.0 and higher
195
+ # and when connected to a replica set.
196
+ #
197
+ # @since 2.6.0
198
+ def test_transactions?
199
+ transactions_enabled? && replica_set?
200
+ end
201
+
160
202
  # For instances where behaviour is different on different versions, we need to
161
203
  # determine in the specs if we are 3.6 or higher.
162
204
  #
@@ -194,6 +236,17 @@ def list_command_enabled?
194
236
  $list_command_enabled ||= $mongo_client.cluster.servers.first.features.list_indexes_enabled?
195
237
  end
196
238
 
239
+ # For instances where behavior is different on different versions, we need to
240
+ # determine in the specs if we are 4.0 or higher.
241
+ #
242
+ # @since 2.6.0
243
+ def scram_sha_256_enabled?
244
+ $mongo_client ||= initialize_scanned_client!
245
+ $scram_sha_256_enabled ||= $mongo_client.cluster.servers.first.features.scram_sha_256_enabled?
246
+ end
247
+
248
+ alias :transactions_enabled? :scram_sha_256_enabled?
249
+
197
250
  # Is the test suite running locally (not on Travis).
198
251
  #
199
252
  # @since 2.1.0
@@ -243,11 +296,23 @@ def auth_enabled?
243
296
  begin
244
297
  $mongo_client.use(:admin).command(getCmdLineOpts: 1).first["argv"].include?("--auth")
245
298
  rescue => e
246
- e.message =~ /(not authorized)|(unauthorized)/
299
+ e.message =~ /(not authorized)|(unauthorized)|(no users authenticated)|(requires authentication)/
247
300
  end
248
301
  end
249
302
  end
250
303
 
304
+ def need_to_skip_on_sharded_auth_40?
305
+ sharded? && auth_enabled? && scram_sha_256_enabled?
306
+ end
307
+
308
+ # Can the driver specify a write concern that won't be overridden? (mongos 4.0+ overrides the write
309
+ # concern)
310
+ #
311
+ # @since 2.6.0
312
+ def can_set_write_concern?
313
+ !sharded? || !scram_sha_256_enabled?
314
+ end
315
+
251
316
  # Initializes a basic scanned client to do an ismaster check.
252
317
  #
253
318
  # @since 2.0.0
@@ -255,5 +320,26 @@ def initialize_scanned_client!
255
320
  Mongo::Client.new(ADDRESSES, TEST_OPTIONS.merge(database: TEST_DB))
256
321
  end
257
322
 
323
+ # Converts a 'camelCase' string or symbol to a :snake_case symbol.
324
+ def camel_to_snake(ident)
325
+ ident = ident.is_a?(String) ? ident.dup : ident.to_s
326
+ ident[0] = ident[0].downcase
327
+ ident.chars.reduce('') { |s, c| s + (/[A-Z]/ =~ c ? "_#{c.downcase}" : c) }.to_sym
328
+ end
329
+
330
+ # Creates a copy of a hash where all keys and string values are converted to snake-case symbols.
331
+ # For example, `{ 'fooBar' => { 'baz' => 'bingBing', :x => 1 } }` converts to
332
+ # `{ :foo_bar => { :baz => :bing_bing, :x => 1 } }`.
333
+ def snakeize_hash(value)
334
+ return camel_to_snake(value) if value.is_a?(String)
335
+ return value unless value.is_a?(Hash)
336
+
337
+ value.reduce({}) do |hash, kv|
338
+ hash.tap do |h|
339
+ h[camel_to_snake(kv.first)] = snakeize_hash(kv.last)
340
+ end
341
+ end
342
+ end
343
+
258
344
  # require all shared examples
259
345
  Dir['./spec/support/shared/*.rb'].sort.each { |file| require file }