mongo 2.20.2 → 2.21.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 (279) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -0
  3. data/Rakefile +11 -11
  4. data/lib/mongo/address.rb +22 -3
  5. data/lib/mongo/auth/aws/credentials_retriever.rb +70 -17
  6. data/lib/mongo/auth/base.rb +1 -1
  7. data/lib/mongo/bulk_write.rb +35 -2
  8. data/lib/mongo/client.rb +38 -6
  9. data/lib/mongo/client_encryption.rb +6 -3
  10. data/lib/mongo/cluster/reapers/cursor_reaper.rb +6 -1
  11. data/lib/mongo/cluster/sdam_flow.rb +20 -7
  12. data/lib/mongo/cluster.rb +14 -4
  13. data/lib/mongo/collection/helpers.rb +1 -1
  14. data/lib/mongo/collection/view/aggregation/behavior.rb +131 -0
  15. data/lib/mongo/collection/view/aggregation.rb +33 -99
  16. data/lib/mongo/collection/view/builder/aggregation.rb +1 -7
  17. data/lib/mongo/collection/view/change_stream.rb +80 -27
  18. data/lib/mongo/collection/view/iterable.rb +76 -60
  19. data/lib/mongo/collection/view/map_reduce.rb +25 -8
  20. data/lib/mongo/collection/view/readable.rb +79 -30
  21. data/lib/mongo/collection/view/writable.rb +109 -48
  22. data/lib/mongo/collection/view.rb +43 -3
  23. data/lib/mongo/collection.rb +158 -23
  24. data/lib/mongo/crypt/auto_encrypter.rb +4 -6
  25. data/lib/mongo/crypt/binding.rb +4 -4
  26. data/lib/mongo/crypt/context.rb +20 -14
  27. data/lib/mongo/crypt/encryption_io.rb +56 -26
  28. data/lib/mongo/crypt/explicit_encrypter.rb +49 -20
  29. data/lib/mongo/crypt/explicit_encryption_context.rb +17 -11
  30. data/lib/mongo/crypt/kms/azure/credentials_retriever.rb +22 -6
  31. data/lib/mongo/crypt/kms/gcp/credentials_retriever.rb +29 -4
  32. data/lib/mongo/csot_timeout_holder.rb +119 -0
  33. data/lib/mongo/cursor/kill_spec.rb +5 -2
  34. data/lib/mongo/cursor/nontailable.rb +27 -0
  35. data/lib/mongo/cursor.rb +86 -24
  36. data/lib/mongo/cursor_host.rb +82 -0
  37. data/lib/mongo/database/view.rb +81 -14
  38. data/lib/mongo/database.rb +88 -18
  39. data/lib/mongo/error/operation_failure.rb +209 -204
  40. data/lib/mongo/error/server_timeout_error.rb +12 -0
  41. data/lib/mongo/error/socket_timeout_error.rb +3 -1
  42. data/lib/mongo/error/timeout_error.rb +23 -0
  43. data/lib/mongo/error.rb +2 -0
  44. data/lib/mongo/grid/fs_bucket.rb +45 -12
  45. data/lib/mongo/grid/stream/read.rb +15 -1
  46. data/lib/mongo/grid/stream/write.rb +21 -4
  47. data/lib/mongo/index/view.rb +77 -16
  48. data/lib/mongo/operation/context.rb +40 -2
  49. data/lib/mongo/operation/create_search_indexes/op_msg.rb +2 -2
  50. data/lib/mongo/operation/delete/op_msg.rb +2 -1
  51. data/lib/mongo/operation/drop_search_index/op_msg.rb +2 -2
  52. data/lib/mongo/operation/find/op_msg.rb +45 -0
  53. data/lib/mongo/operation/get_more/op_msg.rb +33 -0
  54. data/lib/mongo/operation/insert/op_msg.rb +3 -2
  55. data/lib/mongo/operation/insert/result.rb +4 -2
  56. data/lib/mongo/operation/list_collections/result.rb +1 -1
  57. data/lib/mongo/operation/map_reduce/result.rb +1 -1
  58. data/lib/mongo/operation/op_msg_base.rb +3 -1
  59. data/lib/mongo/operation/result.rb +26 -5
  60. data/lib/mongo/operation/shared/executable.rb +12 -1
  61. data/lib/mongo/operation/shared/op_msg_executable.rb +4 -1
  62. data/lib/mongo/operation/shared/response_handling.rb +3 -3
  63. data/lib/mongo/operation/shared/sessions_supported.rb +1 -1
  64. data/lib/mongo/operation/shared/timed.rb +52 -0
  65. data/lib/mongo/operation/shared/write.rb +4 -1
  66. data/lib/mongo/operation/update/op_msg.rb +2 -1
  67. data/lib/mongo/operation/update_search_index/op_msg.rb +2 -2
  68. data/lib/mongo/operation.rb +1 -0
  69. data/lib/mongo/protocol/message.rb +1 -4
  70. data/lib/mongo/protocol/msg.rb +2 -2
  71. data/lib/mongo/retryable/read_worker.rb +69 -29
  72. data/lib/mongo/retryable/write_worker.rb +49 -18
  73. data/lib/mongo/retryable.rb +8 -2
  74. data/lib/mongo/server/connection.rb +11 -5
  75. data/lib/mongo/server/connection_base.rb +22 -2
  76. data/lib/mongo/server/connection_pool.rb +32 -14
  77. data/lib/mongo/server/description/features.rb +1 -1
  78. data/lib/mongo/server/description.rb +18 -5
  79. data/lib/mongo/server/monitor.rb +7 -4
  80. data/lib/mongo/server/pending_connection.rb +7 -3
  81. data/lib/mongo/server/{round_trip_time_averager.rb → round_trip_time_calculator.rb} +25 -7
  82. data/lib/mongo/server.rb +11 -6
  83. data/lib/mongo/server_selector/base.rb +25 -9
  84. data/lib/mongo/session.rb +78 -9
  85. data/lib/mongo/socket/ssl.rb +113 -30
  86. data/lib/mongo/socket/tcp.rb +40 -6
  87. data/lib/mongo/socket.rb +154 -25
  88. data/lib/mongo/uri/options_mapper.rb +1 -0
  89. data/lib/mongo/version.rb +15 -4
  90. data/lib/mongo.rb +1 -0
  91. data/spec/atlas/atlas_connectivity_spec.rb +4 -0
  92. data/spec/atlas/operations_spec.rb +4 -0
  93. data/spec/integration/client_side_encryption/auto_encryption_mongocryptd_spawn_spec.rb +2 -1
  94. data/spec/integration/client_side_encryption/auto_encryption_spec.rb +494 -487
  95. data/spec/integration/client_side_encryption/on_demand_aws_credentials_spec.rb +1 -1
  96. data/spec/integration/client_side_encryption/range_explicit_encryption_prose_spec.rb +66 -22
  97. data/spec/integration/client_side_operations_timeout/encryption_prose_spec.rb +131 -0
  98. data/spec/integration/connection_pool_populator_spec.rb +2 -0
  99. data/spec/integration/cursor_pinning_spec.rb +15 -60
  100. data/spec/integration/cursor_reaping_spec.rb +1 -1
  101. data/spec/integration/docs_examples_spec.rb +1 -1
  102. data/spec/integration/ocsp_verifier_spec.rb +99 -30
  103. data/spec/integration/operation_failure_code_spec.rb +1 -1
  104. data/spec/integration/operation_failure_message_spec.rb +3 -3
  105. data/spec/integration/reconnect_spec.rb +2 -8
  106. data/spec/integration/retryable_errors_spec.rb +2 -2
  107. data/spec/integration/sdam_error_handling_spec.rb +2 -1
  108. data/spec/integration/search_indexes_prose_spec.rb +4 -0
  109. data/spec/integration/server_spec.rb +4 -3
  110. data/spec/integration/srv_monitoring_spec.rb +3 -2
  111. data/spec/integration/srv_spec.rb +4 -0
  112. data/spec/integration/transactions_api_examples_spec.rb +2 -0
  113. data/spec/kerberos/kerberos_spec.rb +4 -0
  114. data/spec/lite_spec_helper.rb +3 -1
  115. data/spec/mongo/auth/user/view_spec.rb +1 -1
  116. data/spec/mongo/caching_cursor_spec.rb +1 -1
  117. data/spec/mongo/client_encryption_spec.rb +1 -0
  118. data/spec/mongo/client_spec.rb +158 -4
  119. data/spec/mongo/collection/view/aggregation_spec.rb +14 -39
  120. data/spec/mongo/collection/view/change_stream_spec.rb +3 -3
  121. data/spec/mongo/collection_spec.rb +5 -6
  122. data/spec/mongo/crypt/auto_encrypter_spec.rb +14 -12
  123. data/spec/mongo/crypt/data_key_context_spec.rb +3 -1
  124. data/spec/mongo/crypt/explicit_encryption_context_spec.rb +2 -2
  125. data/spec/mongo/crypt/handle_spec.rb +1 -1
  126. data/spec/mongo/cursor_spec.rb +26 -9
  127. data/spec/mongo/error/operation_failure_heavy_spec.rb +2 -2
  128. data/spec/mongo/operation/context_spec.rb +79 -0
  129. data/spec/mongo/operation/create/op_msg_spec.rb +106 -110
  130. data/spec/mongo/operation/delete/op_msg_spec.rb +6 -5
  131. data/spec/mongo/operation/find/op_msg_spec.rb +66 -0
  132. data/spec/mongo/operation/get_more/op_msg_spec.rb +65 -0
  133. data/spec/mongo/operation/insert/op_msg_spec.rb +128 -131
  134. data/spec/mongo/operation/shared/csot/examples.rb +113 -0
  135. data/spec/mongo/query_cache_spec.rb +243 -225
  136. data/spec/mongo/retryable_spec.rb +1 -0
  137. data/spec/mongo/server/round_trip_time_calculator_spec.rb +120 -0
  138. data/spec/mongo/socket/ssl_spec.rb +0 -10
  139. data/spec/runners/change_streams/test.rb +2 -2
  140. data/spec/runners/crud/operation.rb +1 -1
  141. data/spec/runners/crud/verifier.rb +3 -1
  142. data/spec/runners/transactions/operation.rb +4 -6
  143. data/spec/runners/unified/ambiguous_operations.rb +13 -0
  144. data/spec/runners/unified/assertions.rb +4 -0
  145. data/spec/runners/unified/change_stream_operations.rb +14 -24
  146. data/spec/runners/unified/crud_operations.rb +82 -59
  147. data/spec/runners/unified/ddl_operations.rb +38 -7
  148. data/spec/runners/unified/grid_fs_operations.rb +37 -2
  149. data/spec/runners/unified/support_operations.rb +43 -4
  150. data/spec/runners/unified/test.rb +22 -10
  151. data/spec/runners/unified.rb +1 -1
  152. data/spec/solo/clean_exit_spec.rb +2 -0
  153. data/spec/spec_tests/client_side_operations_timeout_spec.rb +15 -0
  154. data/spec/spec_tests/data/change_streams_unified/change-streams-clusterTime.yml +3 -1
  155. data/spec/spec_tests/data/change_streams_unified/change-streams-disambiguatedPaths.yml +3 -1
  156. data/spec/spec_tests/data/change_streams_unified/change-streams-errors.yml +3 -1
  157. data/spec/spec_tests/data/change_streams_unified/change-streams-pre_and_post_images.yml +1 -1
  158. data/spec/spec_tests/data/change_streams_unified/change-streams-resume-allowlist.yml +1 -1
  159. data/spec/spec_tests/data/change_streams_unified/change-streams-resume-errorLabels.yml +1 -1
  160. data/spec/spec_tests/data/change_streams_unified/change-streams-showExpandedEvents.yml +1 -1
  161. data/spec/spec_tests/data/client_side_encryption/badQueries.yml +2 -1
  162. data/spec/spec_tests/data/client_side_encryption/timeoutMS.yml +67 -0
  163. data/spec/spec_tests/data/client_side_operations_timeout/bulkWrite.yml +87 -0
  164. data/spec/spec_tests/data/client_side_operations_timeout/change-streams.yml +358 -0
  165. data/spec/spec_tests/data/client_side_operations_timeout/close-cursors.yml +129 -0
  166. data/spec/spec_tests/data/client_side_operations_timeout/command-execution.yml +250 -0
  167. data/spec/spec_tests/data/client_side_operations_timeout/convenient-transactions.yml +113 -0
  168. data/spec/spec_tests/data/client_side_operations_timeout/cursors.yml +70 -0
  169. data/spec/spec_tests/data/client_side_operations_timeout/deprecated-options.yml +3982 -0
  170. data/spec/spec_tests/data/client_side_operations_timeout/error-transformations.yml +96 -0
  171. data/spec/spec_tests/data/client_side_operations_timeout/global-timeoutMS.yml +3236 -0
  172. data/spec/spec_tests/data/client_side_operations_timeout/gridfs-advanced.yml +207 -0
  173. data/spec/spec_tests/data/client_side_operations_timeout/gridfs-delete.yml +152 -0
  174. data/spec/spec_tests/data/client_side_operations_timeout/gridfs-download.yml +182 -0
  175. data/spec/spec_tests/data/client_side_operations_timeout/gridfs-find.yml +100 -0
  176. data/spec/spec_tests/data/client_side_operations_timeout/gridfs-upload.yml +249 -0
  177. data/spec/spec_tests/data/client_side_operations_timeout/legacy-timeouts.yml +204 -0
  178. data/spec/spec_tests/data/client_side_operations_timeout/non-tailable-cursors.yml +307 -0
  179. data/spec/spec_tests/data/client_side_operations_timeout/override-collection-timeoutMS.yml +1877 -0
  180. data/spec/spec_tests/data/client_side_operations_timeout/override-operation-timeoutMS.yml +1918 -0
  181. data/spec/spec_tests/data/client_side_operations_timeout/retryability-legacy-timeouts.yml +1676 -0
  182. data/spec/spec_tests/data/client_side_operations_timeout/retryability-timeoutMS.yml +2824 -0
  183. data/spec/spec_tests/data/client_side_operations_timeout/sessions-inherit-timeoutMS.yml +168 -0
  184. data/spec/spec_tests/data/client_side_operations_timeout/sessions-override-operation-timeoutMS.yml +171 -0
  185. data/spec/spec_tests/data/client_side_operations_timeout/sessions-override-timeoutMS.yml +168 -0
  186. data/spec/spec_tests/data/client_side_operations_timeout/tailable-awaitData.yml +247 -0
  187. data/spec/spec_tests/data/client_side_operations_timeout/tailable-non-awaitData.yml +181 -0
  188. data/spec/spec_tests/data/crud_unified/aggregate-write-readPreference.yml +4 -0
  189. data/spec/spec_tests/data/crud_unified/db-aggregate-write-readPreference.yml +4 -0
  190. data/spec/spec_tests/data/crud_unified/find-test-all-options.yml +29 -0
  191. data/spec/spec_tests/server_selection_rtt_spec.rb +6 -6
  192. data/spec/support/certificates/atlas-ocsp-ca.crt +81 -83
  193. data/spec/support/certificates/atlas-ocsp.crt +107 -107
  194. data/spec/support/cluster_tools.rb +3 -3
  195. data/spec/support/common_shortcuts.rb +39 -21
  196. data/spec/support/constraints.rb +0 -10
  197. data/spec/support/crypt/encrypted_fields/range-encryptedFields-Date.json +1 -1
  198. data/spec/support/crypt/encrypted_fields/range-encryptedFields-DecimalNoPrecision.json +1 -1
  199. data/spec/support/crypt/encrypted_fields/range-encryptedFields-DecimalPrecision.json +1 -1
  200. data/spec/support/crypt/encrypted_fields/range-encryptedFields-DoubleNoPrecision.json +1 -1
  201. data/spec/support/crypt/encrypted_fields/range-encryptedFields-DoublePrecision.json +1 -1
  202. data/spec/support/crypt/encrypted_fields/range-encryptedFields-Int.json +1 -1
  203. data/spec/support/crypt/encrypted_fields/range-encryptedFields-Long.json +1 -1
  204. data/spec/support/dns.rb +16 -0
  205. data/spec/support/shared/session.rb +2 -2
  206. data/spec/support/spec_setup.rb +2 -2
  207. data/spec/support/utils.rb +3 -1
  208. metadata +91 -153
  209. data/spec/mongo/server/round_trip_time_averager_spec.rb +0 -48
  210. data/spec/shared/CANDIDATE.md +0 -28
  211. data/spec/shared/LICENSE +0 -20
  212. data/spec/shared/bin/get-mongodb-download-url +0 -17
  213. data/spec/shared/bin/s3-copy +0 -45
  214. data/spec/shared/bin/s3-upload +0 -69
  215. data/spec/shared/lib/mrss/child_process_helper.rb +0 -80
  216. data/spec/shared/lib/mrss/cluster_config.rb +0 -231
  217. data/spec/shared/lib/mrss/constraints.rb +0 -378
  218. data/spec/shared/lib/mrss/docker_runner.rb +0 -298
  219. data/spec/shared/lib/mrss/eg_config_utils.rb +0 -51
  220. data/spec/shared/lib/mrss/event_subscriber.rb +0 -210
  221. data/spec/shared/lib/mrss/lite_constraints.rb +0 -238
  222. data/spec/shared/lib/mrss/release/candidate.rb +0 -281
  223. data/spec/shared/lib/mrss/release/product_data.rb +0 -144
  224. data/spec/shared/lib/mrss/server_version_registry.rb +0 -113
  225. data/spec/shared/lib/mrss/session_registry.rb +0 -69
  226. data/spec/shared/lib/mrss/session_registry_legacy.rb +0 -60
  227. data/spec/shared/lib/mrss/spec_organizer.rb +0 -179
  228. data/spec/shared/lib/mrss/utils.rb +0 -37
  229. data/spec/shared/lib/tasks/candidate.rake +0 -64
  230. data/spec/shared/share/Dockerfile.erb +0 -251
  231. data/spec/shared/share/haproxy-1.conf +0 -16
  232. data/spec/shared/share/haproxy-2.conf +0 -17
  233. data/spec/shared/shlib/config.sh +0 -27
  234. data/spec/shared/shlib/distro.sh +0 -84
  235. data/spec/shared/shlib/server.sh +0 -423
  236. data/spec/shared/shlib/set_env.sh +0 -110
  237. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Aggregate.yml +0 -242
  238. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Correctness.yml +0 -423
  239. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Delete.yml +0 -183
  240. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-FindOneAndUpdate.yml +0 -240
  241. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-InsertFind.yml +0 -236
  242. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Update.yml +0 -253
  243. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Aggregate.yml +0 -1688
  244. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Correctness.yml +0 -294
  245. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Delete.yml +0 -906
  246. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-FindOneAndUpdate.yml +0 -1685
  247. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-InsertFind.yml +0 -1681
  248. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Update.yml +0 -1698
  249. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Aggregate.yml +0 -330
  250. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Correctness.yml +0 -425
  251. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Delete.yml +0 -227
  252. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-FindOneAndUpdate.yml +0 -328
  253. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-InsertFind.yml +0 -320
  254. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Update.yml +0 -337
  255. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Aggregate.yml +0 -914
  256. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Correctness.yml +0 -293
  257. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Delete.yml +0 -519
  258. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-FindOneAndUpdate.yml +0 -912
  259. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-InsertFind.yml +0 -908
  260. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Update.yml +0 -925
  261. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Aggregate.yml +0 -326
  262. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Correctness.yml +0 -425
  263. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Delete.yml +0 -225
  264. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-FindOneAndUpdate.yml +0 -324
  265. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-InsertFind.yml +0 -320
  266. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Update.yml +0 -339
  267. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Aggregate.yml +0 -242
  268. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Correctness.yml +0 -424
  269. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Delete.yml +0 -183
  270. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-FindOneAndUpdate.yml +0 -240
  271. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-InsertFind.yml +0 -236
  272. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Update.yml +0 -255
  273. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Aggregate.yml +0 -242
  274. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Correctness.yml +0 -423
  275. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Delete.yml +0 -183
  276. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-FindOneAndUpdate.yml +0 -240
  277. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-InsertFind.yml +0 -236
  278. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Update.yml +0 -255
  279. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-WrongType.yml +0 -44
