summaryrefslogtreecommitdiff
path: root/jstests/multiVersion/shell_retryable_writes_downgrade.js
diff options
context:
space:
mode:
Diffstat (limited to 'jstests/multiVersion/shell_retryable_writes_downgrade.js')
-rw-r--r--jstests/multiVersion/shell_retryable_writes_downgrade.js122
1 files changed, 122 insertions, 0 deletions
diff --git a/jstests/multiVersion/shell_retryable_writes_downgrade.js b/jstests/multiVersion/shell_retryable_writes_downgrade.js
new file mode 100644
index 00000000000..652d33c0ddc
--- /dev/null
+++ b/jstests/multiVersion/shell_retryable_writes_downgrade.js
@@ -0,0 +1,122 @@
+/**
+ * Tests that the mongo shell doesn't attempt to retry its write operations after downgrading from
+ * 3.6 to 3.4.
+ */
+(function() {
+ "use strict";
+
+ load("jstests/replsets/rslib.js");
+
+ const rst = new ReplSetTest({nodes: 1});
+ rst.startSet();
+ rst.initiate();
+
+ const primary = rst.getPrimary();
+
+ const db = primary.startSession({retryWrites: true}).getDatabase("test");
+ const coll = db.shell_retryable_writes_downgrade;
+
+ function testCommandCanBeRetried(func, {
+ expectedLogicalSessionId: expectedLogicalSessionId = true,
+ expectedTransactionNumber: expectedTransactionNumber = true
+ } = {}) {
+ const mongoRunCommandOriginal = Mongo.prototype.runCommand;
+
+ const sentinel = {};
+ let cmdObjSeen = sentinel;
+
+ Mongo.prototype.runCommand = function runCommandSpy(dbName, cmdObj, options) {
+ cmdObjSeen = cmdObj;
+ return mongoRunCommandOriginal.apply(this, arguments);
+ };
+
+ try {
+ assert.doesNotThrow(func);
+ } finally {
+ Mongo.prototype.runCommand = mongoRunCommandOriginal;
+ }
+
+ if (cmdObjSeen === sentinel) {
+ throw new Error("Mongo.prototype.runCommand() was never called: " + func.toString());
+ }
+
+ let cmdName = Object.keys(cmdObjSeen)[0];
+
+ // If the command is in a wrapped form, then we look for the actual command object inside
+ // the query/$query object.
+ if (cmdName === "query" || cmdName === "$query") {
+ cmdObjSeen = cmdObjSeen[cmdName];
+ cmdName = Object.keys(cmdObjSeen)[0];
+ }
+
+ if (expectedLogicalSessionId) {
+ assert(cmdObjSeen.hasOwnProperty("lsid"),
+ "Expected operation " + tojson(cmdObjSeen) + " to have a logical session id: " +
+ func.toString());
+ } else {
+ assert(!cmdObjSeen.hasOwnProperty("lsid"),
+ "Expected operation " + tojson(cmdObjSeen) +
+ " to not have a logical session id: " + func.toString());
+ }
+
+ if (expectedTransactionNumber) {
+ assert(cmdObjSeen.hasOwnProperty("txnNumber"),
+ "Expected operation " + tojson(cmdObjSeen) +
+ " to be assigned a transaction number since it can be retried: " +
+ func.toString());
+ } else {
+ assert(!cmdObjSeen.hasOwnProperty("txnNumber"),
+ "Expected operation " + tojson(cmdObjSeen) +
+ " to not be assigned a transaction number since it cannot be retried: " +
+ func.toString());
+ }
+ }
+
+ testCommandCanBeRetried(function() {
+ assert.writeOK(coll.insert({_id: "while fCV=3.6"}));
+ });
+
+ assert.commandWorked(db.adminCommand({setFeatureCompatibilityVersion: "3.4"}));
+
+ // The server continues to accept lsid and txnNumber while in featureCompatibilityVersion=3.4.
+ //
+ // TODO SERVER-31777: The server should return an error if an lsid or txnNumber is specified
+ // while in featureCompatibilityVersion=3.4.
+ testCommandCanBeRetried(function() {
+ assert.writeOK(coll.insert({_id: "while fCV=3.4"}));
+ });
+
+ rst.restart(primary, {binVersion: "3.4"});
+ rst.waitForMaster();
+
+ assert(db.getSession().getOptions().shouldRetryWrites(),
+ "Re-establishing the connection shouldn't change the state of the SessionOptions");
+
+ // After downgrading to MongoDB 3.4, the mongo shell shouldn't attempt to automatically retry
+ // write operations.
+ assert.throws(function() {
+ coll.insert({_id: "while in binVersion=3.4 and disconnected"});
+ });
+
+ // After downgrading to MongoDB 3.4, the mongo shell shouldn't inject an lsid or assign a
+ // transaction number to its write requests.
+ testCommandCanBeRetried(function() {
+ assert.writeOK(coll.insert({_id: "while binVersion=3.4 and reconnected"}));
+ }, {expectedLogicalSessionId: false, expectedTransactionNumber: false});
+
+ rst.restart(primary, {binVersion: "latest", noReplSet: true});
+ rst.waitForMaster();
+ reconnect(primary);
+
+ // When upgrading to MongoDB 3.6 but running as a stand-alone server, the mongo shell should
+ // still assign a transaction number to its write requests (per the Driver's specification).
+ //
+ // TODO SERVER-31777: The server should return an error if an lsid or txnNumber is specified
+ // while in featureCompatibilityVersion=3.4.
+ testCommandCanBeRetried(function() {
+ assert.writeOK(coll.insert({_id: "while binVersion=3.6 as stand-alone and reconnected"}));
+ });
+
+ db.getSession().endSession();
+ rst.stopSet();
+})();