diff options
author | Mihai Andrei <mihai.andrei@10gen.com> | 2021-10-12 18:04:55 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-10-12 18:50:15 +0000 |
commit | 52174ffab806e33d77ccb255ddc0d6c8023acc8d (patch) | |
tree | e85de328d2ebdf6c09812e5e5fb6b398374a8dfa /jstests/libs | |
parent | 602738c03ec549c5469ad8942ea489b95e83d3d6 (diff) | |
download | mongo-52174ffab806e33d77ccb255ddc0d6c8023acc8d.tar.gz |
SERVER-60389 [SBE] Rewrite engine specific assertions to be multiversion compatible
Co-authored-by Mickey. J Winters <mickey.winters@mongodb.com>
Diffstat (limited to 'jstests/libs')
-rw-r--r-- | jstests/libs/sbe_explain_helpers.js | 41 | ||||
-rw-r--r-- | jstests/libs/sbe_util.js | 96 |
2 files changed, 110 insertions, 27 deletions
diff --git a/jstests/libs/sbe_explain_helpers.js b/jstests/libs/sbe_explain_helpers.js index 1ad1c722dfa..578b125aad5 100644 --- a/jstests/libs/sbe_explain_helpers.js +++ b/jstests/libs/sbe_explain_helpers.js @@ -4,30 +4,31 @@ // Include helpers for analyzing explain output. load("jstests/libs/analyze_plan.js"); +load("jstests/libs/sbe_util.js"); -// SBE does not support building IDHACK plans. As such, if SBE is being used, we assert that the -// generated plan is an 'expectedParentStageForIxScan' + IXSCAN over the _id index. -function assertIdHackPlan(db, root, expectedParentStageForIxScan, isSBEEnabled) { - if (isSBEEnabled) { - const parentStage = getPlanStage(root, expectedParentStageForIxScan); - assert.neq(parentStage, null, root); +function isIdIndexScan(db, root, expectedParentStageForIxScan) { + const parentStage = getPlanStage(root, expectedParentStageForIxScan); + if (!parentStage) + return false; - const ixscan = parentStage.inputStage; - assert.neq(ixscan, null, root); - assert.eq(ixscan.stage, "IXSCAN", root); - assert(!ixscan.hasOwnProperty("filter"), root); - assert.eq(ixscan.indexName, "_id_", root); - } else { - assert(isIdhack(db, root), root); - } + const ixscan = parentStage.inputStage; + if (!ixscan) + return false; + + return ixscan.stage === "IXSCAN" && !ixscan.hasOwnProperty("filter") && + ixscan.indexName === "_id_"; } -// When SBE is enabled, we assert that the generated plan used an IXSCAN. Otherwise, we assert that -// 'isIdhack' returns false. -function assertNonIdHackPlan(db, root, isSBEEnabled) { - if (isSBEEnabled) { - assert(isIxscan(db, root), root); +// Helper to make an assertion depending on the engine being used. If we're in a mixed version +// cluster, then we assert that either 'classicAssert' or 'sbeAssert' is true because the +// outcome will depend on which node we're making assertions against. If we're not in a mixed +// version scenario, then we make an assertion depending on the value of 'isSBEEnabled'. +function engineSpecificAssertion(classicAssert, sbeAssert, theDB, msg) { + if (checkBothEnginesAreRunOnCluster(theDB)) { + assert(classicAssert || sbeAssert, msg); + } else if (checkSBEEnabled(theDB)) { + assert(sbeAssert, msg); } else { - assert(!isIdhack(db, root), root); + assert(classicAssert, msg); } } diff --git a/jstests/libs/sbe_util.js b/jstests/libs/sbe_util.js index bb9bdd0d1b7..2a0731bb905 100644 --- a/jstests/libs/sbe_util.js +++ b/jstests/libs/sbe_util.js @@ -11,7 +11,7 @@ load("jstests/libs/fixture_helpers.js"); // For 'isMongos' * If 'featureFlags' is non-empty, checks if SBE and all the feature flags are enabled. */ function checkSBEEnabled(theDB, featureFlags = []) { - let checkResult = true; + let checkResult = false; assert.soon(() => { // Some test suites kill the primary, potentially resulting in networking errors. We use: @@ -33,18 +33,27 @@ function checkSBEEnabled(theDB, featureFlags = []) { continue; } + const getParam = conn.adminCommand({ + getParameter: 1, + internalQueryForceClassicEngine: 1, + internalQueryEnableSlotBasedExecutionEngine: 1 + }); + if (getParam.hasOwnProperty("internalQueryForceClassicEngine") && + !getParam.internalQueryForceClassicEngine) { + checkResult = true; + } + // Some versions use a different parameter to enable SBE instead of disabling it. + if (getParam.hasOwnProperty("internalQueryEnableSlotBasedExecutionEngine") && + getParam.internalQueryEnableSlotBasedExecutionEngine) { + checkResult = true; + } + featureFlags.forEach(function(featureFlag) { const featureFlagParam = conn.adminCommand({getParameter: 1, [featureFlag]: 1}); checkResult = checkResult && featureFlagParam.hasOwnProperty(featureFlag) && featureFlagParam[featureFlag]["value"]; }); - const getParam = - conn.adminCommand({getParameter: 1, internalQueryForceClassicEngine: 1}); - if (getParam.hasOwnProperty("internalQueryForceClassicEngine") && - getParam.internalQueryForceClassicEngine) { - checkResult = false; - } return true; } catch (e) { continue; @@ -56,3 +65,76 @@ function checkSBEEnabled(theDB, featureFlags = []) { return checkResult; } + +/** + * If 'theDB' corresponds to a node in a cluster, then returns true if the cluster that it + * belongs to has at least one node that has SBE enabled and at least one node that has it + * disabled; false otherwise. + */ +function checkBothEnginesAreRunOnCluster(theDB) { + let result = false; + assert.soon(() => { + if (!FixtureHelpers.isMongos(theDB) && !FixtureHelpers.isReplSet(theDB)) { + return true; + } + + // Retry the check if we fail to discover the topology (this can happen if the test + // suite has killed the primary). + let nodes; + try { + nodes = DiscoverTopology.findNonConfigNodes(theDB.getMongo()); + } catch (e) { + return false; + } + + let engineMap = {sbe: 0, classic: 0}; + + for (const node of nodes) { + // If we cannot contact a node because it was killed or is otherwise unreachable, we + // skip it and check the other nodes in the cluster. For our purposes, this is ok + // because test suites which step down/kill certain nodes are configured to use + // exactly one engine, whereas the test suites which are configured use both engines + // (namely, the multiversion suites), do not step down/kill nodes. + try { + const conn = new Mongo(node); + if (FixtureHelpers.isMongos(conn.getDB("admin"))) { + continue; + } + + const getParam = conn.adminCommand({ + getParameter: 1, + internalQueryForceClassicEngine: 1, + internalQueryEnableSlotBasedExecutionEngine: 1 + }); + + if (getParam.hasOwnProperty("internalQueryForceClassicEngine")) { + if (getParam.internalQueryForceClassicEngine) { + engineMap.classic++; + } else { + engineMap.sbe++; + } + } + + // Some versions use a different parameter to enable SBE instead of disabling it. + if (getParam.hasOwnProperty("internalQueryEnableSlotBasedExecutionEngine")) { + if (!getParam.internalQueryEnableSlotBasedExecutionEngine) { + engineMap.classic++; + } else { + engineMap.sbe++; + } + } + + result = (engineMap.sbe > 0 && engineMap.classic > 0); + if (result) { + return true; + } + } catch (e) { + continue; + } + } + + return true; + }); + + return result; +} |