@@ -37,7 +37,7 @@ describe 'On-demand AWS Credentials' do
37
37
  it 'raises an error' do
38
38
  expect_any_instance_of(
39
39
  Mongo::Auth::Aws::CredentialsRetriever
40
- ).to receive(:credentials).with(no_args).once.and_raise(
40
+ ).to receive(:credentials).with(kind_of(Mongo::CsotTimeoutHolder)).once.and_raise(
41
41
  Mongo::Auth::Aws::CredentialsNotFound
42
42
  )
43
43
 
@@ -6,9 +6,7 @@ require 'spec_helper'
6
6
  # be revisited if these tests ever need to be significantly modified.
7
7
  # rubocop:disable RSpec/ExampleLength
8
8
  describe 'Range Explicit Encryption' do
9
- min_server_version '7.0.0-rc0'
10
- # https://jira.mongodb.org/browse/RUBY-3457
11
- max_server_version '7.99.99'
9
+ min_server_version '8.0.0-rc18'
12
10
 
13
11
  require_libmongocrypt
14
12
  include_context 'define shared FLE helpers'
@@ -56,7 +54,7 @@ describe 'Range Explicit Encryption' do
56
54
  value,
57
55
  {
58
56
  key_id: key1_id,
59
- algorithm: 'RangePreview',
57
+ algorithm: 'Range',
60
58
  contention_factor: 0,
61
59
  range_opts: range_opts
62
60
  }
