mongo 2.18.0 → 2.18.2

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 (118) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/lib/mongo/bulk_write.rb +7 -5
  4. data/lib/mongo/client.rb +1 -1
  5. data/lib/mongo/collection/view/writable.rb +0 -2
  6. data/lib/mongo/collection.rb +150 -45
  7. data/lib/mongo/crypt/auto_encrypter.rb +30 -9
  8. data/lib/mongo/crypt/binding.rb +93 -1
  9. data/lib/mongo/crypt/explicit_encrypter.rb +5 -1
  10. data/lib/mongo/crypt/handle.rb +33 -0
  11. data/lib/mongo/crypt/kms.rb +0 -1
  12. data/lib/mongo/cursor.rb +6 -1
  13. data/lib/mongo/error/invalid_read_option.rb +1 -1
  14. data/lib/mongo/operation/aggregate.rb +1 -2
  15. data/lib/mongo/operation/collections_info.rb +3 -15
  16. data/lib/mongo/operation/command.rb +1 -2
  17. data/lib/mongo/operation/count.rb +1 -2
  18. data/lib/mongo/operation/create.rb +1 -2
  19. data/lib/mongo/operation/create_index.rb +1 -2
  20. data/lib/mongo/operation/create_user.rb +1 -2
  21. data/lib/mongo/operation/delete.rb +0 -1
  22. data/lib/mongo/operation/distinct.rb +1 -2
  23. data/lib/mongo/operation/drop.rb +1 -2
  24. data/lib/mongo/operation/drop_database.rb +1 -2
  25. data/lib/mongo/operation/drop_index.rb +1 -2
  26. data/lib/mongo/operation/explain.rb +1 -3
  27. data/lib/mongo/operation/find/builder.rb +0 -1
  28. data/lib/mongo/operation/find.rb +1 -3
  29. data/lib/mongo/operation/get_more.rb +1 -3
  30. data/lib/mongo/operation/indexes.rb +1 -17
  31. data/lib/mongo/operation/insert.rb +0 -1
  32. data/lib/mongo/operation/kill_cursors.rb +1 -2
  33. data/lib/mongo/operation/list_collections.rb +1 -2
  34. data/lib/mongo/operation/map_reduce.rb +1 -2
  35. data/lib/mongo/operation/parallel_scan.rb +1 -2
  36. data/lib/mongo/operation/remove_user.rb +1 -2
  37. data/lib/mongo/operation/shared/{polymorphic_operation.rb → op_msg_executable.rb} +11 -6
  38. data/lib/mongo/operation/shared/sessions_supported.rb +7 -3
  39. data/lib/mongo/operation/update.rb +0 -1
  40. data/lib/mongo/operation/update_user.rb +1 -2
  41. data/lib/mongo/operation/users_info.rb +1 -2
  42. data/lib/mongo/operation/write_command.rb +1 -2
  43. data/lib/mongo/operation.rb +1 -3
  44. data/lib/mongo/protocol.rb +0 -3
  45. data/lib/mongo/query_cache.rb +20 -20
  46. data/lib/mongo/session.rb +1 -1
  47. data/lib/mongo/version.rb +1 -1
  48. data/spec/README.md +5 -1
  49. data/spec/integration/bulk_write_spec.rb +16 -0
  50. data/spec/integration/command_spec.rb +1 -23
  51. data/spec/integration/ocsp_verifier_spec.rb +2 -0
  52. data/spec/mongo/client_construction_spec.rb +4 -4
  53. data/spec/mongo/collection_crud_spec.rb +56 -0
  54. data/spec/mongo/collection_spec.rb +11 -1
  55. data/spec/mongo/crypt/auto_encrypter_spec.rb +41 -6
  56. data/spec/mongo/crypt/binding/version_spec.rb +8 -0
  57. data/spec/mongo/crypt/handle_spec.rb +102 -0
  58. data/spec/mongo/crypt/kms_spec.rb +12 -9
  59. data/spec/mongo/cursor_spec.rb +50 -0
  60. data/spec/shared/lib/mrss/event_subscriber.rb +15 -5
  61. data/spec/spec_tests/data/change_streams_unified/change-streams-resume-errorLabels.yml +3 -0
  62. data/spec/spec_tests/data/client_side_encryption/unified/rewrapManyDataKey.yml +3 -3
  63. data/spec/spec_tests/data/sdam_integration/hello-command-error.yml +6 -14
  64. data/spec/spec_tests/data/sdam_integration/hello-network-error.yml +4 -14
  65. data/spec/spec_tests/data/sdam_integration/hello-timeout.yml +8 -14
  66. data/spec/spec_tests/data/transactions_unified/do-not-retry-read-in-transaction.yml +64 -0
  67. data/spec/spec_tests/data/transactions_unified/retryable-abort-handshake.yml +118 -0
  68. data/spec/spec_tests/data/transactions_unified/retryable-commit-handshake.yml +118 -0
  69. data/spec/support/certificates/retrieve-atlas-cert +38 -0
  70. data/spec/support/spec_config.rb +4 -0
  71. data.tar.gz.sig +0 -0
  72. metadata +1133 -1178
  73. metadata.gz.sig +0 -0
  74. data/lib/mongo/operation/aggregate/command.rb +0 -55
  75. data/lib/mongo/operation/collections_info/command.rb +0 -48
  76. data/lib/mongo/operation/command/command.rb +0 -41
  77. data/lib/mongo/operation/count/command.rb +0 -47
  78. data/lib/mongo/operation/create/command.rb +0 -47
  79. data/lib/mongo/operation/create_index/command.rb +0 -61
  80. data/lib/mongo/operation/create_user/command.rb +0 -46
  81. data/lib/mongo/operation/delete/command.rb +0 -52
  82. data/lib/mongo/operation/distinct/command.rb +0 -47
  83. data/lib/mongo/operation/drop/command.rb +0 -41
  84. data/lib/mongo/operation/drop_database/command.rb +0 -41
  85. data/lib/mongo/operation/drop_index/command.rb +0 -45
  86. data/lib/mongo/operation/explain/command.rb +0 -58
  87. data/lib/mongo/operation/explain/legacy.rb +0 -52
  88. data/lib/mongo/operation/find/builder/legacy.rb +0 -123
  89. data/lib/mongo/operation/find/command.rb +0 -51
  90. data/lib/mongo/operation/find/legacy/result.rb +0 -46
  91. data/lib/mongo/operation/find/legacy.rb +0 -52
  92. data/lib/mongo/operation/get_more/command.rb +0 -43
  93. data/lib/mongo/operation/get_more/legacy.rb +0 -39
  94. data/lib/mongo/operation/indexes/command.rb +0 -42
  95. data/lib/mongo/operation/indexes/legacy.rb +0 -48
  96. data/lib/mongo/operation/insert/command.rb +0 -55
  97. data/lib/mongo/operation/kill_cursors/command.rb +0 -48
  98. data/lib/mongo/operation/list_collections/command.rb +0 -46
  99. data/lib/mongo/operation/map_reduce/command.rb +0 -51
  100. data/lib/mongo/operation/parallel_scan/command.rb +0 -57
  101. data/lib/mongo/operation/remove_user/command.rb +0 -46
  102. data/lib/mongo/operation/shared/op_msg_or_command.rb +0 -41
  103. data/lib/mongo/operation/shared/op_msg_or_find_command.rb +0 -44
  104. data/lib/mongo/operation/update/command.rb +0 -53
  105. data/lib/mongo/operation/update_user/command.rb +0 -45
  106. data/lib/mongo/operation/users_info/command.rb +0 -46
  107. data/lib/mongo/operation/write_command/command.rb +0 -51
  108. data/lib/mongo/protocol/delete.rb +0 -172
  109. data/lib/mongo/protocol/insert.rb +0 -181
  110. data/lib/mongo/protocol/update.rb +0 -214
  111. data/spec/mongo/operation/delete/command_spec.rb +0 -115
  112. data/spec/mongo/operation/find/legacy_spec.rb +0 -131
  113. data/spec/mongo/operation/get_more_spec.rb +0 -63
  114. data/spec/mongo/operation/insert/command_spec.rb +0 -118
  115. data/spec/mongo/operation/update/command_spec.rb +0 -122
  116. data/spec/mongo/protocol/delete_spec.rb +0 -185
  117. data/spec/mongo/protocol/insert_spec.rb +0 -179
  118. data/spec/mongo/protocol/update_spec.rb +0 -204
