Files
mongo/jstests/replsets/libs/dbcheck_old_format_keys_test.js
Zac 591928c619 SERVER-108478 JS formatted by prettier and remove clang-format (#39656)
GitOrigin-RevId: 6c8f6aded47f260aa4f7c231b17dae3302cb1e04
2025-08-21 17:27:09 +00:00

188 lines
6.9 KiB
JavaScript

/**
* Wrapper around ReplSetTest to test dbCheck with old format unique index keys
*/
import {configureFailPoint} from "jstests/libs/fail_point_util.js";
import {ReplSetTest} from "jstests/libs/replsettest.js";
import {forEachNonArbiterNode} from "jstests/replsets/libs/dbcheck_utils.js";
export const defaultNumDocs = 20;
export const defaultNumKeysInserted = 2 * defaultNumDocs;
function loadDummyData() {
const testData = [];
for (let i = 0; i < defaultNumDocs; ++i) {
testData.push({_id: i, a: i, b: i});
}
return testData;
}
export class DbCheckOldFormatKeysTest {
constructor({name = "DbCheckOldFormatKeysTest"}) {
const rst = new ReplSetTest({name, nodes: 3});
rst.startSet();
rst.initiate();
this._rst = rst;
}
getRst() {
return this._rst;
}
getPrimary() {
return this._rst.getPrimary();
}
getSecondaries() {
return this._rst.getSecondaries();
}
insertIndexAndData(dbName, collName, indexSpecs = [{a: 1}, {b: -1}], data = loadDummyData()) {
jsTestLog("Creating indexes on: " + tojson(indexSpecs));
const primary = this.getRst().getPrimary();
const db = primary.getDB(dbName);
let fps = [];
for (let n of this.getRst().nodes) {
fps.push(configureFailPoint(n, "WTIndexCreateUniqueIndexesInOldFormat"));
fps.push(configureFailPoint(n, "WTIndexInsertUniqueKeysInOldFormat"));
}
for (const indexSpec of indexSpecs) {
assert.commandWorked(db.getCollection(collName).createIndex(indexSpec, {unique: true}));
}
jsTestLog(`Inserting documents into collection ${dbName}.${collName}`);
const res = assert.commandWorked(
db.runCommand({insert: collName, documents: data, writeConcern: {w: "majority"}}),
);
this.getRst().awaitReplication();
assert.eq(db.getCollection(collName).find({}).count(), data.length);
jsTestLog(`Inserted with w: majority, opTime ${tojson(res.operationTime)}`);
for (let fp of fps) {
fp.off();
}
forEachNonArbiterNode(this.getRst(), function (node) {
assert.commandWorked(
node.adminCommand({
setParameter: 1,
logComponentVerbosity: {command: 3},
dbCheckHealthLogEveryNBatches: 1,
}),
);
});
}
/**
* Inserts data into the replica set across all nodes. To insert old format unique index keys,
* this function must be called in v4.2 or earlier, prior to upgrading.
*/
insertOldFormatKeyStrings(dbName, collName, indexSpecs = [{a: 1}, {b: -1}], data = loadDummyData()) {
this.insertIndexAndData(dbName, collName, indexSpecs, data);
}
/**
* Creates missing index keys by deleting index keys but skipping the deletion of the records.
* This function should only be called after upgrading to latest and must be called on
* pre-inserted data.
*/
createMissingKeys(nodes, dbName, collName, deleteFilter = {}) {
jsTestLog("Creating missing index keys");
const fps = [];
for (const node of nodes) {
// Skip deleting records and the _id index when running a deletion commmand.
const skipDeleteRecordFp = configureFailPoint(node, "skipDeleteRecord");
const skipUnindexingDocWhenDeletedFp = configureFailPoint(node, "skipUnindexingDocumentWhenDeleted", {
indexName: "_id_",
});
fps.push(skipDeleteRecordFp);
fps.push(skipUnindexingDocWhenDeletedFp);
}
// Call delete on the docs. Deletes all documents if no filter is specified. Any nodes that
// haven't set the failpoints will simply delete all documents.
const coll = this.getPrimary().getDB(dbName).getCollection(collName);
assert.commandWorked(coll.deleteMany(deleteFilter));
this.getRst().awaitReplication();
// Turn off all of the failpoints and return.
for (const fp of fps) {
fp.off();
}
}
createMissingKeysOnPrimary(dbName, collName, deleteFilter = {}) {
this.createMissingKeys([this.getPrimary()], dbName, collName, deleteFilter);
}
createMissingKeysOnSecondaries(dbName, collName, deleteFilter = {}) {
this.createMissingKeys(this.getSecondaries(), dbName, collName, deleteFilter);
}
createMissingKeysOnAllNodes(dbName, collName, deleteFilter = {}) {
this.createMissingKeys(this.getRst().nodes, dbName, collName, deleteFilter);
}
/**
* Creates extra index keys by deleting records but skipping deleting/updating index keys.
* This function should only be called after upgrading to latest and must be called on
* pre-inserted data.
*/
createExtraKeys(nodes, dbName, collName, failpointName, docFilter = {}) {
jsTestLog("Creating extra index keys");
const fps = [];
for (const node of nodes) {
const extraKeysFp = configureFailPoint(node, failpointName, {indexName: "a_1"});
fps.push(extraKeysFp);
}
const coll = this.getPrimary().getDB(dbName).getCollection(collName);
if (failpointName == "skipUnindexingDocumentWhenDeleted") {
// Call delete on the docs. Deletes all documents if no filter is specified. Any nodes
// that haven't set the failpoints will simply delete all documents.
assert.commandWorked(coll.deleteMany(docFilter));
} else if (failpointName == "skipUpdatingIndexDocument") {
assert.commandWorked(coll.updateMany(docFilter, {$unset: {"a": ""}}));
}
this.getRst().awaitReplication();
// Turn off all of the failpoints and return.
for (const fp of fps) {
fp.off();
}
}
createExtraKeysRecordNotFound(nodes, dbName, collName, docFilter = {}) {
this.createExtraKeys(nodes, dbName, collName, "skipUnindexingDocumentWhenDeleted", docFilter);
}
createExtraKeysRecordDoesNotMatch(nodes, dbName, collName, docFilter = {}) {
this.createExtraKeys(nodes, dbName, collName, "skipUpdatingIndexDocument", docFilter);
}
createExtraKeysRecordDoesNotMatchOnPrimary(dbName, collName, docFilter = {}) {
this.createExtraKeysRecordDoesNotMatch([this.getPrimary()], dbName, collName, docFilter);
}
createExtraKeysRecordDoesNotMatchOnAllNodes(dbName, collName, docFilter = {}) {
this.createExtraKeysRecordDoesNotMatch(this.getRst().nodes, dbName, collName, docFilter);
}
createExtraKeysRecordNotFoundOnSecondary(dbName, collName, docFilter = {}) {
this.createExtraKeysRecordNotFound(this.getSecondaries(), dbName, collName, docFilter);
}
createExtraKeysRecordNotFoundOnAllNodes(dbName, collName, docFilter = {}) {
this.createExtraKeysRecordNotFound(this.getRst().nodes, dbName, collName, docFilter);
}
stop() {
this._rst.stopSet();
}
}