@@ -76,8 +74,8 @@ describe 'Range Explicit Encryption' do
76
74
  expr,
77
75
  {
78
76
  key_id: key1_id,
79
- algorithm: 'RangePreview',
80
- query_type: 'rangePreview',
77
+ algorithm: 'Range',
78
+ query_type: 'range',
81
79
  contention_factor: 0,
82
80
  range_opts: range_opts
83
81
  }
@@ -100,8 +98,8 @@ describe 'Range Explicit Encryption' do
100
98
  expr,
101
99
  {
102
100
  key_id: key1_id,
103
- algorithm: 'RangePreview',
104
- query_type: 'rangePreview',
101
+ algorithm: 'Range',
102
+ query_type: 'range',
105
103
  contention_factor: 0,
106
104
  range_opts: range_opts
107
105
  }
@@ -123,8 +121,8 @@ describe 'Range Explicit Encryption' do
123
121
  expr,
124
122
  {
125
123
  key_id: key1_id,
126
- algorithm: 'RangePreview',
127
- query_type: 'rangePreview',
124
+ algorithm: 'Range',
125
+ query_type: 'range',
128
126
  contention_factor: 0,
129
127
  range_opts: range_opts
130
128
  }
@@ -140,8 +138,8 @@ describe 'Range Explicit Encryption' do
140
138
  expr,
