// Tests for setFeatureCompatibilityVersion. (function() { "use strict"; load("jstests/replsets/rslib.js"); load("jstests/libs/feature_compatibility_version.js"); load("jstests/libs/get_index_helpers.js"); const latest = "latest"; const downgrade = "3.4"; let checkCollectionUUIDs = function(adminDB, isDowngrade) { let databaseList = adminDB.runCommand({"listDatabases": 1}).databases; databaseList.forEach(function(database) { let currentDatabase = adminDB.getSiblingDB(database.name); let collectionInfos = currentDatabase.getCollectionInfos(); for (let i = 0; i < collectionInfos.length; i++) { // Always skip system.indexes due to SERVER-30500. if (collectionInfos[i].name == "system.indexes") { continue; } if (isDowngrade) { assert(!collectionInfos[i].info.uuid, "Unexpected uuid for collection: " + tojson(collectionInfos[i])); } else { assert(collectionInfos[i].info.uuid, "Expect uuid for collection: " + tojson(collectionInfos[i])); } } }); }; let setFCV = function(adminDB, version) { assert.commandWorked(adminDB.runCommand({setFeatureCompatibilityVersion: version})); checkFCV(adminDB, version); }; let insertDataForConn = function(conn, dbs, nodeOptions) { for (let i = 0; i < 20; i++) { let doc = {id: i, a: "foo", conn: conn.name}; for (let j in dbs) { if (nodeOptions.hasOwnProperty("configsvr")) { if (j !== "admin" && j !== "local") { // We can't create user databases on a --configsvr instance. continue; } // Config servers have a majority write concern. assert.writeOK( conn.getDB(dbs[j]).foo.insert(doc, {writeConcern: {w: "majority"}})); } else { assert.writeOK(conn.getDB(dbs[j]).foo.insert(doc)); } } } }; // Create and clear dbpath let sharedDbPath = MongoRunner.dataPath + "set_schema_version"; resetDbpath(sharedDbPath); // Return a mongodb connection with startup options, version and dbpath options let startMongodWithVersion = function(nodeOptions, ver, path) { let version = ver || latest; let dbpath = path || sharedDbPath; let conn = MongoRunner.runMongod( Object.assign({}, nodeOptions, {dbpath: dbpath, binVersion: version})); assert.neq(null, conn, "mongod was unable to start up with version=" + version + " and path=" + dbpath); return conn; }; // // Standalone tests. // let standaloneTest = function(nodeOptions) { let noCleanDataOptions = Object.assign({noCleanData: true}, nodeOptions); // New 3.6 standalone. jsTest.log("Starting a binVersion 3.6 standalone"); let conn = startMongodWithVersion(nodeOptions, latest); let adminDB = conn.getDB("admin"); // Insert some data. insertDataForConn(conn, ["admin", "local", "test"], nodeOptions); if (!nodeOptions.hasOwnProperty("shardsvr")) { // Initially featureCompatibilityVersion is 3.6 except for when we run with shardsvr. // We expect featureCompatibilityVersion to be 3.4 for shardsvr. checkFCV(adminDB, "3.6"); // Ensure all collections have UUIDs in 3.6 mode. checkCollectionUUIDs(adminDB, false); // Set featureCompatibilityVersion to 3.4. setFCV(adminDB, "3.4"); } // Ensure featureCompatibilityVersion is 3.4. checkFCV(adminDB, "3.4"); // Ensure no collections in a featureCompatibilityVersion 3.4 database have UUIDs. checkCollectionUUIDs(adminDB, true); // Stop Mongod 3.6 MongoRunner.stopMongod(conn); // Start Mongod 3.4 with same dbpath jsTest.log("Starting a binVersion 3.4 standalone to test downgrade"); let downgradeConn = startMongodWithVersion(noCleanDataOptions, downgrade); let downgradeAdminDB = downgradeConn.getDB("admin"); // Check FCV document checkFCV34(downgradeAdminDB, "3.4"); // Ensure there are no UUIDs checkCollectionUUIDs(downgradeAdminDB, true); // Stop 3.4 MongoRunner.stopMongod(downgradeConn); // Start 3.6 again jsTest.log("Starting a binVersion 3.6 standalone to test upgrade"); conn = startMongodWithVersion(noCleanDataOptions, latest); adminDB = conn.getDB("admin"); // Ensure all collections have UUIDs after switching back to featureCompatibilityVersion // 3.6. setFCV(adminDB, "3.6"); checkCollectionUUIDs(adminDB, false); // Stop Mongod 3.6 for the last time MongoRunner.stopMongod(conn); }; // // Replica set tests. // let replicaSetTest = function(nodeOptions) { // New 3.6 replica set. jsTest.log("Starting a binVersion 3.6 ReplSetTest"); let rst = new ReplSetTest({nodes: 3, nodeOptions: nodeOptions}); rst.startSet(); rst.initiate(); let primaryAdminDB = rst.getPrimary().getDB("admin"); let secondaries = rst.getSecondaries(); // Insert some data. insertDataForConn(rst.getPrimary(), ["admin", "local", "test"], nodeOptions); rst.awaitReplication(); for (let j = 0; j < secondaries.length; j++) { let secondaryAdminDB = secondaries[j].getDB("admin"); // Insert some data into the local DB. insertDataForConn(secondaries[j], ["local"], nodeOptions); } if (!nodeOptions.hasOwnProperty("shardsvr")) { // Initially featureCompatibilityVersion is 3.6 on primary and secondaries except for // when we run with shardsvr. We expect featureCompatibilityVersion to be 3.4 for // shardsvr. checkFCV(primaryAdminDB, "3.6"); for (let j = 0; j < secondaries.length; j++) { let secondaryAdminDB = secondaries[j].getDB("admin"); checkFCV(secondaryAdminDB, "3.6"); } // Ensure all collections have UUIDs in 3.6 mode on both primary and secondaries. checkCollectionUUIDs(primaryAdminDB, false); for (let j = 0; j < secondaries.length; j++) { let secondaryAdminDB = secondaries[j].getDB("admin"); checkCollectionUUIDs(secondaryAdminDB, false); } // Change featureCompatibilityVersion to 3.4. setFCV(primaryAdminDB, "3.4"); rst.awaitReplication(); } // Ensure featureCompatibilityVersion is 3.4. for (let j = 0; j < secondaries.length; j++) { let secondaryAdminDB = secondaries[j].getDB("admin"); checkFCV(secondaryAdminDB, "3.4"); } // Ensure no collections have UUIDs in 3.4 mode on both primary and secondaries. checkCollectionUUIDs(primaryAdminDB, true); for (let j = 0; j < secondaries.length; j++) { let secondaryAdminDB = secondaries[j].getDB("admin"); checkCollectionUUIDs(secondaryAdminDB, true); } // Stop 3.6 RS rst.stopSet(null /* signal */, true /* forRestart */); // Downgrade RS the 3.4 binary, and make sure everything is okay jsTest.log("Starting a binVersion 3.4 ReplSetTest to test downgrade"); rst.startSet({restart: true, binVersion: downgrade}); // Check that the featureCompatiblityDocument is set to 3.4 and that there are no UUIDs let downgradePrimaryAdminDB = rst.getPrimary().getDB("admin"); let downgradeSecondaries = rst.getSecondaries(); // Initially featureCompatibilityVersion document is 3.4 on primary and secondaries. checkCollectionUUIDs(downgradePrimaryAdminDB, true); checkFCV34(downgradePrimaryAdminDB, "3.4"); for (let j = 0; j < downgradeSecondaries.length; j++) { let secondaryAdminDB = downgradeSecondaries[j].getDB("admin"); checkFCV34(secondaryAdminDB, "3.4"); // Ensure no collections have UUIDs checkCollectionUUIDs(secondaryAdminDB, true); } rst.stopSet(null /* signal */, true /* forRestart */); // Start 3.6 replica set again jsTest.log("Starting a binVersion 3.6 ReplSetTest to test upgrade"); rst.startSet({restart: true, binVersion: latest}); primaryAdminDB = rst.getPrimary().getDB("admin"); secondaries = rst.getSecondaries(); // Ensure all collections have UUIDs after switching back to featureCompatibilityVersion 3.6 // on both primary and secondaries. setFCV(primaryAdminDB, "3.6"); rst.awaitReplication(); for (let j = 0; j < secondaries.length; j++) { let secondaryAdminDB = secondaries[j].getDB("admin"); checkFCV(secondaryAdminDB, "3.6"); } checkCollectionUUIDs(primaryAdminDB, false); for (let j = 0; j < secondaries.length; j++) { let secondaryAdminDB = secondaries[j].getDB("admin"); checkCollectionUUIDs(secondaryAdminDB, false); } rst.stopSet(); }; // Do tests for regular standalones and replica sets. standaloneTest({}); replicaSetTest({}); // Do tests for standalones and replica sets started with --shardsvr. standaloneTest({shardsvr: ""}); replicaSetTest({shardsvr: ""}); // Do tests for standalones and replica sets started with --configsvr. if (jsTest.options().storageEngine !== "mmapv1") { // We don't allow starting config servers with the MMAP storage engine. standaloneTest({configsvr: ""}); replicaSetTest({configsvr: ""}); } })();