summaryrefslogtreecommitdiff
path: root/jstests/libs
diff options
context:
space:
mode:
Diffstat (limited to 'jstests/libs')
-rw-r--r--jstests/libs/override_methods/set_read_and_write_concerns.js30
-rw-r--r--jstests/libs/override_methods/set_read_preference_secondary.js88
2 files changed, 114 insertions, 4 deletions
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 30c853fb54b..267b5ab9bfc 100644
--- a/jstests/libs/override_methods/set_read_and_write_concerns.js
+++ b/jstests/libs/override_methods/set_read_and_write_concerns.js
@@ -57,6 +57,31 @@
"updateUser",
]);
+ const kCommandsToEmulateWriteConcern = new Set([
+ "aggregate",
+ "appendOplogNote",
+ "captrunc",
+ "cleanupOrphaned",
+ "clone",
+ "cloneCollection",
+ "cloneCollectionAsCapped",
+ "convertToCapped",
+ "copydb",
+ "create",
+ "createIndexes",
+ "drop",
+ "dropDatabase",
+ "dropIndexes",
+ "emptycapped",
+ "godinsert",
+ "mapReduce",
+ "mapreduce",
+ "mapreduce.shardedfinish",
+ "moveChunk",
+ "renameCollection",
+ "revokePrivilegesFromRole",
+ ]);
+
function runCommandWithReadAndWriteConcerns(
conn, dbName, commandName, commandObj, func, makeFuncArgs) {
if (typeof commandObj !== "object" || commandObj === null) {
@@ -79,10 +104,7 @@
var shouldForceReadConcern = kCommandsSupportingReadConcern.has(commandName);
var shouldForceWriteConcern = kCommandsSupportingWriteConcern.has(commandName);
- var shouldEmulateWriteConcern =
- (commandName === "aggregate" || commandName === "createIndexes" ||
- commandName === "mapReduce" || commandName === "mapreduce" ||
- commandName === "mapreduce.shardedfinish");
+ var shouldEmulateWriteConcern = kCommandsToEmulateWriteConcern.has(commandName);
if (commandName === "aggregate") {
if (OverrideHelpers.isAggregationWithOutStage(commandName, commandObjUnwrapped)) {
diff --git a/jstests/libs/override_methods/set_read_preference_secondary.js b/jstests/libs/override_methods/set_read_preference_secondary.js
new file mode 100644
index 00000000000..270bbf40272
--- /dev/null
+++ b/jstests/libs/override_methods/set_read_preference_secondary.js
@@ -0,0 +1,88 @@
+/**
+ * Use prototype overrides to set read preference to "secondary" when running tests.
+ */
+(function() {
+ "use strict";
+
+ load("jstests/libs/override_methods/override_helpers.js");
+
+ const kReadPreferenceSecondary = {
+ mode: "secondary"
+ };
+ const kCommandsSupportingReadPreference = new Set([
+ "aggregate",
+ "collStats",
+ "count",
+ "dbStats",
+ "distinct",
+ "find",
+ "geoNear",
+ "geoSearch",
+ "group",
+ "mapReduce",
+ "mapreduce",
+ "parallelCollectionScan",
+ ]);
+
+ function runCommandWithReadPreferenceSecondary(
+ conn, dbName, commandName, commandObj, func, makeFuncArgs) {
+ if (typeof commandObj !== "object" || commandObj === null) {
+ return func.apply(conn, makeFuncArgs(commandObj));
+ }
+
+ // If the command is in a wrapped form, then we look for the actual command object inside
+ // the query/$query object.
+ var commandObjUnwrapped = commandObj;
+ if (commandName === "query" || commandName === "$query") {
+ commandObjUnwrapped = commandObj[commandName];
+ commandName = Object.keys(commandObjUnwrapped)[0];
+ }
+
+ if (commandObj[commandName] === "system.profile") {
+ throw new Error("Cowardly refusing to run test with overridden read preference" +
+ " when it reads from a non-replicated collection: " +
+ tojson(commandObj));
+ }
+
+ var 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 {
+ // 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 func.apply(conn, makeFuncArgs(commandObj));
+ }
+
+ startParallelShell = () => {throw new Error(
+ "Cowardly refusing to a run a test that starts a parallel shell because prior to" +
+ " MongoDB 3.4 replica set connections couldn't be used in it.");
+ };
+
+ OverrideHelpers.overrideRunCommand(runCommandWithReadPreferenceSecondary);
+})();