mongo/jstests/auth/default_max_time_ms_aggrega...

138 lines
4.2 KiB
JavaScript

/**
* Tests that 'defaultMaxTimeMS' is applied correctly to aggregate commands.
*
* @tags: [
* requires_replication,
* requires_sharding,
* requires_auth,
* # Transactions aborted upon fcv upgrade or downgrade; cluster parameters use internal txns.
* uses_transactions,
* requires_fcv_80,
* requires_scripting,
* ]
*/
import {ReplSetTest} from "jstests/libs/replsettest.js";
import {ShardingTest} from "jstests/libs/shardingtest.js";
function setDefaultReadMaxTimeMS(db, newValue) {
assert.commandWorked(db.runCommand({setClusterParameter: {defaultMaxTimeMS: {readOperations: newValue}}}));
// Currently, the mongos cluster parameter cache is not updated on setClusterParameter. An
// explicit call to getClusterParameter will refresh the cache.
assert.commandWorked(db.runCommand({getClusterParameter: "defaultMaxTimeMS"}));
}
function runTests(conn) {
const dbName = jsTestName();
const adminDB = conn.getDB("admin");
// Create the admin user, which is used to insert.
adminDB.createUser({user: "admin", pwd: "admin", roles: ["root"]});
assert.eq(1, adminDB.auth("admin", "admin"));
const testDB = adminDB.getSiblingDB(dbName);
const collName = "test";
const coll = testDB.getCollection(collName);
for (let i = 0; i < 10; ++i) {
assert.commandWorked(coll.insert({a: 1}));
}
const slowStage = {
$match: {
$expr: {
$function: {
body: function () {
sleep(1000);
return true;
},
args: [],
lang: "js",
},
},
},
};
// Sets the default maxTimeMS for read operations with a small value.
setDefaultReadMaxTimeMS(adminDB, 1);
// Prepare a regular user without the 'bypassDefaultMaxTimeMS' privilege.
adminDB.createUser({user: "regularUser", pwd: "password", roles: ["readWriteAnyDatabase"]});
const regularUserConn = new Mongo(conn.host).getDB("admin");
assert(regularUserConn.auth("regularUser", "password"), "Auth failed");
const regularUserDB = regularUserConn.getSiblingDB(dbName);
// A long running aggregation will fail even without specifying a maxTimeMS option.
// Note the error could manifest as an Interrupted error sometimes due to the JavaScript
// execution being interrupted. This happens with both using the per-query option and the
// default parameter.
assert.commandFailedWithCode(
regularUserDB.runCommand({
aggregate: collName,
pipeline: [slowStage],
cursor: {},
}),
[ErrorCodes.Interrupted, ErrorCodes.MaxTimeMSExpired],
);
// Specifying a maxTimeMS option will overwrite the default value.
assert.commandWorked(
regularUserDB.runCommand({
aggregate: collName,
pipeline: [slowStage],
cursor: {},
maxTimeMS: 0,
}),
);
// If the aggregate performs a write operation, the time limit will not apply.
assert.commandWorked(
regularUserDB.runCommand({
aggregate: collName,
pipeline: [
slowStage,
{
$out: "foo",
},
],
cursor: {},
}),
);
assert.commandWorked(
regularUserDB.runCommand({
aggregate: collName,
pipeline: [
slowStage,
{
$merge: "bar",
},
],
cursor: {},
}),
);
// Unsets the default MaxTimeMS to make queries not to time out in the following code.
setDefaultReadMaxTimeMS(adminDB, 0);
adminDB.logout();
regularUserDB.logout();
}
const rst = new ReplSetTest({nodes: 1, keyFile: "jstests/libs/key1"});
rst.startSet();
rst.initiate();
runTests(rst.getPrimary());
rst.stopSet();
const st = new ShardingTest({
mongos: 1,
shards: {nodes: 1},
config: {nodes: 1},
keyFile: "jstests/libs/key1",
mongosOptions: {setParameter: {"failpoint.skipClusterParameterRefresh": "{'mode':'alwaysOn'}"}},
});
runTests(st.s);
st.stop();