mongo 2.13.3 → 2.14.0.rc1
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/lib/mongo/address/ipv4.rb +1 -1
- data/lib/mongo/address/ipv6.rb +1 -1
- data/lib/mongo/address.rb +1 -1
- data/lib/mongo/bulk_write.rb +17 -0
- data/lib/mongo/caching_cursor.rb +74 -0
- data/lib/mongo/client.rb +47 -8
- data/lib/mongo/cluster/topology/single.rb +1 -1
- data/lib/mongo/cluster.rb +3 -3
- data/lib/mongo/collection/view/aggregation.rb +25 -4
- data/lib/mongo/collection/view/builder/find_command.rb +38 -18
- data/lib/mongo/collection/view/explainable.rb +27 -8
- data/lib/mongo/collection/view/iterable.rb +72 -12
- data/lib/mongo/collection/view/readable.rb +12 -2
- data/lib/mongo/collection/view/writable.rb +15 -1
- data/lib/mongo/collection/view.rb +24 -20
- data/lib/mongo/collection.rb +26 -2
- data/lib/mongo/crypt/encryption_io.rb +6 -6
- data/lib/mongo/cursor.rb +1 -0
- data/lib/mongo/database/view.rb +1 -1
- data/lib/mongo/database.rb +8 -14
- data/lib/mongo/error/invalid_read_concern.rb +28 -0
- data/lib/mongo/error/server_certificate_revoked.rb +22 -0
- data/lib/mongo/error/unsupported_option.rb +14 -12
- data/lib/mongo/error.rb +2 -0
- data/lib/mongo/grid/fs_bucket.rb +37 -37
- data/lib/mongo/lint.rb +2 -1
- data/lib/mongo/logger.rb +3 -3
- data/lib/mongo/operation/aggregate/result.rb +9 -8
- data/lib/mongo/operation/collections_info/command.rb +0 -5
- data/lib/mongo/operation/collections_info/result.rb +3 -16
- data/lib/mongo/operation/delete/bulk_result.rb +2 -0
- data/lib/mongo/operation/delete/result.rb +3 -0
- data/lib/mongo/operation/explain/command.rb +4 -0
- data/lib/mongo/operation/explain/legacy.rb +4 -0
- data/lib/mongo/operation/explain/op_msg.rb +6 -0
- data/lib/mongo/operation/explain/result.rb +3 -0
- data/lib/mongo/operation/find/legacy/result.rb +2 -0
- data/lib/mongo/operation/find/result.rb +3 -0
- data/lib/mongo/operation/get_more/result.rb +3 -0
- data/lib/mongo/operation/indexes/result.rb +5 -0
- data/lib/mongo/operation/insert/bulk_result.rb +5 -0
- data/lib/mongo/operation/insert/result.rb +5 -0
- data/lib/mongo/operation/list_collections/result.rb +5 -0
- data/lib/mongo/operation/map_reduce/result.rb +10 -0
- data/lib/mongo/operation/parallel_scan/command.rb +2 -1
- data/lib/mongo/operation/parallel_scan/result.rb +4 -0
- data/lib/mongo/operation/result.rb +35 -6
- data/lib/mongo/operation/shared/bypass_document_validation.rb +1 -0
- data/lib/mongo/operation/shared/causal_consistency_supported.rb +1 -0
- data/lib/mongo/operation/shared/collections_info_or_list_collections.rb +2 -0
- data/lib/mongo/operation/shared/executable.rb +1 -0
- data/lib/mongo/operation/shared/idable.rb +2 -1
- data/lib/mongo/operation/shared/limited.rb +1 -0
- data/lib/mongo/operation/shared/object_id_generator.rb +1 -0
- data/lib/mongo/operation/shared/read_preference_supported.rb +36 -38
- data/lib/mongo/operation/shared/result/aggregatable.rb +1 -0
- data/lib/mongo/operation/shared/sessions_supported.rb +3 -3
- data/lib/mongo/operation/shared/specifiable.rb +1 -0
- data/lib/mongo/operation/shared/write.rb +1 -0
- data/lib/mongo/operation/shared/write_concern_supported.rb +1 -0
- data/lib/mongo/operation/update/legacy/result.rb +7 -0
- data/lib/mongo/operation/update/result.rb +8 -0
- data/lib/mongo/operation/users_info/result.rb +3 -0
- data/lib/mongo/operation.rb +2 -0
- data/lib/mongo/protocol/msg.rb +2 -2
- data/lib/mongo/protocol/query.rb +11 -11
- data/lib/mongo/query_cache.rb +242 -0
- data/lib/mongo/retryable.rb +8 -1
- data/lib/mongo/server/connection_common.rb +2 -2
- data/lib/mongo/server/connection_pool.rb +3 -0
- data/lib/mongo/server/monitor/connection.rb +3 -3
- data/lib/mongo/server/monitor.rb +1 -1
- data/lib/mongo/server/pending_connection.rb +2 -2
- data/lib/mongo/server/push_monitor.rb +1 -1
- data/lib/mongo/server.rb +5 -1
- data/lib/mongo/server_selector/base.rb +5 -1
- data/lib/mongo/server_selector/secondary_preferred.rb +7 -2
- data/lib/mongo/session.rb +3 -0
- data/lib/mongo/socket/ocsp_cache.rb +97 -0
- data/lib/mongo/socket/ocsp_verifier.rb +368 -0
- data/lib/mongo/socket/ssl.rb +45 -24
- data/lib/mongo/socket.rb +6 -4
- data/lib/mongo/srv/monitor.rb +7 -13
- data/lib/mongo/srv/resolver.rb +14 -10
- data/lib/mongo/timeout.rb +2 -0
- data/lib/mongo/uri/options_mapper.rb +582 -0
- data/lib/mongo/uri/srv_protocol.rb +3 -2
- data/lib/mongo/uri.rb +21 -390
- data/lib/mongo/utils.rb +12 -1
- data/lib/mongo/version.rb +1 -1
- data/lib/mongo.rb +9 -0
- data/spec/NOTES.aws-auth.md +12 -7
- data/spec/README.md +56 -1
- data/spec/integration/bson_symbol_spec.rb +2 -4
- data/spec/integration/bulk_write_spec.rb +48 -0
- data/spec/integration/client_authentication_options_spec.rb +55 -28
- data/spec/integration/connection_pool_populator_spec.rb +3 -1
- data/spec/integration/cursor_reaping_spec.rb +53 -17
- data/spec/integration/ocsp_connectivity_spec.rb +26 -0
- data/spec/integration/ocsp_verifier_cache_spec.rb +188 -0
- data/spec/integration/ocsp_verifier_spec.rb +334 -0
- data/spec/integration/query_cache_spec.rb +1045 -0
- data/spec/integration/query_cache_transactions_spec.rb +179 -0
- data/spec/integration/retryable_writes/retryable_writes_40_and_newer_spec.rb +1 -0
- data/spec/integration/retryable_writes/shared/performs_legacy_retries.rb +2 -0
- data/spec/integration/sdam_error_handling_spec.rb +69 -18
- data/spec/integration/sdam_events_spec.rb +7 -8
- data/spec/integration/server_selection_spec.rb +36 -0
- data/spec/integration/srv_monitoring_spec.rb +38 -3
- data/spec/integration/srv_spec.rb +56 -0
- data/spec/lite_spec_helper.rb +4 -2
- data/spec/mongo/address_spec.rb +1 -1
- data/spec/mongo/caching_cursor_spec.rb +70 -0
- data/spec/mongo/client_construction_spec.rb +54 -1
- data/spec/mongo/client_encryption_spec.rb +10 -16
- data/spec/mongo/client_spec.rb +40 -0
- data/spec/mongo/cluster/topology/single_spec.rb +14 -5
- data/spec/mongo/cluster_spec.rb +3 -0
- data/spec/mongo/collection/view/explainable_spec.rb +87 -4
- data/spec/mongo/collection/view/map_reduce_spec.rb +2 -0
- data/spec/mongo/collection_spec.rb +60 -0
- data/spec/mongo/crypt/auto_decryption_context_spec.rb +1 -1
- data/spec/mongo/crypt/auto_encryption_context_spec.rb +1 -1
- data/spec/mongo/crypt/data_key_context_spec.rb +1 -1
- data/spec/mongo/crypt/explicit_decryption_context_spec.rb +1 -1
- data/spec/mongo/crypt/explicit_encryption_context_spec.rb +1 -1
- data/spec/mongo/database_spec.rb +44 -64
- data/spec/mongo/error/no_server_available_spec.rb +1 -1
- data/spec/mongo/index/view_spec.rb +2 -4
- data/spec/mongo/logger_spec.rb +13 -11
- data/spec/mongo/operation/read_preference_legacy_spec.rb +19 -9
- data/spec/mongo/operation/read_preference_op_msg_spec.rb +3 -3
- data/spec/mongo/query_cache_spec.rb +279 -0
- data/spec/mongo/server/app_metadata_shared.rb +7 -33
- data/spec/mongo/server/connection_pool_spec.rb +7 -3
- data/spec/mongo/server/connection_spec.rb +14 -7
- data/spec/mongo/server_selector/secondary_preferred_spec.rb +6 -6
- data/spec/mongo/socket/ssl_spec.rb +1 -1
- data/spec/mongo/socket_spec.rb +1 -1
- data/spec/mongo/uri/srv_protocol_spec.rb +64 -33
- data/spec/mongo/uri_option_parsing_spec.rb +11 -11
- data/spec/mongo/uri_spec.rb +68 -41
- data/spec/mongo/utils_spec.rb +39 -0
- data/spec/runners/auth.rb +3 -0
- data/spec/runners/connection_string.rb +35 -124
- data/spec/runners/transactions/operation.rb +2 -13
- data/spec/spec_tests/cmap_spec.rb +7 -3
- data/spec/spec_tests/data/change_streams/change-streams-errors.yml +0 -1
- data/spec/spec_tests/data/change_streams/change-streams.yml +0 -1
- data/spec/spec_tests/data/cmap/pool-checkout-connection.yml +6 -2
- data/spec/spec_tests/data/cmap/pool-create-min-size.yml +3 -0
- data/spec/spec_tests/data/connection_string/valid-warnings.yml +24 -0
- data/spec/spec_tests/data/sdam_monitoring/discovered_standalone.yml +1 -3
- data/spec/spec_tests/data/sdam_monitoring/standalone.yml +2 -2
- data/spec/spec_tests/data/sdam_monitoring/standalone_repeated.yml +2 -2
- data/spec/spec_tests/data/sdam_monitoring/standalone_suppress_equal_description_changes.yml +2 -2
- data/spec/spec_tests/data/sdam_monitoring/standalone_to_rs_with_me_mismatch.yml +2 -2
- data/spec/spec_tests/data/uri_options/auth-options.yml +25 -0
- data/spec/spec_tests/data/uri_options/compression-options.yml +6 -3
- data/spec/spec_tests/data/uri_options/read-preference-options.yml +24 -0
- data/spec/spec_tests/data/uri_options/ruby-connection-options.yml +1 -0
- data/spec/spec_tests/data/uri_options/tls-options.yml +160 -4
- data/spec/spec_tests/dns_seedlist_discovery_spec.rb +9 -1
- data/spec/spec_tests/uri_options_spec.rb +31 -33
- data/spec/support/certificates/atlas-ocsp-ca.crt +28 -0
- data/spec/support/certificates/atlas-ocsp.crt +41 -0
- data/spec/support/client_registry.rb +4 -8
- data/spec/support/client_registry_macros.rb +4 -4
- data/spec/support/common_shortcuts.rb +45 -0
- data/spec/support/constraints.rb +23 -0
- data/spec/support/lite_constraints.rb +24 -0
- data/spec/support/matchers.rb +16 -0
- data/spec/support/ocsp +1 -0
- data/spec/support/session_registry.rb +52 -0
- data/spec/support/spec_config.rb +22 -12
- data/spec/support/spec_setup.rb +38 -48
- data/spec/support/utils.rb +19 -1
- data.tar.gz.sig +1 -3
- metadata +938 -933
- metadata.gz.sig +0 -0
- data/spec/integration/secondary_reads_spec.rb +0 -102
- data/spec/shared/LICENSE +0 -20
- data/spec/shared/bin/get-mongodb-download-url +0 -17
- data/spec/shared/lib/mrss/child_process_helper.rb +0 -80
- data/spec/shared/lib/mrss/cluster_config.rb +0 -221
- data/spec/shared/lib/mrss/constraints.rb +0 -346
- data/spec/shared/lib/mrss/docker_runner.rb +0 -265
- data/spec/shared/lib/mrss/lite_constraints.rb +0 -191
- data/spec/shared/lib/mrss/server_version_registry.rb +0 -115
- data/spec/shared/lib/mrss/spec_organizer.rb +0 -152
- data/spec/shared/lib/mrss/utils.rb +0 -15
- data/spec/shared/share/Dockerfile.erb +0 -231
- data/spec/shared/shlib/distro.sh +0 -73
- data/spec/shared/shlib/server.sh +0 -290
- data/spec/shared/shlib/set_env.sh +0 -128
@@ -0,0 +1,179 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'QueryCache with transactions' do
|
4
|
+
around do |spec|
|
5
|
+
Mongo::QueryCache.clear
|
6
|
+
Mongo::QueryCache.cache { spec.run }
|
7
|
+
end
|
8
|
+
|
9
|
+
before do
|
10
|
+
authorized_collection.delete_many
|
11
|
+
subscriber.clear_events!
|
12
|
+
end
|
13
|
+
|
14
|
+
# These tests do not currently use the session registry because transactions
|
15
|
+
# leak sessions independently of the query cache. This will be resolved by
|
16
|
+
# RUBY-2391.
|
17
|
+
|
18
|
+
let(:subscriber) { EventSubscriber.new }
|
19
|
+
|
20
|
+
let(:client) do
|
21
|
+
authorized_client.tap do |client|
|
22
|
+
client.subscribe(Mongo::Monitoring::COMMAND, subscriber)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
let(:authorized_collection) { client['collection_spec'] }
|
27
|
+
|
28
|
+
describe 'in transactions' do
|
29
|
+
require_transaction_support
|
30
|
+
require_wired_tiger
|
31
|
+
|
32
|
+
let(:collection) { authorized_client['test'] }
|
33
|
+
|
34
|
+
let(:events) do
|
35
|
+
subscriber.command_started_events('find')
|
36
|
+
end
|
37
|
+
|
38
|
+
before do
|
39
|
+
Utils.create_collection(authorized_client, 'test')
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'with convenient API' do
|
43
|
+
context 'when same query is performed inside and outside of transaction' do
|
44
|
+
it 'performs one query' do
|
45
|
+
collection.find.to_a
|
46
|
+
|
47
|
+
session = authorized_client.start_session
|
48
|
+
session.with_transaction do
|
49
|
+
collection.find({}, session: session).to_a
|
50
|
+
end
|
51
|
+
|
52
|
+
expect(subscriber.command_started_events('find').length).to eq(1)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'when transaction has a different read concern' do
|
57
|
+
it 'performs two queries' do
|
58
|
+
collection.find.to_a
|
59
|
+
|
60
|
+
session = authorized_client.start_session
|
61
|
+
session.with_transaction(
|
62
|
+
read_concern: { level: :snapshot }
|
63
|
+
) do
|
64
|
+
collection.find({}, session: session).to_a
|
65
|
+
end
|
66
|
+
|
67
|
+
expect(subscriber.command_started_events('find').length).to eq(2)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'when transaction has a different read preference' do
|
72
|
+
it 'performs two queries' do
|
73
|
+
collection.find.to_a
|
74
|
+
|
75
|
+
session = authorized_client.start_session
|
76
|
+
session.with_transaction(
|
77
|
+
read: { mode: :primary }
|
78
|
+
) do
|
79
|
+
collection.find({}, session: session).to_a
|
80
|
+
end
|
81
|
+
|
82
|
+
expect(subscriber.command_started_events('find').length).to eq(2)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context 'when transaction is committed' do
|
87
|
+
it 'clears the cache' do
|
88
|
+
session = authorized_client.start_session
|
89
|
+
session.with_transaction do
|
90
|
+
collection.insert_one({ test: 1 }, session: session)
|
91
|
+
collection.insert_one({ test: 2 }, session: session)
|
92
|
+
|
93
|
+
expect(collection.find({}, session: session).to_a.length).to eq(2)
|
94
|
+
expect(collection.find({}, session: session).to_a.length).to eq(2)
|
95
|
+
|
96
|
+
# The driver caches the queries within the transaction
|
97
|
+
expect(subscriber.command_started_events('find').length).to eq(1)
|
98
|
+
session.commit_transaction
|
99
|
+
end
|
100
|
+
|
101
|
+
expect(collection.find.to_a.length).to eq(2)
|
102
|
+
|
103
|
+
# The driver clears the cache and runs the query again
|
104
|
+
expect(subscriber.command_started_events('find').length).to eq(2)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context 'when transaction is aborted' do
|
109
|
+
it 'clears the cache' do
|
110
|
+
session = authorized_client.start_session
|
111
|
+
session.with_transaction do
|
112
|
+
collection.insert_one({ test: 1 }, session: session)
|
113
|
+
collection.insert_one({ test: 2 }, session: session)
|
114
|
+
|
115
|
+
expect(collection.find({}, session: session).to_a.length).to eq(2)
|
116
|
+
expect(collection.find({}, session: session).to_a.length).to eq(2)
|
117
|
+
|
118
|
+
# The driver caches the queries within the transaction
|
119
|
+
expect(subscriber.command_started_events('find').length).to eq(1)
|
120
|
+
session.abort_transaction
|
121
|
+
end
|
122
|
+
|
123
|
+
expect(collection.find.to_a.length).to eq(0)
|
124
|
+
|
125
|
+
# The driver clears the cache and runs the query again
|
126
|
+
expect(subscriber.command_started_events('find').length).to eq(2)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
context 'with low-level API' do
|
132
|
+
context 'when transaction is committed' do
|
133
|
+
it 'clears the cache' do
|
134
|
+
session = authorized_client.start_session
|
135
|
+
session.start_transaction
|
136
|
+
|
137
|
+
collection.insert_one({ test: 1 }, session: session)
|
138
|
+
collection.insert_one({ test: 2 }, session: session)
|
139
|
+
|
140
|
+
expect(collection.find({}, session: session).to_a.length).to eq(2)
|
141
|
+
expect(collection.find({}, session: session).to_a.length).to eq(2)
|
142
|
+
|
143
|
+
# The driver caches the queries within the transaction
|
144
|
+
expect(subscriber.command_started_events('find').length).to eq(1)
|
145
|
+
|
146
|
+
session.commit_transaction
|
147
|
+
|
148
|
+
expect(collection.find.to_a.length).to eq(2)
|
149
|
+
|
150
|
+
# The driver clears the cache and runs the query again
|
151
|
+
expect(subscriber.command_started_events('find').length).to eq(2)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
context 'when transaction is aborted' do
|
156
|
+
it 'clears the cache' do
|
157
|
+
session = authorized_client.start_session
|
158
|
+
session.start_transaction
|
159
|
+
|
160
|
+
collection.insert_one({ test: 1 }, session: session)
|
161
|
+
collection.insert_one({ test: 2 }, session: session)
|
162
|
+
|
163
|
+
expect(collection.find({}, session: session).to_a.length).to eq(2)
|
164
|
+
expect(collection.find({}, session: session).to_a.length).to eq(2)
|
165
|
+
|
166
|
+
# The driver caches the queries within the transaction
|
167
|
+
expect(subscriber.command_started_events('find').length).to eq(1)
|
168
|
+
|
169
|
+
session.abort_transaction
|
170
|
+
|
171
|
+
expect(collection.find.to_a.length).to eq(0)
|
172
|
+
|
173
|
+
# The driver clears the cache and runs the query again
|
174
|
+
expect(subscriber.command_started_events('find').length).to eq(2)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe 'SDAM error handling' do
|
4
|
-
|
4
|
+
clean_slate_for_all
|
5
5
|
|
6
6
|
after do
|
7
7
|
# Close all clients after every test to avoid leaking expectations into
|
@@ -19,7 +19,6 @@ describe 'SDAM error handling' do
|
|
19
19
|
new_local_client(SpecConfig.instance.addresses,
|
20
20
|
SpecConfig.instance.all_test_options.merge(
|
21
21
|
socket_timeout: 3, connect_timeout: 3,
|
22
|
-
heartbeat_frequency: 100,
|
23
22
|
# Uncomment to print all events to stdout:
|
24
23
|
#sdam_proc: Utils.subscribe_all_sdam_proc(diagnostic_subscriber),
|
25
24
|
**Utils.disable_retries_client_options)
|
@@ -29,14 +28,6 @@ describe 'SDAM error handling' do
|
|
29
28
|
let(:server) { client.cluster.next_primary }
|
30
29
|
|
31
30
|
shared_examples_for 'marks server unknown' do
|
32
|
-
before do
|
33
|
-
server.monitor.stop!
|
34
|
-
end
|
35
|
-
|
36
|
-
after do
|
37
|
-
client.close
|
38
|
-
end
|
39
|
-
|
40
31
|
it 'marks server unknown' do
|
41
32
|
expect(server).not_to be_unknown
|
42
33
|
RSpec::Mocks.with_temporary_scope do
|
@@ -47,14 +38,6 @@ describe 'SDAM error handling' do
|
|
47
38
|
end
|
48
39
|
|
49
40
|
shared_examples_for 'does not mark server unknown' do
|
50
|
-
before do
|
51
|
-
server.monitor.stop!
|
52
|
-
end
|
53
|
-
|
54
|
-
after do
|
55
|
-
client.close
|
56
|
-
end
|
57
|
-
|
58
41
|
it 'does not mark server unknown' do
|
59
42
|
expect(server).not_to be_unknown
|
60
43
|
RSpec::Mocks.with_temporary_scope do
|
@@ -214,6 +197,74 @@ describe 'SDAM error handling' do
|
|
214
197
|
end
|
215
198
|
end
|
216
199
|
|
200
|
+
describe 'when there is an error during connection establishment' do
|
201
|
+
require_topology :single
|
202
|
+
|
203
|
+
# The push monitor creates sockets unpredictably and interferes with this
|
204
|
+
# test.
|
205
|
+
max_server_version '4.2'
|
206
|
+
|
207
|
+
# When TLS is used there are two socket classes and we can't simply
|
208
|
+
# mock the base Socket class.
|
209
|
+
require_no_tls
|
210
|
+
|
211
|
+
{
|
212
|
+
SystemCallError => Mongo::Error::SocketError,
|
213
|
+
Errno::ETIMEDOUT => Mongo::Error::SocketTimeoutError,
|
214
|
+
}.each do |raw_error_cls, mapped_error_cls|
|
215
|
+
context raw_error_cls.name do
|
216
|
+
let(:socket) do
|
217
|
+
double('mock socket').tap do |socket|
|
218
|
+
allow(socket).to receive(:set_encoding)
|
219
|
+
allow(socket).to receive(:setsockopt)
|
220
|
+
allow(socket).to receive(:getsockopt)
|
221
|
+
allow(socket).to receive(:connect)
|
222
|
+
allow(socket).to receive(:close)
|
223
|
+
socket.should receive(:write).and_raise(raw_error_cls, 'mocked failure')
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
it 'marks server unknown' do
|
228
|
+
server = client.cluster.next_primary
|
229
|
+
client.cluster.servers.map(&:disconnect!)
|
230
|
+
|
231
|
+
RSpec::Mocks.with_temporary_scope do
|
232
|
+
|
233
|
+
Socket.should receive(:new).with(any_args).ordered.once.and_return(socket)
|
234
|
+
|
235
|
+
lambda do
|
236
|
+
client.command(ping: 1)
|
237
|
+
end.should raise_error(mapped_error_cls, /mocked failure/)
|
238
|
+
|
239
|
+
server.should be_unknown
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
it 'recovers' do
|
244
|
+
server = client.cluster.next_primary
|
245
|
+
# If we do not kill the monitor, the client will recover automatically.
|
246
|
+
|
247
|
+
RSpec::Mocks.with_temporary_scope do
|
248
|
+
|
249
|
+
Socket.should receive(:new).with(any_args).ordered.once.and_return(socket)
|
250
|
+
Socket.should receive(:new).with(any_args).ordered.once.and_call_original
|
251
|
+
|
252
|
+
lambda do
|
253
|
+
client.command(ping: 1)
|
254
|
+
end.should raise_error(mapped_error_cls, /mocked failure/)
|
255
|
+
|
256
|
+
client.command(ping: 1)
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
after do
|
263
|
+
# Since we stopped monitoring on the client, close it.
|
264
|
+
ClientRegistry.instance.close_all_clients
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
217
268
|
describe 'when there is an error on monitoring connection' do
|
218
269
|
clean_slate_for_all
|
219
270
|
|
@@ -67,8 +67,9 @@ describe 'SDAM events' do
|
|
67
67
|
started_events.length.should <= 10
|
68
68
|
|
69
69
|
succeeded_events = subscriber.select_succeeded_events(Mongo::Monitoring::Event::ServerHeartbeatSucceeded)
|
70
|
-
|
71
|
-
|
70
|
+
# Since we gracefully close the client, we expect each heartbeat
|
71
|
+
# to complete.
|
72
|
+
started_events.length.should == succeeded_events.length
|
72
73
|
end
|
73
74
|
end
|
74
75
|
|
@@ -104,12 +105,10 @@ describe 'SDAM events' do
|
|
104
105
|
(succeeded_awaited = events.select(&:awaited?)).should_not be_empty
|
105
106
|
(succeeded_regular = events.reject(&:awaited?)).should_not be_empty
|
106
107
|
|
107
|
-
#
|
108
|
-
#
|
109
|
-
started_awaited.length.should
|
110
|
-
|
111
|
-
started_regular.length.should > 1
|
112
|
-
(succeeded_regular.length..succeeded_regular.length+1).should include(started_regular.length)
|
108
|
+
# Since we gracefully close the client, we expect each heartbeat
|
109
|
+
# to complete.
|
110
|
+
started_awaited.length.should == succeeded_awaited.length
|
111
|
+
started_regular.length.should == succeeded_regular.length
|
113
112
|
end
|
114
113
|
end
|
115
114
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Server selection' do
|
4
|
+
context 'replica set' do
|
5
|
+
require_topology :replica_set
|
6
|
+
# 2.6 server does not provide replSetGetConfig and hence we cannot add
|
7
|
+
# the tags to the members.
|
8
|
+
min_server_version '3.0'
|
9
|
+
|
10
|
+
context 'when mixed case tag names are used' do
|
11
|
+
# For simplicity this test assumes our Evergreen configuration:
|
12
|
+
# nodes are started from port 27017 onwards and there are more than
|
13
|
+
# one of them.
|
14
|
+
|
15
|
+
let(:desired_index) do
|
16
|
+
if authorized_client.cluster.next_primary.address.port == 27017
|
17
|
+
1
|
18
|
+
else
|
19
|
+
0
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
let(:client) do
|
24
|
+
new_local_client(SpecConfig.instance.addresses,
|
25
|
+
SpecConfig.instance.authorized_test_options.merge(
|
26
|
+
server_selection_timeout: 4,
|
27
|
+
read: {mode: :secondary, tag_sets: [nodeIndex: desired_index.to_s]},
|
28
|
+
))
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'selects the server' do
|
32
|
+
client['nonexistent'].count.should == 0
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -76,6 +76,37 @@ describe 'SRV Monitoring' do
|
|
76
76
|
require 'support/dns'
|
77
77
|
end
|
78
78
|
|
79
|
+
around do |example|
|
80
|
+
# Speed up the tests by listening on the fake ports we are using.
|
81
|
+
done = false
|
82
|
+
|
83
|
+
servers = []
|
84
|
+
threads = [27998, 27999].map do |port|
|
85
|
+
Thread.new do
|
86
|
+
server = TCPServer.open(port)
|
87
|
+
servers << server
|
88
|
+
begin
|
89
|
+
loop do
|
90
|
+
break if done
|
91
|
+
server.accept.close rescue nil
|
92
|
+
end
|
93
|
+
ensure
|
94
|
+
server.close
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
begin
|
100
|
+
example.run
|
101
|
+
ensure
|
102
|
+
done = true
|
103
|
+
servers.map(&:close)
|
104
|
+
|
105
|
+
threads.map(&:kill)
|
106
|
+
threads.map(&:join)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
79
110
|
let(:uri) do
|
80
111
|
"mongodb+srv://test-fake.test.build.10gen.cc/?tls=#{SpecConfig.instance.ssl?}&tlsInsecure=true"
|
81
112
|
end
|
@@ -88,11 +119,15 @@ describe 'SRV Monitoring' do
|
|
88
119
|
new_local_client(uri,
|
89
120
|
SpecConfig.instance.ssl_options.merge(
|
90
121
|
server_selection_timeout: 3.16,
|
91
|
-
|
122
|
+
socket_timeout: 8.11,
|
92
123
|
connect_timeout: 8.12,
|
93
124
|
resolv_options: {
|
94
|
-
|
95
|
-
|
125
|
+
# Using localhost instead of 127.0.0.1 here causes Ruby's resolv
|
126
|
+
# client to drop responses.
|
127
|
+
nameserver: '127.0.0.1',
|
128
|
+
# TODO figure out why the address & port here need to be given
|
129
|
+
# twice - if given once, DNS resolution fails.
|
130
|
+
nameserver_port: [['127.0.0.1', 5300], ['127.0.0.1', 5300]],
|
96
131
|
},
|
97
132
|
logger: logger,
|
98
133
|
),
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'SRV lookup' do
|
4
|
+
context 'end to end' do
|
5
|
+
|
6
|
+
# JRuby apparently does not implement non-blocking UDP I/O which is used
|
7
|
+
# by RubyDNS:
|
8
|
+
# NotImplementedError: recvmsg_nonblock is not implemented
|
9
|
+
fails_on_jruby
|
10
|
+
|
11
|
+
before(:all) do
|
12
|
+
require 'support/dns'
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:uri) do
|
16
|
+
"mongodb+srv://test-fake.test.build.10gen.cc/?tls=#{SpecConfig.instance.ssl?}&tlsInsecure=true"
|
17
|
+
end
|
18
|
+
|
19
|
+
let(:client) do
|
20
|
+
new_local_client(uri,
|
21
|
+
SpecConfig.instance.ssl_options.merge(
|
22
|
+
server_selection_timeout: 3.16,
|
23
|
+
timeout: 4.11,
|
24
|
+
connect_timeout: 4.12,
|
25
|
+
resolv_options: {
|
26
|
+
nameserver: 'localhost',
|
27
|
+
nameserver_port: [['localhost', 5300], ['127.0.0.1', 5300]],
|
28
|
+
},
|
29
|
+
),
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'DNS resolver not responding' do
|
34
|
+
it 'fails to create client' do
|
35
|
+
lambda do
|
36
|
+
client
|
37
|
+
end.should raise_error(Mongo::Error::NoSRVRecords, /The DNS query returned no SRV records for 'test-fake.test.build.10gen.cc'/)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'times out in connect_timeout' do
|
41
|
+
start_time = Time.now
|
42
|
+
|
43
|
+
lambda do
|
44
|
+
client
|
45
|
+
end.should raise_error(Mongo::Error::NoSRVRecords)
|
46
|
+
|
47
|
+
elapsed_time = Time.now - start_time
|
48
|
+
elapsed_time.should > 4
|
49
|
+
# The number of queries performed depends on local DNS search suffixes,
|
50
|
+
# therefore we cannot reliably assert how long it would take for this
|
51
|
+
# resolution to time out.
|
52
|
+
#elapsed_time.should < 8
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/spec/lite_spec_helper.rb
CHANGED
@@ -49,6 +49,7 @@ end
|
|
49
49
|
autoload :Benchmark, 'benchmark'
|
50
50
|
autoload :IceNine, 'ice_nine'
|
51
51
|
autoload :Timecop, 'timecop'
|
52
|
+
autoload :ChildProcess, 'childprocess'
|
52
53
|
|
53
54
|
if BSON::Environment.jruby?
|
54
55
|
require 'concurrent-ruby'
|
@@ -60,7 +61,7 @@ end
|
|
60
61
|
require 'support/utils'
|
61
62
|
require 'support/spec_config'
|
62
63
|
|
63
|
-
Mongo::Logger.logger = Logger.new(
|
64
|
+
Mongo::Logger.logger = Logger.new(STDOUT)
|
64
65
|
unless SpecConfig.instance.client_debug?
|
65
66
|
Mongo::Logger.logger.level = Logger::INFO
|
66
67
|
end
|
@@ -76,6 +77,7 @@ require 'support/crypt'
|
|
76
77
|
require 'support/json_ext_formatter'
|
77
78
|
require 'support/sdam_formatter_integration'
|
78
79
|
require 'support/background_thread_registry'
|
80
|
+
require 'support/session_registry'
|
79
81
|
|
80
82
|
if SpecConfig.instance.mri?
|
81
83
|
require 'timeout_interrupt'
|
@@ -104,7 +106,7 @@ RSpec.configure do |config|
|
|
104
106
|
end
|
105
107
|
end
|
106
108
|
|
107
|
-
if SpecConfig.instance.ci?
|
109
|
+
if SpecConfig.instance.ci?
|
108
110
|
# Allow a max of 30 seconds per test.
|
109
111
|
# Tests should take under 10 seconds ideally but it seems
|
110
112
|
# we have some that run for more than 10 seconds in CI.
|
data/spec/mongo/address_spec.rb
CHANGED
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Mongo::CachingCursor do
|
4
|
+
|
5
|
+
around do |spec|
|
6
|
+
Mongo::QueryCache.clear
|
7
|
+
Mongo::QueryCache.cache { spec.run }
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:authorized_collection) do
|
11
|
+
authorized_client['caching_cursor']
|
12
|
+
end
|
13
|
+
|
14
|
+
before do
|
15
|
+
authorized_collection.drop
|
16
|
+
end
|
17
|
+
|
18
|
+
let(:server) do
|
19
|
+
view.send(:server_selector).select_server(authorized_client.cluster)
|
20
|
+
end
|
21
|
+
|
22
|
+
let(:reply) do
|
23
|
+
view.send(:send_initial_query, server)
|
24
|
+
end
|
25
|
+
|
26
|
+
let(:cursor) do
|
27
|
+
described_class.new(view, reply, server)
|
28
|
+
end
|
29
|
+
|
30
|
+
let(:view) do
|
31
|
+
Mongo::Collection::View.new(authorized_collection)
|
32
|
+
end
|
33
|
+
|
34
|
+
before do
|
35
|
+
authorized_collection.delete_many
|
36
|
+
3.times { |i| authorized_collection.insert_one(_id: i) }
|
37
|
+
end
|
38
|
+
|
39
|
+
describe '#cached_docs' do
|
40
|
+
context 'when no query has been performed' do
|
41
|
+
it 'returns nil' do
|
42
|
+
expect(cursor.cached_docs).to be_nil
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'when a query has been performed' do
|
47
|
+
it 'returns the number of documents' do
|
48
|
+
cursor.to_a
|
49
|
+
expect(cursor.cached_docs.length).to eq(3)
|
50
|
+
expect(cursor.cached_docs).to eq([{ '_id' => 0 }, { '_id' => 1 }, { '_id' => 2 }])
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe '#try_next' do
|
56
|
+
it 'fetches the next document' do
|
57
|
+
expect(cursor.try_next).to eq('_id' => 0)
|
58
|
+
expect(cursor.try_next).to eq('_id' => 1)
|
59
|
+
expect(cursor.try_next).to eq('_id' => 2)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe '#each' do
|
64
|
+
it 'iterates the cursor' do
|
65
|
+
result = cursor.each.to_a
|
66
|
+
expect(result.length).to eq(3)
|
67
|
+
expect(result).to eq([{ '_id' => 0 }, { '_id' => 1 }, { '_id' => 2 }])
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -496,6 +496,7 @@ describe Mongo::Client do
|
|
496
496
|
end
|
497
497
|
|
498
498
|
context 'when the compressor is not supported by the driver' do
|
499
|
+
require_warning_clean
|
499
500
|
|
500
501
|
let(:options) do
|
501
502
|
{ compressors: ['snoopy'] }
|
@@ -674,7 +675,7 @@ describe Mongo::Client do
|
|
674
675
|
context 'when providing a custom logger' do
|
675
676
|
|
676
677
|
let(:logger) do
|
677
|
-
Logger.new(
|
678
|
+
Logger.new(STDOUT).tap do |l|
|
678
679
|
l.level = Logger::FATAL
|
679
680
|
end
|
680
681
|
end
|
@@ -1343,6 +1344,46 @@ describe Mongo::Client do
|
|
1343
1344
|
end
|
1344
1345
|
end
|
1345
1346
|
|
1347
|
+
context 'when setting read concern options' do
|
1348
|
+
min_server_fcv '3.2'
|
1349
|
+
|
1350
|
+
context 'when read concern is valid' do
|
1351
|
+
let(:options) do
|
1352
|
+
{ read_concern: { level: :local } }
|
1353
|
+
end
|
1354
|
+
|
1355
|
+
it 'does not warn' do
|
1356
|
+
expect(Mongo::Logger.logger).to_not receive(:warn)
|
1357
|
+
new_local_client_nmio(SpecConfig.instance.addresses, options)
|
1358
|
+
end
|
1359
|
+
end
|
1360
|
+
|
1361
|
+
context 'when read concern has an invalid key' do
|
1362
|
+
skip_if_linting
|
1363
|
+
|
1364
|
+
let(:options) do
|
1365
|
+
{ read_concern: { hello: :local } }
|
1366
|
+
end
|
1367
|
+
|
1368
|
+
it 'logs a warning' do
|
1369
|
+
expect(Mongo::Logger.logger).to receive(:warn).with(/Read concern has invalid keys: hello/)
|
1370
|
+
new_local_client_nmio(SpecConfig.instance.addresses, options)
|
1371
|
+
end
|
1372
|
+
end
|
1373
|
+
|
1374
|
+
context 'when read concern has a non-user-settable key' do
|
1375
|
+
let(:options) do
|
1376
|
+
{ read_concern: { after_cluster_time: 100 } }
|
1377
|
+
end
|
1378
|
+
|
1379
|
+
it 'raises an exception' do
|
1380
|
+
expect do
|
1381
|
+
new_local_client_nmio(SpecConfig.instance.addresses, options)
|
1382
|
+
end.to raise_error(Mongo::Error::InvalidReadConcern, 'The after_cluster_time read_concern option cannot be specified by the user')
|
1383
|
+
end
|
1384
|
+
end
|
1385
|
+
end
|
1386
|
+
|
1346
1387
|
context 'when an invalid option is provided' do
|
1347
1388
|
|
1348
1389
|
let(:options) do
|
@@ -1494,6 +1535,18 @@ describe Mongo::Client do
|
|
1494
1535
|
end
|
1495
1536
|
end
|
1496
1537
|
end
|
1538
|
+
|
1539
|
+
context ':auth_mech_properties option' do
|
1540
|
+
context 'is nil' do
|
1541
|
+
let(:options) do
|
1542
|
+
{auth_mech_properties: nil}
|
1543
|
+
end
|
1544
|
+
|
1545
|
+
it 'creates the client without the option' do
|
1546
|
+
client.options.should_not have_key(:auth_mech_properties)
|
1547
|
+
end
|
1548
|
+
end
|
1549
|
+
end
|
1497
1550
|
end
|
1498
1551
|
|
1499
1552
|
context 'when making a block client' do
|