mongo 2.18.0 → 2.18.2

Sign up to get free protection for your applications and to get access to all the features.
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.