diff options
-rw-r--r-- | jstests/multiVersion/genericSetFCVUsage/set_fcv_downgrade_on_disk_changes.js | 247 |
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(); +})(); |