@@ -114,24 +114,24 @@ module Mongo
114
114
  #
115
115
  # @param [ Mongo::CachingCursor ] cursor The CachingCursor instance to store.
116
116
  #
117
- # @option opts [ String | nil ] namespace The namespace of the query,
117
+ # @option opts [ String | nil ] :namespace The namespace of the query,
118
118
  # in the format "database_name.collection_name".
119
- # @option opts [ Array, Hash ] selector The selector passed to the query.
119
+ # @option opts [ Array, Hash ] :selector The selector passed to the query.
120
120
  # For most queries, this will be a Hash, but for aggregations, this
121
121
  # will be an Array representing the aggregation pipeline. May not be nil.
122
- # @option opts [ Integer | nil ] skip The skip value of the query.
123
- # @option opts [ Hash | nil ] sort The order of the query results
122
+ # @option opts [ Integer | nil ] :skip The skip value of the query.
123
+ # @option opts [ Hash | nil ] :sort The order of the query results
124
124
  # (e.g. { name: -1 }).
125
- # @option opts [ Integer | nil ] limit The limit value of the query.
126
- # @option opts [ Hash | nil ] projection The projection of the query
125
+ # @option opts [ Integer | nil ] :limit The limit value of the query.
126
+ # @option opts [ Hash | nil ] :projection The projection of the query
127
127
  # results (e.g. { name: 1 }).