141
139
  {
142
140
  key_id: key1_id,
143
- algorithm: 'RangePreview',
144
- query_type: 'rangePreview',
141
+ algorithm: 'Range',
142
+ query_type: 'range',
145
143
  contention_factor: 0,
146
144
  range_opts: range_opts
147
145
  }
@@ -163,7 +161,7 @@ describe 'Range Explicit Encryption' do
163
161
  value_converter.call(201),
164
162
  {
165
163
  key_id: key1_id,
166
- algorithm: 'RangePreview',
164
+ algorithm: 'Range',
167
165
  contention_factor: 0,
168
166
  range_opts: range_opts
169
167
  }
@@ -183,7 +181,7 @@ describe 'Range Explicit Encryption' do
183
181
  value,
184
182
  {
185
183
  key_id: key1_id,
186
- algorithm: 'RangePreview',
184
+ algorithm: 'Range',
187
185
  contention_factor: 0,
188
186
  range_opts: range_opts
189
187
  }
@@ -198,7 +196,7 @@ describe 'Range Explicit Encryption' do
198
196
  value_converter.call(6),
199
197
  {
200
198
  key_id: key1_id,
201
- algorithm: 'RangePreview',
199
+ algorithm: 'Range',
202
200
  contention_factor: 0,
203
201
  range_opts: {
204
202
  min: value_converter.call(0),
@@ -244,7 +242,7 @@ describe 'Range Explicit Encryption' do
244
242
  insert_payload = client_encryption.encrypt(
245
243
  num,
246
244
  key_id: key1_id,
247
- algorithm: 'RangePreview',
245
+ algorithm: 'Range',
248
246
  contention_factor: 0,
249
247
  range_opts: range_opts
250
248
  )
@@ -290,7 +288,7 @@ describe 'Range Explicit Encryption' do
290
288
  insert_payload = client_encryption.encrypt(
291
289
  BSON::Int64.new(num),
292
290
  key_id: key1_id,
293
- algorithm: 'RangePreview',
291
+ algorithm: 'Range',
294
292
  contention_factor: 0,
295
293
  range_opts: range_opts
296
294
  )
@@ -337,7 +335,7 @@ describe 'Range Explicit Encryption' do
337
335
  insert_payload = client_encryption.encrypt(
338
336
  num,
339
337
  key_id: key1_id,
340
- algorithm: 'RangePreview',
338
+ algorithm: 'Range',
341
339
  contention_factor: 0,
342
340
  range_opts: range_opts
343
341
  )
@@ -381,7 +379,7 @@ describe 'Range Explicit Encryption' do
381
379
  insert_payload = client_encryption.encrypt(
382
380
  num,
383
381
  key_id: key1_id,
384
- algorithm: 'RangePreview',
382
+ algorithm: 'Range',
385
383
  contention_factor: 0,
386
384
  range_opts: range_opts
387
385
  )
@@ -427,7 +425,7 @@ describe 'Range Explicit Encryption' do
427
425
  insert_payload = client_encryption.encrypt(
428
426
  Time.new(num),
429
427
  key_id: key1_id,
430
- algorithm: 'RangePreview',
428
+ algorithm: 'Range',
431
429
  contention_factor: 0,
432
430
  range_opts: range_opts
433
431
  )
@@ -476,7 +474,7 @@ describe 'Range Explicit Encryption' do
476
474
  insert_payload = client_encryption.encrypt(
477
475
  BSON::Decimal128.new(num),
478
476
  key_id: key1_id,
479
- algorithm: 'RangePreview',
477
+ algorithm: 'Range',
480
478
  contention_factor: 0,
481
479
  range_opts: range_opts
482
480
  )
@@ -522,7 +520,7 @@ describe 'Range Explicit Encryption' do
522
520
  insert_payload = client_encryption.encrypt(
523
521
  BSON::Decimal128.new(num),
524
522
  key_id: key1_id,
525
- algorithm: 'RangePreview',
523
+ algorithm: 'Range',
526
524
  contention_factor: 0,
527
525
  range_opts: range_opts
528
526
  )
@@ -535,5 +533,51 @@ describe 'Range Explicit Encryption' do
535
533
 
536
534
  include_examples 'common cases'
537
535
  end
536
+
537
+ describe 'Range Explicit Encryption applies defaults' do
538
+ let(:payload_defaults) do
539
+ client_encryption.encrypt(
540
+ 123,
541
+ key_id: key1_id,
542
+ algorithm: 'Range',
543
+ contention_factor: 0,
544
+ range_opts: {
545
+ min: 0,
546
+ max: 1000
547
+ }
548
+ )
549
+ end
550
+
551
+ it 'uses libmongocrypt default' do
552
+ payload = client_encryption.encrypt(
553
+ 123,
554
+ key_id: key1_id,
555
+ algorithm: 'Range',
556
+ contention_factor: 0,
557
+ range_opts: {
558
+ min: 0,
559
+ max: 1000,
560
+ sparsity: 2,
561
+ trim_factor: 6
562
+ }
563
+ )
564
+ expect(payload.to_s.size).to eq(payload_defaults.to_s.size)
565
+ end
566
+
567
+ it 'accepts trim_factor 0' do
568
+ payload = client_encryption.encrypt(
569
+ 123,
570
+ key_id: key1_id,
571
+ algorithm: 'Range',
572
+ contention_factor: 0,
573
+ range_opts: {
574
+ min: 0,
575
+ max: 1000,
576
+ trim_factor: 0
577
+ }
578
+ )
579
+ expect(payload.to_s.size).to eq(payload_defaults.to_s.size)
580
+ end
581
+ end
538
582
  end
539
583
  # rubocop:enable RSpec/ExampleLength
@@ -0,0 +1,131 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'CSOT for encryption' do
6
+ require_libmongocrypt
7
+ require_no_multi_mongos
8
+ min_server_fcv '4.2'
9
+
10
+ include_context 'define shared FLE helpers'
11
+ include_context 'with local kms_providers'
12
+
13
+ let(:subscriber) { Mrss::EventSubscriber.new }
14
+
15
+ describe 'mongocryptd' do
16
+ before do
17
+ Process.spawn(
18
+ 'mongocryptd',
19
+ '--pidfilepath=bypass-spawning-mongocryptd.pid', '--port=23000', '--idleShutdownTimeoutSecs=60',
20
+ %i[ out err ] => '/dev/null'
21
+ )
22
+ end
23
+
24
+ let(:client) do
25
+ Mongo::Client.new('mongodb://localhost:23000/?timeoutMS=1000').tap do |client|
26
+ client.subscribe(Mongo::Monitoring::COMMAND, subscriber)
27
+ end
28
+ end
29
+
30
+ let(:ping_command) do
31
+ subscriber.started_events.find do |event|
32
+ event.command_name == 'ping'
33
+ end&.command
34
+ end
35
+
36
+ after do
37
+ client.close
38
+ end
39
+
40
+ it 'does not set maxTimeMS for commands sent to mongocryptd' do
41
+ expect do
42
+ client.use('admin').command(ping: 1)
43
+ end.to raise_error(Mongo::Error::OperationFailure)
44
+
45
+ expect(ping_command).not_to have_key('maxTimeMS')
46
+ end
47
+ end
48
+
49
+ describe 'ClientEncryption' do
50
+ let(:key_vault_client) do
51
+ ClientRegistry.instance.new_local_client(
52
+ SpecConfig.instance.addresses,
53
+ SpecConfig.instance.test_options.merge(timeout_ms: 20)
54
+ )
55
+ end
56
+
57
+ let(:client_encryption) do
58
+ Mongo::ClientEncryption.new(
59
+ key_vault_client,
60
+ key_vault_namespace: key_vault_namespace,
61
+ kms_providers: local_kms_providers
62
+ )
63
+ end
64
+
65
+ describe '#createDataKey' do
66
+ before do
67
+ authorized_client.use(key_vault_db)[key_vault_coll].drop
68
+ authorized_client.use(key_vault_db)[key_vault_coll].create
69
+ authorized_client.use(:admin).command({
70
+ configureFailPoint: 'failCommand',
71
+ mode: {
72
+ times: 1
73
+ },
74
+ data: {
75
+ failCommands: [ 'insert' ],
76
+ blockConnection: true,
77
+ blockTimeMS: 30
78
+ }
79
+ })
80
+ end
81
+
82
+ after do
83
+ authorized_client.use(:admin).command({
84
+ configureFailPoint: 'failCommand',
85
+ mode: 'off',
86
+ })
87
+ key_vault_client.close
88
+ end
89
+
90
+ it 'fails with timeout error' do
91
+ expect do
92
+ client_encryption.create_data_key('local')
93
+ end.to raise_error(Mongo::Error::TimeoutError)
94
+ end
95
+ end
96
+
97
+ describe '#encrypt' do
98
+ let!(:data_key_id) do
99
+ client_encryption.create_data_key('local')
100
+ end
101
+
102
+ before do
103
+ authorized_client.use(:admin).command({
104
+ configureFailPoint: 'failCommand',
105
+ mode: {
106
+ times: 1
107
+ },
108
+ data: {
109
+ failCommands: [ 'find' ],
110
+ blockConnection: true,
111
+ blockTimeMS: 30
112
+ }
113
+ })
114
+ end
115
+
116
+ after do
117
+ authorized_client.use(:admin).command({
118
+ configureFailPoint: 'failCommand',
119
+ mode: 'off',
120
+ })
121
+ end
122
+
123
+ it 'fails with timeout error' do
124
+ expect do
125
+ client_encryption.encrypt('hello', key_id: data_key_id,
126
+ algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic')
127
+ end.to raise_error(Mongo::Error::TimeoutError)
128
+ end
129
+ end
130
+ end
131
+ end
@@ -26,6 +26,8 @@ describe 'Connection pool populator integration' do
26
26
 
27
27
  declare_topology_double
28
28
 
29
+ retry_test
30
+
29
31
  let(:app_metadata) do
30
32
  Mongo::Server::AppMetadata.new(options)
31
33
  end
@@ -52,73 +52,28 @@ describe 'Cursor pinning' do
52
52
  context 'lb' do
53
53
  require_topology :load_balanced
54
54
 
55
- # In load-balanced topology, we cannot create new connections to a
56
- # particular service.
55
+ # In load-balanced topology, a cursor retains the connection used to create
56
+ # it until the cursor is closed.
57
57
 
58
- context 'when no connection is available' do
58
+ context 'when connection is available' do
59
+ require_multi_mongos
59
60
 
60
- it 'raises ConnectionCheckOutTimeout' do
61
- server.pool.size.should == 0
61
+ let(:client) { authorized_client.with(max_pool_size: 2) }
62
62
 
63
+ it 'does not return connection to the pool if cursor not drained' do
64
+ expect(server.pool).not_to receive(:check_in)
63
65
  enum = collection.find({}, batch_size: 1).to_enum
64
- # Still zero because we haven't iterated
65
- server.pool.size.should == 0
66
-
66
+ # Get the first element only; cursor is not drained, so there should
67
+ # be no check_in of the connection.
67
68
  enum.next
68
- server.pool.size.should == 1
69
-
70
- # Grab the connection that was used
71
- server.with_connection do
72
- # This requires a new connection, but we cannot make one.
73
- lambda do
74
- enum.next
75
- end.should raise_error(Mongo::Error::ConnectionCheckOutTimeout)
76
-
77
- server.pool.size.should == 1
78
- end
79
69
  end
80
- end
81
-
82
- context 'when connection is available' do
83
- require_multi_mongos
84
-
85
- let(:client) { authorized_client.with(max_pool_size: 4) }
86
-
87
- it 'uses the available connection' do
88
- server.pool.size.should == 0
89
-
90
- # Create 4 connections.
91
-
92
- enums = []
93
- connections = []
94
- connection_ids = []
95
-
96
- 4.times do
97
- view = collection.find({}, batch_size: 1)
98
- enum = view.to_enum
99
-
100
- enum.next
101
-
102
- enums << enum
103
- connection_ids << view.cursor.initial_result.connection_global_id
104
- connections << server.pool.check_out
105
- end
106
-
107
- connection_ids.uniq.length.should be > 1
108
-
109
- server.pool.size.should == 4
110
-
111
- connections.each do |c|
112
- server.pool.check_in(c)
113
- end
114
70
 
115
- # At this point, in theory, all connections are equally likely to
116
- # be chosen, but we have cursors referencing more than one
117
- # distinct service.
118
- # Iterate each cursor to ensure they all continue to work.
119
- enums.each do |enum|
120
- enum.next
121
- end
71
+ it 'returns connection to the pool when cursor is drained' do
72
+ view = collection.find({}, batch_size: 1)
73
+ enum = view.to_enum
74
+ expect_any_instance_of(Mongo::Cursor).to receive(:check_in_connection)
75
+ # Drain the cursor
76
+ enum.each { |it| it.nil? }
122
77
  end
123
78
  end
124
79
  end
@@ -24,7 +24,7 @@ describe 'Cursor reaping' do
24
24
  let(:subscriber) { Mrss::EventSubscriber.new }
25
25
 
26
26
  let(:client) do
27
- authorized_client.tap do |client|
27
+ authorized_client.with(max_pool_size: 10).tap do |client|
28
28
  client.subscribe(Mongo::Monitoring::COMMAND, subscriber)
29
29
  end
30
30
  end
@@ -9,7 +9,7 @@ describe 'aggregation examples in Ruby' do
9
9
  # the tests in this file.
10
10
  begin
11
11
  ClientRegistry.instance.global_client('authorized')['_placeholder'].create
12
- rescue Mongo::Error::OperationFailure => e
12
+ rescue Mongo::Error::OperationFailure::Family => e
13
13
  # Collection already exists
14
14
  if e.code != 48
15
15
  raise
@@ -9,21 +9,6 @@ describe Mongo::Socket::OcspVerifier do
9
9
  with_openssl_debug
10
10
  retry_test sleep: 5
11
11
 
12
- def self.with_ocsp_responder(port = 8100, path = '/', &setup)
13
- around do |example|
14
- server = WEBrick::HTTPServer.new(Port: port)
15
- server.mount_proc path, &setup
16
- Thread.new { server.start }
17
- begin
18
- example.run
19
- ensure
20
- server.shutdown
21
- end
22
-
23
- ::Utils.wait_for_port_free(port, 5)
24
- end
25
- end
26
-
27
12
  shared_examples 'verifies' do
28
13
  context 'mri' do
29
14
  fails_on_jruby
@@ -188,10 +173,21 @@ describe Mongo::Socket::OcspVerifier do
188
173
 
189
174
  context 'one time' do
190
175
 
191
- with_ocsp_responder do |req, res|
192
- res.status = 303
193
- res['locAtion'] = "http://localhost:8101#{req.path}"
194
- res.body = "See http://localhost:8101#{req.path}"
176
+ around do |example|
177
+ server = WEBrick::HTTPServer.new(Port: 8100)
178
+ server.mount_proc '/' do |req, res|
179
+ res.status = 303
180
+ res['locAtion'] = "http://localhost:8101#{req.path}"
181
+ res.body = "See http://localhost:8101#{req.path}"
182
+ end
183
+ Thread.new { server.start }
184
+ begin
185
+ example.run
186
+ ensure
187
+ server.shutdown
188
+ end
189
+
190
+ ::Utils.wait_for_port_free(8100, 5)
195
191
  end
196
192
 
197
193
  include_context 'verifier', algorithm: algorithm
@@ -252,10 +248,21 @@ describe Mongo::Socket::OcspVerifier do
252
248
  port: 8101,
253
249
  )
254
250
 
255
- with_ocsp_responder do |req, res|
256
- res.status = 303
257
- res['locAtion'] = req.path
258
- res.body = "See #{req.path} indefinitely"
251
+ around do |example|
252
+ server = WEBrick::HTTPServer.new(Port: 8100)
253
+ server.mount_proc '/' do |req, res|
254
+ res.status = 303
255
+ res['locAtion'] = req.path
256
+ res.body = "See #{req.path} indefinitely"
257
+ end
258
+ Thread.new { server.start }
259
+ begin
260
+ example.run
261
+ ensure
262
+ server.shutdown
263
+ end
264
+
265
+ ::Utils.wait_for_port_free(8100, 5)
259
266
  end
260
267
 
261
268
  include_context 'verifier', algorithm: algorithm
@@ -267,23 +274,85 @@ describe Mongo::Socket::OcspVerifier do
267
274
 
268
275
  include_context 'verifier', algorithm: 'rsa'
269
276
 
270
- [400, 404, 500, 503].each do |code|
271
- context "code #{code}" do
272
- with_ocsp_responder do |req, res|
277
+ context '40x / 50x' do
278
+ around do |example|
279
+ server = WEBrick::HTTPServer.new(Port: 8100)
280
+ server.mount_proc '/' do |req, res|
273
281
  res.status = code
274
282
  res.body = "HTTP #{code}"
275
283
  end
284
+ Thread.new { server.start }
285
+ begin
286
+ example.run
287
+ ensure
288
+ server.shutdown
289
+ end
290
+
291
+ ::Utils.wait_for_port_free(8100, 5)
292
+ end
293
+
294
+ [400, 404, 500, 503].each do |_code|
295
+ context "code #{_code}" do
296
+ let(:code) { _code }
297
+ include_examples 'does not verify'
298
+ end
299
+ end
300
+ end
301
+
302
+ context '204' do
303
+ around do |example|
304
+ server = WEBrick::HTTPServer.new(Port: 8100)
305
+ server.mount_proc '/' do |req, res|
306
+ res.status = 204
307
+ end
308
+ Thread.new { server.start }
309
+ begin
310
+ example.run
311
+ ensure
312
+ server.shutdown
313
+ end
276
314
 
315
+ ::Utils.wait_for_port_free(8100, 5)
316
+ end
317
+
318
+ context "code 204" do
319
+ let(:code) { 204 }
277
320
  include_examples 'does not verify'
278
321
  end
279
322
  end
323
+ end
324
+
325
+ context 'responder URI has no path' do
326
+ require_external_connectivity
327
+
328
+ # https://github.com/jruby/jruby-openssl/issues/210
329
+ fails_on_jruby
280
330
 
281
- context 'code 204' do
282
- with_ocsp_responder do |req, res|
283
- res.status = 204
331
+ include_context 'basic verifier'
332
+
333
+ # The fake certificates all have paths in them for use with the ocsp mock.
334
+ # Use real certificates retrieved from Atlas for this test as they don't
335
+ # have a path in the OCSP URI (which the test also asserts).
336
+ # Note that these certificates expire in 3 months and need to be replaced
337
+ # with a more permanent solution.
338
+ # Use the spec/support/certificates/retrieve-atlas-cert script to retrieve
339
+ # current certificates from Atlas.
340
+ let(:cert_path) { File.join(File.dirname(__FILE__), '../support/certificates/atlas-ocsp.crt') }
341
+ let(:ca_cert_path) { File.join(File.dirname(__FILE__), '../support/certificates/atlas-ocsp-ca.crt') }
342
+ let(:cert_store) do
343
+ OpenSSL::X509::Store.new.tap do |store|
344
+ store.set_default_paths
284
345
  end
346
+ end
285
347
 
286
- include_examples 'does not verify'
348
+ before do
349
+ verifier.ocsp_uris.length.should > 0
350
+ URI.parse(verifier.ocsp_uris.first).path.should == ''
351
+ end
352
+
353
+ it 'verifies' do
354
+ # TODO This test will fail if the certificate expires
355
+ expect(verifier.verify).to be(true), "If atlas-ocsp certificates have expired, run spec/support/certificates/retrieve-atlas-cert to get a new ones"
287
356
  end
288
357
  end
289
358
  end
@@ -17,7 +17,7 @@ describe 'OperationFailure code' do
17
17
  collection.insert_one(_id: 1)
18
18
  collection.insert_one(_id: 1)
19
19
  fail('Should have raised')
20
- rescue Mongo::Error::OperationFailure => e
20
+ rescue Mongo::Error::OperationFailure::Family => e
21
21
  expect(e.code).to eq(11000)
22
22
  # 4.0 and 4.2 sharded clusters set code name.
23
23
  # 4.0 and 4.2 replica sets and standalones do not,
@@ -22,7 +22,7 @@ describe 'OperationFailure message' do
22
22
  begin
23
23
  client.command(bogus_command: nil)
24
24
  fail('Should have raised')
25
- rescue Mongo::Error::OperationFailure => e
25
+ rescue Mongo::Error::OperationFailure::Family => e
26
26
  e.code_name.should == 'CommandNotFound'
27
27
  e.message.should =~ %r,\A\[59:CommandNotFound\]: no such (?:command|cmd): '?bogus_command'?,
28
28
  end
@@ -36,7 +36,7 @@ describe 'OperationFailure message' do
36
36
  begin
37
37
  client.command(bogus_command: nil)
38
38
  fail('Should have raised')
39
- rescue Mongo::Error::OperationFailure => e
39
+ rescue Mongo::Error::OperationFailure::Family => e
40
40
  e.code_name.should be nil
41
41
  e.message.should =~ %r,\A\[59\]: no such (?:command|cmd): '?bogus_command'?,
42
42
  end
@@ -53,7 +53,7 @@ describe 'OperationFailure message' do
53
53
  collection.insert_one(_id: 1)
54
54
  collection.insert_one(_id: 1)
55
55
  fail('Should have raised')
56
- rescue Mongo::Error::OperationFailure => e
56
+ rescue Mongo::Error::OperationFailure::Family => e
57
57
  e.code_name.should be nil
58
58
  e.message.should =~ %r,\A\[11000\]: (?:insertDocument :: caused by :: 11000 )?E11000 duplicate key error (?:collection|index):,
59
59
  end