summaryrefslogtreecommitdiff
path: root/jstests/libs
diff options
context:
space:
mode:
authorMihai Andrei <mihai.andrei@10gen.com>2021-10-12 18:04:55 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-10-12 18:50:15 +0000
commit52174ffab806e33d77ccb255ddc0d6c8023acc8d (patch)
treee85de328d2ebdf6c09812e5e5fb6b398374a8dfa /jstests/libs
parent602738c03ec549c5469ad8942ea489b95e83d3d6 (diff)
downloadmongo-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.js41
-rw-r--r--jstests/libs/sbe_util.js96
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;
+}