128
- # @option opts [ Hash | nil ] collation The collation of the query
128
+ # @option opts [ Hash | nil ] :collation The collation of the query
129
129
  # (e.g. { "locale" => "fr_CA" }).
130
- # @option opts [ Hash | nil ] read_concern The read concern of the query
130
+ # @option opts [ Hash | nil ] :read_concern The read concern of the query
131
131
  # (e.g. { level: :majority }).
132
- # @option opts [ Hash | nil ] read_preference The read preference of
132
+ # @option opts [ Hash | nil ] :read_preference The read preference of
133
133
  # the query (e.g. { mode: :secondary }).
134
- # @option opts [ Boolean | nil ] multi_collection Whether the query
134
+ # @option opts [ Boolean | nil ] :multi_collection Whether the query
135
135
  # results could potentially come from multiple collections. When true,
136
136
  # these results will be stored under the nil namespace key and cleared
137
137
  # on every write command.
@@ -152,24 +152,24 @@ module Mongo
152
152
  # For the given query options, retrieve a cached cursor that can be used
153
153
  # to obtain the correct query results, if one exists in the cache.
154
154
  #
155
- # @option opts [ String | nil ] namespace The namespace of the query,
155
+ # @option opts [ String | nil ] :namespace The namespace of the query,
156
156
  # in the format "database_name.collection_name".
157
- # @option opts [ Array, Hash ] selector The selector passed to the query.
157
+ # @option opts [ Array, Hash ] :selector The selector passed to the query.
158
158
  # For most queries, this will be a Hash, but for aggregations, this
159
159
  # will be an Array representing the aggregation pipeline. May not be nil.
160
- # @option opts [ Integer | nil ] skip The skip value of the query.
161
- # @option opts [ Hash | nil ] sort The order of the query results
160
+ # @option opts [ Integer | nil ] :skip The skip value of the query.
161
+ # @option opts [ Hash | nil ] :sort The order of the query results
162
162
  # (e.g. { name: -1 }).
163
- # @option opts [ Integer | nil ] limit The limit value of the query.
164
- # @option opts [ Hash | nil ] projection The projection of the query
163
+ # @option opts [ Integer | nil ] :limit The limit value of the query.
164
+ # @option opts [ Hash | nil ] :projection The projection of the query
165
165
  # results (e.g. { name: 1 }).
166
- # @option opts [ Hash | nil ] collation The collation of the query
166
+ # @option opts [ Hash | nil ] :collation The collation of the query
167
167
  # (e.g. { "locale" => "fr_CA" }).
168
- # @option opts [ Hash | nil ] read_concern The read concern of the query
168
+ # @option opts [ Hash | nil ] :read_concern The read concern of the query
169
169
  # (e.g. { level: :majority }).
170
- # @option opts [ Hash | nil ] read_preference The read preference of
170
+ # @option opts [ Hash | nil ] :read_preference The read preference of
171
171
  # the query (e.g. { mode: :secondary }).
172
- # @option opts [ Boolean | nil ] multi_collection Whether the query
172
+ # @option opts [ Boolean | nil ] :multi_collection Whether the query
173
173
  # results could potentially come from multiple collections. When true,
174
174
  # these results will be stored under the nil namespace key and cleared
175
175
  # on every write command.
data/lib/mongo/session.rb CHANGED
@@ -522,7 +522,7 @@ module Mongo
522
522
  #
523
523
  # @option options [ Integer ] :max_commit_time_ms The maximum amount of
524
524
  # time to allow a single commitTransaction command to run, in milliseconds.
525
- # @option options [ Hash ] read_concern The read concern options hash,
525
+ # @option options [ Hash ] :read_concern The read concern options hash,
526
526
  # with the following optional keys:
527
527
  # - *:level* -- the read preference level as a symbol; valid values
528
528
  # are *:local*, *:majority*, and *:snapshot*
data/lib/mongo/version.rb CHANGED
@@ -20,5 +20,5 @@ module Mongo
20
20
  # The current version of the driver.
