summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Hirschhorn <max.hirschhorn@mongodb.com>2018-02-12 11:47:50 -0500
committerMax Hirschhorn <max.hirschhorn@mongodb.com>2018-02-12 11:47:50 -0500
commit3536849e28ba1d01eda1b280abd4ef62087b7107 (patch)
treeadf16c23460191c1cd681f8d42b2cc7d8b8cf876
parent2f284c453aac4ba7a5dfe257cdd688504317c2bb (diff)
downloadmongo-3536849e28ba1d01eda1b280abd4ef62087b7107.tar.gz
SERVER-32522 Clean up {read,write}Concern and readPreference overrides.
Introduces OverrideHelpers object with convenience methods for inspecting certain aggregation and map-reduce commands, as well as overriding startParallelShell(), Mongo.prototype.runCommand(), and Mongo.prototype.runCommandWithMetadata(). Also removes a number of tests that were incorrectly blacklisted from the read_concern_majority_passthrough.yml and read_concern_linearizable_passthrough.yml test suites. (cherry picked from commit 35b5b72146ca570b5c6fed8aaa7e891edf7d6a78) (cherry picked from commit e828226f4c5ab12835e10a09f104759e8fbf09f3)
-rw-r--r--buildscripts/resmokeconfig/suites/aggregation_read_concern_majority_passthrough.yml44
-rw-r--r--buildscripts/resmokeconfig/suites/change_streams.yml14
-rw-r--r--buildscripts/resmokeconfig/suites/change_streams_mongos_passthrough.yml15
-rw-r--r--buildscripts/resmokeconfig/suites/change_streams_secondary_reads.yml21
-rw-r--r--buildscripts/resmokeconfig/suites/change_streams_sharded_collections_passthrough.yml15
-rw-r--r--buildscripts/resmokeconfig/suites/read_concern_linearizable_passthrough.yml101
-rw-r--r--buildscripts/resmokeconfig/suites/read_concern_majority_passthrough.yml96
-rw-r--r--buildscripts/resmokeconfig/suites/retryable_writes_jscore_stepdown_passthrough.yml25
-rw-r--r--jstests/change_streams/change_stream_invalidation.js2
-rw-r--r--jstests/change_streams/report_latest_observed_oplog_timestamp.js2
-rw-r--r--jstests/core/batch_write_command_delete.js7
-rw-r--r--jstests/core/batch_write_command_insert.js6
-rw-r--r--jstests/core/batch_write_command_update.js6
-rw-r--r--jstests/core/collection_info_cache_race.js4
-rw-r--r--jstests/core/commands_that_do_not_write_do_not_accept_wc.js7
-rw-r--r--jstests/core/constructors.js8
-rw-r--r--jstests/core/crud_api.js6
-rw-r--r--jstests/core/dropdb_race.js7
-rw-r--r--jstests/core/error2.js6
-rw-r--r--jstests/core/eval0.js5
-rw-r--r--jstests/core/eval1.js10
-rw-r--r--jstests/core/eval3.js10
-rw-r--r--jstests/core/eval4.js12
-rw-r--r--jstests/core/eval5.js10
-rw-r--r--jstests/core/eval6.js10
-rw-r--r--jstests/core/eval7.js5
-rw-r--r--jstests/core/eval9.js10
-rw-r--r--jstests/core/eval_mr.js14
-rw-r--r--jstests/core/eval_nolock.js10
-rw-r--r--jstests/core/evala.js10
-rw-r--r--jstests/core/evalb.js8
-rw-r--r--jstests/core/evald.js12
-rw-r--r--jstests/core/evale.js10
-rw-r--r--jstests/core/evalg.js12
-rw-r--r--jstests/core/evalh.js7
-rw-r--r--jstests/core/evalj.js5
-rw-r--r--jstests/core/explain_agg_write_concern.js9
-rw-r--r--jstests/core/fsync.js2
-rw-r--r--jstests/core/geo_update_btree.js7
-rw-r--r--jstests/core/js3.js10
-rw-r--r--jstests/core/js7.js5
-rw-r--r--jstests/core/js9.js10
-rw-r--r--jstests/core/json_schema/misc_validation.js8
-rw-r--r--jstests/core/profile_insert.js7
-rw-r--r--jstests/core/recursion.js12
-rw-r--r--jstests/core/regex_not_id.js6
-rw-r--r--jstests/core/remove8.js12
-rw-r--r--jstests/core/rename4.js5
-rw-r--r--jstests/core/shell_writeconcern.js6
-rw-r--r--jstests/core/stages_delete.js7
-rw-r--r--jstests/core/storefunc.js6
-rw-r--r--jstests/core/update_multi5.js4
-rw-r--r--jstests/core/write_result.js7
-rw-r--r--jstests/libs/override_methods/auto_retry_on_network_error.js17
-rw-r--r--jstests/libs/override_methods/enable_causal_consistency.js17
-rw-r--r--jstests/libs/override_methods/enable_sessions.js17
-rw-r--r--jstests/libs/override_methods/override_helpers.js109
-rw-r--r--jstests/libs/override_methods/retry_writes_at_least_once.js17
-rw-r--r--jstests/libs/override_methods/set_read_and_write_concerns.js354
-rw-r--r--jstests/libs/override_methods/set_read_preference_secondary.js87
60 files changed, 766 insertions, 527 deletions
diff --git a/buildscripts/resmokeconfig/suites/aggregation_read_concern_majority_passthrough.yml b/buildscripts/resmokeconfig/suites/aggregation_read_concern_majority_passthrough.yml
index 1344f26cec0..2e93b600856 100644
--- a/buildscripts/resmokeconfig/suites/aggregation_read_concern_majority_passthrough.yml
+++ b/buildscripts/resmokeconfig/suites/aggregation_read_concern_majority_passthrough.yml
@@ -7,18 +7,32 @@ selector:
- jstests/aggregation/expressions/*.js
- jstests/aggregation/sources/*/*.js
exclude_files:
- - jstests/aggregation/bugs/server18198.js # Uses a mocked mongo client to test read preference.
- - jstests/aggregation/mongos_merge.js # Cannot specify write concern when
- # secondaryThrottle is not set.
- - jstests/aggregation/mongos_slaveok.js # Majority read on secondary requires afterOpTime.
- - jstests/aggregation/shard_targeting.js # Cannot specify write concern when
- # secondaryThrottle is not set.
- - jstests/aggregation/sources/collStats/shard_host_info.js # Cannot specify write concern when
- # secondaryThrottle is not set.
- - jstests/aggregation/sources/facet/use_cases.js # Cannot specify write concern when
- # secondaryThrottle is not set.
- - jstests/aggregation/testSlave.js # Majority read on secondary requires afterOpTime.
- - jstests/aggregation/sources/out/*.js # Cannot specify write concern when secondaryThrottle is not set.
+ # This test specifies a $out stage not as the last stage in the aggregation pipeline, causing a
+ # non-local readConcern to erroneously be sent with the command.
+ - jstests/aggregation/sources/out/required_last_position.js
+ # These tests fail due to the inability to specify a writeConcern when secondaryThrottle is not
+ # set as part of the moveChunk command.
+ - jstests/aggregation/mongos_merge.js
+ - jstests/aggregation/shard_targeting.js
+ - jstests/aggregation/sources/facet/use_cases.js
+ # These test fail because afterOpTime is required to guarantee a secondary has advanced its
+ # majority-committed snapshot.
+ - jstests/aggregation/mongos_slaveok.js
+ - jstests/aggregation/testSlave.js
+ exclude_with_any_tags:
+ ##
+ # The next three tags correspond to the special errors thrown by the
+ # set_read_and_write_concerns.js override when it refuses to replace the readConcern or
+ # writeConcern of a particular command. Above each tag are the message(s) that cause the tag to be
+ # warranted.
+ ##
+ # "Cowardly refusing to override read concern of command: ..."
+ - assumes_read_concern_unchanged
+ # "Cowardly refusing to override write concern of command: ..."
+ - assumes_write_concern_unchanged
+ # "Cowardly refusing to run test with overridden write concern when it uses a command that can
+ # only perform w=1 writes: ..."
+ - requires_eval_command
executor:
config:
@@ -27,7 +41,9 @@ executor:
TestData:
defaultReadConcernLevel: majority
enableMajorityReadConcern: ''
- eval: "var testingReplication = true; load('jstests/libs/override_methods/set_read_and_write_concerns.js');"
+ eval: >-
+ var testingReplication = true;
+ load('jstests/libs/override_methods/set_read_and_write_concerns.js');
readMode: commands
hooks:
# The CheckReplDBHash hook waits until all operations have replicated to and have been applied
@@ -44,5 +60,3 @@ executor:
enableTestCommands: 1
numInitialSyncAttempts: 1
num_nodes: 2
- # Needs to be set for any ephemeral or no-journaling storage engine
- write_concern_majority_journal_default: false
diff --git a/buildscripts/resmokeconfig/suites/change_streams.yml b/buildscripts/resmokeconfig/suites/change_streams.yml
index 89d5a1c231e..238ccb05196 100644
--- a/buildscripts/resmokeconfig/suites/change_streams.yml
+++ b/buildscripts/resmokeconfig/suites/change_streams.yml
@@ -3,6 +3,20 @@ test_kind: js_test
selector:
roots:
- jstests/change_streams/**/*.js
+ exclude_with_any_tags:
+ ##
+ # The next three tags correspond to the special errors thrown by the
+ # set_read_and_write_concerns.js override when it refuses to replace the readConcern or
+ # writeConcern of a particular command. Above each tag are the message(s) that cause the tag to be
+ # warranted.
+ ##
+ # "Cowardly refusing to override read concern of command: ..."
+ - assumes_read_concern_unchanged
+ # "Cowardly refusing to override write concern of command: ..."
+ - assumes_write_concern_unchanged
+ # "Cowardly refusing to run test with overridden write concern when it uses a command that can
+ # only perform w=1 writes: ..."
+ - requires_eval_command
executor:
config:
diff --git a/buildscripts/resmokeconfig/suites/change_streams_mongos_passthrough.yml b/buildscripts/resmokeconfig/suites/change_streams_mongos_passthrough.yml
index 21fc4db91f8..b4bca33769f 100644
--- a/buildscripts/resmokeconfig/suites/change_streams_mongos_passthrough.yml
+++ b/buildscripts/resmokeconfig/suites/change_streams_mongos_passthrough.yml
@@ -7,6 +7,21 @@ selector:
# This test exercises an internal detail of mongos<->mongod communication and is not expected
# to work against a mongos.
- jstests/change_streams/report_latest_observed_oplog_timestamp.js
+ exclude_with_any_tags:
+ ##
+ # The next three tags correspond to the special errors thrown by the
+ # set_read_and_write_concerns.js override when it refuses to replace the readConcern or
+ # writeConcern of a particular command. Above each tag are the message(s) that cause the tag to be
+ # warranted.
+ ##
+ # "Cowardly refusing to override read concern of command: ..."
+ - assumes_read_concern_unchanged
+ # "Cowardly refusing to override write concern of command: ..."
+ - assumes_write_concern_unchanged
+ # "Cowardly refusing to run test with overridden write concern when it uses a command that can
+ # only perform w=1 writes: ..."
+ - requires_eval_command
+
executor:
config:
shell_options:
diff --git a/buildscripts/resmokeconfig/suites/change_streams_secondary_reads.yml b/buildscripts/resmokeconfig/suites/change_streams_secondary_reads.yml
index 35c2e62224f..7f84c527d78 100644
--- a/buildscripts/resmokeconfig/suites/change_streams_secondary_reads.yml
+++ b/buildscripts/resmokeconfig/suites/change_streams_secondary_reads.yml
@@ -9,6 +9,27 @@ selector:
- jstests/change_streams/only_wake_getmore_for_relevant_changes.js
# This test is not expected to work when run against a mongos.
- jstests/change_streams/report_latest_observed_oplog_timestamp.js
+ exclude_with_any_tags:
+ ##
+ # The next three tags correspond to the special errors thrown by the
+ # set_read_and_write_concerns.js override when it refuses to replace the readConcern or
+ # writeConcern of a particular command. Above each tag are the message(s) that cause the tag to be
+ # warranted.
+ ##
+ # "Cowardly refusing to override read concern of command: ..."
+ - assumes_read_concern_unchanged
+ # "Cowardly refusing to override write concern of command: ..."
+ - assumes_write_concern_unchanged
+ # "Cowardly refusing to run test with overridden write concern when it uses a command that can
+ # only perform w=1 writes: ..."
+ - requires_eval_command
+ ##
+ # The next tag corresponds to the special error thrown by the set_read_preference_secondary.js
+ # override when it refuses to replace the readPreference of a particular command. Above each tag
+ # are the message(s) that cause the tag to be warranted.
+ ##
+ # "Cowardly refusing to override read preference of command: ..."
+ - assumes_read_preference_unchanged
executor:
config:
diff --git a/buildscripts/resmokeconfig/suites/change_streams_sharded_collections_passthrough.yml b/buildscripts/resmokeconfig/suites/change_streams_sharded_collections_passthrough.yml
index 02c305d732d..86b444d5dc3 100644
--- a/buildscripts/resmokeconfig/suites/change_streams_sharded_collections_passthrough.yml
+++ b/buildscripts/resmokeconfig/suites/change_streams_sharded_collections_passthrough.yml
@@ -6,6 +6,21 @@ selector:
exclude_files:
# Exercises an internal detail of mongos<->mongod communication. Not expected to work on mongos.
- jstests/change_streams/report_latest_observed_oplog_timestamp.js
+ exclude_with_any_tags:
+ ##
+ # The next three tags correspond to the special errors thrown by the
+ # set_read_and_write_concerns.js override when it refuses to replace the readConcern or
+ # writeConcern of a particular command. Above each tag are the message(s) that cause the tag to be
+ # warranted.
+ ##
+ # "Cowardly refusing to override read concern of command: ..."
+ - assumes_read_concern_unchanged
+ # "Cowardly refusing to override write concern of command: ..."
+ - assumes_write_concern_unchanged
+ # "Cowardly refusing to run test with overridden write concern when it uses a command that can
+ # only perform w=1 writes: ..."
+ - requires_eval_command
+
executor:
config:
shell_options:
diff --git a/buildscripts/resmokeconfig/suites/read_concern_linearizable_passthrough.yml b/buildscripts/resmokeconfig/suites/read_concern_linearizable_passthrough.yml
index 7b1c58618f7..70fd8ae354b 100644
--- a/buildscripts/resmokeconfig/suites/read_concern_linearizable_passthrough.yml
+++ b/buildscripts/resmokeconfig/suites/read_concern_linearizable_passthrough.yml
@@ -4,78 +4,30 @@ selector:
roots:
- jstests/core/**/*.js
exclude_files:
- # Tests that won't work with an injected 'linearizable' readConcern
- # and/or an injected 'majority' writeConcern. Where a function is
- # listed the reason is we don't have a reliable solution to override
- # the write concern for that function.
- - jstests/core/batch_write_command*.js # these tests use various write concerns
- - jstests/core/bench_test*.js # benchRun() used for writes
- - jstests/core/capped_update.js # uses godinsert and can't run under replication.
- - jstests/core/crud_api.js # has specific w:0 tests
- - jstests/core/error2.js # db.eval() used
- - jstests/core/eval0.js # db.eval() used
- - jstests/core/eval1.js # db.eval() used
- - jstests/core/eval3.js # db.eval() used
- - jstests/core/eval4.js # db.eval() used
- - jstests/core/eval5.js # db.eval() used
- - jstests/core/eval6.js # db.eval() used
- - jstests/core/eval7.js # db.eval() used
- - jstests/core/eval9.js # db.eval() used
- - jstests/core/evala.js # db.eval() used
- - jstests/core/evalb.js # db.eval() used
- - jstests/core/evald.js # db.eval() used
- - jstests/core/evale.js # db.eval() used
- - jstests/core/evalg.js # db.eval() used
- - jstests/core/eval_mr.js # db.eval() used
- - jstests/core/eval_nolock.js # db.eval() used
- - jstests/core/fsync.js # Uses fsyncLock() which prevents a linearizable read from writing
- # an entry to the oplog.
- - jstests/core/geo_s2cursorlimitskip.js # drops system.profile collection and counts ops.
- - jstests/core/js3.js # db.dbEval() used
- - jstests/core/js7.js # db.eval() used
- - jstests/core/js9.js # db.eval() used
- - jstests/core/max_time_ms.js # SERVER-27665 maxTimeNeverTimeOut failPoint.
- - jstests/core/mr_merge.js # mr temp tables aren't replicated
- - jstests/core/mr_merge2.js # mr temp tables aren't replicated
- - jstests/core/mr_outreduce.js # mr temp tables aren't replicated
- - jstests/core/mr_outreduce2.js # mr temp tables aren't replicated
- - jstests/core/opcounters_active.js # off by n problem with opcounters
- - jstests/core/opcounters_write_cmd.js # off by n problem with opcounters
- - jstests/core/profile1.js # system.profile not replicated
- - jstests/core/profile2.js # system.profile not replicated
- - jstests/core/profile3.js # system.profile not replicated
- - jstests/core/profile_agg.js # system.profile not replicated
- - jstests/core/profile_count.js # system.profile not replicated
- - jstests/core/profile_delete.js # system.profile not replicated
- - jstests/core/profile_distinct.js # system.profile not replicated
- - jstests/core/profile_find.js # system.profile not replicated
- - jstests/core/profile_findandmodify.js # system.profile not replicated
- - jstests/core/profile_geonear.js # system.profile not replicated
- - jstests/core/profile_getmore.js # system.profile not replicated
- - jstests/core/profile_group.js # system.profile not replicated
- - jstests/core/profile_insert.js # system.profile not replicated
- - jstests/core/profile_list_collections.js # system.profile not replicated
- - jstests/core/profile_list_indexes.js # system.profile not replicated
- - jstests/core/profile_mapreduce.js # system.profile not replicated
- - jstests/core/profile_parallel_collection_scan.js # system.profile not replicated
- - jstests/core/profile_repair_cursor.js # system.profile not replicated
- - jstests/core/profile_sampling.js # system.profile not replicated
- - jstests/core/profile_update.js # system.profile not replicated
- - jstests/core/read_after_optime.js # verifies read after optime fails on standalone
- - jstests/core/remove8.js # db.eval() used
- - jstests/core/rename4.js # db.eval() used
- - jstests/core/shell1.js # tests setSlaveOk() variations on standalone mongod
- - jstests/core/shellkillop.js # db.eval() used
- - jstests/core/shell_writeconcern.js # checks write concern shell helpers
- - jstests/core/storefunc.js # db.eval() used
- - jstests/core/write_result.js # Tests invalid writeConcern, we shouldn't override.
- # Tests that need triaging & remediation | blacklist decision
- # Comments list possible problem point under review.
- - jstests/core/capped6.js # Uses captrunc test command.
- - jstests/core/stages_delete.js # Uses stageDebug command for deletes.
- - jstests/core/list_all_local_cursors.js # collectionless aggregation stage
- - jstests/core/list_all_local_sessions.js # collectionless aggregation stage
- - jstests/core/list_local_sessions.js # collectionless aggregation stage
+ # These tests are not expected to pass with replica-sets:
+ - jstests/core/dbadmin.js
+ - jstests/core/opcounters_write_cmd.js
+ - jstests/core/read_after_optime.js
+ - jstests/core/capped_update.js
+ # These tests use benchRun(), which isn't configured to use the overridden writeConcern.
+ - jstests/core/bench_test*.js
+ # fsync.js runs the {fsync: 1, lock: 1} command, which prevents a linearizable read from writing
+ # an entry to the oplog.
+ - jstests/core/fsync.js
+ exclude_with_any_tags:
+ ##
+ # The next three tags correspond to the special errors thrown by the
+ # set_read_and_write_concerns.js override when it refuses to replace the readConcern or
+ # writeConcern of a particular command. Above each tag are the message(s) that cause the tag to be
+ # warranted.
+ ##
+ # "Cowardly refusing to override read concern of command: ..."
+ - assumes_read_concern_unchanged
+ # "Cowardly refusing to override write concern of command: ..."
+ - assumes_write_concern_unchanged
+ # "Cowardly refusing to run test with overridden write concern when it uses a command that can
+ # only perform w=1 writes: ..."
+ - requires_eval_command
executor:
config:
@@ -83,7 +35,9 @@ executor:
global_vars:
TestData:
defaultReadConcernLevel: linearizable
- eval: "var testingReplication = true; load('jstests/libs/override_methods/set_read_and_write_concerns.js');"
+ eval: >-
+ var testingReplication = true;
+ load('jstests/libs/override_methods/set_read_and_write_concerns.js');
readMode: commands
hooks:
# The CheckReplDBHash hook waits until all operations have replicated to and have been applied
@@ -102,4 +56,3 @@ executor:
enableTestCommands: 1
numInitialSyncAttempts: 1
num_nodes: 2
- write_concern_majority_journal_default: false
diff --git a/buildscripts/resmokeconfig/suites/read_concern_majority_passthrough.yml b/buildscripts/resmokeconfig/suites/read_concern_majority_passthrough.yml
index 6e626d2e375..1dcfc8ccf7d 100644
--- a/buildscripts/resmokeconfig/suites/read_concern_majority_passthrough.yml
+++ b/buildscripts/resmokeconfig/suites/read_concern_majority_passthrough.yml
@@ -4,75 +4,27 @@ selector:
roots:
- jstests/core/**/*.js
exclude_files:
- # Tests that won't work with an injected 'majority' readConcern
- # and/or an injected 'majority' writeConcern. Where a function is
- # listed the reason is we don't have a reliable solution to override
- # the write concern for that function.
- - jstests/core/batch_write_command*.js # these tests use various write concerns
- - jstests/core/bench_test*.js # benchRun() used for writes
- - jstests/core/capped_update.js # uses godinsert and can't run under replication.
- - jstests/core/crud_api.js # has specific w:0 tests
- - jstests/core/error2.js # db.eval() used
- - jstests/core/eval0.js # db.eval() used
- - jstests/core/eval1.js # db.eval() used
- - jstests/core/eval3.js # db.eval() used
- - jstests/core/eval4.js # db.eval() used
- - jstests/core/eval5.js # db.eval() used
- - jstests/core/eval6.js # db.eval() used
- - jstests/core/eval7.js # db.eval() used
- - jstests/core/eval9.js # db.eval() used
- - jstests/core/evala.js # db.eval() used
- - jstests/core/evalb.js # db.eval() used
- - jstests/core/evald.js # db.eval() used
- - jstests/core/evale.js # db.eval() used
- - jstests/core/evalg.js # db.eval() used
- - jstests/core/eval_mr.js # db.eval() used
- - jstests/core/eval_nolock.js # db.eval() used
- - jstests/core/geo_s2cursorlimitskip.js # drops system.profile collection and counts ops.
- - jstests/core/js3.js # db.dbEval() used
- - jstests/core/js7.js # db.eval() used
- - jstests/core/js9.js # db.eval() used
- - jstests/core/mr_merge.js # mr temp tables aren't replicated
- - jstests/core/mr_merge2.js # mr temp tables aren't replicated
- - jstests/core/mr_outreduce.js # mr temp tables aren't replicated
- - jstests/core/mr_outreduce2.js # mr temp tables aren't replicated
- - jstests/core/opcounters_active.js # off by n problem with opcounters
- - jstests/core/opcounters_write_cmd.js # off by n problem with opcounters
- - jstests/core/profile1.js # system.profile not replicated
- - jstests/core/profile2.js # system.profile not replicated
- - jstests/core/profile3.js # system.profile not replicated
- - jstests/core/profile_agg.js # system.profile not replicated
- - jstests/core/profile_count.js # system.profile not replicated
- - jstests/core/profile_delete.js # system.profile not replicated
- - jstests/core/profile_distinct.js # system.profile not replicated
- - jstests/core/profile_find.js # system.profile not replicated
- - jstests/core/profile_findandmodify.js # system.profile not replicated
- - jstests/core/profile_geonear.js # system.profile not replicated
- - jstests/core/profile_getmore.js # system.profile not replicated
- - jstests/core/profile_group.js # system.profile not replicated
- - jstests/core/profile_insert.js # system.profile not replicated
- - jstests/core/profile_list_collections.js # system.profile not replicated
- - jstests/core/profile_list_indexes.js # system.profile not replicated
- - jstests/core/profile_mapreduce.js # system.profile not replicated
- - jstests/core/profile_parallel_collection_scan.js # system.profile not replicated
- - jstests/core/profile_repair_cursor.js # system.profile not replicated
- - jstests/core/profile_sampling.js # system.profile not replicated
- - jstests/core/profile_update.js # system.profile not replicated
- - jstests/core/read_after_optime.js # verifies read after optime fails on standalone
- - jstests/core/remove8.js # db.eval() used
- - jstests/core/rename4.js # db.eval() used
- - jstests/core/shell1.js # tests setSlaveOk() variations on standalone mongod
- - jstests/core/shellkillop.js # db.eval() used
- - jstests/core/shell_writeconcern.js # checks write concern shell helpers
- - jstests/core/storefunc.js # db.eval() used
- - jstests/core/write_result.js # Tests invalid writeConcern, we shouldn't override.
- # Tests that need triaging & remediation | blacklist decision
- # Comments list possible problem point under review.
- - jstests/core/capped6.js # Uses captrunc test command.
- - jstests/core/stages_delete.js # Uses stageDebug command for deletes.
- - jstests/core/list_all_local_cursors.js # collectionless aggregation stage
- - jstests/core/list_all_local_sessions.js # collectionless aggregation stage
- - jstests/core/list_local_sessions.js # collectionless aggregation stage
+ # These tests are not expected to pass with replica-sets:
+ - jstests/core/dbadmin.js
+ - jstests/core/opcounters_write_cmd.js
+ - jstests/core/read_after_optime.js
+ - jstests/core/capped_update.js
+ # These tests use benchRun(), which isn't configured to use the overridden writeConcern.
+ - jstests/core/bench_test*.js
+ exclude_with_any_tags:
+ ##
+ # The next three tags correspond to the special errors thrown by the
+ # set_read_and_write_concerns.js override when it refuses to replace the readConcern or
+ # writeConcern of a particular command. Above each tag are the message(s) that cause the tag to be
+ # warranted.
+ ##
+ # "Cowardly refusing to override read concern of command: ..."
+ - assumes_read_concern_unchanged
+ # "Cowardly refusing to override write concern of command: ..."
+ - assumes_write_concern_unchanged
+ # "Cowardly refusing to run test with overridden write concern when it uses a command that can
+ # only perform w=1 writes: ..."
+ - requires_eval_command
executor:
config:
@@ -80,7 +32,9 @@ executor:
global_vars:
TestData:
defaultReadConcernLevel: majority
- eval: "var testingReplication = true; load('jstests/libs/override_methods/set_read_and_write_concerns.js');"
+ eval: >-
+ var testingReplication = true;
+ load('jstests/libs/override_methods/set_read_and_write_concerns.js');
readMode: commands
hooks:
# The CheckReplDBHash hook waits until all operations have replicated to and have been applied
@@ -100,5 +54,3 @@ executor:
writePeriodicNoops: 1
enableMajorityReadConcern: ''
num_nodes: 2
- # Needs to be set for any ephemeral or no-journaling storage engine
- write_concern_majority_journal_default: false
diff --git a/buildscripts/resmokeconfig/suites/retryable_writes_jscore_stepdown_passthrough.yml b/buildscripts/resmokeconfig/suites/retryable_writes_jscore_stepdown_passthrough.yml
index e86873f2376..c003c2ad3ff 100644
--- a/buildscripts/resmokeconfig/suites/retryable_writes_jscore_stepdown_passthrough.yml
+++ b/buildscripts/resmokeconfig/suites/retryable_writes_jscore_stepdown_passthrough.yml
@@ -59,25 +59,21 @@ selector:
- jstests/core/validate_cmd_ns.js # Calls _exec() directly, not retryable.
exclude_with_any_tags:
- - cannot_inject_read_write_concern
-
+ ##
# The next four tags correspond to the special errors thrown by the auto_retry_on_network_error.js
- # override when it refuses to run a certain command. Above each tag are the messages that
- # warrant it.
-
+ # override when it refuses to run a certain command. Above each tag are the message(s) that cause
+ # the tag to be warranted.
+ ##
# "Refusing to run a test that issues a getMore command since if a network error occurs during
# it then we won't know whether the cursor was advanced or not"
- requires_getmore
-
# "Refusing to run a test that issues non-retryable write operations since the test likely makes
# assertions on the write results and can lead to spurious failures if a network error occurs"
- requires_non_retryable_writes
-
# "Refusing to run a test that issues commands that are not blindly retryable"
# "Refusing to run a test that issues an aggregation command with $out because it is not
# retryable"
- requires_non_retryable_commands
-
# "Refusing to run a test that issues commands that may return different values after a failover"
# "Refusing to run a test that issues an aggregation command with explain because it may return
# incomplete results"
@@ -86,6 +82,19 @@ selector:
# "Refusing to run a test that issues a mapReduce command, because it calls std::terminate() if
# interrupted by a stepdown"
- does_not_support_stepdowns
+ ##
+ # The next three tags correspond to the special errors thrown by the
+ # set_read_and_write_concerns.js override when it refuses to replace the readConcern or
+ # writeConcern of a particular command. Above each tag are the message(s) that cause the tag to be
+ # warranted.
+ ##
+ # "Cowardly refusing to override read concern of command: ..."
+ - assumes_read_concern_unchanged
+ # "Cowardly refusing to override write concern of command: ..."
+ - assumes_write_concern_unchanged
+ # "Cowardly refusing to run test with overridden write concern when it uses a command that can
+ # only perform w=1 writes: ..."
+ - requires_eval_command
executor:
config:
diff --git a/jstests/change_streams/change_stream_invalidation.js b/jstests/change_streams/change_stream_invalidation.js
index 7f3a1c0529b..02d595e445b 100644
--- a/jstests/change_streams/change_stream_invalidation.js
+++ b/jstests/change_streams/change_stream_invalidation.js
@@ -93,7 +93,7 @@
// After collection creation, we see oplog entries for the collection.
const collNowExists = assertCreateCollection(db, collDoesNotExistName);
- assert.writeOK(collNowExists.insert({_id: 0}, {writeConcern: {j: true}}));
+ assert.writeOK(collNowExists.insert({_id: 0}));
change = cst.getOneChange(aggcursor);
assert.eq(change.operationType, "insert", tojson(change));
diff --git a/jstests/change_streams/report_latest_observed_oplog_timestamp.js b/jstests/change_streams/report_latest_observed_oplog_timestamp.js
index e75c50794a1..45abd52ada9 100644
--- a/jstests/change_streams/report_latest_observed_oplog_timestamp.js
+++ b/jstests/change_streams/report_latest_observed_oplog_timestamp.js
@@ -39,7 +39,7 @@
// in the stream.
jsTestLog("Adding documents to collection.");
for (let i = 1; i < batchSize * 2; i++) {
- assert.writeOK(cursorCollection.insert({_id: i}, {writeConcern: {w: 1}}));
+ assert.writeOK(cursorCollection.insert({_id: i}));
}
// Look at one batch's worth.
diff --git a/jstests/core/batch_write_command_delete.js b/jstests/core/batch_write_command_delete.js
index 4e272571a34..0d767a9cb9d 100644
--- a/jstests/core/batch_write_command_delete.js
+++ b/jstests/core/batch_write_command_delete.js
@@ -1,7 +1,12 @@
// Cannot implicitly shard accessed collections because of following errmsg: A single
// update/delete on a sharded collection must contain an exact match on _id or contain the shard
// key.
-// @tags: [assumes_unsharded_collection, requires_non_retryable_writes]
+//
+// @tags: [
+// assumes_unsharded_collection,
+// assumes_write_concern_unchanged,
+// requires_non_retryable_writes,
+// ]
//
// Ensures that mongod respects the batch write protocols for delete
diff --git a/jstests/core/batch_write_command_insert.js b/jstests/core/batch_write_command_insert.js
index cf2907c0675..962a4eb37ad 100644
--- a/jstests/core/batch_write_command_insert.js
+++ b/jstests/core/batch_write_command_insert.js
@@ -1,6 +1,10 @@
// Cannot implicitly shard accessed collections because of not being able to create unique index
// using hashed shard key pattern.
-// @tags: [cannot_create_unique_index_when_using_hashed_shard_key]
+//
+// @tags: [
+// assumes_write_concern_unchanged,
+// cannot_create_unique_index_when_using_hashed_shard_key,
+// ]
//
// Ensures that mongod respects the batch write protocol for inserts
diff --git a/jstests/core/batch_write_command_update.js b/jstests/core/batch_write_command_update.js
index 8a37d77067e..24f86256d98 100644
--- a/jstests/core/batch_write_command_update.js
+++ b/jstests/core/batch_write_command_update.js
@@ -1,7 +1,11 @@
// Cannot implicitly shard accessed collections because of following errmsg: A single
// update/delete on a sharded collection must contain an exact match on _id or contain the shard
// key.
-// @tags: [assumes_unsharded_collection, requires_non_retryable_writes]
+// @tags: [
+// assumes_unsharded_collection,
+// assumes_write_concern_unchanged,
+// requires_non_retryable_writes,
+// ]
//
// Ensures that mongod respects the batch write protocols for updates
diff --git a/jstests/core/collection_info_cache_race.js b/jstests/core/collection_info_cache_race.js
index d57fc3340db..8fcde050e99 100644
--- a/jstests/core/collection_info_cache_race.js
+++ b/jstests/core/collection_info_cache_race.js
@@ -5,9 +5,9 @@ var coll = db.collection_info_cache_race;
coll.drop();
assert.commandWorked(db.createCollection(coll.getName(), {autoIndexId: false}));
// Fails when SERVER-16502 was not fixed, due to invariant
-assert.writeOK(coll.save({_id: false}, {writeConcern: {w: 1}}));
+assert.writeOK(coll.save({_id: false}));
coll.drop();
assert.commandWorked(db.createCollection(coll.getName(), {autoIndexId: false}));
assert.eq(null, coll.findOne());
-assert.writeOK(coll.save({_id: false}, {writeConcern: {w: 1}}));
+assert.writeOK(coll.save({_id: false}));
diff --git a/jstests/core/commands_that_do_not_write_do_not_accept_wc.js b/jstests/core/commands_that_do_not_write_do_not_accept_wc.js
index a87a38d8ae4..e2e4e55a51b 100644
--- a/jstests/core/commands_that_do_not_write_do_not_accept_wc.js
+++ b/jstests/core/commands_that_do_not_write_do_not_accept_wc.js
@@ -1,9 +1,12 @@
-// @tags: [does_not_support_stepdowns]
-
/**
* This file tests commands that do not support write concern. It passes both valid and invalid
* writeConcern fields to commands and expects the commands to fail with a writeConcernNotSupported
* error.
+ *
+ * @tags: [
+ * assumes_write_concern_unchanged,
+ * does_not_support_stepdowns,
+ * ]
*/
(function() {
diff --git a/jstests/core/constructors.js b/jstests/core/constructors.js
index 52ce8f04065..4d6f8b498cc 100644
--- a/jstests/core/constructors.js
+++ b/jstests/core/constructors.js
@@ -1,6 +1,10 @@
-// @tags: [does_not_support_stepdowns, requires_non_retryable_commands]
-
// Tests to see what validity checks are done for 10gen specific object construction
+//
+// @tags: [
+// does_not_support_stepdowns,
+// requires_eval_command,
+// requires_non_retryable_commands,
+// ]
// Takes a list of constructors and returns a new list with an extra entry for each constructor with
// "new" prepended
diff --git a/jstests/core/crud_api.js b/jstests/core/crud_api.js
index abf40389a43..3a1f7418305 100644
--- a/jstests/core/crud_api.js
+++ b/jstests/core/crud_api.js
@@ -1,7 +1,11 @@
// Cannot implicitly shard accessed collections because of following errmsg: A single
// update/delete on a sharded collection must contain an exact match on _id or contain the shard
// key.
-// @tags: [assumes_unsharded_collection]
+//
+// @tags: [
+// assumes_unsharded_collection,
+// assumes_write_concern_unchanged,
+// ]
(function() {
"use strict";
diff --git a/jstests/core/dropdb_race.js b/jstests/core/dropdb_race.js
index 9366df68a9b..40557dc8551 100644
--- a/jstests/core/dropdb_race.js
+++ b/jstests/core/dropdb_race.js
@@ -1,6 +1,9 @@
-// @tags: [does_not_support_stepdowns]
-
// test dropping a db with simultaneous commits
+//
+// @tags: [
+// assumes_write_concern_unchanged,
+// does_not_support_stepdowns,
+// ]
m = db.getMongo();
baseName = "jstests_dur_droprace";
diff --git a/jstests/core/error2.js b/jstests/core/error2.js
index 7c26f5688d7..6674d5663c6 100644
--- a/jstests/core/error2.js
+++ b/jstests/core/error2.js
@@ -1,6 +1,8 @@
-// @tags: [requires_non_retryable_commands]
-
// Test that client gets stack trace on failed invoke
+// @tags: [
+// requires_eval_command,
+// requires_non_retryable_commands,
+// ]
f = db.jstests_error2;
diff --git a/jstests/core/eval0.js b/jstests/core/eval0.js
index 4592f3c9d60..7e075feb2d5 100644
--- a/jstests/core/eval0.js
+++ b/jstests/core/eval0.js
@@ -1,4 +1,7 @@
-// @tags: [requires_non_retryable_commands]
+// @tags: [
+// requires_eval_command,
+// requires_non_retryable_commands,
+// ]
assert.writeOK(db.evalprep.insert({}), "db must exist for eval to succeed");
db.evalprep.drop();
diff --git a/jstests/core/eval1.js b/jstests/core/eval1.js
index a18b6176c5c..fca8ef7c0ec 100644
--- a/jstests/core/eval1.js
+++ b/jstests/core/eval1.js
@@ -1,6 +1,10 @@
-// Cannot implicitly shard accessed collections because unsupported use of sharded collection
-// from db.eval.
-// @tags: [assumes_unsharded_collection, requires_non_retryable_commands]
+// @tags: [
+// # Cannot implicitly shard accessed collections because unsupported use of sharded collection
+// # from db.eval.
+// assumes_unsharded_collection,
+// requires_eval_command,
+// requires_non_retryable_commands,
+// ]
t = db.eval1;
t.drop();
diff --git a/jstests/core/eval3.js b/jstests/core/eval3.js
index eacb6d70203..6c5e8b7c56d 100644
--- a/jstests/core/eval3.js
+++ b/jstests/core/eval3.js
@@ -1,6 +1,10 @@
-// Cannot implicitly shard accessed collections because unsupported use of sharded collection
-// from db.eval.
-// @tags: [assumes_unsharded_collection, requires_non_retryable_commands]
+// @tags: [
+// # Cannot implicitly shard accessed collections because unsupported use of sharded collection
+// # from db.eval.
+// assumes_unsharded_collection,
+// requires_eval_command,
+// requires_non_retryable_commands,
+// ]
t = db.eval3;
t.drop();
diff --git a/jstests/core/eval4.js b/jstests/core/eval4.js
index b7d19a4ac3b..74d25b10184 100644
--- a/jstests/core/eval4.js
+++ b/jstests/core/eval4.js
@@ -1,7 +1,11 @@
-// Cannot implicitly shard accessed collections because unsupported use of sharded collection
-// from db.eval.
-// @tags: [assumes_unsharded_collection, requires_non_retryable_commands,
-// requires_non_retryable_writes]
+// @tags: [
+// # Cannot implicitly shard accessed collections because unsupported use of sharded collection
+// # from db.eval.
+// assumes_unsharded_collection,
+// requires_eval_command,
+// requires_non_retryable_commands,
+// requires_non_retryable_writes,
+// ]
t = db.eval4;
t.drop();
diff --git a/jstests/core/eval5.js b/jstests/core/eval5.js
index fc495d86403..f3d30c49779 100644
--- a/jstests/core/eval5.js
+++ b/jstests/core/eval5.js
@@ -1,6 +1,10 @@
-// Cannot implicitly shard accessed collections because unsupported use of sharded collection
-// from db.eval.
-// @tags: [assumes_unsharded_collection, requires_non_retryable_commands]
+// @tags: [
+// # Cannot implicitly shard accessed collections because unsupported use of sharded collection
+// # from db.eval.
+// assumes_unsharded_collection,
+// requires_eval_command,
+// requires_non_retryable_commands,
+// ]
t = db.eval5;
t.drop();
diff --git a/jstests/core/eval6.js b/jstests/core/eval6.js
index 751bdbf9e34..d8ad52e95d5 100644
--- a/jstests/core/eval6.js
+++ b/jstests/core/eval6.js
@@ -1,6 +1,10 @@
-// Cannot implicitly shard accessed collections because unsupported use of sharded collection
-// from db.eval.
-// @tags: [assumes_unsharded_collection, requires_non_retryable_commands]
+// @tags: [
+// # Cannot implicitly shard accessed collections because unsupported use of sharded collection
+// # from db.eval.
+// assumes_unsharded_collection,
+// requires_eval_command,
+// requires_non_retryable_commands,
+// ]
t = db.eval6;
t.drop();
diff --git a/jstests/core/eval7.js b/jstests/core/eval7.js
index 32c37139e53..751779dba29 100644
--- a/jstests/core/eval7.js
+++ b/jstests/core/eval7.js
@@ -1,4 +1,7 @@
-// @tags: [requires_non_retryable_commands]
+// @tags: [
+// requires_eval_command,
+// requires_non_retryable_commands,
+// ]
assert.writeOK(db.evalprep.insert({}), "db must exist for eval to succeed");
db.evalprep.drop();
diff --git a/jstests/core/eval9.js b/jstests/core/eval9.js
index 2f015b46485..ce6f909dd2f 100644
--- a/jstests/core/eval9.js
+++ b/jstests/core/eval9.js
@@ -1,6 +1,10 @@
-// Cannot implicitly shard accessed collections because unsupported use of sharded collection
-// from db.eval.
-// @tags: [assumes_unsharded_collection, requires_non_retryable_commands]
+// @tags: [
+// # Cannot implicitly shard accessed collections because unsupported use of sharded collection
+// # from db.eval.
+// assumes_unsharded_collection,
+// requires_eval_command,
+// requires_non_retryable_commands,
+// ]
assert.writeOK(db.evalprep.insert({}), "db must exist for eval to succeed");
db.evalprep.drop();
diff --git a/jstests/core/eval_mr.js b/jstests/core/eval_mr.js
index 9c3ac3c7efe..33b56039321 100644
--- a/jstests/core/eval_mr.js
+++ b/jstests/core/eval_mr.js
@@ -1,9 +1,13 @@
-// Cannot implicitly shard accessed collections because of following errmsg: Cannot output to a
-// non-sharded collection because sharded collection exists already.
-// @tags: [assumes_unsharded_collection, does_not_support_stepdowns,
-// requires_non_retryable_commands]
-
// Test that the eval command can't be used to invoke the mapReduce command. SERVER-17889.
+//
+// @tags: [
+// # Cannot implicitly shard accessed collections because of following errmsg: Cannot output to a
+// # non-sharded collection because sharded collection exists already.
+// assumes_unsharded_collection,
+// does_not_support_stepdowns,
+// requires_eval_command,
+// requires_non_retryable_commands,
+// ]
(function() {
"use strict";
db.eval_mr.drop();
diff --git a/jstests/core/eval_nolock.js b/jstests/core/eval_nolock.js
index 8ae7f41f815..8ff0738110e 100644
--- a/jstests/core/eval_nolock.js
+++ b/jstests/core/eval_nolock.js
@@ -1,6 +1,10 @@
-// Cannot implicitly shard accessed collections because unsupported use of sharded collection
-// from db.eval.
-// @tags: [assumes_unsharded_collection, requires_non_retryable_commands]
+// @tags: [
+// # Cannot implicitly shard accessed collections because unsupported use of sharded collection
+// # from db.eval.
+// assumes_unsharded_collection,
+// requires_eval_command,
+// requires_non_retryable_commands,
+// ]
t = db.eval_nolock;
t.drop();
diff --git a/jstests/core/evala.js b/jstests/core/evala.js
index 00c2b548636..2d3187fdcc1 100644
--- a/jstests/core/evala.js
+++ b/jstests/core/evala.js
@@ -1,6 +1,10 @@
-// Cannot implicitly shard accessed collections because unsupported use of sharded collection
-// from db.eval.
-// @tags: [assumes_unsharded_collection, requires_non_retryable_commands]
+// @tags: [
+// # Cannot implicitly shard accessed collections because unsupported use of sharded collection
+// # from db.eval.
+// assumes_unsharded_collection,
+// requires_eval_command,
+// requires_non_retryable_commands,
+// ]
t = db.evala;
t.drop();
diff --git a/jstests/core/evalb.js b/jstests/core/evalb.js
index a3d9251af57..d92573eef1c 100644
--- a/jstests/core/evalb.js
+++ b/jstests/core/evalb.js
@@ -1,7 +1,11 @@
-// @tags: [does_not_support_stepdowns, requires_non_retryable_commands]
-
// Check the return value of a db.eval function running a database query, and ensure the function's
// contents are logged in the profile log.
+//
+// @tags: [
+// does_not_support_stepdowns,
+// requires_eval_command,
+// requires_non_retryable_commands,
+// ]
// Use a reserved database name to avoid a conflict in the parallel test suite.
var stddb = db;
diff --git a/jstests/core/evald.js b/jstests/core/evald.js
index b4317c4a24a..bb81d08dfb0 100644
--- a/jstests/core/evald.js
+++ b/jstests/core/evald.js
@@ -1,7 +1,11 @@
-// Cannot implicitly shard accessed collections because unsupported use of sharded collection
-// from db.eval.
-// @tags: [assumes_unsharded_collection, does_not_support_stepdowns,
-// requires_non_retryable_commands]
+// @tags: [
+// # Cannot implicitly shard accessed collections because unsupported use of sharded collection
+// # from db.eval.
+// assumes_unsharded_collection,
+// does_not_support_stepdowns,
+// requires_eval_command,
+// requires_non_retryable_commands,
+// ]
t = db.jstests_evald;
t.drop();
diff --git a/jstests/core/evale.js b/jstests/core/evale.js
index 8e20ee5177e..659b83fd339 100644
--- a/jstests/core/evale.js
+++ b/jstests/core/evale.js
@@ -1,6 +1,10 @@
-// Cannot implicitly shard accessed collections because unsupported use of sharded collection
-// from db.eval.
-// @tags: [assumes_unsharded_collection, requires_non_retryable_commands]
+// @tags: [
+// # Cannot implicitly shard accessed collections because unsupported use of sharded collection
+// # from db.eval.
+// assumes_unsharded_collection,
+// requires_eval_command,
+// requires_non_retryable_commands,
+// ]
t = db.jstests_evale;
t.drop();
diff --git a/jstests/core/evalg.js b/jstests/core/evalg.js
index dcb5b98f000..536fdcadb81 100644
--- a/jstests/core/evalg.js
+++ b/jstests/core/evalg.js
@@ -1,8 +1,12 @@
-// Cannot implicitly shard accessed collections because unsupported use of sharded collection
-// from db.eval.
-// @tags: [assumes_unsharded_collection, requires_non_retryable_commands]
-
// SERVER-17499: Test behavior of getMore on aggregation cursor under eval command.
+//
+// @tags: [
+// # Cannot implicitly shard accessed collections because unsupported use of sharded collection
+// # from db.eval.
+// assumes_unsharded_collection,
+// requires_eval_command,
+// requires_non_retryable_commands,
+// ]
db.evalg.drop();
for (var i = 0; i < 102; ++i) {
db.evalg.insert({});
diff --git a/jstests/core/evalh.js b/jstests/core/evalh.js
index 3881c92be80..31ea47ce891 100644
--- a/jstests/core/evalh.js
+++ b/jstests/core/evalh.js
@@ -1,7 +1,10 @@
-// @tags: [requires_non_retryable_commands]
-
/**
* Test that db.eval does not support auth.
+ *
+ * @tags: [
+ * requires_eval_command,
+ * requires_non_retryable_commands,
+ * ]
*/
(function() {
'use strict';
diff --git a/jstests/core/evalj.js b/jstests/core/evalj.js
index fa5e3305501..e58adf3c040 100644
--- a/jstests/core/evalj.js
+++ b/jstests/core/evalj.js
@@ -1,4 +1,7 @@
-// @tags: [requires_non_retryable_commands]
+// @tags: [
+// requires_eval_command,
+// requires_non_retryable_commands,
+// ]
(function() {
"use strict";
diff --git a/jstests/core/explain_agg_write_concern.js b/jstests/core/explain_agg_write_concern.js
index e007eb5d6d3..84f83cb0755 100644
--- a/jstests/core/explain_agg_write_concern.js
+++ b/jstests/core/explain_agg_write_concern.js
@@ -1,7 +1,12 @@
// Cannot implicitly shard accessed collections because unsupported use of sharded collection
// for output collection of aggregation pipeline.
-// @tags: [assumes_unsharded_collection, does_not_support_stepdowns,
-// requires_non_retryable_commands]
+//
+// @tags: [
+// assumes_unsharded_collection,
+// assumes_write_concern_unchanged,
+// does_not_support_stepdowns,
+// requires_non_retryable_commands,
+// ]
/**
* Tests related to the aggregate commands behavior with writeConcern and writeConcern + explain.
diff --git a/jstests/core/fsync.js b/jstests/core/fsync.js
index 9e472dc640f..c5ba3fe13a0 100644
--- a/jstests/core/fsync.js
+++ b/jstests/core/fsync.js
@@ -6,6 +6,8 @@
* - Confirm that writes can progress after fsyncUnlock
* - Confirm that the command can be run repeatedly without breaking things
* - Confirm that the pseudo commands and eval can perform fsyncLock/Unlock
+ *
+ * @tags: [requires_eval_command]
*/
(function() {
"use strict";
diff --git a/jstests/core/geo_update_btree.js b/jstests/core/geo_update_btree.js
index d40c5ad8719..6aa12733654 100644
--- a/jstests/core/geo_update_btree.js
+++ b/jstests/core/geo_update_btree.js
@@ -1,6 +1,9 @@
-// @tags: [requires_non_retryable_writes]
-
// Tests whether the geospatial search is stable under btree updates
+//
+// @tags: [
+// assumes_write_concern_unchanged,
+// requires_non_retryable_writes,
+// ]
var coll = db.getCollection("jstests_geo_update_btree");
coll.drop();
diff --git a/jstests/core/js3.js b/jstests/core/js3.js
index db7668243a3..d22a579141b 100644
--- a/jstests/core/js3.js
+++ b/jstests/core/js3.js
@@ -1,6 +1,10 @@
-// Cannot implicitly shard accessed collections because unsupported use of sharded collection
-// from db.eval.
-// @tags: [assumes_unsharded_collection, requires_non_retryable_commands]
+// @tags: [
+// # Cannot implicitly shard accessed collections because unsupported use of sharded collection
+// # from db.eval.
+// assumes_unsharded_collection,
+// requires_eval_command,
+// requires_non_retryable_commands,
+// ]
t = db.jstests_js3;
diff --git a/jstests/core/js7.js b/jstests/core/js7.js
index 78a84cafa95..a9f0f703c30 100644
--- a/jstests/core/js7.js
+++ b/jstests/core/js7.js
@@ -1,4 +1,7 @@
-// @tags: [requires_non_retryable_commands]
+// @tags: [
+// requires_eval_command,
+// requires_non_retryable_commands,
+// ]
t = db.jstests_js7;
t.drop();
diff --git a/jstests/core/js9.js b/jstests/core/js9.js
index c26c3544eb3..fdeb2615944 100644
--- a/jstests/core/js9.js
+++ b/jstests/core/js9.js
@@ -1,6 +1,10 @@
-// Cannot implicitly shard accessed collections because unsupported use of sharded collection
-// from db.eval.
-// @tags: [assumes_unsharded_collection, requires_non_retryable_commands]
+// @tags: [
+// # Cannot implicitly shard accessed collections because unsupported use of sharded collection
+// # from db.eval.
+// assumes_unsharded_collection,
+// requires_eval_command,
+// requires_non_retryable_commands,
+// ]
c = db.jstests_js9;
c.drop();
diff --git a/jstests/core/json_schema/misc_validation.js b/jstests/core/json_schema/misc_validation.js
index ddb7092a44a..78e0252bb80 100644
--- a/jstests/core/json_schema/misc_validation.js
+++ b/jstests/core/json_schema/misc_validation.js
@@ -12,8 +12,12 @@
* - applyOps
* - $elemMatch projection
*
- * @tags: [assumes_no_implicit_collection_creation_after_drop, requires_non_retryable_commands,
- * requires_non_retryable_writes]
+ * @tags: [
+ * assumes_no_implicit_collection_creation_after_drop,
+ * requires_eval_command,
+ * requires_non_retryable_commands,
+ * requires_non_retryable_writes,
+ * ]
*/
(function() {
"use strict";
diff --git a/jstests/core/profile_insert.js b/jstests/core/profile_insert.js
index 41d1b4e9b03..6c32162701c 100644
--- a/jstests/core/profile_insert.js
+++ b/jstests/core/profile_insert.js
@@ -1,6 +1,9 @@
-// @tags: [does_not_support_stepdowns]
-
// Confirms that profiled insert execution contains all expected metrics with proper values.
+//
+// @tags: [
+// assumes_write_concern_unchanged,
+// does_not_support_stepdowns,
+// ]
(function() {
"use strict";
diff --git a/jstests/core/recursion.js b/jstests/core/recursion.js
index 4a0488a723d..0114b72515c 100644
--- a/jstests/core/recursion.js
+++ b/jstests/core/recursion.js
@@ -1,7 +1,11 @@
-// @tags: [does_not_support_stepdowns, requires_non_retryable_commands]
-
-// Basic tests for a form of stack recursion that's been shown to cause C++
-// side stack overflows in the past. See SERVER-19614.
+// Basic tests for a form of stack recursion that's been shown to cause C++ side stack overflows in
+// the past. See SERVER-19614.
+//
+// @tags: [
+// does_not_support_stepdowns,
+// requires_eval_command,
+// requires_non_retryable_commands,
+// ]
(function() {
"use strict";
diff --git a/jstests/core/regex_not_id.js b/jstests/core/regex_not_id.js
index 1f15250f240..35b2c858867 100644
--- a/jstests/core/regex_not_id.js
+++ b/jstests/core/regex_not_id.js
@@ -3,10 +3,10 @@
var testColl = db.regex_not_id;
testColl.drop();
-assert.writeOK(testColl.insert({_id: "ABCDEF1"}, {writeConcern: {w: 1}}));
+assert.writeOK(testColl.insert({_id: "ABCDEF1"}));
// Should be an error.
-assert.writeError(testColl.insert({_id: /^A/}, {writeConcern: {w: 1}}));
+assert.writeError(testColl.insert({_id: /^A/}));
// _id doesn't have to be first; still disallowed
-assert.writeError(testColl.insert({xxx: "ABCDEF", _id: /ABCDEF/}, {writeConcern: {w: 1}})); \ No newline at end of file
+assert.writeError(testColl.insert({xxx: "ABCDEF", _id: /ABCDEF/}));
diff --git a/jstests/core/remove8.js b/jstests/core/remove8.js
index d45891faac6..ab82a915449 100644
--- a/jstests/core/remove8.js
+++ b/jstests/core/remove8.js
@@ -1,7 +1,11 @@
-// Cannot implicitly shard accessed collections because unsupported use of sharded collection
-// from db.eval.
-// @tags: [assumes_unsharded_collection, requires_non_retryable_commands,
-// requires_non_retryable_writes]
+// @tags: [
+// # Cannot implicitly shard accessed collections because unsupported use of sharded collection
+// # from db.eval.
+// assumes_unsharded_collection,
+// requires_eval_command,
+// requires_non_retryable_commands,
+// requires_non_retryable_writes,
+// ]
t = db.remove8;
t.drop();
diff --git a/jstests/core/rename4.js b/jstests/core/rename4.js
index 2879140ed5c..e1e9dbe2a9b 100644
--- a/jstests/core/rename4.js
+++ b/jstests/core/rename4.js
@@ -1,4 +1,7 @@
-// @tags: [requires_non_retryable_writes]
+// @tags: [
+// requires_eval_command,
+// requires_non_retryable_commands,
+// ]
t = db.jstests_rename4;
t.drop();
diff --git a/jstests/core/shell_writeconcern.js b/jstests/core/shell_writeconcern.js
index 6d3680dee83..26d68304c63 100644
--- a/jstests/core/shell_writeconcern.js
+++ b/jstests/core/shell_writeconcern.js
@@ -1,7 +1,11 @@
// Cannot implicitly shard accessed collections because of following errmsg: A single
// update/delete on a sharded collection must contain an exact match on _id or contain the shard
// key.
-// @tags: [assumes_unsharded_collection, cannot_inject_read_write_concern]
+//
+// @tags: [
+// assumes_unsharded_collection,
+// assumes_write_concern_unchanged,
+// ]
"use strict";
// check that shell writeconcern work correctly
diff --git a/jstests/core/stages_delete.js b/jstests/core/stages_delete.js
index 1d33d778acc..46d7f316212 100644
--- a/jstests/core/stages_delete.js
+++ b/jstests/core/stages_delete.js
@@ -1,4 +1,9 @@
-// @tags: [does_not_support_stepdowns]
+// @tags: [
+// # This test attempts to remove documents using the stageDebug command, which doesn't support
+// # specifying a writeConcern.
+// assumes_write_concern_unchanged,
+// does_not_support_stepdowns,
+// ]
// Test basic delete stage functionality.
var coll = db.stages_delete;
diff --git a/jstests/core/storefunc.js b/jstests/core/storefunc.js
index 960763753ed..42caed6f861 100644
--- a/jstests/core/storefunc.js
+++ b/jstests/core/storefunc.js
@@ -1,4 +1,8 @@
-// @tags: [requires_non_retryable_commands, requires_non_retryable_writes]
+// @tags: [
+// requires_eval_command,
+// requires_non_retryable_commands,
+// requires_non_retryable_writes,
+// ]
// Use a private sister database to avoid conflicts with other tests that use system.js
var testdb = db.getSisterDB("storefunc");
diff --git a/jstests/core/update_multi5.js b/jstests/core/update_multi5.js
index 6c3ae9265a8..a1be71cd652 100644
--- a/jstests/core/update_multi5.js
+++ b/jstests/core/update_multi5.js
@@ -9,8 +9,8 @@
assert.writeOK(t.insert({path: 'r1', subscribers: [1, 2]}));
assert.writeOK(t.insert({path: 'r2', subscribers: [3, 4]}));
- var res = assert.writeOK(t.update(
- {}, {$addToSet: {subscribers: 5}}, {upsert: false, multi: true, writeConcern: {w: 1}}));
+ var res =
+ assert.writeOK(t.update({}, {$addToSet: {subscribers: 5}}, {upsert: false, multi: true}));
assert.eq(res.nMatched, 2, tojson(res));
diff --git a/jstests/core/write_result.js b/jstests/core/write_result.js
index 9ccef44458d..dc641501815 100644
--- a/jstests/core/write_result.js
+++ b/jstests/core/write_result.js
@@ -1,7 +1,12 @@
// Cannot implicitly shard accessed collections because of following errmsg: A single
// update/delete on a sharded collection must contain an exact match on _id or contain the shard
// key.
-// @tags: [assumes_unsharded_collection, requires_non_retryable_writes]
+//
+// @tags: [
+// assumes_unsharded_collection,
+// assumes_write_concern_unchanged,
+// requires_non_retryable_writes,
+// ]
//
// Tests the behavior of single writes using write commands
diff --git a/jstests/libs/override_methods/auto_retry_on_network_error.js b/jstests/libs/override_methods/auto_retry_on_network_error.js
index a8fd23f4636..e29d9f780fb 100644
--- a/jstests/libs/override_methods/auto_retry_on_network_error.js
+++ b/jstests/libs/override_methods/auto_retry_on_network_error.js
@@ -11,6 +11,7 @@
(function() {
"use strict";
+ load("jstests/libs/override_methods/override_helpers.js");
load("jstests/libs/retryable_writes_util.js");
const kMaxNumRetries = 3;
@@ -330,20 +331,8 @@
} while (numRetries >= 0);
}
- const startParallelShellOriginal = startParallelShell;
-
- startParallelShell = function(jsCode, port, noConnect) {
- let newCode;
- const overridesFile = "jstests/libs/override_methods/auto_retry_on_network_error.js";
- if (typeof(jsCode) === "function") {
- // Load the override file and immediately invoke the supplied function.
- newCode = `load("${overridesFile}"); (${jsCode})();`;
- } else {
- newCode = `load("${overridesFile}"); ${jsCode};`;
- }
-
- return startParallelShellOriginal(newCode, port, noConnect);
- };
+ OverrideHelpers.prependOverrideInParallelShell(
+ "jstests/libs/override_methods/auto_retry_on_network_error.js");
const connectOriginal = connect;
diff --git a/jstests/libs/override_methods/enable_causal_consistency.js b/jstests/libs/override_methods/enable_causal_consistency.js
index f932304df7a..9e8a4bdde59 100644
--- a/jstests/libs/override_methods/enable_causal_consistency.js
+++ b/jstests/libs/override_methods/enable_causal_consistency.js
@@ -4,20 +4,11 @@
(function() {
"use strict";
+ load("jstests/libs/override_methods/override_helpers.js");
+
db.getMongo().setCausalConsistency();
db.getMongo().setReadPref("secondary");
- var originalStartParallelShell = startParallelShell;
- startParallelShell = function(jsCode, port, noConnect) {
- var newCode;
- var overridesFile = "jstests/libs/override_methods/enable_causal_consistency.js";
- if (typeof(jsCode) === "function") {
- // Load the override file and immediately invoke the supplied function.
- newCode = `load("${overridesFile}"); (${jsCode})();`;
- } else {
- newCode = `load("${overridesFile}"); ${jsCode};`;
- }
-
- return originalStartParallelShell(newCode, port, noConnect);
- };
+ OverrideHelpers.prependOverrideInParallelShell(
+ "jstests/libs/override_methods/enable_causal_consistency.js");
})();
diff --git a/jstests/libs/override_methods/enable_sessions.js b/jstests/libs/override_methods/enable_sessions.js
index ebb78f703c3..2d304927c35 100644
--- a/jstests/libs/override_methods/enable_sessions.js
+++ b/jstests/libs/override_methods/enable_sessions.js
@@ -4,6 +4,8 @@
(function() {
"use strict";
+ load("jstests/libs/override_methods/override_helpers.js");
+
var runCommandOriginal = Mongo.prototype.runCommand;
var runCommandWithMetadataOriginal = Mongo.prototype.runCommandWithMetadata;
var getDBOriginal = Mongo.prototype.getDB;
@@ -18,19 +20,8 @@
db = driverSession.getDatabase(db.getName());
sessionMap.set(db.getMongo(), driverSession);
- var originalStartParallelShell = startParallelShell;
- startParallelShell = function(jsCode, port, noConnect) {
- var newCode;
- var overridesFile = "jstests/libs/override_methods/enable_sessions.js";
- if (typeof(jsCode) === "function") {
- // Load the override file and immediately invoke the supplied function.
- newCode = `load("${overridesFile}"); (${jsCode})();`;
- } else {
- newCode = `load("${overridesFile}"); ${jsCode};`;
- }
-
- return originalStartParallelShell(newCode, port, noConnect);
- };
+ OverrideHelpers.prependOverrideInParallelShell(
+ "jstests/libs/override_methods/enable_sessions.js");
function startSession(conn) {
const driverSession = conn.startSession(sessionOptions);
diff --git a/jstests/libs/override_methods/override_helpers.js b/jstests/libs/override_methods/override_helpers.js
new file mode 100644
index 00000000000..437f1a07669
--- /dev/null
+++ b/jstests/libs/override_methods/override_helpers.js
@@ -0,0 +1,109 @@
+/**
+ * The OverrideHelpers object defines convenience methods for overriding commands and functions in
+ * the mongo shell.
+ */
+var OverrideHelpers = (function() {
+ "use strict";
+
+ function makeIsAggregationWithFirstStage(stageName) {
+ return function(commandName, commandObj) {
+ if (commandName !== "aggregate" || typeof commandObj !== "object" ||
+ commandObj === null) {
+ return false;
+ }
+
+ if (!Array.isArray(commandObj.pipeline) || commandObj.pipeline.length === 0) {
+ return false;
+ }
+
+ const firstStage = commandObj.pipeline[0];
+ if (typeof firstStage !== "object" || firstStage === null) {
+ return false;
+ }
+
+ return Object.keys(firstStage)[0] === stageName;
+ };
+ }
+
+ function isAggregationWithOutStage(commandName, commandObj) {
+ if (commandName !== "aggregate" || typeof commandObj !== "object" || commandObj === null) {
+ return false;
+ }
+
+ if (!Array.isArray(commandObj.pipeline) || commandObj.pipeline.length === 0) {
+ return false;
+ }
+
+ const lastStage = commandObj.pipeline[commandObj.pipeline.length - 1];
+ if (typeof lastStage !== "object" || lastStage === null) {
+ return false;
+ }
+
+ return Object.keys(lastStage)[0] === "$out";
+ }
+
+ function isMapReduceWithInlineOutput(commandName, commandObj) {
+ if ((commandName !== "mapReduce" && commandName !== "mapreduce") ||
+ typeof commandObj !== "object" || commandObj === null) {
+ return false;
+ }
+
+ if (typeof commandObj.out !== "object") {
+ return false;
+ }
+
+ return commandObj.out.hasOwnProperty("inline");
+ }
+
+ function prependOverrideInParallelShell(overrideFile) {
+ const startParallelShellOriginal = startParallelShell;
+
+ startParallelShell = function(jsCode, port, noConnect) {
+ let newCode;
+ if (typeof jsCode === "function") {
+ // Load the override file and immediately invoke the supplied function.
+ newCode = `load("${overrideFile}"); (${jsCode})();`;
+ } else {
+ newCode = `load("${overrideFile}"); ${jsCode};`;
+ }
+
+ return startParallelShellOriginal(newCode, port, noConnect);
+ };
+ }
+
+ function overrideRunCommand(overrideFunc) {
+ const mongoRunCommandOriginal = Mongo.prototype.runCommand;
+ const mongoRunCommandWithMetadataOriginal = Mongo.prototype.runCommandWithMetadata;
+
+ Mongo.prototype.runCommand = function(dbName, commandObj, options) {
+ const commandName = Object.keys(commandObj)[0];
+ return overrideFunc(this,
+ dbName,
+ commandName,
+ commandObj,
+ mongoRunCommandOriginal,
+ (commandObj) => [dbName, commandObj, options]);
+ };
+
+ Mongo.prototype.runCommandWithMetadata = function(dbName, metadata, commandArgs) {
+ const commandName = Object.keys(commandArgs)[0];
+ return overrideFunc(this,
+ dbName,
+ commandName,
+ commandArgs,
+ mongoRunCommandWithMetadataOriginal,
+ (commandArgs) => [dbName, metadata, commandArgs]);
+ };
+ }
+
+ return {
+ isAggregationWithListLocalCursorsStage:
+ makeIsAggregationWithFirstStage("$listLocalCursors"),
+ isAggregationWithListLocalSessionsStage:
+ makeIsAggregationWithFirstStage("$listLocalSessions"),
+ isAggregationWithOutStage: isAggregationWithOutStage,
+ isMapReduceWithInlineOutput: isMapReduceWithInlineOutput,
+ prependOverrideInParallelShell: prependOverrideInParallelShell,
+ overrideRunCommand: overrideRunCommand,
+ };
+})();
diff --git a/jstests/libs/override_methods/retry_writes_at_least_once.js b/jstests/libs/override_methods/retry_writes_at_least_once.js
index f0562c958d1..5e211d88b49 100644
--- a/jstests/libs/override_methods/retry_writes_at_least_once.js
+++ b/jstests/libs/override_methods/retry_writes_at_least_once.js
@@ -6,6 +6,7 @@
(function() {
"use strict";
+ load("jstests/libs/override_methods/override_helpers.js");
load("jstests/libs/retryable_writes_util.js");
Random.setRandomSeed();
@@ -64,18 +65,6 @@
return res;
}
- const startParallelShellOriginal = startParallelShell;
-
- startParallelShell = function(jsCode, port, noConnect) {
- let newCode;
- const overridesFile = "jstests/libs/override_methods/retry_writes_at_least_once.js";
- if (typeof(jsCode) === "function") {
- // Load the override file and immediately invoke the supplied function.
- newCode = `load("${overridesFile}"); (${jsCode})();`;
- } else {
- newCode = `load("${overridesFile}"); ${jsCode};`;
- }
-
- return startParallelShellOriginal(newCode, port, noConnect);
- };
+ OverrideHelpers.prependOverrideInParallelShell(
+ "jstests/libs/override_methods/retry_writes_at_least_once.js");
})();
diff --git a/jstests/libs/override_methods/set_read_and_write_concerns.js b/jstests/libs/override_methods/set_read_and_write_concerns.js
index 7d1e3fc8e0f..e6605f72419 100644
--- a/jstests/libs/override_methods/set_read_and_write_concerns.js
+++ b/jstests/libs/override_methods/set_read_and_write_concerns.js
@@ -1,201 +1,221 @@
/**
- * Use prototype overrides to set read concern and write concern while running core tests.
+ * Use prototype overrides to set read concern and write concern while running tests.
*/
(function() {
"use strict";
+ load("jstests/libs/override_methods/override_helpers.js");
+
if (typeof TestData === "undefined" || !TestData.hasOwnProperty("defaultReadConcernLevel")) {
throw new Error(
- "The default read-concern level must be set as the 'defaultReadConcernLevel' " +
- "property on TestData");
- }
- var defaultReadConcern = {level: TestData.defaultReadConcernLevel};
-
- var defaultWriteConcern = {
- w: "majority",
- // Use a "signature" value that won't typically match a value assigned in normal use.
- // This way the wtimeout set by this override is distinguishable in the server logs.
- wtimeout: 5 * 60 * 1000 + 321, // 300321ms
- };
- if (TestData.hasOwnProperty("defaultWriteConcern")) {
- defaultWriteConcern = TestData.defaultWriteConcern;
+ "The readConcern level to use must be set as the 'defaultReadConcernLevel'" +
+ " property on the global TestData object");
}
- var originalDBQuery = DBQuery;
+ const kDefaultReadConcern = {level: TestData.defaultReadConcernLevel};
+ const kDefaultWriteConcern =
+ (TestData.hasOwnProperty("defaultWriteConcern")) ? TestData.defaultWriteConcern : {
+ w: "majority",
+ // Use a "signature" value that won't typically match a value assigned in normal use.
+ // This way the wtimeout set by this override is distinguishable in the server logs.
+ wtimeout: 5 * 60 * 1000 + 321, // 300321ms
+ };
+
+ const kCommandsSupportingReadConcern = new Set([
+ "aggregate",
+ "count",
+ "distinct",
+ "find",
+ "geoNear",
+ "geoSearch",
+ "group",
+ "parallelCollectionScan",
+ ]);
+
+ const kCommandsSupportingWriteConcern = new Set([
+ "_configsvrAddShard",
+ "_configsvrAddShardToZone",
+ "_configsvrCommitChunkMerge",
+ "_configsvrCommitChunkMigration",
+ "_configsvrCommitChunkSplit",
+ "_configsvrCreateDatabase",
+ "_configsvrEnableSharding",
+ "_configsvrMoveChunk",
+ "_configsvrMovePrimary",
+ "_configsvrRemoveShard",
+ "_configsvrRemoveShardFromZone",
+ "_configsvrShardCollection",
+ "_configsvrUpdateZoneKeyRange",
+ "_mergeAuthzCollections",
+ "_recvChunkStart",
+ "appendOplogNote",
+ "applyOps",
+ "authSchemaUpgrade",
+ "aggregate",
+ "captrunc",
+ "cleanupOrphaned",
+ "clone",
+ "cloneCollection",
+ "cloneCollectionAsCapped",
+ "collMod",
+ "convertToCapped",
+ "copydb",
+ "create",
+ "createIndexes",
+ "createRole",
+ "createUser",
+ "delete",
+ "drop",
+ "dropAllRolesFromDatabase",
+ "dropAllUsersFromDatabase",
+ "dropDatabase",
+ "dropIndexes",
+ "dropRole",
+ "dropUser",
+ "emptycapped",
+ "findAndModify",
+ "findandmodify",
+ "godinsert",
+ "grantPrivilegesToRole",
+ "grantRolesToRole",
+ "grantRolesToUser",
+ "insert",
+ "mapReduce",
+ "mapreduce",
+ "mapreduce.shardedfinish",
+ "moveChunk",
+ "renameCollection",
+ "revokePrivilegesFromRole",
+ "revokeRolesFromRole",
+ "revokeRolesFromUser",
+ "setFeatureCompatibilityVersion",
+ "update",
+ "updateRole",
+ "updateUser",
+ ]);
+
+ function runCommandWithReadAndWriteConcerns(
+ conn, dbName, commandName, commandObj, func, makeFuncArgs) {
+ if (typeof commandObj !== "object" || commandObj === null) {
+ return func.apply(conn, makeFuncArgs(commandObj));
+ }
- DBQuery = function(mongo, db, collection, ns, query, fields, limit, skip, batchSize, options) {
- if (ns.endsWith("$cmd")) {
- if (query.hasOwnProperty("writeConcern") &&
- bsonWoCompare(query.writeConcern, defaultWriteConcern) !== 0) {
- jsTestLog("Warning: DBQuery overriding existing writeConcern of: " +
- tojson(query.writeConcern));
- query.writeConcern = defaultWriteConcern;
- }
+ // If the command is in a wrapped form, then we look for the actual command object inside
+ // the query/$query object.
+ let commandObjUnwrapped = commandObj;
+ if (commandName === "query" || commandName === "$query") {
+ commandObjUnwrapped = commandObj[commandName];
+ commandName = Object.keys(commandObjUnwrapped)[0];
}
- return originalDBQuery.apply(this, arguments);
- };
+ if (commandName === "eval" || commandName === "$eval") {
+ throw new Error("Cowardly refusing to run test with overridden write concern when it" +
+ " uses a command that can only perform w=1 writes: " +
+ tojson(commandObj));
+ }
- DBQuery.Option = originalDBQuery.Option;
+ let shouldForceReadConcern = kCommandsSupportingReadConcern.has(commandName);
+ let shouldForceWriteConcern = kCommandsSupportingWriteConcern.has(commandName);
- var originalStartParallelShell = startParallelShell;
- startParallelShell = function(jsCode, port, noConnect) {
- var newCode;
- var overridesFile = "jstests/libs/override_methods/set_read_and_write_concerns.js";
- if (typeof(jsCode) === "function") {
- // Load the override file and immediately invoke the supplied function.
- newCode = `load("${overridesFile}"); (${jsCode})();`;
- } else {
- newCode = `load("${overridesFile}"); ${jsCode};`;
- }
+ if (commandName === "aggregate") {
+ if (OverrideHelpers.isAggregationWithListLocalCursorsStage(commandName,
+ commandObjUnwrapped)) {
+ // The $listLocalCursors stage can only be used with readConcern={level: "local"}.
+ shouldForceReadConcern = false;
+ }
- return originalStartParallelShell(newCode, port, noConnect);
- };
+ if (OverrideHelpers.isAggregationWithListLocalSessionsStage(commandName,
+ commandObjUnwrapped)) {
+ // The $listLocalSessions stage can only be used with readConcern={level: "local"}.
+ shouldForceReadConcern = false;
+ }
- const originalRunCommand = DB.prototype._runCommandImpl;
- DB.prototype._runCommandImpl = function(dbName, obj, options) {
- var cmdName = "";
- for (var fieldName in obj) {
- cmdName = fieldName;
- break;
- }
+ if (OverrideHelpers.isAggregationWithOutStage(commandName, commandObjUnwrapped)) {
+ // The $out stage can only be used with readConcern={level: "local"}.
+ shouldForceReadConcern = false;
+ } else {
+ // A writeConcern can only be used with a $out stage.
+ shouldForceWriteConcern = false;
+ }
- // These commands directly support a writeConcern argument.
- var commandsToForceWriteConcern = [
- "_configsvrAddShard",
- "_configsvrAddShardToZone",
- "_configsvrCommitChunkMerge",
- "_configsvrCommitChunkMigration",
- "_configsvrCommitChunkSplit",
- "_configsvrCreateDatabase",
- "_configsvrEnableSharding",
- "_configsvrMoveChunk",
- "_configsvrMovePrimary",
- "_configsvrRemoveShard",
- "_configsvrRemoveShardFromZone",
- "_configsvrShardCollection",
- "_configsvrUpdateZoneKeyRange",
- "_mergeAuthzCollections",
- "_recvChunkStart",
- "appendOplogNote",
- "applyOps",
- "authSchemaUpgrade",
- "captrunc",
- "cleanupOrphaned",
- "clone",
- "cloneCollection",
- "cloneCollectionAsCapped",
- "collMod",
- "convertToCapped",
- "copydb",
- "create",
- "createIndexes",
- "createRole",
- "createUser",
- "delete",
- "drop",
- "dropAllRolesFromDatabase",
- "dropAllUsersFromDatabase",
- "dropDatabase",
- "dropIndexes",
- "dropRole",
- "dropUser",
- "emptycapped",
- "findAndModify",
- "findandmodify",
- "godinsert",
- "grantPrivilegesToRole",
- "grantRolesToRole",
- "grantRolesToUser",
- "insert",
- "mapreduce.shardedfinish",
- "moveChunk",
- "renameCollection",
- "revokePrivilegesFromRole",
- "revokeRolesFromRole",
- "revokeRolesFromUser",
- "setFeatureCompatibilityVersion",
- "update",
- "updateRole",
- "updateUser",
- ];
-
- // These are reading commands that support majority readConcern.
- var commandsToForceReadConcern = [
- "count",
- "distinct",
- "find",
- "geoNear",
- "geoSearch",
- "group",
- "parallelCollectionScan",
- ];
-
- var forceWriteConcern = Array.contains(commandsToForceWriteConcern, cmdName);
- var forceReadConcern = Array.contains(commandsToForceReadConcern, cmdName);
-
- if (cmdName === "aggregate") {
- // Aggregate can be either a read or a write depending on whether it has a $out stage.
- // $out is required to be the last stage of the pipeline.
- var stages = obj.pipeline;
- const lastStage = stages && Array.isArray(stages) && (stages.length !== 0)
- ? stages[stages.length - 1]
- : undefined;
- const hasOut =
- lastStage && (typeof lastStage === 'object') && lastStage.hasOwnProperty('$out');
- const hasExplain = obj.hasOwnProperty("explain");
- if (!hasExplain) {
- if (hasOut) {
- forceWriteConcern = true;
- } else {
- forceReadConcern = true;
- }
+ if (commandObjUnwrapped.explain) {
+ // Attempting to specify a readConcern while explaining an aggregation would always
+ // return an error prior to SERVER-30582 and it otherwise only compatible with
+ // readConcern={level: "local"}.
+ shouldForceReadConcern = false;
}
+ } else if (OverrideHelpers.isMapReduceWithInlineOutput(commandName, commandObjUnwrapped)) {
+ // A writeConcern can only be used with non-inline output.
+ shouldForceWriteConcern = false;
}
- else if (cmdName === "mapReduce") {
- var stages = obj.pipeline;
- const lastStage = stages && Array.isArray(stages) && (stages.length !== 0)
- ? stages[stages.length - 1]
- : undefined;
- const hasOut =
- lastStage && (typeof lastStage === 'object') && lastStage.hasOwnProperty('$out');
- if (hasOut) {
- forceWriteConcern = true;
+ const inWrappedForm = commandObj !== commandObjUnwrapped;
+
+ if (shouldForceReadConcern) {
+ // We create a copy of 'commandObj' to avoid mutating the parameter the caller
+ // specified.
+ commandObj = Object.assign({}, commandObj);
+ if (inWrappedForm) {
+ commandObjUnwrapped = Object.assign({}, commandObjUnwrapped);
+ commandObj[Object.keys(commandObj)[0]] = commandObjUnwrapped;
+ } else {
+ commandObjUnwrapped = commandObj;
}
- }
- if (forceWriteConcern) {
- if (obj.hasOwnProperty("writeConcern")) {
- if (bsonWoCompare(obj.writeConcern, defaultWriteConcern) !== 0) {
- jsTestLog("Warning: _runCommandImpl overriding existing writeConcern of: " +
- tojson(obj.writeConcern));
- obj.writeConcern = defaultWriteConcern;
+ if (commandObjUnwrapped.hasOwnProperty("readConcern")) {
+ let readConcern = commandObjUnwrapped.readConcern;
+
+ if (typeof readConcern !== "object" || readConcern === null ||
+ (readConcern.hasOwnProperty("level") &&
+ bsonWoCompare({_: readConcern.level}, {_: kDefaultReadConcern.level}) !== 0)) {
+ throw new Error("Cowardly refusing to override read concern of command: " +
+ tojson(commandObj));
}
+
+ // We create a copy of the readConcern object to avoid mutating the parameter the
+ // caller specified.
+ readConcern = Object.assign({}, readConcern, kDefaultReadConcern);
+ commandObjUnwrapped.readConcern = readConcern;
+ } else {
+ commandObjUnwrapped.readConcern = kDefaultReadConcern;
+ }
+ }
+
+ if (shouldForceWriteConcern) {
+ // We create a copy of 'commandObj' to avoid mutating the parameter the caller
+ // specified.
+ commandObj = Object.assign({}, commandObj);
+ if (inWrappedForm) {
+ commandObjUnwrapped = Object.assign({}, commandObjUnwrapped);
+ commandObj[Object.keys(commandObj)[0]] = commandObjUnwrapped;
} else {
- obj.writeConcern = defaultWriteConcern;
+ commandObjUnwrapped = commandObj;
}
- } else if (forceReadConcern) {
- if (obj.hasOwnProperty("readConcern")) {
- if (bsonWoCompare(obj.readConcern, defaultReadConcern) !== 0) {
- jsTestLog("Warning: _runCommandImpl overriding existing readConcern of: " +
- tojson(obj.readConcern));
- obj.readConcern = defaultReadConcern;
+ if (commandObjUnwrapped.hasOwnProperty("writeConcern")) {
+ let writeConcern = commandObjUnwrapped.writeConcern;
+
+ if (typeof writeConcern !== "object" || writeConcern === null ||
+ (writeConcern.hasOwnProperty("w") &&
+ bsonWoCompare({_: writeConcern.w}, {_: kDefaultWriteConcern.w}) !== 0)) {
+ throw new Error("Cowardly refusing to override write concern of command: " +
+ tojson(commandObj));
}
+
+ // We create a copy of the writeConcern object to avoid mutating the parameter the
+ // caller specified.
+ writeConcern = Object.assign({}, writeConcern, kDefaultWriteConcern);
+ commandObjUnwrapped.writeConcern = writeConcern;
} else {
- obj.readConcern = defaultReadConcern;
+ commandObjUnwrapped.writeConcern = kDefaultWriteConcern;
}
}
- var res = originalRunCommand.call(this, dbName, obj, options);
-
- return res;
- };
+ return func.apply(conn, makeFuncArgs(commandObj));
+ }
- // Use a majority write concern if the operation does not specify one.
- DBCollection.prototype.getWriteConcern = function() {
- return new WriteConcern(defaultWriteConcern);
- };
+ OverrideHelpers.prependOverrideInParallelShell(
+ "jstests/libs/override_methods/set_read_and_write_concerns.js");
+ OverrideHelpers.overrideRunCommand(runCommandWithReadAndWriteConcerns);
})();
diff --git a/jstests/libs/override_methods/set_read_preference_secondary.js b/jstests/libs/override_methods/set_read_preference_secondary.js
index 9955c7f016d..d81532bf8d5 100644
--- a/jstests/libs/override_methods/set_read_preference_secondary.js
+++ b/jstests/libs/override_methods/set_read_preference_secondary.js
@@ -4,31 +4,16 @@
(function() {
"use strict";
- const readPreferenceSecondary = {mode: "secondary"};
+ load("jstests/libs/override_methods/override_helpers.js");
- db.getMongo().setReadPref("secondary");
-
- const originalStartParallelShell = startParallelShell;
- startParallelShell = function(jsCode, port, noConnect) {
- let newCode;
- const overridesFile = "jstests/libs/override_methods/set_read_preference_secondary.js";
- if (typeof(jsCode) === "function") {
- // Load the override file and immediately invoke the supplied function.
- newCode = `load("${overridesFile}"); (${jsCode})();`;
- } else {
- newCode = `load("${overridesFile}"); ${jsCode};`;
- }
-
- return originalStartParallelShell(newCode, port, noConnect);
- };
-
- // These are reading commands that support a read preference.
- const commandsToForceReadPreference = new Set([
+ const kReadPreferenceSecondary = {mode: "secondary"};
+ const kCommandsSupportingReadPreference = new Set([
"aggregate",
"collStats",
"count",
"dbStats",
"distinct",
+ "find",
"geoNear",
"geoSearch",
"group",
@@ -37,33 +22,55 @@
"parallelCollectionScan",
]);
- const originalRunCommand = DB.prototype._runCommandImpl;
- DB.prototype._runCommandImpl = function(dbName, obj, options) {
- const cmdName = Object.keys(obj)[0];
+ function runCommandWithReadPreferenceSecondary(
+ conn, dbName, commandName, commandObj, func, makeFuncArgs) {
+ if (typeof commandObj !== "object" || commandObj === null) {
+ return func.apply(conn, makeFuncArgs(commandObj));
+ }
- let forceReadPreference = commandsToForceReadPreference.has(cmdName);
- if (cmdName === "aggregate" && obj.pipeline && Array.isArray(obj.pipeline) &&
- obj.pipeline.length > 0 &&
- obj.pipeline[obj.pipeline.length - 1].hasOwnProperty("$out")) {
- forceReadPreference = false;
- } else if ((cmdName === "mapReduce" || cmdName === "mapreduce") &&
- obj.hasOwnProperty("out") && typeof obj.out === "object" && !obj.out.inline) {
- forceReadPreference = false;
+ // If the command is in a wrapped form, then we look for the actual command object inside
+ // the query/$query object.
+ let commandObjUnwrapped = commandObj;
+ if (commandName === "query" || commandName === "$query") {
+ commandObjUnwrapped = commandObj[commandName];
+ commandName = Object.keys(commandObjUnwrapped)[0];
}
- if (forceReadPreference) {
- if (obj.hasOwnProperty("$readPreference")) {
- if (bsonWoCompare(obj.$readPreference, readPreferenceSecondary) !== 0) {
- jsTestLog("Warning: _runCommandImpl overriding existing $readPreference of: " +
- tojson(obj.$readPreference));
- obj.$readPreference = readPreferenceSecondary;
- }
+ let shouldForceReadPreference = kCommandsSupportingReadPreference.has(commandName);
+ if (OverrideHelpers.isAggregationWithOutStage(commandName, commandObjUnwrapped)) {
+ // An aggregation with a $out stage must be sent to the primary.
+ shouldForceReadPreference = false;
+ } else if ((commandName === "mapReduce" || commandName === "mapreduce") &&
+ !OverrideHelpers.isMapReduceWithInlineOutput(commandName, commandObjUnwrapped)) {
+ // A map-reduce operation with non-inline output must be sent to the primary.
+ shouldForceReadPreference = false;
+ }
+
+ if (shouldForceReadPreference) {
+ if (commandObj === commandObjUnwrapped) {
+ // We wrap the command object using a "query" field rather than a "$query" field to
+ // match the implementation of DB.prototype._attachReadPreferenceToCommand().
+ commandObj = {query: commandObj};
} else {
- obj.$readPreference = readPreferenceSecondary;
+ // We create a copy of 'commandObj' to avoid mutating the parameter the caller
+ // specified.
+ commandObj = Object.assign({}, commandObj);
+ }
+
+ if (commandObj.hasOwnProperty("$readPreference") &&
+ !bsonBinaryEqual({_: commandObj.$readPreference}, {_: kReadPreferenceSecondary})) {
+ throw new Error("Cowardly refusing to override read preference of command: " +
+ tojson(commandObj));
}
+
+ commandObj.$readPreference = kReadPreferenceSecondary;
}
- return originalRunCommand.call(this, dbName, obj, options);
- };
+ return func.apply(conn, makeFuncArgs(commandObj));
+ }
+
+ OverrideHelpers.prependOverrideInParallelShell(
+ "jstests/libs/override_methods/set_read_preference_secondary.js");
+ OverrideHelpers.overrideRunCommand(runCommandWithReadPreferenceSecondary);
})();