summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--jstests/multiVersion/genericSetFCVUsage/set_fcv_downgrade_on_disk_changes.js247
1 files changed, 247 insertions, 0 deletions
diff --git a/jstests/multiVersion/genericSetFCVUsage/set_fcv_downgrade_on_disk_changes.js b/jstests/multiVersion/genericSetFCVUsage/set_fcv_downgrade_on_disk_changes.js
new file mode 100644
index 00000000000..f4e078c2869
--- /dev/null
+++ b/jstests/multiVersion/genericSetFCVUsage/set_fcv_downgrade_on_disk_changes.js
@@ -0,0 +1,247 @@
+/**
+ * Unified test that makes sure calling setFeatureCompatibilityVersion with
+ * {downgradeOnDiskChanges: true} is able to successfully downgrade all expected on-disk changes in
+ * one invocation.
+ */
+(function() {
+"use strict";
+
+load('jstests/multiVersion/libs/multi_rs.js');
+load('jstests/multiVersion/libs/multi_cluster.js');
+
+let dbpath = MongoRunner.dataPath + jsTestName();
+resetDbpath(dbpath);
+
+const latest = "latest";
+const lastContinuous = "last-continuous";
+
+/**
+ * Each new feature that adds downgrade logic to the setFeatureCompatibilityVersion command with
+ * {downgradeOnDiskChanges: true} should add their test cases to this test file. Each test case
+ * should follow this 'dummyTest' template and implement the following three test functions:
+ * this.onDiskChangesBeforeDowngrade: This function will be called before the FCV downgrade to
+ * introduce durable on-disk changes that will be downgraded as part the FCV downgrade.
+ * this.validateAfterFCVDowngrade: This function will be called after the FCV downgrade to validate
+ * the downgrade of the incompatible on-disk changes introduced in onDiskChangesBeforeDowngrade.
+ * this.validateAfterBinaryDowngrade: This function will be called after the binary downgrade to
+ * 'last-continuous' binaries to validate the downgrade of the incompatible on-disk changes
+ * introduced in onDiskChangesBeforeDowngrade.
+ *
+ * Each new test should also be added to the downgradeOnDiskChangesTests list below.
+ */
+function dummyTest() {
+ const documents = [{_id: "dummy"}];
+ this.onDiskChangesBeforeDowngrade = function(conn) {
+ jsTestLog("Running onDiskChangesBeforeDowngrade of dummyTest");
+ let testDB = conn.getDB("test");
+ assert.commandWorked(testDB.runCommand({insert: "dummy", documents: documents}));
+ };
+
+ this.validateAfterFCVDowngrade = function(conn) {
+ jsTestLog("Running validateAfterFCVDowngrade of dummyTest");
+ let testDB = conn.getDB("test");
+ let res = testDB.dummy.find({});
+ assert.sameMembers(res.toArray(), documents, () => tojson(res));
+ };
+
+ this.validateAfterBinaryDowngrade = function(conn) {
+ jsTestLog("Running validateAfterBinaryDowngrade of dummyTest");
+ this.validateAfterFCVDowngrade(conn);
+ };
+}
+
+const downgradeOnDiskChangesTests = [
+ new dummyTest(),
+];
+
+function runStandaloneTest() {
+ jsTestLog("Running standalone test");
+
+ let conn;
+ let adminDB;
+
+ // A 'latest' binary standalone should default to 'latestFCV'.
+ conn = MongoRunner.runMongod({dbpath: dbpath, binVersion: latest});
+ assert.neq(
+ null, conn, "mongod was unable to start up with version=" + latest + " and no data files");
+ adminDB = conn.getDB("admin");
+ checkFCV(adminDB, latestFCV);
+
+ jsTestLog("Introducing on-disk changes to be downgraded in FCV downgrade");
+ for (let test of downgradeOnDiskChangesTests) {
+ test.onDiskChangesBeforeDowngrade(conn);
+ }
+
+ jsTestLog(
+ "Test that setFeatureCompatibilityVersion succeeds with {downgradeOnDiskChanges: true}");
+ assert.commandWorked(adminDB.runCommand(
+ {setFeatureCompatibilityVersion: lastContinuousFCV, downgradeOnDiskChanges: true}));
+ checkFCV(adminDB, lastContinuousFCV);
+ checkLog.contains(conn, "Downgrading on-disk format");
+
+ jsTestLog("Validating on-disk changes after FCV downgrade");
+ for (let test of downgradeOnDiskChangesTests) {
+ test.validateAfterFCVDowngrade(conn);
+ }
+
+ MongoRunner.stopMongod(conn);
+
+ // Test that the node can restart with a last-continuous binary.
+ conn = MongoRunner.runMongod({dbpath: dbpath, binVersion: lastContinuous, noCleanData: true});
+ assert.neq(null,
+ conn,
+ "mongod was unable to start up with binary version=" + lastContinuous +
+ " and featureCompatibilityVersion=" + lastContinuousFCV);
+ adminDB = conn.getDB("admin");
+ checkFCV(adminDB, lastContinuousFCV);
+
+ jsTestLog("Validating on-disk changes after binary downgrade");
+ for (let test of downgradeOnDiskChangesTests) {
+ test.validateAfterBinaryDowngrade(conn);
+ }
+
+ MongoRunner.stopMongod(conn);
+
+ // Test that the node can restart with a latest binary.
+ conn = MongoRunner.runMongod({dbpath: dbpath, binVersion: latest, noCleanData: true});
+ assert.neq(null,
+ conn,
+ "mongod was unable to start up with binary version=" + latest +
+ " and featureCompatibilityVersion=" + lastContinuousFCV);
+ adminDB = conn.getDB("admin");
+ checkFCV(adminDB, lastContinuousFCV);
+
+ // Test that the FCV can be upgraded back to 'latestFCV'.
+ assert.commandWorked(adminDB.runCommand({setFeatureCompatibilityVersion: latestFCV}));
+ checkFCV(adminDB, latestFCV);
+
+ MongoRunner.stopMongod(conn);
+}
+
+function runReplicaSetTest() {
+ jsTestLog("Running replica set test");
+
+ // 'latest' binary replica set.
+ let rst = new ReplSetTest({nodes: 2, nodeOpts: {binVersion: latest}});
+ rst.startSet();
+ rst.initiateWithHighElectionTimeout();
+ let primaryAdminDB = rst.getPrimary().getDB("admin");
+ let secondaryAdminDB = rst.getSecondary().getDB("admin");
+
+ // FCV should default to 'latestFCV' on primary and secondary in a 'latest' binary replica set.
+ checkFCV(primaryAdminDB, latestFCV);
+ rst.awaitReplication();
+ checkFCV(secondaryAdminDB, latestFCV);
+
+ jsTestLog("Introducing on-disk changes to be downgraded in FCV downgrade");
+ for (let test of downgradeOnDiskChangesTests) {
+ test.onDiskChangesBeforeDowngrade(rst.getPrimary());
+ }
+
+ jsTestLog(
+ "Test that setFeatureCompatibilityVersion succeeds with {downgradeOnDiskChanges: true} " +
+ "and propogates to the secondary");
+ assert.commandWorked(primaryAdminDB.runCommand(
+ {setFeatureCompatibilityVersion: lastContinuousFCV, downgradeOnDiskChanges: true}));
+ checkFCV(primaryAdminDB, lastContinuousFCV);
+ rst.awaitReplication();
+ checkFCV(secondaryAdminDB, lastContinuousFCV);
+
+ jsTestLog("Validating on-disk changes after FCV downgrade");
+ for (let test of downgradeOnDiskChangesTests) {
+ test.validateAfterFCVDowngrade(rst.getPrimary());
+ }
+
+ // Test that the cluster can restart with a last-continuous binary.
+ rst.upgradeSet({binVersion: lastContinuous});
+ primaryAdminDB = rst.getPrimary().getDB("admin");
+ secondaryAdminDB = rst.getSecondary().getDB("admin");
+ checkFCV(primaryAdminDB, lastContinuousFCV);
+ checkFCV(secondaryAdminDB, lastContinuousFCV);
+
+ jsTestLog("Validating on-disk changes after binary downgrade");
+ for (let test of downgradeOnDiskChangesTests) {
+ test.validateAfterBinaryDowngrade(rst.getPrimary());
+ }
+
+ // Test that the cluster can restart with a latest binary.
+ rst.upgradeSet({binVersion: latest});
+ primaryAdminDB = rst.getPrimary().getDB("admin");
+ secondaryAdminDB = rst.getSecondary().getDB("admin");
+ checkFCV(primaryAdminDB, lastContinuousFCV);
+ checkFCV(secondaryAdminDB, lastContinuousFCV);
+
+ // Test that the FCV can be upgraded back to 'latestFCV'.
+ assert.commandWorked(primaryAdminDB.runCommand({setFeatureCompatibilityVersion: latestFCV}));
+ checkFCV(primaryAdminDB, latestFCV);
+ rst.awaitReplication();
+ checkFCV(secondaryAdminDB, latestFCV);
+
+ rst.stopSet();
+}
+
+function runShardingTest() {
+ jsTestLog("Running sharding test");
+
+ // A 'latest' binary cluster started with clean data files will set FCV to 'latestFCV'.
+ let st =
+ new ShardingTest({shards: {rs0: {nodes: [{binVersion: latest}, {binVersion: latest}]}}});
+ let mongosAdminDB = st.s.getDB("admin");
+ let configPrimaryAdminDB = st.configRS.getPrimary().getDB("admin");
+ let shardPrimaryAdminDB = st.rs0.getPrimary().getDB("admin");
+
+ checkFCV(configPrimaryAdminDB, latestFCV);
+ checkFCV(shardPrimaryAdminDB, latestFCV);
+
+ jsTestLog("Introducing on-disk changes to be downgraded in FCV downgrade");
+ for (let test of downgradeOnDiskChangesTests) {
+ test.onDiskChangesBeforeDowngrade(st.s);
+ }
+
+ jsTestLog(
+ "Test that setFeatureCompatibilityVersion succeeds with {downgradeOnDiskChanges: true} " +
+ "on mongos");
+ assert.commandWorked(mongosAdminDB.runCommand(
+ {setFeatureCompatibilityVersion: lastContinuousFCV, downgradeOnDiskChanges: true}));
+
+ // FCV propagates to config and shard.
+ checkFCV(configPrimaryAdminDB, lastContinuousFCV);
+ checkFCV(shardPrimaryAdminDB, lastContinuousFCV);
+
+ jsTestLog("Validating on-disk changes after FCV downgrade");
+ for (let test of downgradeOnDiskChangesTests) {
+ test.validateAfterFCVDowngrade(st.s);
+ }
+
+ // Test that the cluster can restart with a last-continuous binary.
+ st.upgradeCluster(lastContinuous, {waitUntilStable: true});
+ configPrimaryAdminDB = st.configRS.getPrimary().getDB("admin");
+ shardPrimaryAdminDB = st.rs0.getPrimary().getDB("admin");
+ checkFCV(configPrimaryAdminDB, lastContinuousFCV);
+ checkFCV(shardPrimaryAdminDB, lastContinuousFCV);
+
+ jsTestLog("Validating on-disk changes after binary downgrade");
+ for (let test of downgradeOnDiskChangesTests) {
+ test.validateAfterBinaryDowngrade(st.s);
+ }
+
+ // Test that the cluster can restart with a latest binary.
+ st.upgradeCluster(latest, {waitUntilStable: true});
+ configPrimaryAdminDB = st.configRS.getPrimary().getDB("admin");
+ shardPrimaryAdminDB = st.rs0.getPrimary().getDB("admin");
+ checkFCV(configPrimaryAdminDB, lastContinuousFCV);
+ checkFCV(shardPrimaryAdminDB, lastContinuousFCV);
+
+ // Test that the FCV can be upgraded back to 'latestFCV'.
+ mongosAdminDB = st.s.getDB("admin");
+ assert.commandWorked(mongosAdminDB.runCommand({setFeatureCompatibilityVersion: latestFCV}));
+ checkFCV(configPrimaryAdminDB, latestFCV);
+ checkFCV(shardPrimaryAdminDB, latestFCV);
+
+ st.stop();
+}
+
+runStandaloneTest();
+runReplicaSetTest();
+runShardingTest();
+})();