21
21
  #
22
22
  # @since 2.0.0
23
- VERSION = '2.18.0'.freeze
23
+ VERSION = '2.18.2'.freeze
24
24
  end
data/spec/README.md CHANGED
@@ -408,7 +408,8 @@ The client-side encryption tests require the mongocryptd binary to be in the
408
408
  system path.
409
409
 
410
410
  Download enterprise versions of MongoDB here: https://www.mongodb.com/download-center/enterprise
411
- Read more about installing mongocryptd here: https://mongodb.com/docs/manual/reference/security-client-side-encryption-appendix/#mongocryptd
411
+ Download the Automatic Encryption Shared Library https://www.mongodb.com/docs/manual/core/queryable-encryption/reference/shared-library/#std-label-qe-reference-shared-library-download
412
+ Install and Configure mongocryptd: https://www.mongodb.com/docs/manual/core/queryable-encryption/reference/mongocryptd/
412
413
 
413
414
  Install libmongocrypt on your machine:
414
415
 
@@ -426,6 +427,9 @@ Option 1: Download a pre-built binary
426
427
  Option 2: Build from source
427
428
  - To build libmongocrypt from source, follow the instructions in the README on the libmongocrypt GitHub repo: https://github.com/mongodb/libmongocrypt
428
429
 
430
+ Option 3: Use libmongocrypt-helper gem (Linux only)
431
+ - Run command `FLE=helper bundle install`
432
+
429
433
  Create AWS KMS keys
430
434
  Many of the Client-Side Encryption tests require that you have an encryption
431
435
  master key hosted on AWS's Key Management Service. Set up a master key by following
@@ -18,6 +18,22 @@ describe 'Bulk writes' do
18
18
  authorized_collection.bulk_write(operations)
19
19
  end.not_to raise_error
20
20
  end
21
+
22
+ context 'in transaction' do
23
+ require_transaction_support
24
+ min_server_version "4.4"
25
+
26
+ it 'succeeds' do
27
+ authorized_collection.create
28
+ expect do
29
+ authorized_collection.client.start_session do |session|
30
+ session.with_transaction do
31
+ authorized_collection.bulk_write(operations, { session: session })
32
+ end
33
+ end
34
+ end.not_to raise_error
35
+ end
36
+ end
21
37
  end
22
38
 
23
39
  context 'when bulk write needs to be split' do
@@ -12,7 +12,7 @@ describe 'Command' do
12
12
 
13
13
  let(:payload) do
14
14
  server.with_connection do |connection|
15
- command.send(:final_operation, connection).send(:message, connection).payload.dup.tap do |payload|
15
+ command.send(:final_operation).send(:message, connection).payload.dup.tap do |payload|
16
16
  if payload['request_id'].is_a?(Integer)
17
17
  payload['request_id'] = 42
18
18
  end
@@ -150,28 +150,6 @@ describe 'Command' do
150
150
  expect(payload).to eq(expected_payload)
151
151
  end
152
152
  end
153
-
154
- # Servers using legacy wire protocol message do not have $db in payload.
155
- # $db is added to the payload later when the command monitoring event is
156
- # published.
157
- context 'pre-OP_MSG servers' do
158
- max_server_version '3.4'
159
-
160
- let(:expected_payload) do
161
- {
162
- 'command' => {
163
- 'find' => 'collection_name',
164
- },
165
- 'command_name' => 'find',
166
- 'database_name' => 'foo',
167
- 'request_id' => 42,
168
- }
169
- end
170
-
171
- it 'returns expected payload' do
172
- expect(payload).to eq(expected_payload)
173
- end
174
- end
175
153
  end
176
154
 
177
155
  end
@@ -335,6 +335,8 @@ describe Mongo::Socket::OcspVerifier do
335
335
  # have a path in the OCSP URI (which the test also asserts).
336
336
  # Note that these certificates expire in 3 months and need to be replaced
337
337
  # with a more permanent solution.
338
+ # Use the spec/support/certificates/retrieve-atlas-cert script to retrieve
339
+ # current certificates from Atlas.
338
340
  let(:cert_path) { File.join(File.dirname(__FILE__), '../support/certificates/atlas-ocsp.crt') }
339
341
  let(:ca_cert_path) { File.join(File.dirname(__FILE__), '../support/certificates/atlas-ocsp-ca.crt') }
340
342
  let(:cert_store) do
@@ -1773,28 +1773,28 @@ describe Mongo::Client do
1773
1773
  expect do
1774
1774
  client = new_local_client_nmio(['127.0.0.1:27017'],
1775
1775
  :read => {:mode => :bogus})
