diff options
Diffstat (limited to 'jstests/multiVersion/targetedTestsLastLtsFeatures/query_stats_upgrade_downgrade.js')
| -rw-r--r-- | jstests/multiVersion/targetedTestsLastLtsFeatures/query_stats_upgrade_downgrade.js | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/jstests/multiVersion/targetedTestsLastLtsFeatures/query_stats_upgrade_downgrade.js b/jstests/multiVersion/targetedTestsLastLtsFeatures/query_stats_upgrade_downgrade.js new file mode 100644 index 00000000000..20ff7add9cd --- /dev/null +++ b/jstests/multiVersion/targetedTestsLastLtsFeatures/query_stats_upgrade_downgrade.js @@ -0,0 +1,272 @@ +/** + * Verifies that $queryStats operates correctly when upgrading and downgrading. + */ + +load("jstests/multiVersion/libs/multi_rs.js"); +load("jstests/multiVersion/libs/multi_cluster.js"); +load("jstests/libs/collection_drop_recreate.js"); +load("jstests/libs/query_stats_utils.js"); + +(function() { +"use strict"; + +const lastLTSVersion = "last-lts"; + +class UpgradeDowngradeTestFixture { + constructor() { + this.collectionName = "coll"; + } + + getTestDB() { + return this.rst.getPrimary().getDB(jsTestName()); + } + + createAndPopulateTestCollection() { + let testDB = this.getTestDB(); + let coll = assertDropAndRecreateCollection(testDB, "coll"); + assert.commandWorked(coll.insertMany([{x: 0}, {x: 1}, {x: 2}])); + } + + setup() { + jsTestLog("Starting ReplicaSet Upgrade/Downgrade Test!"); + + this.rst = new ReplSetTest({ + name: jsTestName(), + nodes: [{binVersion: lastLTSVersion}, {binVersion: lastLTSVersion}] + }); + this.rst.startSet(); + this.rst.initiate(); + this.createAndPopulateTestCollection(); + } + + teardown() { + jsTestLog("Teardown ReplicaSet Upgrade/Downgrade Test!"); + + this.rst.stopSet(); + } + + getTestCollection() { + return this.getTestDB().getCollection(this.collectionName); + } + + adminCommand(command) { + return this.rst.getPrimary().getDB("admin").runCommand(command); + } + + upgradeBinaries() { + this.rst.upgradeSet({binVersion: "latest"}); + } + + upgradeFCV() { + assert.commandWorked(this.adminCommand({setFeatureCompatibilityVersion: latestFCV})); + } + + downgradeFCV() { + // Downgrade FCV (without restarting) and check that $queryStats returns an error. + assert.commandWorked(this.adminCommand({setFeatureCompatibilityVersion: lastLTSFCV})); + } + + testQueryStatsParam(expectedResult) { + if (expectedResult === true) { + assert.commandWorked( + this.adminCommand({setParameter: 1, internalQueryStatsRateLimit: -1})); + } else { + // Check that $queryStats related parameter does not work. + assert.commandFailed( + this.adminCommand({setParameter: 1, internalQueryStatsRateLimit: -1})); + } + } + + testQueryStatsCommandFailure() { + assert.commandFailedWithCode( + this.adminCommand({aggregate: 1, pipeline: [{$queryStats: {}}], cursor: {}}), + [ErrorCodes.QueryFeatureNotAllowed, 40324]); + } + + isShardedCluster() { + return false; + } + + verifyQueryStatsOutput({expectedNShapes}) { + const queryStats = getQueryStats(this, {collName: this.collectionName}); + assert.eq(expectedNShapes, queryStats.length, queryStats); + verifyMetrics(queryStats); + } +} + +class ShardedClusterUpgradeDowngradeTestFixture extends UpgradeDowngradeTestFixture { + setup() { + jsTestLog("Starting Sharded Upgrade/Downgrade Test!"); + this.shardedTest = new ShardingTest({ + name: jsTestName(), + shards: 1, + mongos: 1, + config: 1, + rs: {nodes: [{binVersion: lastLTSVersion}, {binVersion: lastLTSVersion}]}, + mongosOptions: {binVersion: lastLTSVersion}, + }); + this.createAndPopulateTestCollection(); + } + + isShardedCluster() { + return true; + } + + adminCommand(command) { + return this.shardedTest.s.adminCommand(command); + } + + getTestDB() { + return this.shardedTest.s.getDB(jsTestName()); + } + + upgradeBinaries() { + this.shardedTest.upgradeCluster('latest'); + } + + teardown() { + jsTestLog("Teardown ReplicaSet Upgrade/Downgrade Test!"); + this.shardedTest.stop(); + } +} + +function runTest(fixture) { + // 0. Initialize the fixture, we begin with a binary version that doesn't support queryStats. + fixture.setup(); + + // 1. Test that queryStats related features don't work in the base binary. + // 1.a. Verify queryStats is disabled by checking that setting queryStats related parameters and + // running the $queryStats stage both fail. + fixture.testQueryStatsParam(false); + fixture.testQueryStatsCommandFailure(); + + // 1.b. Run some queries while running base binary. We don't expect these queries to be + // collected by queryStats. + { + let coll = fixture.getTestCollection(); + let res = coll.aggregate([{$match: {x: 2}}]).toArray(); + assert.eq(1, res.length, res); + + res = coll.find({x: 2}).toArray(); + assert.eq(1, res.length, res); + } + + // 2. Upgrade both the binaries and FCV. After the upgrade we expect query stats features + // to work. Further, we verify that the previously executed queries were not collected by + // checking the results from the $queryStats stage. + fixture.upgradeBinaries(); + fixture.upgradeFCV(); + + // 2.a. Verify that queryStats parameters can be set after the upgrade, and that previously + // executed queries were not collected. + fixture.testQueryStatsParam(true); + fixture.verifyQueryStatsOutput({expectedNShapes: 0}); + + // 2.b. Execute two new queries (i.e new query shapes) and check that they are collected. + { + let coll = fixture.getTestCollection(); + let res = coll.aggregate([{$match: {x: 2}}, {$sort: {x: -1}}]).toArray(); + assert.eq(1, res.length, res); + + res = coll.find({x: 2}, {noCursorTimeout: true}).toArray(); + assert.eq(1, res.length, res); + + fixture.verifyQueryStatsOutput({ + expectedNShapes: 2 /* 1 each for the above. $queryStats is not included because we + filter on the collection name. */ + }); + } + + // 3. Downgrade FCV (without restarting). Without restarting the server, we expect the + // queryStatsStore to keep existing entries, but to not collect any more statistics while an FCV + // that doesn't support queryStats is in place. + fixture.downgradeFCV(); + + // 3.a. Run additional queries (new query shapes) after the downgrade. + { + let coll = fixture.getTestCollection(); + let res = coll.aggregate([{$match: {x: 2}}]).toArray(); + assert.eq(1, res.length, res); + + res = coll.find({x: 2}).toArray(); + assert.eq(1, res.length, res); + } + + // 3.b. If we are testing a sharded cluster, we don't expect queryStats to be disabled after the + // FCV downgrade. This is because in a sharded cluster, query stats resides on mongos, and + // mongos doesn't have a concept of its own in memory FCV settings. When a sharded cluster has + // its FCV downgraded, it forwards the downgrade request to the shards and the config + // servers. However, the router itself bases its FCV on its binaries. In our case, once we + // upgrade the binary on the mongos, we can no longer downgrade the FCV to "disable" queryStats. + // As a result, in the sharded scenario we expect the two queries run after the downgrade to + // have been collected by query stats. + if (fixture.isShardedCluster()) { + fixture.verifyQueryStatsOutput({ + expectedNShapes: 4 /* 2 from the previous queries + the two additional ones captured + after the downgrade. */ + }); + fixture.teardown(); + return; + } + + // 3.c. After the FCV downgrade (i.e FCV v5.0), running $queryStats should return an error. + fixture.testQueryStatsCommandFailure(); + + // 3.d. Upgrade the FCV without restart. QueryStatsStore should not have been cleared. Previous + // stats collected should be returned. The queries made during the downgrade should not + // have been collected. Note that getQueryStats() uses the same query to collect the statistics, + // so running $queryStats doesn't result in additional entries. + fixture.upgradeFCV(); + fixture.verifyQueryStatsOutput({expectedNShapes: 2}); + + // 4. Test query stats during a failed FCV downgrade. During the failed FCV downgrade, the FCV + // reverts back to the lastLTSFCV which doesn't support queryStats. + jsTestLog("Turning the failpoint on."); + assert.commandWorked( + fixture.adminCommand({configureFailPoint: 'failDowngrading', mode: "alwaysOn"})); + + assert.commandFailedWithCode(fixture.adminCommand({setFeatureCompatibilityVersion: lastLTSFCV}), + 549181); + + // 4.a. Current FCV is lower than the FCV necessary (7.2) for queryStats to run. These queries + // should not be collected. + { + let coll = fixture.getTestCollection(); + let res = coll.aggregate([{$match: {x: 2}}]).toArray(); + assert.eq(1, res.length, res); + + res = coll.find({x: 2}).toArray(); + assert.eq(1, res.length, res); + } + // 4.b. Running $queryStats should return an error. + fixture.testQueryStatsCommandFailure(ErrorCodes.QueryFeatureNotAllowed); + + // 4.c. Complete the downgrade, then successfully upgrade FCV. Check that the queries run during + // the failed downgrade were not collected. + assert.commandWorked( + fixture.adminCommand({configureFailPoint: 'failDowngrading', mode: "off"})); + assert.commandWorked(fixture.adminCommand({setFeatureCompatibilityVersion: lastLTSFCV})); + + fixture.upgradeFCV(); + fixture.verifyQueryStatsOutput({expectedNShapes: 2}); + + // 4.d. Execute two new queries (new query shapes), these should result in new entries. + { + let coll = fixture.getTestCollection(); + let res = coll.aggregate([{$match: {x: 2}}], {allowDiskUse: false}).toArray(); + assert.eq(1, res.length, res); + + res = coll.find({x: 2}, {allowPartialResults: true}).toArray(); + assert.eq(1, res.length, res); + + fixture.verifyQueryStatsOutput({expectedNShapes: 4}); + } + + fixture.teardown(); +} + +// Perform Upgrade/Downgrade test on replica set. +runTest(new UpgradeDowngradeTestFixture()); +// Perform Upgrade/Downgrade test on sharded cluster. +runTest(new ShardedClusterUpgradeDowngradeTestFixture()); +})();
\ No newline at end of file |
