mongo 2.18.2 → 2.18.3
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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/README.md +1 -1
- data/lib/mongo/collection/view/iterable.rb +15 -0
- data/lib/mongo/collection/view.rb +1 -0
- data/lib/mongo/crypt/auto_encrypter.rb +1 -0
- data/lib/mongo/crypt/explicit_encrypter.rb +1 -0
- data/lib/mongo/crypt.rb +11 -0
- data/lib/mongo/grid/file/chunk.rb +2 -1
- data/lib/mongo/grid/file/info.rb +2 -1
- data/lib/mongo/protocol/bit_vector.rb +3 -1
- data/lib/mongo/protocol/caching_hash.rb +3 -20
- data/lib/mongo/protocol/message.rb +4 -8
- data/lib/mongo/protocol/msg.rb +1 -0
- data/lib/mongo/protocol/serializers.rb +24 -17
- data/lib/mongo/server/app_metadata/environment.rb +255 -0
- data/lib/mongo/server/app_metadata/truncator.rb +142 -0
- data/lib/mongo/server/app_metadata.rb +29 -42
- data/lib/mongo/version.rb +1 -1
- data/spec/integration/connection/faas_env_spec.rb +63 -0
- data/spec/integration/find_options_spec.rb +227 -0
- data/spec/integration/ocsp_verifier_spec.rb +1 -1
- data/spec/lite_spec_helper.rb +9 -0
- data/spec/mongo/address_spec.rb +1 -1
- data/spec/mongo/client_construction_spec.rb +3 -3
- data/spec/mongo/client_spec.rb +1 -9
- data/spec/mongo/cluster_spec.rb +2 -2
- data/spec/mongo/crypt_spec.rb +21 -0
- data/spec/mongo/index/view_spec.rb +1 -0
- data/spec/mongo/protocol/caching_hash_spec.rb +0 -45
- data/spec/mongo/protocol/msg_spec.rb +2 -4
- data/spec/mongo/server/app_metadata/environment_spec.rb +193 -0
- data/spec/mongo/server/app_metadata/truncator_spec.rb +158 -0
- data/spec/mongo/server/app_metadata_spec.rb +33 -47
- data/spec/mongo/socket/ssl_spec.rb +2 -8
- data/spec/runners/crud/requirement.rb +2 -2
- data/spec/shared/lib/mrss/docker_runner.rb +4 -0
- data/spec/shared/lib/mrss/lite_constraints.rb +8 -0
- data/spec/shared/lib/mrss/server_version_registry.rb +16 -23
- data/spec/shared/share/Dockerfile.erb +24 -19
- data/spec/shared/shlib/server.sh +31 -7
- data/spec/shared/shlib/set_env.sh +4 -4
- data/spec/solo/clean_exit_spec.rb +3 -10
- data/spec/spec_tests/data/change_streams_unified/change-streams-showExpandedEvents.yml +15 -6
- data/spec/spec_tests/data/command_monitoring_unified/redacted-commands.yml +8 -0
- data/spec/support/aws_utils.rb +3 -3
- data/spec/support/certificates/atlas-ocsp-ca.crt +67 -67
- data/spec/support/certificates/atlas-ocsp.crt +103 -103
- data/spec/support/shared/app_metadata.rb +14 -2
- data.tar.gz.sig +0 -0
- metadata +1155 -1138
- metadata.gz.sig +0 -0
@@ -0,0 +1,142 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (C) 2016-2023 MongoDB Inc.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
module Mongo
|
18
|
+
class Server
|
19
|
+
class AppMetadata
|
20
|
+
# Implements the metadata truncation logic described in the handshake
|
21
|
+
# spec.
|
22
|
+
#
|
23
|
+
# @api private
|
24
|
+
class Truncator
|
25
|
+
# @return [ BSON::Document ] the document being truncated.
|
26
|
+
attr_reader :document
|
27
|
+
|
28
|
+
# The max application metadata document byte size.
|
29
|
+
MAX_DOCUMENT_SIZE = 512
|
30
|
+
|
31
|
+
# Creates a new Truncator instance and tries enforcing the maximum
|
32
|
+
# document size on the given document.
|
33
|
+
#
|
34
|
+
# @param [ BSON::Document] document The document to (potentially)
|
35
|
+
# truncate.
|
36
|
+
#
|
37
|
+
# @note The document is modified in-place; if you wish to keep the
|
38
|
+
# original unchanged, you must deep-clone it prior to sending it to
|
39
|
+
# a truncator.
|
40
|
+
def initialize(document)
|
41
|
+
@document = document
|
42
|
+
try_truncate!
|
43
|
+
end
|
44
|
+
|
45
|
+
# The current size of the document, in bytes, as a serialized BSON
|
46
|
+
# document.
|
47
|
+
#
|
48
|
+
# @return [ Integer ] the size of the document
|
49
|
+
def size
|
50
|
+
@document.to_bson.to_s.length
|
51
|
+
end
|
52
|
+
|
53
|
+
# Whether the document fits within the required maximum document size.
|
54
|
+
#
|
55
|
+
# @return [ true | false ] if the document is okay or not.
|
56
|
+
def ok?
|
57
|
+
size <= MAX_DOCUMENT_SIZE
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
# How many extra bytes must be trimmed before the document may be
|
63
|
+
# considered #ok?.
|
64
|
+
#
|
65
|
+
# @return [ Integer ] how many bytes larger the document is than the
|
66
|
+
# maximum document size.
|
67
|
+
def excess
|
68
|
+
size - MAX_DOCUMENT_SIZE
|
69
|
+
end
|
70
|
+
|
71
|
+
# Attempt to truncate the document using the documented metadata
|
72
|
+
# priorities (see the handshake specification).
|
73
|
+
def try_truncate!
|
74
|
+
%i[ env_fields os_fields env platform ].each do |target|
|
75
|
+
break if ok?
|
76
|
+
|
77
|
+
send(:"try_truncate_#{target}!")
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Attempt to truncate or remove the {{:platform}} key from the
|
82
|
+
# document.
|
83
|
+
def try_truncate_platform!
|
84
|
+
@document.delete(:platform) unless try_truncate_string(@document[:platform])
|
85
|
+
end
|
86
|
+
|
87
|
+
# Attempt to truncate the keys in the {{:env}} subdocument.
|
88
|
+
def try_truncate_env_fields!
|
89
|
+
try_truncate_hash(@document[:env], reserved: %w[ name ])
|
90
|
+
end
|
91
|
+
|
92
|
+
# Attempt to truncate the keys in the {{:os}} subdocument.
|
93
|
+
def try_truncate_os_fields!
|
94
|
+
try_truncate_hash(@document[:os], reserved: %w[ type ])
|
95
|
+
end
|
96
|
+
|
97
|
+
# Remove the {{:env}} key from the document.
|
98
|
+
def try_truncate_env!
|
99
|
+
@document.delete(:env)
|
100
|
+
end
|
101
|
+
|
102
|
+
# A helper method for truncating a string (in-place) by whatever
|
103
|
+
# {{#excess}} is required.
|
104
|
+
#
|
105
|
+
# @param [ String ] string the string value to truncate.
|
106
|
+
#
|
107
|
+
# @note the parameter is modified in-place.
|
108
|
+
def try_truncate_string(string)
|
109
|
+
length = string&.length || 0
|
110
|
+
|
111
|
+
return false if excess > length
|
112
|
+
|
113
|
+
string[(length - excess)..-1] = ''
|
114
|
+
end
|
115
|
+
|
116
|
+
# A helper method for removing the keys of a Hash (in-place) until
|
117
|
+
# the document is the necessary size. The keys are considered in order
|
118
|
+
# (using the Hash's native key ordering), and each will be removed from
|
119
|
+
# the hash in turn, until the document is the necessary size.
|
120
|
+
#
|
121
|
+
# Any keys in the {{reserved}} list will be ignored.
|
122
|
+
#
|
123
|
+
# @param [ Hash | nil ] hash the Hash instance to consider.
|
124
|
+
# @param [ Array ] reserved the list of keys to ignore in the hash.
|
125
|
+
#
|
126
|
+
# @note the hash parameter is modified in-place.
|
127
|
+
def try_truncate_hash(hash, reserved: [])
|
128
|
+
return false unless hash
|
129
|
+
|
130
|
+
keys = hash.keys - reserved
|
131
|
+
keys.each do |key|
|
132
|
+
hash.delete(key)
|
133
|
+
|
134
|
+
return true if ok?
|
135
|
+
end
|
136
|
+
|
137
|
+
false
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -15,6 +15,9 @@
|
|
15
15
|
# See the License for the specific language governing permissions and
|
16
16
|
# limitations under the License.
|
17
17
|
|
18
|
+
require 'mongo/server/app_metadata/environment'
|
19
|
+
require 'mongo/server/app_metadata/truncator'
|
20
|
+
|
18
21
|
module Mongo
|
19
22
|
class Server
|
20
23
|
# Application metadata that is sent to the server during a handshake,
|
@@ -26,11 +29,6 @@ module Mongo
|
|
26
29
|
class AppMetadata
|
27
30
|
extend Forwardable
|
28
31
|
|
29
|
-
# The max application metadata document byte size.
|
30
|
-
#
|
31
|
-
# @since 2.4.0
|
32
|
-
MAX_DOCUMENT_SIZE = 512.freeze
|
33
|
-
|
34
32
|
# The max application name byte size.
|
35
33
|
#
|
36
34
|
# @since 2.4.0
|
@@ -139,6 +137,23 @@ module Mongo
|
|
139
137
|
document
|
140
138
|
end
|
141
139
|
|
140
|
+
# Get BSON::Document to be used as value for `client` key in
|
141
|
+
# handshake document.
|
142
|
+
#
|
143
|
+
# @return [BSON::Document] Document describing client for handshake.
|
144
|
+
#
|
145
|
+
# @api private
|
146
|
+
def client_document
|
147
|
+
@client_document ||=
|
148
|
+
BSON::Document.new.tap do |doc|
|
149
|
+
doc[:application] = { name: @app_name } if @app_name
|
150
|
+
doc[:driver] = driver_doc
|
151
|
+
doc[:os] = os_doc
|
152
|
+
doc[:platform] = platform
|
153
|
+
env_doc.tap { |env| doc[:env] = env if env }
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
142
157
|
private
|
143
158
|
|
144
159
|
# Check whether it is possible to build a valid app metadata document
|
@@ -152,20 +167,6 @@ module Mongo
|
|
152
167
|
true
|
153
168
|
end
|
154
169
|
|
155
|
-
# Get BSON::Document to be used as value for `client` key in
|
156
|
-
# handshake document.
|
157
|
-
#
|
158
|
-
# @return [BSON::Document] Document describing client for handshake.
|
159
|
-
def full_client_document
|
160
|
-
BSON::Document.new.tap do |doc|
|
161
|
-
doc[:application] = { name: @app_name } if @app_name
|
162
|
-
doc[:driver] = driver_doc
|
163
|
-
doc[:os] = os_doc
|
164
|
-
doc[:platform] = platform
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
|
169
170
|
# Get the metadata as BSON::Document to be sent to
|
170
171
|
# as part of the handshake. The document should
|
171
172
|
# be appended to a suitable handshake command.
|
@@ -173,30 +174,11 @@ module Mongo
|
|
173
174
|
# @return [BSON::Document] Document for connection's handshake.
|
174
175
|
def document
|
175
176
|
@document ||= begin
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
client_document[:os].delete(:architecture)
|
181
|
-
elsif client_document[:platform]
|
182
|
-
client_document.delete(:platform)
|
183
|
-
else
|
184
|
-
client_document = nil
|
185
|
-
end
|
177
|
+
client = Truncator.new(client_document).document
|
178
|
+
BSON::Document.new(compression: @compressors, client: client).tap do |doc|
|
179
|
+
doc[:saslSupportedMechs] = @request_auth_mech if @request_auth_mech
|
180
|
+
doc.update(Utils.transform_server_api(@server_api)) if @server_api
|
186
181
|
end
|
187
|
-
document = BSON::Document.new(
|
188
|
-
{
|
189
|
-
compression: @compressors,
|
190
|
-
client: client_document,
|
191
|
-
}
|
192
|
-
)
|
193
|
-
document[:saslSupportedMechs] = @request_auth_mech if @request_auth_mech
|
194
|
-
if @server_api
|
195
|
-
document.update(
|
196
|
-
Utils.transform_server_api(@server_api)
|
197
|
-
)
|
198
|
-
end
|
199
|
-
document
|
200
182
|
end
|
201
183
|
end
|
202
184
|
|
@@ -223,6 +205,11 @@ module Mongo
|
|
223
205
|
}
|
224
206
|
end
|
225
207
|
|
208
|
+
def env_doc
|
209
|
+
env = Environment.new
|
210
|
+
env.faas? ? env.to_h : nil
|
211
|
+
end
|
212
|
+
|
226
213
|
def type
|
227
214
|
(RbConfig::CONFIG && RbConfig::CONFIG['host_os']) ?
|
228
215
|
RbConfig::CONFIG['host_os'].split('_').first[/[a-z]+/i].downcase : 'unknown'
|
data/lib/mongo/version.rb
CHANGED
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
# Test Plan scenarios from the handshake spec
|
6
|
+
SCENARIOS = {
|
7
|
+
'Valid AWS' => {
|
8
|
+
'AWS_EXECUTION_ENV' => 'AWS_Lambda_ruby2.7',
|
9
|
+
'AWS_REGION' => 'us-east-2',
|
10
|
+
'AWS_LAMBDA_FUNCTION_MEMORY_SIZE' => '1024',
|
11
|
+
},
|
12
|
+
|
13
|
+
'Valid Azure' => {
|
14
|
+
'FUNCTIONS_WORKER_RUNTIME' => 'ruby',
|
15
|
+
},
|
16
|
+
|
17
|
+
'Valid GCP' => {
|
18
|
+
'K_SERVICE' => 'servicename',
|
19
|
+
'FUNCTION_MEMORY_MB' => '1024',
|
20
|
+
'FUNCTION_TIMEOUT_SEC' => '60',
|
21
|
+
'FUNCTION_REGION' => 'us-central1',
|
22
|
+
},
|
23
|
+
|
24
|
+
'Valid Vercel' => {
|
25
|
+
'VERCEL' => '1',
|
26
|
+
'VERCEL_URL' => '*.vercel.app',
|
27
|
+
'VERCEL_REGION' => 'cdg1',
|
28
|
+
},
|
29
|
+
|
30
|
+
'Invalid - multiple providers' => {
|
31
|
+
'AWS_EXECUTION_ENV' => 'AWS_Lambda_ruby2.7',
|
32
|
+
'AWS_REGION' => 'us-east-2',
|
33
|
+
'AWS_LAMBDA_FUNCTION_MEMORY_SIZE' => '1024',
|
34
|
+
'FUNCTIONS_WORKER_RUNTIME' => 'ruby',
|
35
|
+
},
|
36
|
+
|
37
|
+
'Invalid - long string' => {
|
38
|
+
'AWS_EXECUTION_ENV' => 'AWS_Lambda_ruby2.7',
|
39
|
+
'AWS_REGION' => 'a' * 512,
|
40
|
+
'AWS_LAMBDA_FUNCTION_MEMORY_SIZE' => '1024',
|
41
|
+
},
|
42
|
+
|
43
|
+
'Invalid - wrong types' => {
|
44
|
+
'AWS_EXECUTION_ENV' => 'AWS_Lambda_ruby2.7',
|
45
|
+
'AWS_REGION' => 'us-east-2',
|
46
|
+
'AWS_LAMBDA_FUNCTION_MEMORY_SIZE' => 'big',
|
47
|
+
},
|
48
|
+
}.freeze
|
49
|
+
|
50
|
+
describe 'Connect under FaaS Env' do
|
51
|
+
clean_slate
|
52
|
+
|
53
|
+
SCENARIOS.each do |name, env|
|
54
|
+
context "when given #{name}" do
|
55
|
+
local_env(env)
|
56
|
+
|
57
|
+
it 'connects successfully' do
|
58
|
+
resp = authorized_client.database.command(ping: 1)
|
59
|
+
expect(resp).to be_a(Mongo::Operation::Result)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,227 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe 'Find operation options' do
|
6
|
+
require_mri
|
7
|
+
require_no_auth
|
8
|
+
min_server_fcv '4.4'
|
9
|
+
|
10
|
+
let(:subscriber) { Mrss::EventSubscriber.new }
|
11
|
+
|
12
|
+
let(:seeds) do
|
13
|
+
[ SpecConfig.instance.addresses.first ]
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:client_options) do
|
17
|
+
{}
|
18
|
+
end
|
19
|
+
|
20
|
+
let(:collection_options) do
|
21
|
+
{}
|
22
|
+
end
|
23
|
+
|
24
|
+
let(:client) do
|
25
|
+
ClientRegistry.instance.new_local_client(
|
26
|
+
seeds,
|
27
|
+
SpecConfig.instance.test_options
|
28
|
+
.merge(database: SpecConfig.instance.test_db)
|
29
|
+
.merge(client_options)
|
30
|
+
).tap do |client|
|
31
|
+
client.subscribe(Mongo::Monitoring::COMMAND, subscriber)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
let(:collection) do
|
36
|
+
client['find_options', collection_options]
|
37
|
+
end
|
38
|
+
|
39
|
+
let(:find_command) do
|
40
|
+
subscriber.started_events.find { |cmd| cmd.command_name == 'find' }
|
41
|
+
end
|
42
|
+
|
43
|
+
let(:should_create_collection) { true }
|
44
|
+
|
45
|
+
before do
|
46
|
+
client['find_options'].drop
|
47
|
+
collection.create if should_create_collection
|
48
|
+
collection.insert_many([ { a: 1 }, { a: 2 }, { a: 3 } ])
|
49
|
+
end
|
50
|
+
|
51
|
+
describe 'collation' do
|
52
|
+
let(:client_options) do
|
53
|
+
{}
|
54
|
+
end
|
55
|
+
|
56
|
+
let(:collation) do
|
57
|
+
{ 'locale' => 'en_US' }
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'when defined on the collection' do
|
61
|
+
let(:collection_options) do
|
62
|
+
{ collation: collation }
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'uses the collation defined on the collection' do
|
66
|
+
collection.find.to_a
|
67
|
+
expect(find_command.command['collation']).to be_nil
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'when defined on the operation' do
|
72
|
+
let(:collection_options) do
|
73
|
+
{}
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'uses the collation defined on the collection' do
|
77
|
+
collection.find({}, collation: collation).to_a
|
78
|
+
expect(find_command.command['collation']).to eq(collation)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context 'when defined on both collection and operation' do
|
83
|
+
let(:collection_options) do
|
84
|
+
{ 'locale' => 'de_AT' }
|
85
|
+
end
|
86
|
+
|
87
|
+
let(:should_create_collection) { false }
|
88
|
+
|
89
|
+
it 'uses the collation defined on the collection' do
|
90
|
+
collection.find({}, collation: collation).to_a
|
91
|
+
expect(find_command.command['collation']).to eq(collation)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe 'read concern' do
|
97
|
+
context 'when defined on the client' do
|
98
|
+
let(:client_options) do
|
99
|
+
{ read_concern: { level: :local } }
|
100
|
+
end
|
101
|
+
|
102
|
+
let(:collection_options) do
|
103
|
+
{}
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'uses the read concern defined on the client' do
|
107
|
+
collection.find.to_a
|
108
|
+
expect(find_command.command['readConcern']).to eq('level' => 'local')
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'when defined on the collection' do
|
112
|
+
let(:collection_options) do
|
113
|
+
{ read_concern: { level: :majority } }
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'uses the read concern defined on the collection' do
|
117
|
+
collection.find.to_a
|
118
|
+
expect(find_command.command['readConcern']).to eq('level' => 'majority')
|
119
|
+
end
|
120
|
+
|
121
|
+
context 'when defined on the operation' do
|
122
|
+
let(:operation_read_concern) do
|
123
|
+
{ level: :available }
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'uses the read concern defined on the operation' do
|
127
|
+
collection.find({}, read_concern: operation_read_concern).to_a
|
128
|
+
expect(find_command.command['readConcern']).to eq('level' => 'available')
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
context 'when defined on the operation' do
|
134
|
+
let(:collection_options) do
|
135
|
+
{}
|
136
|
+
end
|
137
|
+
|
138
|
+
let(:operation_read_concern) do
|
139
|
+
{ level: :available }
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'uses the read concern defined on the operation' do
|
143
|
+
collection.find({}, read_concern: operation_read_concern).to_a
|
144
|
+
expect(find_command.command['readConcern']).to eq('level' => 'available')
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
context 'when defined on the collection' do
|
150
|
+
let(:client_options) do
|
151
|
+
{}
|
152
|
+
end
|
153
|
+
|
154
|
+
let(:collection_options) do
|
155
|
+
{ read_concern: { level: :majority } }
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'uses the read concern defined on the collection' do
|
159
|
+
collection.find.to_a
|
160
|
+
expect(find_command.command['readConcern']).to eq('level' => 'majority')
|
161
|
+
end
|
162
|
+
|
163
|
+
context 'when defined on the operation' do
|
164
|
+
let(:operation_read_concern) do
|
165
|
+
{ level: :available }
|
166
|
+
end
|
167
|
+
|
168
|
+
it 'uses the read concern defined on the operation' do
|
169
|
+
collection.find({}, read_concern: operation_read_concern).to_a
|
170
|
+
expect(find_command.command['readConcern']).to eq('level' => 'available')
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
describe 'read preference' do
|
177
|
+
require_topology :replica_set
|
178
|
+
|
179
|
+
context 'when defined on the client' do
|
180
|
+
let(:client_options) do
|
181
|
+
{ read: { mode: :secondary } }
|
182
|
+
end
|
183
|
+
|
184
|
+
let(:collection_options) do
|
185
|
+
{}
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'uses the read preference defined on the client' do
|
189
|
+
collection.find.to_a
|
190
|
+
expect(find_command.command['$readPreference']).to eq('mode' => 'secondary')
|
191
|
+
end
|
192
|
+
|
193
|
+
context 'when defined on the collection' do
|
194
|
+
let(:collection_options) do
|
195
|
+
{ read: { mode: :secondary_preferred } }
|
196
|
+
end
|
197
|
+
|
198
|
+
it 'uses the read concern defined on the collection' do
|
199
|
+
collection.find.to_a
|
200
|
+
expect(find_command.command['$readPreference']).to eq('mode' => 'secondaryPreferred')
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
describe 'cursor type' do
|
207
|
+
let(:collection_options) do
|
208
|
+
{ capped: true, size: 1000 }
|
209
|
+
end
|
210
|
+
|
211
|
+
context 'when cursor type is :tailable' do
|
212
|
+
it 'sets the cursor type to tailable' do
|
213
|
+
collection.find({}, cursor_type: :tailable).first
|
214
|
+
expect(find_command.command['tailable']).to be true
|
215
|
+
expect(find_command.command['awaitData']).to be_falsey
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
context 'when cursor type is :tailable_await' do
|
220
|
+
it 'sets the cursor type to tailable' do
|
221
|
+
collection.find({}, cursor_type: :tailable_await).first
|
222
|
+
expect(find_command.command['tailable']).to be true
|
223
|
+
expect(find_command.command['awaitData']).to be true
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
@@ -352,7 +352,7 @@ describe Mongo::Socket::OcspVerifier do
|
|
352
352
|
|
353
353
|
it 'verifies' do
|
354
354
|
# TODO This test will fail if the certificate expires
|
355
|
-
verifier.verify.
|
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"
|
356
356
|
end
|
357
357
|
end
|
358
358
|
end
|
data/spec/lite_spec_helper.rb
CHANGED
@@ -110,6 +110,15 @@ RSpec.configure do |config|
|
|
110
110
|
config.include(MongosMacros)
|
111
111
|
config.extend(Mongo::Macros)
|
112
112
|
|
113
|
+
# Used for spec/solo/*
|
114
|
+
def require_solo
|
115
|
+
before(:all) do
|
116
|
+
unless %w(1 true yes).include?(ENV['SOLO'])
|
117
|
+
skip 'Set SOLO=1 in environment to run solo tests'
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
113
122
|
if SpecConfig.instance.ci?
|
114
123
|
SdamFormatterIntegration.subscribe
|
115
124
|
config.add_formatter(JsonExtFormatter, File.join(File.dirname(__FILE__), '../tmp/rspec.json'))
|
data/spec/mongo/address_spec.rb
CHANGED
@@ -305,7 +305,7 @@ describe Mongo::Address do
|
|
305
305
|
RSpec::Mocks.with_temporary_scope do
|
306
306
|
resolved_address = double('address')
|
307
307
|
# This test's expectation
|
308
|
-
expect(resolved_address).to receive(:socket).with(0, connect_timeout: 10)
|
308
|
+
expect(resolved_address).to receive(:socket).with(0, { connect_timeout: 10 })
|
309
309
|
|
310
310
|
expect(Mongo::Address::IPv4).to receive(:new).and_return(resolved_address)
|
311
311
|
|
@@ -953,7 +953,7 @@ describe Mongo::Client do
|
|
953
953
|
end
|
954
954
|
|
955
955
|
it 'includes the platform info in the app metadata' do
|
956
|
-
expect(app_metadata.
|
956
|
+
expect(app_metadata.client_document[:platform]).to match(/mongoid-6\.0\.2/)
|
957
957
|
end
|
958
958
|
end
|
959
959
|
|
@@ -980,7 +980,7 @@ describe Mongo::Client do
|
|
980
980
|
end
|
981
981
|
|
982
982
|
it 'does not include the platform info in the app metadata' do
|
983
|
-
expect(app_metadata.
|
983
|
+
expect(app_metadata.client_document[:platform]).to eq(platform_string)
|
984
984
|
end
|
985
985
|
end
|
986
986
|
|
@@ -999,7 +999,7 @@ describe Mongo::Client do
|
|
999
999
|
end
|
1000
1000
|
|
1001
1001
|
it 'does not include the platform info in the app metadata' do
|
1002
|
-
expect(app_metadata.
|
1002
|
+
expect(app_metadata.client_document[:platform]).to eq(platform_string)
|
1003
1003
|
end
|
1004
1004
|
end
|
1005
1005
|
end
|
data/spec/mongo/client_spec.rb
CHANGED
@@ -947,7 +947,7 @@ describe Mongo::Client do
|
|
947
947
|
before do
|
948
948
|
sessions_checked_out = 0
|
949
949
|
|
950
|
-
allow_any_instance_of(Mongo::Server).to receive(:with_connection).and_wrap_original do |m, *args, &block|
|
950
|
+
allow_any_instance_of(Mongo::Server).to receive(:with_connection).and_wrap_original do |m, *args, **kwargs, &block|
|
951
951
|
m.call(*args) do |connection|
|
952
952
|
sessions_checked_out = 0
|
953
953
|
res = block.call(connection)
|
@@ -955,14 +955,6 @@ describe Mongo::Client do
|
|
955
955
|
res
|
956
956
|
end
|
957
957
|
end
|
958
|
-
|
959
|
-
allow_any_instance_of(Mongo::Session).to receive(:materialize).and_wrap_original do |m, *args|
|
960
|
-
sessions_checked_out += 1
|
961
|
-
m.call(*args).tap do
|
962
|
-
checked_out_connections = args[0].connection_pool.instance_variable_get("@checked_out_connections")
|
963
|
-
expect(checked_out_connections.length).to eq 1
|
964
|
-
end
|
965
|
-
end
|
966
958
|
end
|
967
959
|
|
968
960
|
it 'doesn\'t have any live sessions' do
|
data/spec/mongo/cluster_spec.rb
CHANGED
@@ -480,7 +480,7 @@ describe Mongo::Cluster do
|
|
480
480
|
end
|
481
481
|
|
482
482
|
it 'constructs an AppMetadata object with the app_name' do
|
483
|
-
expect(cluster.app_metadata.
|
483
|
+
expect(cluster.app_metadata.client_document[:application]).to eq('name' => 'cluster_test')
|
484
484
|
end
|
485
485
|
end
|
486
486
|
|
@@ -491,7 +491,7 @@ describe Mongo::Cluster do
|
|
491
491
|
end
|
492
492
|
|
493
493
|
it 'constructs an AppMetadata object with no app_name' do
|
494
|
-
expect(cluster.app_metadata.
|
494
|
+
expect(cluster.app_metadata.client_document[:application]).to be_nil
|
495
495
|
end
|
496
496
|
end
|
497
497
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Mongo::Crypt do
|
6
|
+
describe '.validate_ffi!' do
|
7
|
+
context 'when ffi is available' do
|
8
|
+
context 'when ffi is loaded' do
|
9
|
+
it 'does not raise' do
|
10
|
+
expect do
|
11
|
+
described_class.validate_ffi!
|
12
|
+
end.not_to raise_error
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
# There is no reasonably simple way to test the path where ffi is not
|
17
|
+
# available. The ffi gem is a part of our standard test dependencies, so
|
18
|
+
# it's always available. So, we would need a dedicated configuration
|
19
|
+
# just to test this feature; it seems to be an overhead.
|
20
|
+
end
|
21
|
+
end
|
@@ -960,6 +960,7 @@ describe Mongo::Index::View do
|
|
960
960
|
min_server_fcv '5.0'
|
961
961
|
|
962
962
|
it 'passes wildcardProjection correctly' do
|
963
|
+
skip 'https://jira.mongodb.org/browse/RUBY-3216'
|
963
964
|
expect(indexes[:wildcardProjection]).to eq({ '_id' => false, 'rating' => true })
|
964
965
|
end
|
965
966
|
end
|