1776
- end.to raise_error(Mongo::Error::InvalidReadOption, 'Invalid read option: {"mode"=>:bogus}: mode bogus is not one of recognized modes')
1776
+ end.to raise_error(Mongo::Error::InvalidReadOption, 'Invalid read preference value: {"mode"=>:bogus}: mode bogus is not one of recognized modes')
1777
1777
  end
1778
1778
 
1779
1779
  it 'rejects bogus read preference as string' do
1780
1780
  expect do
1781
1781
  client = new_local_client_nmio(['127.0.0.1:27017'],
1782
1782
  :read => {:mode => 'bogus'})
1783
- end.to raise_error(Mongo::Error::InvalidReadOption, 'Invalid read option: {"mode"=>"bogus"}: mode bogus is not one of recognized modes')
1783
+ end.to raise_error(Mongo::Error::InvalidReadOption, 'Invalid read preference value: {"mode"=>"bogus"}: mode bogus is not one of recognized modes')
1784
1784
  end
1785
1785
 
1786
1786
  it 'rejects read option specified as a string' do
1787
1787
  expect do
1788
1788
  client = new_local_client_nmio(['127.0.0.1:27017'],
1789
1789
  :read => 'primary')
1790
- end.to raise_error(Mongo::Error::InvalidReadOption, 'Invalid read option: primary: must be a hash')
1790
+ end.to raise_error(Mongo::Error::InvalidReadOption, 'Invalid read preference value: "primary": the read preference must be specified as a hash: { mode: "primary" }')
1791
1791
  end
1792
1792
 
1793
1793
  it 'rejects read option specified as a symbol' do
1794
1794
  expect do
1795
1795
  client = new_local_client_nmio(['127.0.0.1:27017'],
1796
1796
  :read => :primary)
1797
- end.to raise_error(Mongo::Error::InvalidReadOption, 'Invalid read option: primary: must be a hash')
1797
+ end.to raise_error(Mongo::Error::InvalidReadOption, "Invalid read preference value: :primary: the read preference must be specified as a hash: { mode: :primary }")
1798
1798
  end
1799
1799
  end
1800
1800
  end
@@ -362,6 +362,42 @@ describe Mongo::Collection do
362
362
  expect(result.inserted_ids.size).to eq(2)
363
363
  end
364
364
 
365
+ context 'when an enumerable is used instead of an array' do
366
+
367
+ context 'when the enumerable is not empty' do
368
+
369
+ let(:source_data) do
370
+ [{ name: 'test1' }, { name: 'test2' }]
371
+ end
372
+
373
+ let(:result) do
374
+ authorized_collection.insert_many(source_data.lazy)
375
+ end
376
+
377
+ it 'should accepts them without raising an error' do
378
+ expect { result }.to_not raise_error
379
+ expect(result.inserted_count).to eq(source_data.size)
380
+ end
381
+ end
382
+
383
+ context 'when the enumerable is empty' do
384
+
385
+ let(:source_data) do
386
+ []
387
+ end
388
+
389
+ let(:result) do
390
+ authorized_collection.insert_many(source_data.lazy)
391
+ end
392
+
393
+ it 'should raise ArgumentError' do
394
+ expect do
395
+ result
396
+ end.to raise_error(ArgumentError, /Bulk write requests cannot be empty/)
397
+ end
398
+ end
399
+ end
400
+
365
401
  context 'when a session is provided' do
366
402
 
367
403
  let(:session) do
@@ -4412,4 +4448,24 @@ describe Mongo::Collection do
4412
4448
  expect(result).to be_nil
4413
4449
  end
4414
4450
  end
4451
+
4452
+ context "when creating collection with view_on and pipeline" do
4453
+ before do
4454
+ authorized_client["my_view"].drop
4455
+ authorized_collection.insert_one({ bar: "here!" })
4456
+ authorized_client["my_view",
4457
+ view_on: authorized_collection.name,
4458
+ pipeline: [ { :'$project' => { "baz": "$bar" } } ]
4459
+ ].create
4460
+ end
4461
+
4462
+ it "the view has a document" do
4463
+ expect(authorized_client["my_view"].find.to_a.length).to eq(1)
4464
+ end
4465
+
4466
+ it "applies the pipeline" do
4467
+ expect(authorized_client["my_view"].find.first).to have_key("baz")
4468
+ expect(authorized_client["my_view"].find.first["baz"]).to eq("here!")
4469
+ end
4470
+ end
4415
4471
  end
@@ -647,7 +647,11 @@ describe Mongo::Collection do
647
647
  context 'when the collection is capped' do
