/**
* Demonstrates a race condition between CBR sampling and a concurrent write that transitions an
* index from non-multikey to multikey.
*
* The race:
* 1. QueryPlanner::plan() reads the index as non-multikey; IndexScanNode::index.multikey = false.
* 2. generateSample() starts a sequential collection scan.
* 3. The scan yields: abandonSnapshot() releases the storage snapshot.
* 4. A concurrent write inserts {a: [1, 2, 3]}, making the compound index multikey on path 'a'.
* 5. The scan resumes on a newer snapshot and includes the array document in _sample.
* 6. estimateIndexSeeks() dispatches to estimateNDV() (non-multikey path) because
* node->index.multikey is still false from step 1.
* 7. countNDV() applies NonArrayProjector to each sample document.
* 8. NonArrayProjector encounters the array and tasserts (11158502), crashing the server.
*
* @tags: [requires_fcv_83]
*/
import {configureFailPoint} from "jstests/libs/fail_point_util.js";
const conn = MongoRunner.runMongod({
setParameter: {
internalQueryFrameworkControl: "forceClassicEngine",
featureFlagCostBasedRanker: true,
internalQueryCBRCEMode: "samplingCE",
internalQuerySamplingBySequentialScan: true,
internalQueryExecYieldIterations: 1,
internalQueryExecYieldPeriodMS: 0,
},
});
assert.neq(null, conn, "mongod failed to start");
const adminDB = conn.getDB("admin");
const testDB = conn.getDB(jsTestName());
const coll = testDB[jsTestName()];
coll.drop();
const kNumDocs = 200;
const docs = [];
for (let i = 0; i < kNumDocs; i++) {
docs.push({a: i, b: i, c: i});
}
assert.commandWorked(coll.insertMany(docs));
assert.commandWorked(coll.createIndexes([{a: 1, b: 1, c: 1}]));
const fpBeforeSampling = configureFailPoint(adminDB, "hangBeforeCBRSamplingGenerateSample");
const awaitQuery = startParallelShell(
`const testColl = db.getSiblingDB("${jsTestName()}")["${jsTestName()}"];
testColl.find({a: {$lt: 50}, c: {$lt: 50}}).explain().finish();`,
conn.port,
);
fpBeforeSampling.wait();
const fpYield = configureFailPoint(adminDB, "setYieldAllLocksHang", {
namespace: coll.getFullName(),
});
fpBeforeSampling.off();
fpYield.wait();
assert.commandWorked(coll.insertOne({a: [1, 2, 3], b: 1}));
fpYield.off();
awaitQuery();
MongoRunner.stopMongod(conn);