mongo 2.9.2 → 2.10.0.rc0
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.tar.gz.sig +0 -0
- data/lib/mongo.rb +1 -0
- data/lib/mongo/auth/user/view.rb +4 -4
- data/lib/mongo/bulk_write.rb +14 -8
- data/lib/mongo/bulk_write/result.rb +1 -1
- data/lib/mongo/bulk_write/result_combiner.rb +2 -2
- data/lib/mongo/bulk_write/transformable.rb +17 -9
- data/lib/mongo/client.rb +107 -16
- data/lib/mongo/cluster.rb +47 -25
- data/lib/mongo/cluster/topology/replica_set_no_primary.rb +1 -1
- data/lib/mongo/cluster_time.rb +139 -0
- data/lib/mongo/collection.rb +84 -25
- data/lib/mongo/collection/view.rb +7 -3
- data/lib/mongo/collection/view/aggregation.rb +4 -4
- data/lib/mongo/collection/view/builder/aggregation.rb +31 -6
- data/lib/mongo/collection/view/builder/find_command.rb +4 -1
- data/lib/mongo/collection/view/builder/map_reduce.rb +4 -1
- data/lib/mongo/collection/view/change_stream.rb +54 -66
- data/lib/mongo/collection/view/iterable.rb +2 -2
- data/lib/mongo/collection/view/map_reduce.rb +6 -4
- data/lib/mongo/collection/view/readable.rb +36 -16
- data/lib/mongo/collection/view/writable.rb +68 -22
- data/lib/mongo/cursor.rb +87 -20
- data/lib/mongo/database.rb +47 -43
- data/lib/mongo/database/view.rb +54 -11
- data/lib/mongo/error.rb +13 -4
- data/lib/mongo/error/invalid_write_concern.rb +2 -2
- data/lib/mongo/error/operation_failure.rb +65 -11
- data/lib/mongo/error/parser.rb +41 -8
- data/lib/mongo/grid/fs_bucket.rb +26 -6
- data/lib/mongo/grid/stream/read.rb +9 -2
- data/lib/mongo/grid/stream/write.rb +21 -5
- data/lib/mongo/index/view.rb +3 -3
- data/lib/mongo/lint.rb +10 -3
- data/lib/mongo/operation.rb +2 -0
- data/lib/mongo/operation/aggregate/result.rb +19 -6
- data/lib/mongo/operation/collections_info.rb +1 -1
- data/lib/mongo/operation/get_more/result.rb +9 -0
- data/lib/mongo/operation/list_collections/command.rb +1 -3
- data/lib/mongo/operation/list_collections/op_msg.rb +1 -2
- data/lib/mongo/operation/parallel_scan/command.rb +4 -1
- data/lib/mongo/operation/parallel_scan/op_msg.rb +4 -1
- data/lib/mongo/operation/result.rb +27 -4
- data/lib/mongo/operation/shared/executable.rb +19 -5
- data/lib/mongo/operation/shared/executable_no_validate.rb +1 -2
- data/lib/mongo/operation/shared/executable_transaction_label.rb +0 -9
- data/lib/mongo/operation/shared/polymorphic_result.rb +9 -1
- data/lib/mongo/operation/shared/result/aggregatable.rb +2 -2
- data/lib/mongo/operation/shared/sessions_supported.rb +42 -32
- data/lib/mongo/operation/shared/specifiable.rb +40 -0
- data/lib/mongo/operation/shared/unpinnable.rb +39 -0
- data/lib/mongo/operation/shared/write.rb +1 -1
- data/lib/mongo/protocol/update.rb +6 -2
- data/lib/mongo/retryable.rb +79 -39
- data/lib/mongo/server/connection.rb +10 -3
- data/lib/mongo/server/description.rb +25 -1
- data/lib/mongo/server/monitor/connection.rb +1 -1
- data/lib/mongo/server_selector.rb +10 -0
- data/lib/mongo/server_selector/selectable.rb +172 -32
- data/lib/mongo/session.rb +654 -581
- data/lib/mongo/session/session_pool.rb +1 -1
- data/lib/mongo/socket.rb +7 -28
- data/lib/mongo/socket/ssl.rb +26 -1
- data/lib/mongo/socket/tcp.rb +3 -0
- data/lib/mongo/socket/unix.rb +3 -0
- data/lib/mongo/uri.rb +112 -265
- data/lib/mongo/uri/srv_protocol.rb +4 -1
- data/lib/mongo/version.rb +1 -1
- data/lib/mongo/write_concern.rb +10 -29
- data/lib/mongo/write_concern/acknowledged.rb +12 -0
- data/lib/mongo/write_concern/base.rb +17 -13
- data/lib/mongo/write_concern/unacknowledged.rb +12 -0
- data/spec/atlas/atlas_connectivity_spec.rb +7 -37
- data/spec/atlas/operations_spec.rb +25 -0
- data/spec/integration/change_stream_examples_spec.rb +45 -31
- data/spec/integration/change_stream_spec.rb +305 -5
- data/spec/integration/client_spec.rb +44 -0
- data/spec/integration/command_monitoring_spec.rb +1 -0
- data/spec/integration/command_spec.rb +7 -1
- data/spec/integration/mmapv1_spec.rb +28 -0
- data/spec/integration/mongos_pinning_spec.rb +34 -0
- data/spec/integration/operation_failure_code_spec.rb +2 -2
- data/spec/integration/{read_concern.rb → read_concern_spec.rb} +7 -1
- data/spec/integration/read_preference_spec.rb +485 -0
- data/spec/integration/retryable_writes_spec.rb +8 -19
- data/spec/integration/sdam_error_handling_spec.rb +1 -1
- data/spec/integration/sdam_events_spec.rb +2 -2
- data/spec/integration/server_description_spec.rb +14 -17
- data/spec/integration/server_selector_spec.rb +7 -3
- data/spec/integration/server_spec.rb +48 -0
- data/spec/integration/ssl_uri_options_spec.rb +1 -1
- data/spec/integration/step_down_spec.rb +10 -4
- data/spec/integration/transactions_examples_spec.rb +11 -10
- data/spec/lite_spec_helper.rb +19 -16
- data/spec/mongo/auth/scram/negotiation_spec.rb +11 -8
- data/spec/mongo/bulk_write/ordered_combiner_spec.rb +6 -6
- data/spec/mongo/bulk_write/unordered_combiner_spec.rb +4 -4
- data/spec/mongo/bulk_write_spec.rb +12 -2
- data/spec/mongo/client_construction_spec.rb +160 -8
- data/spec/mongo/client_spec.rb +5 -4
- data/spec/mongo/cluster_spec.rb +6 -6
- data/spec/mongo/cluster_time_spec.rb +148 -0
- data/spec/mongo/collection/view/aggregation_spec.rb +34 -15
- data/spec/mongo/collection/view/change_stream_spec.rb +62 -3
- data/spec/mongo/collection/view/map_reduce_spec.rb +7 -5
- data/spec/mongo/collection/view/readable_spec.rb +4 -4
- data/spec/mongo/collection_spec.rb +331 -14
- data/spec/mongo/cursor_spec.rb +117 -5
- data/spec/mongo/database_spec.rb +240 -8
- data/spec/mongo/error/operation_failure_spec.rb +47 -1
- data/spec/mongo/error/parser_spec.rb +160 -23
- data/spec/mongo/operation/insert/bulk_spec.rb +2 -1
- data/spec/mongo/operation/result_spec.rb +27 -0
- data/spec/mongo/operation/update/bulk_spec.rb +1 -0
- data/spec/mongo/retryable_spec.rb +2 -0
- data/spec/mongo/server/app_metadata_spec.rb +2 -2
- data/spec/mongo/server/connection_spec.rb +13 -17
- data/spec/mongo/server/monitor/connection_spec.rb +13 -10
- data/spec/mongo/server_selector_spec.rb +34 -2
- data/spec/mongo/session/session_pool_spec.rb +14 -3
- data/spec/mongo/session_spec.rb +3 -3
- data/spec/mongo/session_transaction_spec.rb +4 -3
- data/spec/mongo/socket/ssl_spec.rb +19 -5
- data/spec/mongo/socket_spec.rb +1 -62
- data/spec/mongo/uri/srv_protocol_spec.rb +14 -20
- data/spec/mongo/uri_option_parsing_spec.rb +94 -8
- data/spec/mongo/uri_spec.rb +23 -10
- data/spec/mongo/write_concern_spec.rb +56 -3
- data/spec/spec_tests/change_streams_spec.rb +2 -1
- data/spec/spec_tests/cmap_spec.rb +1 -1
- data/spec/spec_tests/crud_spec.rb +12 -2
- data/spec/spec_tests/data/change_streams/change-streams-errors.yml +24 -1
- data/spec/spec_tests/data/change_streams/change-streams.yml +172 -3
- data/spec/spec_tests/data/command_monitoring/bulkWrite.yml +1 -1
- data/spec/spec_tests/data/command_monitoring/updateMany.yml +0 -2
- data/spec/spec_tests/data/command_monitoring/updateOne.yml +0 -5
- data/spec/spec_tests/data/crud/read/aggregate-out.yml +0 -6
- data/spec/spec_tests/data/crud/read/count-empty.yml +29 -0
- data/spec/spec_tests/data/crud/write/bulkWrite-arrayFilters.yml +1 -0
- data/spec/spec_tests/data/crud/write/bulkWrite-collation.yml +101 -0
- data/spec/spec_tests/data/crud/write/bulkWrite.yml +401 -0
- data/spec/spec_tests/data/crud/write/insertMany.yml +58 -2
- data/spec/spec_tests/data/crud/write/updateMany-arrayFilters.yml +3 -0
- data/spec/spec_tests/data/crud/write/updateOne-arrayFilters.yml +6 -1
- data/spec/spec_tests/data/crud_v2/aggregate-merge.yml +103 -0
- data/spec/spec_tests/data/crud_v2/aggregate-out-readConcern.yml +110 -0
- data/spec/spec_tests/data/crud_v2/bulkWrite-arrayFilters.yml +81 -0
- data/spec/spec_tests/data/crud_v2/db-aggregate.yml +38 -0
- data/spec/spec_tests/data/crud_v2/updateWithPipelines.yml +92 -0
- data/spec/spec_tests/data/retryable_writes/insertOne-serverErrors.yml +2 -2
- data/spec/spec_tests/data/transactions/abort.yml +3 -0
- data/spec/spec_tests/data/transactions/bulk.yml +3 -8
- data/spec/spec_tests/data/transactions/causal-consistency.yml +3 -8
- data/spec/spec_tests/data/transactions/commit.yml +3 -1
- data/spec/spec_tests/data/transactions/count.yml +3 -0
- data/spec/spec_tests/data/transactions/delete.yml +3 -0
- data/spec/spec_tests/data/transactions/error-labels.yml +4 -1
- data/spec/spec_tests/data/transactions/errors-client.yml +56 -0
- data/spec/spec_tests/data/transactions/errors.yml +3 -0
- data/spec/spec_tests/data/transactions/findOneAndDelete.yml +3 -0
- data/spec/spec_tests/data/transactions/findOneAndReplace.yml +3 -0
- data/spec/spec_tests/data/transactions/findOneAndUpdate.yml +3 -0
- data/spec/spec_tests/data/transactions/insert.yml +3 -0
- data/spec/spec_tests/data/transactions/isolation.yml +3 -0
- data/spec/spec_tests/data/transactions/mongos-pin-auto.yml +1671 -0
- data/spec/spec_tests/data/transactions/mongos-recovery-token.yml +347 -0
- data/spec/spec_tests/data/transactions/pin-mongos.yml +557 -0
- data/spec/spec_tests/data/transactions/read-concern.yml +3 -0
- data/spec/spec_tests/data/transactions/read-pref.yml +3 -0
- data/spec/spec_tests/data/transactions/reads.yml +3 -0
- data/spec/spec_tests/data/transactions/retryable-abort.yml +5 -2
- data/spec/spec_tests/data/transactions/retryable-commit.yml +4 -1
- data/spec/spec_tests/data/transactions/retryable-writes.yml +3 -0
- data/spec/spec_tests/data/transactions/run-command.yml +3 -0
- data/spec/spec_tests/data/transactions/transaction-options.yml +6 -0
- data/spec/spec_tests/data/transactions/update.yml +3 -8
- data/spec/spec_tests/data/transactions/write-concern.yml +348 -38
- data/spec/spec_tests/data/transactions_api/callback-aborts.yml +6 -0
- data/spec/spec_tests/data/transactions_api/callback-commits.yml +5 -0
- data/spec/spec_tests/data/transactions_api/callback-retry.yml +7 -2
- data/spec/spec_tests/data/transactions_api/commit-retry.yml +70 -15
- data/spec/spec_tests/data/transactions_api/commit-transienttransactionerror-4.2.yml +3 -0
- data/spec/spec_tests/data/transactions_api/commit-transienttransactionerror.yml +3 -0
- data/spec/spec_tests/data/transactions_api/commit-writeconcernerror.yml +59 -109
- data/spec/spec_tests/data/transactions_api/commit.yml +5 -0
- data/spec/spec_tests/data/transactions_api/transaction-options.yml +10 -0
- data/spec/spec_tests/retryable_reads_spec.rb +5 -2
- data/spec/spec_tests/retryable_writes_spec.rb +5 -2
- data/spec/spec_tests/sdam_monitoring_spec.rb +3 -3
- data/spec/spec_tests/sdam_spec.rb +2 -2
- data/spec/spec_tests/transactions_api_spec.rb +1 -67
- data/spec/spec_tests/transactions_spec.rb +2 -66
- data/spec/support/authorization.rb +4 -0
- data/spec/support/change_streams.rb +30 -10
- data/spec/support/change_streams/operation.rb +27 -0
- data/spec/support/client_registry.rb +44 -25
- data/spec/support/cluster_config.rb +25 -14
- data/spec/support/cluster_tools.rb +32 -10
- data/spec/support/command_monitoring.rb +1 -1
- data/spec/support/common_shortcuts.rb +30 -0
- data/spec/support/connection_string.rb +8 -3
- data/spec/support/constraints.rb +34 -0
- data/spec/support/crud.rb +31 -16
- data/spec/support/crud/context.rb +23 -0
- data/spec/support/crud/operation.rb +311 -14
- data/spec/support/crud/spec.rb +2 -1
- data/spec/support/crud/test.rb +24 -27
- data/spec/support/crud/test_base.rb +22 -0
- data/spec/support/crud/verifier.rb +15 -1
- data/spec/support/event_subscriber.rb +12 -0
- data/spec/support/sdam_formatter_integration.rb +12 -6
- data/spec/support/shared/server_selector.rb +10 -0
- data/spec/support/shared/session.rb +13 -12
- data/spec/support/spec_config.rb +32 -22
- data/spec/support/spec_setup.rb +2 -2
- data/spec/support/transactions.rb +87 -0
- data/spec/support/transactions/context.rb +33 -0
- data/spec/support/transactions/operation.rb +99 -349
- data/spec/support/transactions/spec.rb +1 -3
- data/spec/support/transactions/test.rb +110 -49
- data/spec/support/utils.rb +74 -1
- metadata +52 -10
- metadata.gz.sig +0 -0
- data/spec/support/crud/read.rb +0 -265
- data/spec/support/crud/write.rb +0 -284
data/spec/support/spec_setup.rb
CHANGED
@@ -29,12 +29,12 @@ class SpecSetup
|
|
29
29
|
raise
|
30
30
|
end
|
31
31
|
end
|
32
|
-
admin_unauthorized_client.close
|
32
|
+
admin_unauthorized_client.close(true)
|
33
33
|
|
34
34
|
# Adds the test user to the test database with permissions on all
|
35
35
|
# databases that will be used in the test suite.
|
36
36
|
create_user(admin_authorized_test_client, SpecConfig.instance.test_user)
|
37
|
-
admin_authorized_test_client.close
|
37
|
+
admin_authorized_test_client.close(true)
|
38
38
|
end
|
39
39
|
|
40
40
|
def create_user(client, user)
|
@@ -12,6 +12,93 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
+
require 'support/transactions/context'
|
15
16
|
require 'support/transactions/operation'
|
16
17
|
require 'support/transactions/spec'
|
17
18
|
require 'support/transactions/test'
|
19
|
+
|
20
|
+
def define_transactions_spec_tests(test_paths)
|
21
|
+
|
22
|
+
test_paths.each do |file|
|
23
|
+
|
24
|
+
spec = Mongo::Transactions::Spec.new(file)
|
25
|
+
|
26
|
+
context(spec.description) do
|
27
|
+
require_wired_tiger
|
28
|
+
|
29
|
+
define_spec_tests_with_requirements(spec) do |req|
|
30
|
+
spec.tests.each do |test|
|
31
|
+
|
32
|
+
before do
|
33
|
+
if test.multiple_mongoses?
|
34
|
+
unless SpecConfig.instance.addresses.length > 1
|
35
|
+
skip "Test requires multiple mongoses"
|
36
|
+
end
|
37
|
+
else
|
38
|
+
# Many transaction spec tests that do not specifically deal with
|
39
|
+
# sharded transactions fail when run against a multi-mongos cluster
|
40
|
+
if SpecConfig.instance.addresses.length > 1
|
41
|
+
skip "Test does not specify multiple mongoses"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context(test.description) do
|
47
|
+
|
48
|
+
if test.skip_reason
|
49
|
+
before(:all) do
|
50
|
+
skip test.skip_reason
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
before(:all) do
|
55
|
+
if req.satisfied?
|
56
|
+
test.setup_test
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
after(:all) do
|
61
|
+
if req.satisfied?
|
62
|
+
test.teardown_test
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
let(:results) do
|
67
|
+
$tx_spec_results_cache ||= {}
|
68
|
+
$tx_spec_results_cache[test.object_id] ||= test.run
|
69
|
+
end
|
70
|
+
|
71
|
+
let(:verifier) { Mongo::CRUD::Verifier.new(test) }
|
72
|
+
|
73
|
+
it 'returns the correct results' do
|
74
|
+
verifier.verify_operation_result(test.expected_results, results[:results])
|
75
|
+
end
|
76
|
+
|
77
|
+
if test.outcome && test.outcome.collection_data?
|
78
|
+
it 'has the correct data in the collection' do
|
79
|
+
results
|
80
|
+
verifier.verify_collection_data(
|
81
|
+
test.outcome.collection_data,
|
82
|
+
results[:contents])
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
if test.expectations
|
87
|
+
it 'has the correct number of command_started events' do
|
88
|
+
verifier.verify_command_started_event_count(
|
89
|
+
test.expectations, results[:events])
|
90
|
+
end
|
91
|
+
|
92
|
+
test.expectations.each_with_index do |expectation, i|
|
93
|
+
it "has the correct command_started event #{i}" do
|
94
|
+
verifier.verify_command_started_event(
|
95
|
+
test.expectations, results[:events], i)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# Copyright (C) 2019 MongoDB, Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
module Mongo
|
16
|
+
module Transactions
|
17
|
+
Context = Struct.new(
|
18
|
+
:session0,
|
19
|
+
:session1,
|
20
|
+
:session,
|
21
|
+
) do
|
22
|
+
def transform_arguments(arguments)
|
23
|
+
arguments.dup.tap do |out|
|
24
|
+
[:session].each do |key|
|
25
|
+
if out[key]
|
26
|
+
out[key] = send(key)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -14,126 +14,42 @@
|
|
14
14
|
|
15
15
|
module Mongo
|
16
16
|
module Transactions
|
17
|
-
class Operation
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
'
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
'insertMany' => :insert_many,
|
31
|
-
'insertOne' => :insert_one,
|
32
|
-
'replaceOne' => :replace_one,
|
33
|
-
'updateMany' => :update_many,
|
34
|
-
'updateOne' => :update_one,
|
35
|
-
'findOneAndDelete' => :find_one_and_delete,
|
36
|
-
'findOneAndReplace' => :find_one_and_replace,
|
37
|
-
'findOneAndUpdate' => :find_one_and_update,
|
38
|
-
'bulkWrite' => :bulk_write,
|
39
|
-
'count' => :count,
|
40
|
-
'countDocuments' => :count_documents,
|
41
|
-
'distinct' => :distinct,
|
42
|
-
'find' => :find,
|
43
|
-
'runCommand' => :run_command,
|
44
|
-
}.freeze
|
45
|
-
|
46
|
-
# Map of operation options to method names.
|
47
|
-
#
|
48
|
-
# @since 2.6.0
|
49
|
-
ARGUMENT_MAP = {
|
50
|
-
array_filters: 'arrayFilters',
|
51
|
-
batch_size: 'batchSize',
|
52
|
-
collation: 'collation',
|
53
|
-
read_preference: 'readPreference',
|
54
|
-
document: 'document',
|
55
|
-
field_name: 'fieldName',
|
56
|
-
filter: 'filter',
|
57
|
-
ordered: 'ordered',
|
58
|
-
pipeline: 'pipeline',
|
59
|
-
projection: 'projection',
|
60
|
-
replacement: 'replacement',
|
61
|
-
return_document: 'returnDocument',
|
62
|
-
session: 'session',
|
63
|
-
sort: 'sort',
|
64
|
-
update: 'update',
|
65
|
-
upsert: 'upsert'
|
66
|
-
}.freeze
|
67
|
-
|
68
|
-
# The operation name.
|
69
|
-
#
|
70
|
-
# @return [ String ] name The operation name.
|
71
|
-
#
|
72
|
-
# @since 2.6.0
|
73
|
-
attr_reader :name
|
74
|
-
|
75
|
-
# Instantiate the operation.
|
76
|
-
#
|
77
|
-
# @return [ Hash ] spec The operation spec.
|
78
|
-
#
|
79
|
-
# @since 2.6.0
|
80
|
-
def initialize(spec, session0, session1, transaction_session=nil)
|
81
|
-
@spec = spec
|
82
|
-
@name = spec['name']
|
83
|
-
@session0 = session0
|
84
|
-
@session1 = session1
|
85
|
-
@arguments = case spec['arguments'] && spec['arguments']['session']
|
86
|
-
when 'session0'
|
87
|
-
spec['arguments'].merge('session' => @session0)
|
88
|
-
when 'session1'
|
89
|
-
spec['arguments'].merge('session' => @session1)
|
90
|
-
else
|
91
|
-
args = spec['arguments'] || {}
|
92
|
-
if transaction_session
|
93
|
-
args = args.merge('session' => transaction_session)
|
94
|
-
end
|
95
|
-
args
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
attr_reader :arguments
|
17
|
+
class Operation < Mongo::CRUD::Operation
|
18
|
+
include RSpec::Matchers
|
19
|
+
|
20
|
+
def execute(target, session0, session1, active_session=nil)
|
21
|
+
session = case arguments && arguments['session']
|
22
|
+
when 'session0'
|
23
|
+
session0
|
24
|
+
when 'session1'
|
25
|
+
session1
|
26
|
+
else
|
27
|
+
# active session could be nil
|
28
|
+
active_session
|
29
|
+
end
|
100
30
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
#
|
106
|
-
# @param [ Collection ] collection The collection to execute
|
107
|
-
# the operation on.
|
108
|
-
#
|
109
|
-
# @return [ Result ] The result of executing the operation.
|
110
|
-
#
|
111
|
-
# @since 2.6.0
|
112
|
-
def execute(collection)
|
113
|
-
# Determine which object the operation method should be called on.
|
114
|
-
obj = case object
|
115
|
-
when 'session0'
|
116
|
-
@session0
|
117
|
-
when 'session1'
|
118
|
-
@session1
|
119
|
-
when 'database'
|
120
|
-
collection.database
|
121
|
-
else
|
122
|
-
collection = collection.with(read: read_preference) if collection_read_preference
|
123
|
-
collection = collection.with(read_concern: read_concern) if read_concern
|
124
|
-
collection = collection.with(write: write_concern) if write_concern
|
125
|
-
collection
|
126
|
-
end
|
31
|
+
context = Context.new(
|
32
|
+
session0,
|
33
|
+
session1,
|
34
|
+
session)
|
127
35
|
|
128
|
-
|
129
|
-
|
36
|
+
op_name = Utils.underscore(name).to_sym
|
37
|
+
if op_name == :with_transaction
|
38
|
+
args = [target]
|
130
39
|
else
|
131
40
|
args = []
|
132
41
|
end
|
133
42
|
if op_name.nil?
|
134
43
|
raise "Unknown operation #{name}"
|
135
44
|
end
|
136
|
-
send(op_name,
|
45
|
+
result = send(op_name, target, context, *args)
|
46
|
+
if result
|
47
|
+
if result.is_a?(Hash)
|
48
|
+
result = result.dup
|
49
|
+
result['error'] = false
|
50
|
+
end
|
51
|
+
end
|
52
|
+
result
|
137
53
|
rescue Mongo::Error::OperationFailure => e
|
138
54
|
err_doc = e.instance_variable_get(:@result).send(:first_document)
|
139
55
|
error_code_name = err_doc['codeName'] || err_doc['writeConcernError'] && err_doc['writeConcernError']['codeName']
|
@@ -142,55 +58,81 @@ module Mongo
|
|
142
58
|
# but does return the error code (or we can parse the error code
|
143
59
|
# out of the message).
|
144
60
|
# https://jira.mongodb.org/browse/SERVER-39706
|
145
|
-
|
146
|
-
error_code_name = 'DuplicateKey'
|
147
|
-
else
|
148
|
-
warn "Error without error code name: #{e.code}"
|
149
|
-
end
|
61
|
+
warn "Error without error code name: #{e.code}"
|
150
62
|
end
|
151
63
|
|
152
64
|
{
|
153
|
-
'
|
65
|
+
'errorCode' => e.code,
|
66
|
+
'errorCodeName' => e.code_name,
|
154
67
|
'errorContains' => e.message,
|
155
68
|
'errorLabels' => e.labels,
|
156
69
|
'exception' => e,
|
70
|
+
'error' => true,
|
157
71
|
}
|
158
72
|
rescue Mongo::Error => e
|
159
73
|
{
|
160
74
|
'errorContains' => e.message,
|
161
75
|
'errorLabels' => e.labels,
|
162
76
|
'exception' => e,
|
77
|
+
'error' => true,
|
78
|
+
}
|
79
|
+
# We do not have a base class for client side BSON-related errors.
|
80
|
+
# See https://jira.mongodb.org/browse/RUBY-1806.
|
81
|
+
# Rescue this particular exception for the time being.
|
82
|
+
rescue BSON::String::IllegalKey => e
|
83
|
+
{
|
84
|
+
'exception' => e,
|
85
|
+
'clientError' => true,
|
86
|
+
'error' => true,
|
163
87
|
}
|
164
88
|
end
|
165
89
|
|
166
90
|
private
|
167
91
|
|
168
|
-
|
169
|
-
|
92
|
+
# operations
|
93
|
+
|
94
|
+
def run_command(database, context)
|
95
|
+
# Convert the first key (i.e. the command name) to a symbol.
|
96
|
+
cmd = arguments['command'].dup
|
97
|
+
command_name = cmd.first.first
|
98
|
+
command_value = cmd.delete(command_name)
|
99
|
+
cmd = { command_name.to_sym => command_value }.merge(cmd)
|
100
|
+
|
101
|
+
opts = Utils.snakeize_hash(context.transform_arguments(options)).dup
|
102
|
+
opts[:read] = opts.delete(:read_preference)
|
103
|
+
database.command(cmd, opts).documents.first
|
104
|
+
end
|
105
|
+
|
106
|
+
def start_transaction(session, context)
|
107
|
+
session.start_transaction(Utils.convert_operation_options(arguments['options']))
|
108
|
+
nil
|
170
109
|
end
|
171
110
|
|
172
|
-
def commit_transaction(session)
|
173
|
-
session.commit_transaction
|
111
|
+
def commit_transaction(session, context)
|
112
|
+
session.commit_transaction
|
113
|
+
nil
|
174
114
|
end
|
175
115
|
|
176
|
-
def abort_transaction(session)
|
177
|
-
session.abort_transaction
|
116
|
+
def abort_transaction(session, context)
|
117
|
+
session.abort_transaction
|
118
|
+
nil
|
178
119
|
end
|
179
120
|
|
180
|
-
def with_transaction(session, collection)
|
181
|
-
unless callback =
|
121
|
+
def with_transaction(session, context, collection)
|
122
|
+
unless callback = arguments['callback']
|
182
123
|
raise ArgumentError, 'with_transaction requires a callback to be present'
|
183
124
|
end
|
184
125
|
|
185
|
-
if
|
186
|
-
options = Utils.snakeize_hash(
|
126
|
+
if arguments['options']
|
127
|
+
options = Utils.snakeize_hash(arguments['options'])
|
187
128
|
else
|
188
129
|
options = nil
|
189
130
|
end
|
190
131
|
session.with_transaction(options) do
|
191
132
|
callback['operations'].each do |op_spec|
|
192
|
-
op = Operation.new(
|
193
|
-
|
133
|
+
op = Operation.new(@crud_test, op_spec)
|
134
|
+
target = @crud_test.resolve_target(@crud_test.test_client, op)
|
135
|
+
rv = op.execute(target, context.session0, context.session1, session)
|
194
136
|
if rv && rv['exception']
|
195
137
|
raise rv['exception']
|
196
138
|
end
|
@@ -198,237 +140,45 @@ module Mongo
|
|
198
140
|
end
|
199
141
|
end
|
200
142
|
|
201
|
-
def
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
command_value = cmd.delete(command_name)
|
206
|
-
cmd = { command_name.to_sym => command_value }.merge(cmd)
|
207
|
-
|
208
|
-
opts = Utils.snakeize_hash(options)
|
209
|
-
opts[:read] = opts.delete(:read_preference)
|
210
|
-
database.command(cmd, opts).documents.first
|
211
|
-
end
|
212
|
-
|
213
|
-
def aggregate(collection)
|
214
|
-
collection.aggregate(pipeline, options).to_a
|
215
|
-
end
|
216
|
-
|
217
|
-
def bulk_write(collection)
|
218
|
-
result = collection.bulk_write(requests, options)
|
219
|
-
return_doc = {}
|
220
|
-
return_doc['deletedCount'] = result.deleted_count || 0
|
221
|
-
return_doc['insertedIds'] = result.inserted_ids if result.inserted_ids
|
222
|
-
return_doc['upsertedId'] = result.upserted_id if upsert
|
223
|
-
return_doc['upsertedCount'] = result.upserted_count || 0
|
224
|
-
return_doc['matchedCount'] = result.matched_count || 0
|
225
|
-
return_doc['modifiedCount'] = result.modified_count || 0
|
226
|
-
return_doc['upsertedIds'] = result.upserted_ids if result.upserted_ids
|
227
|
-
return_doc
|
228
|
-
end
|
229
|
-
|
230
|
-
def count(collection)
|
231
|
-
collection.count(filter, options).to_s
|
232
|
-
end
|
233
|
-
|
234
|
-
def count_documents(collection)
|
235
|
-
collection.count_documents(filter, options)
|
236
|
-
end
|
237
|
-
|
238
|
-
def delete_many(collection)
|
239
|
-
result = collection.delete_many(filter, options)
|
240
|
-
{ 'deletedCount' => result.deleted_count }
|
241
|
-
end
|
242
|
-
|
243
|
-
def delete_one(collection)
|
244
|
-
result = collection.delete_one(filter, options)
|
245
|
-
{ 'deletedCount' => result.deleted_count }
|
246
|
-
end
|
247
|
-
|
248
|
-
def distinct(collection)
|
249
|
-
collection.distinct(field_name, filter, options)
|
250
|
-
end
|
251
|
-
|
252
|
-
def find(collection)
|
253
|
-
opts = modifiers ? options.merge(modifiers: BSON::Document.new(modifiers)) : options
|
254
|
-
collection.find(filter, opts).to_a
|
255
|
-
end
|
256
|
-
|
257
|
-
def insert_many(collection)
|
258
|
-
result = collection.insert_many(documents, options)
|
259
|
-
{ 'insertedIds' => result.inserted_ids }
|
143
|
+
def assert_session_transaction_state(collection, context)
|
144
|
+
session = context.send(arguments['session'])
|
145
|
+
actual_state = session.instance_variable_get('@state').to_s.sub(/^transaction_|_transaction$/, '').sub(/^no$/, 'none')
|
146
|
+
expect(actual_state).to eq(arguments['state'])
|
260
147
|
end
|
261
148
|
|
262
|
-
def
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
def update_return_doc(result)
|
268
|
-
return_doc = {}
|
269
|
-
return_doc['upsertedId'] = result.upserted_id if upsert
|
270
|
-
return_doc['upsertedCount'] = result.upserted_count
|
271
|
-
return_doc['matchedCount'] = result.matched_count
|
272
|
-
return_doc['modifiedCount'] = result.modified_count if result.modified_count
|
273
|
-
return_doc
|
274
|
-
end
|
275
|
-
|
276
|
-
def replace_one(collection)
|
277
|
-
result = collection.replace_one(filter, replacement, options)
|
278
|
-
update_return_doc(result)
|
279
|
-
end
|
280
|
-
|
281
|
-
def update_many(collection)
|
282
|
-
result = collection.update_many(filter, update, options)
|
283
|
-
update_return_doc(result)
|
284
|
-
end
|
285
|
-
|
286
|
-
def update_one(collection)
|
287
|
-
result = collection.update_one(filter, update, options)
|
288
|
-
update_return_doc(result)
|
289
|
-
end
|
290
|
-
|
291
|
-
def find_one_and_delete(collection)
|
292
|
-
collection.find_one_and_delete(filter, options)
|
293
|
-
end
|
294
|
-
|
295
|
-
def find_one_and_replace(collection)
|
296
|
-
collection.find_one_and_replace(filter, replacement, options)
|
297
|
-
end
|
298
|
-
|
299
|
-
def find_one_and_update(collection)
|
300
|
-
collection.find_one_and_update(filter, update, options)
|
301
|
-
end
|
302
|
-
|
303
|
-
def object
|
304
|
-
@spec['object']
|
305
|
-
end
|
306
|
-
|
307
|
-
def options
|
308
|
-
ARGUMENT_MAP.reduce({}) do |opts, (key, value)|
|
309
|
-
arguments.key?(value) ? opts.merge!(key => send(key)) : opts
|
149
|
+
def targeted_fail_point(collection, context)
|
150
|
+
args = context.transform_arguments(options)
|
151
|
+
session = args[:session]
|
152
|
+
unless session.pinned_server
|
153
|
+
raise ArgumentError, 'Targeted fail point requires session to be pinned to a server'
|
310
154
|
end
|
311
|
-
end
|
312
|
-
|
313
|
-
def collation
|
314
|
-
arguments['collation']
|
315
|
-
end
|
316
155
|
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
def replacement
|
322
|
-
arguments['replacement']
|
323
|
-
end
|
324
|
-
|
325
|
-
def sort
|
326
|
-
arguments['sort']
|
327
|
-
end
|
328
|
-
|
329
|
-
def projection
|
330
|
-
arguments['projection']
|
331
|
-
end
|
156
|
+
client = ClusterTools.instance.direct_client(session.pinned_server.address,
|
157
|
+
database: 'admin')
|
158
|
+
client.command(arguments['failPoint'])
|
332
159
|
|
333
|
-
|
334
|
-
|
160
|
+
$disable_fail_points ||= []
|
161
|
+
$disable_fail_points << [
|
162
|
+
arguments['failPoint'],
|
163
|
+
session.pinned_server.address,
|
164
|
+
]
|
335
165
|
end
|
336
166
|
|
337
|
-
def
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
arguments['ordered']
|
343
|
-
end
|
344
|
-
|
345
|
-
def field_name
|
346
|
-
arguments['fieldName']
|
347
|
-
end
|
348
|
-
|
349
|
-
def filter
|
350
|
-
arguments['filter']
|
351
|
-
end
|
352
|
-
|
353
|
-
def pipeline
|
354
|
-
arguments['pipeline']
|
355
|
-
end
|
356
|
-
|
357
|
-
def array_filters
|
358
|
-
arguments['arrayFilters']
|
359
|
-
end
|
360
|
-
|
361
|
-
def batch_size
|
362
|
-
arguments['batchSize']
|
363
|
-
end
|
364
|
-
|
365
|
-
def session
|
366
|
-
arguments['session']
|
367
|
-
end
|
368
|
-
|
369
|
-
def requests
|
370
|
-
arguments['requests'].map do |request|
|
371
|
-
case request.keys.first
|
372
|
-
when 'insertOne' then
|
373
|
-
{ insert_one: request['insertOne']['document'] }
|
374
|
-
when 'updateOne' then
|
375
|
-
update = request['updateOne']
|
376
|
-
{ update_one: { filter: update['filter'], update: update['update'] } }
|
377
|
-
when 'name' then
|
378
|
-
bulk_request(request)
|
379
|
-
end
|
167
|
+
def assert_session_pinned(collection, context)
|
168
|
+
args = context.transform_arguments(options)
|
169
|
+
session = args[:session]
|
170
|
+
unless session.pinned_server
|
171
|
+
raise ArgumentError, 'Expected session to be pinned'
|
380
172
|
end
|
381
173
|
end
|
382
174
|
|
383
|
-
def
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
op[op_name][:update] = request['arguments']['update'] if request['arguments']['update']
|
389
|
-
op[op_name][:upsert] = request['arguments']['upsert'] if request['arguments']['upsert']
|
390
|
-
op[op_name][:replacement] = request['arguments']['replacement'] if request['arguments']['replacement']
|
391
|
-
op[op_name][:array_filters] = request['arguments']['arrayFilters'] if request['arguments']['arrayFilters']
|
392
|
-
op[op_name] = request['arguments']['document'] if request['arguments']['document']
|
393
|
-
op
|
394
|
-
end
|
395
|
-
|
396
|
-
def upsert
|
397
|
-
arguments['upsert']
|
398
|
-
end
|
399
|
-
|
400
|
-
def return_document
|
401
|
-
case arguments['returnDocument']
|
402
|
-
when 'Before'
|
403
|
-
:before
|
404
|
-
when 'After'
|
405
|
-
:after
|
175
|
+
def assert_session_unpinned(collection, context)
|
176
|
+
args = context.transform_arguments(options)
|
177
|
+
session = args[:session]
|
178
|
+
if session.pinned_server
|
179
|
+
raise ArgumentError, 'Expected session to not be pinned'
|
406
180
|
end
|
407
181
|
end
|
408
|
-
|
409
|
-
def update
|
410
|
-
arguments['update']
|
411
|
-
end
|
412
|
-
|
413
|
-
def modifiers
|
414
|
-
arguments['modifiers']
|
415
|
-
end
|
416
|
-
|
417
|
-
def read_concern
|
418
|
-
Utils.snakeize_hash(@spec['collectionOptions'] && @spec['collectionOptions']['readConcern'])
|
419
|
-
end
|
420
|
-
|
421
|
-
def write_concern
|
422
|
-
Utils.snakeize_hash(@spec['collectionOptions'] && @spec['collectionOptions']['writeConcern'])
|
423
|
-
end
|
424
|
-
|
425
|
-
def read_preference
|
426
|
-
Utils.snakeize_hash(arguments['readPreference'])
|
427
|
-
end
|
428
|
-
|
429
|
-
def collection_read_preference
|
430
|
-
Utils.snakeize_hash(@spec['collectionOptions'] && @spec['collectionOptions']['readPreference'])
|
431
|
-
end
|
432
182
|
end
|
433
183
|
end
|
434
184
|
end
|