mirror of https://github.com/mongodb/mongo
118 lines
4.9 KiB
JavaScript
118 lines
4.9 KiB
JavaScript
/**
|
|
* Tests the validate command with {background:true} in a replica set.
|
|
*
|
|
* Checks that {full:true} cannot be run with {background:true}.
|
|
* Checks that {background:true} runs.
|
|
* Checks that {background:true} can run concurrently with CRUD ops on the same collection.
|
|
*
|
|
* @tags: [
|
|
* # inMemory does not have checkpoints; background validation only runs on a checkpoint.
|
|
* requires_persistence,
|
|
* # A failpoint is set that only exists on the mongod.
|
|
* assumes_against_mongod_not_mongos,
|
|
* # A failpoint is set against the primary only.
|
|
* does_not_support_stepdowns,
|
|
* # Checkpoint cursors cannot be open in lsm.
|
|
* does_not_support_wiredtiger_lsm,
|
|
* requires_replication,
|
|
* ]
|
|
*/
|
|
|
|
import {configureFailPoint} from "jstests/libs/fail_point_util.js";
|
|
import {ReplSetTest} from "jstests/libs/replsettest.js";
|
|
|
|
const dbName = "db_background_validation_repl";
|
|
const collName = "coll_background_validation_repl";
|
|
|
|
// Starts and returns a replica set.
|
|
const initTest = () => {
|
|
const replSet = new ReplSetTest({nodes: 1, name: "rs"});
|
|
replSet.startSet();
|
|
replSet.initiate();
|
|
const primary = replSet.getPrimary();
|
|
|
|
let testColl = primary.getDB(dbName)[collName];
|
|
testColl.drop();
|
|
return replSet;
|
|
};
|
|
|
|
const doTest = (replSet) => {
|
|
/*
|
|
* Create some indexes and insert some data, so we can validate them more meaningfully.
|
|
*/
|
|
const testDB = replSet.getPrimary().getDB(dbName);
|
|
const testColl = testDB[collName];
|
|
assert.commandWorked(testColl.createIndex({a: 1}));
|
|
assert.commandWorked(testColl.createIndex({b: 1}));
|
|
assert.commandWorked(testColl.createIndex({c: 1}));
|
|
|
|
const numDocs = 100;
|
|
for (let i = 0; i < numDocs; ++i) {
|
|
assert.commandWorked(testColl.insert({a: i, b: i, c: i}));
|
|
}
|
|
|
|
/**
|
|
* Ensure {full:true} and {background:true} cannot be run together.
|
|
*/
|
|
assert.commandFailedWithCode(testColl.validate({background: true, full: true}), ErrorCodes.InvalidOptions);
|
|
|
|
assert.commandWorked(testDB.adminCommand({fsync: 1}));
|
|
|
|
// Check that {backround:true} is successful.
|
|
let res = testColl.validate({background: true});
|
|
assert.commandWorked(res);
|
|
assert(res.valid, "Validate cmd with {background:true} failed: " + tojson(res));
|
|
|
|
/*
|
|
* Test background validation with concurrent CRUD operations.
|
|
*/
|
|
|
|
// Set a failpoint in the background validation code to pause validation while holding a
|
|
// collection lock.
|
|
let failPoint = configureFailPoint(testDB, "pauseCollectionValidationWithLock");
|
|
|
|
jsTest.log(`Starting parallel shell on port ${replSet.getPrimary().port}`);
|
|
// Start an asynchronous thread to run collection validation with {background:true}.
|
|
// Ensure we can perform multiple collection validations on the same collection
|
|
// concurrently.
|
|
let awaitValidateCommand = startParallelShell(function () {
|
|
const asyncTestDB = db.getSiblingDB("db_background_validation_repl");
|
|
const asyncTestColl = asyncTestDB.coll_background_validation_repl;
|
|
const validateRes = asyncTestColl.validate({background: true});
|
|
assert.commandWorked(validateRes, "asynchronous background validate command failed: " + tojson(validateRes));
|
|
assert(validateRes.valid, "asynchronous background validate command was not valid: " + tojson(validateRes));
|
|
}, replSet.getPrimary().port);
|
|
|
|
// Wait for background validation command to start.
|
|
jsTest.log("Waiting for failpoint to hit...");
|
|
failPoint.wait();
|
|
|
|
// Check that CRUD ops are succesful while validation is in progress.
|
|
assert.commandWorked(testColl.remove({a: 1, b: 1, c: 1}));
|
|
assert.commandWorked(testColl.insert({a: 1, b: 1, c: 1, d: 100}));
|
|
assert.commandWorked(testColl.update({d: 100}, {"e": "updated"}));
|
|
let docRes = testColl.find({"e": "updated"});
|
|
assert.eq(1, docRes.toArray().length, "expected to find a single document, found: " + tojson(docRes.toArray()));
|
|
|
|
// Clear the failpoint and make sure the validate command was successful.
|
|
failPoint.off();
|
|
awaitValidateCommand();
|
|
|
|
/**
|
|
* Verify everything is still OK by running foreground validation.
|
|
*/
|
|
res = testColl.validate({background: false});
|
|
assert.commandWorked(res);
|
|
assert(res.valid, "Validate cmd with {background:true} failed: " + tojson(res));
|
|
assert.eq(res.nIndexes, 4, "Expected 4 indexes: " + tojson(res));
|
|
assert.eq(res.nrecords, numDocs, "Expected " + numDocs + " collection records:" + tojson(res));
|
|
assert.eq(res.keysPerIndex._id_, numDocs, "Expected " + numDocs + " _id index records: " + tojson(res));
|
|
assert.eq(res.keysPerIndex.a_1, numDocs, "Expected " + numDocs + " a_1 index records: " + tojson(res));
|
|
assert.eq(res.keysPerIndex.b_1, numDocs, "Expected " + numDocs + " b_1 index records: " + tojson(res));
|
|
assert.eq(res.keysPerIndex.c_1, numDocs, "Expected " + numDocs + " c_1 index records: " + tojson(res));
|
|
};
|
|
|
|
const replSet = initTest();
|
|
doTest(replSet);
|
|
replSet.stopSet();
|