648
648
 
649
649
  let(:collection) do
650
- described_class.new(database, :specs, :capped => true, :size => 1024)
650
+ described_class.new(database, :specs, :capped => true, :size => 4096, :max => 512)
651
+ end
652
+
653
+ let(:collstats) do
654
+ database.read_command(:collstats => :specs).documents.first
651
655
  end
652
656
 
653
657
  before do
@@ -658,6 +662,12 @@ describe Mongo::Collection do
658
662
  it 'returns true' do
659
663
  expect(collection).to be_capped
660
664
  end
665
+
666
+ it "applies the options" do
667
+ expect(collstats["capped"]).to be true
668
+ expect(collstats["max"]).to eq(512)
669
+ expect(collstats["maxSize"]).to eq(4096)
670
+ end
661
671
  end
662
672
 
663
673
  context 'when the collection is not capped' do
@@ -16,12 +16,16 @@ describe Mongo::Crypt::AutoEncrypter do
16
16
  described_class.new(
17
17
  auto_encryption_options.merge(
18
18
  client: authorized_client.use(:auto_encryption),
19
- # Spawn mongocryptd on non-default port for sharded cluster tests
20
- extra_options: extra_options
19
+ extra_options: auto_encrypter_extra_options
21
20
  )
22
21
  )
23
22
  end
24
23
 
24
+ let(:auto_encrypter_extra_options) do
25
+ # Spawn mongocryptd on non-default port for sharded cluster tests
26
+ extra_options
27
+ end
28
+
25
29
  let(:client) { authorized_client }
26
30
 
27
31
  let(:db_name) { 'auto_encryption' }
@@ -155,7 +159,7 @@ describe Mongo::Crypt::AutoEncrypter do
155
159
  end
156
160
  end
157
161
 
158
- context 'with schema map in auto encryption commands' do
162
+ shared_examples 'with schema map in auto encryption commands' do
159
163
  include_context 'without jsonSchema validator'
160
164
 
161
165
  let(:auto_encryption_options) do
@@ -193,7 +197,7 @@ describe Mongo::Crypt::AutoEncrypter do
193
197
  end
194
198
  end
195
199
 
196
- context 'with schema map file in auto encryption commands' do
200
+ shared_examples 'with schema map file in auto encryption commands' do
197
201
  include_context 'without jsonSchema validator'
198
202
 
199
203
  let(:schema_map_file) do
@@ -246,7 +250,7 @@ describe Mongo::Crypt::AutoEncrypter do
246
250
  end
247
251
  end
248
252
 
249
- context 'with schema map collection validator' do
253
+ shared_examples 'with schema map collection validator' do
250
254
  include_context 'with jsonSchema validator'
251
255
 
252
256
  let(:auto_encryption_options) do
@@ -302,7 +306,7 @@ describe Mongo::Crypt::AutoEncrypter do
302
306
  end
303
307
  end
304
308
 
305
- context 'with no validator or client option' do
309
+ shared_examples 'with no validator or client option' do
306
310
  include_context 'without jsonSchema validator'
307
311
 
308
312
  let(:auto_encryption_options) do
@@ -403,4 +407,35 @@ describe Mongo::Crypt::AutoEncrypter do
403
407
  end
404
408
  end
405
409
  end
410
+
411
+ context 'when using crypt shared library' do
412
+ min_server_version '6.0.0'
413
+
414
+ let(:auto_encrypter_extra_options) do
415
+ {
416
+ crypt_shared_lib_path: SpecConfig.instance.crypt_shared_lib_path
417
+ }
418
+ end
419
+
420
+ let(:auto_encryption_options) do
421
+ {
422
+ kms_providers: kms_providers,
423
+ kms_tls_options: kms_tls_options,
424
+ key_vault_namespace: key_vault_namespace,
425
+ schema_map: { "#{db_name}.#{collection_name}": schema_map },
426
+ }
427
+ end
428
+
429
+ it_behaves_like 'with schema map in auto encryption commands'
430
+ it_behaves_like 'with schema map file in auto encryption commands'
431
+ it_behaves_like 'with schema map collection validator'
432
+ it_behaves_like 'with no validator or client option'
433
+ end
434
+
435
+ context 'when using mongocryptd' do
436
+ it_behaves_like 'with schema map in auto encryption commands'
437
+ it_behaves_like 'with schema map file in auto encryption commands'
438
+ it_behaves_like 'with schema map collection validator'
439
+ it_behaves_like 'with no validator or client option'
440
+ end
406
441
  end
@@ -41,5 +41,13 @@ describe 'Mongo::Crypt::Binding' do
41
41
  end.not_to raise_error(LoadError, /libmongocrypt version .* or above is required, but version .* was found./)
