mongo/jstests/noPassthrough/architecture/failcommand_failpoint_not_p...

173 lines
4.7 KiB
JavaScript

import {Thread} from "jstests/libs/parallelTester.js";
const conn = MongoRunner.runMongod();
assert.neq(null, conn);
const kDbName = "test_failcommand_noparallel";
const db = conn.getDB(kDbName);
// Test times when closing connection.
// Use distinct because it is rarely used by internal operations, making it less likely unrelated
// activity triggers the failpoint.
assert.commandWorked(
db.adminCommand({
configureFailPoint: "failCommand",
mode: {times: 2},
data: {
closeConnection: true,
failCommands: ["distinct"],
},
}),
);
assert.throws(() => db.runCommand({distinct: "c", key: "_id"}));
assert.throws(() => db.runCommand({distinct: "c", key: "_id"}));
assert.commandWorked(db.runCommand({distinct: "c", key: "_id"}));
assert.commandWorked(db.adminCommand({configureFailPoint: "failCommand", mode: "off"}));
// Test the blockConnection patterns.
jsTest.log("Test validation of blockConnection fields");
{
// 'blockTimeMS' must be non-negative.
assert.commandWorked(
db.adminCommand({
configureFailPoint: "failCommand",
mode: "alwaysOn",
data: {
blockConnection: true,
blockTimeMS: -100,
failCommands: ["hello"],
},
}),
);
assert.commandFailedWithCode(db.runCommand({hello: 1}), ErrorCodes.InvalidOptions);
assert.commandWorked(db.adminCommand({configureFailPoint: "failCommand", mode: "off"}));
}
// Insert a test document.
assert.commandWorked(
db.runCommand({
insert: "c",
documents: [{_id: "block_test", run_id: 0}],
}),
);
/**
* Returns the "run_id" of the test document.
*/
function checkRunId() {
const ret = db.runCommand({find: "c", filter: {_id: "block_test"}});
assert.commandWorked(ret);
const doc = ret["cursor"]["firstBatch"][0];
return doc["run_id"];
}
/**
* Runs update to increment the "run_id" of the test document by one.
*/
function incrementRunId() {
assert.commandWorked(
db.runCommand({
update: "c",
updates: [{q: {_id: "block_test"}, u: {$inc: {run_id: 1}}}],
}),
);
}
/**
* Starts and returns a thread for updating the test document by incrementing the
* "run_id" by one.
*/
function startIncrementRunIdThread() {
const latch = new CountDownLatch(1);
let thread = new Thread(
function (connStr, dbName, latch) {
jsTest.log("Sending update");
const client = new Mongo(connStr);
const db = client.getDB(dbName);
latch.countDown();
assert.commandWorked(
db.runCommand({
update: "c",
updates: [{q: {_id: "block_test"}, u: {$inc: {run_id: 1}}}],
}),
);
jsTest.log("Successfully applied update");
},
conn.host,
kDbName,
latch,
);
thread.start();
latch.await();
return thread;
}
assert.eq(checkRunId(), 0);
const kLargeBlockTimeMS = 60 * 1000;
jsTest.log("Test that only commands listed in failCommands block");
{
assert.commandWorked(
db.adminCommand({
configureFailPoint: "failCommand",
mode: "alwaysOn",
data: {
blockConnection: true,
blockTimeMS: kLargeBlockTimeMS,
failCommands: ["update"],
},
}),
);
let thread = startIncrementRunIdThread();
// Check that other commands get through.
assert.commandWorked(db.runCommand({hello: 1}));
assert.eq(checkRunId(), 0);
// Wait for the blocked update to get through.
thread.join();
assert.soon(() => {
return checkRunId() == 1;
});
assert.commandWorked(db.adminCommand({configureFailPoint: "failCommand", mode: "off"}));
}
jsTest.log("Test command changes");
{
assert.commandWorked(
db.adminCommand({
configureFailPoint: "failCommand",
mode: "alwaysOn",
data: {
blockConnection: true,
blockTimeMS: kLargeBlockTimeMS,
failCommands: ["update", "insert"],
},
}),
);
assert.eq(checkRunId(), 1);
// Drop update from the command list and verify that the update gets through.
assert.commandWorked(
db.adminCommand({
configureFailPoint: "failCommand",
mode: "alwaysOn",
data: {
blockConnection: true,
blockTimeMS: kLargeBlockTimeMS,
failCommands: ["insert"],
},
}),
);
incrementRunId();
assert.eq(checkRunId(), 2);
assert.commandWorked(db.adminCommand({configureFailPoint: "failCommand", mode: "off"}));
}
MongoRunner.stopMongod(conn);