42
42
  end
43
43
  end
44
+
45
+ context 'when in a non-parsable format' do
46
+ it 'does not raise ArgumentError' do
47
+ expect do
48
+ Mongo::Crypt::Binding.validate_version("1.5.3-dev+20220730git8f8675fa11")
49
+ end.not_to raise_error(ArgumentError, /Malformed version number string/)
50
+ end
51
+ end
44
52
  end
45
53
  end
@@ -18,6 +18,10 @@ describe Mongo::Crypt::Handle do
18
18
  kms_tls_options,
19
19
  schema_map: schema_map,
20
20
  schema_map_path: schema_map_path,
21
+ bypass_query_analysis: bypass_query_analysis,
22
+ crypt_shared_lib_path: crypt_shared_lib_path,
23
+ crypt_shared_lib_required: crypt_shared_lib_required,
24
+ explicit_encryption_only: explicit_encryption_only,
21
25
  )
22
26
  end
23
27
 
@@ -29,6 +33,22 @@ describe Mongo::Crypt::Handle do
29
33
  nil
30
34
  end
31
35
 
36
+ let(:bypass_query_analysis) do
37
+ nil
38
+ end
39
+
40
+ let(:crypt_shared_lib_path) do
41
+ nil
42
+ end
43
+
44
+ let(:crypt_shared_lib_required) do
45
+ nil
46
+ end
47
+
48
+ let(:explicit_encryption_only) do
49
+ nil
50
+ end
51
+
32
52
  shared_examples 'a functioning Mongo::Crypt::Handle' do
33
53
  context 'with valid schema map' do
34
54
  it 'does not raise an exception' do
@@ -73,6 +93,88 @@ describe Mongo::Crypt::Handle do
73
93
  expect { handle }.not_to raise_error
74
94
  end
75
95
  end
96
+
97
+ context 'with crypt_shared_lib_path' do
98
+ min_server_version '6.0.0'
99
+
100
+ context 'with correct path' do
101
+ let(:crypt_shared_lib_path) do
102
+ SpecConfig.instance.crypt_shared_lib_path
103
+ end
104
+
105
+ it 'loads the crypt shared lib' do
106
+ expect(handle.crypt_shared_lib_version).not_to eq(0)
107
+ end
108
+ end
109
+
110
+ context 'with incorrect path' do
111
+ let(:crypt_shared_lib_path) do
112
+ '/some/bad/path/mongo_crypt_v1.so'
113
+ end
114
+
115
+ it 'raises an exception' do
116
+ expect { handle }.to raise_error(Mongo::Error::CryptError)
117
+ end
118
+ end
119
+ end
120
+
121
+ context 'with crypt_shared_lib_required' do
122
+ min_server_version '6.0.0'
123
+
124
+ context 'set to true' do
125
+ let(:crypt_shared_lib_required) do
126
+ true
127
+ end
128
+
129
+ context 'when shared lib is available' do
130
+ let(:crypt_shared_lib_path) do
131
+ SpecConfig.instance.crypt_shared_lib_path
132
+ end
133
+
134
+ it 'does not raise an exception' do
135
+ expect { handle }.not_to raise_error
136
+ end
137
+ end
138
+
139
+ context 'when shared lib is not available' do
140
+ let(:crypt_shared_lib_path) do
141
+ '/some/bad/path/mongo_crypt_v1.so'
142
+ end
143
+
144
+ it 'raises an exception' do
145
+ expect { handle }.to raise_error(Mongo::Error::CryptError)
146
+ end
147
+ end
148
+ end
149
+ end
150
+
151
+ context 'if bypass_query_analysis is true' do
152
+ min_server_version '6.0.0'
153
+
154
+ let(:bypass_query_analysis) do
155
+ true
156
+ end
157
+
158
+ it 'does not load the crypt shared lib' do
159
+ expect_any_instance_of(Binding).not_to receive(:setopt_append_crypt_shared_lib_search_path)
160
+
161
+ expect(handle.crypt_shared_lib_version).to eq(0)
162
+ end
163
+ end
164
+
165
+ context 'if explicit_encryption_only is true' do
166
+ min_server_version '6.0.0'
167
+
168
+ let(:explicit_encryption_only) do
169
+ true
170
+ end
171
+
172
+ it 'does not load the crypt shared lib' do
173
+ expect_any_instance_of(Binding).not_to receive(:setopt_append_crypt_shared_lib_search_path)
174
+
175
+ expect(handle.crypt_shared_lib_version).to eq(0)
176
+ end
177
+ end
76
178
  end
77
179
 
78
180
  context 'local' do
@@ -33,7 +33,6 @@ describe Mongo::Crypt::KMS do
33
33
  %i(
34
34
  ssl_verify_certificate
35
35
  ssl_verify_hostname
36
- ssl_verify_ocsp_endpoint
37
36
  ).each do |insecure_opt|
38
37
  expect {
39
38
  Mongo::Crypt::KMS::Validations.validate_tls_options(
@@ -46,14 +45,18 @@ describe Mongo::Crypt::KMS do
46
45
  end
47
46
 
48
47
  it 'allows valid options' do
49
- options = {
50
- aws: {
51
- ssl: true,
52
- ssl_cert_string: 'Content is not validated',
53
-
54
- }
55
- }
48
+ expect do
49
+ Mongo::Crypt::KMS::Validations.validate_tls_options(
50
+ {
51
+ aws: {
52
+ ssl: true,
53
+ ssl_cert_string: 'Content is not validated',
54
+ ssl_verify_ocsp_endpoint: false
55
+ }
56
+ }
57
+ )
58
+ end.not_to raise_error
56
59
  end
57
60
  end
58
61
  end
59
- end
62
+ end
@@ -734,4 +734,54 @@ describe Mongo::Cursor do
734
734
  end
735
735
  end
736
736
  end
737
+
738
+ describe '#batch_size' do
739
+ let(:subscriber) { Mrss::EventSubscriber.new }
740
+
741
+ let(:subscribed_client) do
742
+ authorized_client.tap do |client|
743
+ client.subscribe(Mongo::Monitoring::COMMAND, subscriber)
744
+ end
745
+ end
746
+
747
+ let(:collection) do
748
+ subscribed_client[TEST_COLL]
749
+ end
750
+
751
+ let(:view) do
752
+ collection.find({}, limit: limit)
753
+ end
754
+
755
+ before do
756
+ collection.drop
757
+ collection.insert_many([].fill({ "bar": "baz" }, 0, 102))
758
+ end
759
+
760
+ context 'when limit is 0 and batch_size is not set' do
761
+ let(:limit) do
762
+ 0
763
+ end
764
+
765
+ it 'does not set batch_size' do
766
+ view.to_a
767
+ get_more_commands = subscriber.started_events.select { |e| e.command_name == 'getMore' }
768
+ expect(get_more_commands.length).to eq(1)
769
+ expect(get_more_commands.first.command.keys).not_to include('batchSize')
770
+ end
771
+ end
772
+
773
+ context 'when limit is not zero and batch_size is not set' do
774
+ let(:limit) do
775
+ 1000
776
+ end
777
+
778
+ it 'sets batch_size' do
779
+ view.to_a
780
+ get_more_commands = subscriber.started_events.select { |e| e.command_name == 'getMore' }
781
+
782
+ expect(get_more_commands.length).to eq(1)
783
+ expect(get_more_commands.first.command.keys).to include('batchSize')
784
+ end
785
+ end
786
+ end
737
787
  end
@@ -84,22 +84,32 @@ module Mrss
84
84
 
85
85
  # Locates command stated events for the specified command name,
86
86
  # asserts that there is exactly one such event, and returns it.
87
- def single_command_started_event(command_name, include_auth: false)
87
+ def single_command_started_event(command_name, include_auth: false, database_name: nil)
88
88
  events = if include_auth
89
89
  started_events
90
90
  else
91
91
  non_auth_command_started_events
92
92
  end
93
- events.select! do |event|
94
- event.command[command_name]
93
+ get_one_event(events, command_name, 'started', database_name: database_name)
94
+ end
95
+
96
+ # Locates command succeeded events for the specified command name,
97
+ # asserts that there is exactly one such event, and returns it.
98
+ def single_command_succeeded_event(command_name, database_name: nil)
99
+ get_one_event(succeeded_events, command_name, 'succeeded', database_name: database_name)
100
+ end
101
+
102
+ def get_one_event(events, command_name, kind, database_name: nil)
103
+ events = events.select do |event|
104
+ event.command_name == command_name and
105
+ database_name.nil? || database_name == event.database_name
95
106
  end
96
107
  if events.length != 1
97
- raise "Expected a single #{command_name} event but we have #{events.length}"
108
+ raise "Expected a single '#{command_name}' #{kind} event#{database_name ? " for '#{database_name}'" : ''} but we have #{events.length}"
98
109
  end
99
110
  events.first
100
111
  end
101
112
 
102
-
103
113
  # Get the first succeeded event published for the name, and then delete it.
104
114
  #
105
115
  # @param [ String ] name The event name.