mongo/jstests/noPassthrough/query/js/deprecated_serverside_js.js

208 lines
7.0 KiB
JavaScript

// Server-side Javascript is deprecated in 8.0
//
// In this test, we run queries with $where, $function, and $accumulator multiple times.
// We want to make sure that the deprecation warning message is only logged twice despite
// the multiple invocations in an effort to not clutter the dev's console.
// More specifically, we expect to only log 1 out of 128 events.
// @tags: [requires_scripting]
import {iterateMatchingLogLines} from "jstests/libs/log.js";
import {ShardingTest} from "jstests/libs/shardingtest.js";
const dbName = "testDB";
const collName = "testColl";
const whereCmdObj = {
find: collName,
filter: {
$where: function () {
return this.cust_id.split("").reverse().join("") == "FED";
},
},
};
const accumulatorCmdObj = {
aggregate: collName,
cursor: {},
pipeline: [
{
$group: {
_id: "$cust_id",
idCount: {
$accumulator: {
init: function () {
return 0;
},
accumulateArgs: ["$val"],
accumulate: function (state, val) {
return state + val;
},
merge: function (state1, state2) {
return state1 + state2;
},
finalize: function (state) {
return state;
},
},
},
},
},
],
};
const functionFindCmdObj = {
find: collName,
filter: {
$expr: {
$function: {
body: function (id) {
return id.split("").reverse().join("") == "FED";
},
args: ["$cust_id"],
lang: "js",
},
},
},
};
const functionAggCmdObj = {
aggregate: collName,
cursor: {},
pipeline: [
{
$project: {
newValue: {
$function: {
args: ["$amount", -1],
body: function (first, second) {
return first + second;
},
lang: "js",
},
},
_id: 0,
},
},
],
};
const whereDeprecationMsg = {
msg: "$where is deprecated. For more information, see https://www.mongodb.com/docs/manual/reference/operator/query/where/",
};
const functionDeprecationMsg = {
msg: "$function is deprecated. For more information, see https://www.mongodb.com/docs/manual/reference/operator/aggregation/function/",
};
const accumulatorDeprecationMsg = {
msg: "$accumulator is deprecated. For more information, see https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator/",
};
const data = [
{cust_id: "ABC", amount: 100},
{cust_id: "ABC", amount: 200},
{cust_id: "DEF", amount: 50},
{cust_id: "ABC", amount: 10},
{cust_id: "ABC", amount: 20},
{cust_id: "DEF", amount: 5},
];
function checkLogs(db, deprecationMsg, numLogLines) {
const globalLogs = db.adminCommand({getLog: "global"});
const matchingLogLines = [...iterateMatchingLogLines(globalLogs.log, deprecationMsg)];
assert.eq(matchingLogLines.length, numLogLines, matchingLogLines);
}
/**
* This function will test for the logging of the deprecation messages for different operators
* that use server-side Javascript. The server logs for the first tick of an expression and then
* every 128 ticks, so the query is run a total of 129 times. The test can run either on mongod
* or mongos, and supports both find and agg. If a ShardingTest is provided, the primary shard's
* logs will also be checked.
*
* db: The specified mongod or mongos in which the query is executed.
* deprecationMsg: The expected log message for an expression.
* command: The agg or find command involving only one of the expressions.
* shards: The ShardingTest containing the shards that pair up with the mongos. Null by
* default to accomodate for the mongod case.
*/
function deprecationTest(db, deprecationMsg, command, shards = null) {
assert.commandWorked(db.adminCommand({clearLog: "global"}));
// Assert that deprecation msg is not logged before the command is even run.
checkLogs(db, deprecationMsg, 0);
if (shards) {
assert.commandWorked(shards.shard0.getDB(dbName).adminCommand({clearLog: "global"}));
// Same as above but in the primary shard.
checkLogs(shards.shard0.getDB(dbName), deprecationMsg, 0);
}
assert.commandWorked(db.runCommand(command));
// Now that we have ran the command, make sure the deprecation message is logged once.
checkLogs(db, deprecationMsg, 1);
if (shards) {
// Same as above but in the primary shard.
checkLogs(shards.shard0.getDB(dbName), deprecationMsg, 1);
}
// Now run the query 128 more times to get another log.
for (let i = 0; i < 128; i++) {
assert.commandWorked(db.runCommand(command));
}
// We check that we only had one more log.
checkLogs(db, deprecationMsg, 2);
if (shards) {
// Same as above but in the primary shard.
checkLogs(shards.shard0.getDB(dbName), deprecationMsg, 2);
// Check that we didn't log on other shards but the primary.
checkLogs(shards.shard1.getDB(dbName), deprecationMsg, 0);
}
}
jsTest.log("Test standalone");
const standalone = MongoRunner.runMongod({});
const standaloneDB = standalone.getDB(dbName);
const standaloneColl = standaloneDB.getCollection(collName);
assert.commandWorked(standaloneColl.insert(data));
deprecationTest(standaloneDB, whereDeprecationMsg, whereCmdObj);
deprecationTest(standaloneDB, accumulatorDeprecationMsg, accumulatorCmdObj);
deprecationTest(standaloneDB, functionDeprecationMsg, functionAggCmdObj);
deprecationTest(standaloneDB, functionDeprecationMsg, functionFindCmdObj);
MongoRunner.stopMongod(standalone);
jsTest.log("Test sharded");
const shards = new ShardingTest({shards: 2, mongos: 1});
const session = shards.s.getDB(dbName).getMongo().startSession();
const shardedDB = session.getDatabase(dbName);
assert.commandWorked(
shards.s0.adminCommand({enableSharding: shardedDB.getName(), primaryShard: shards.shard0.shardName}),
);
const shardedColl = shardedDB.testColl;
assert.commandWorked(shardedDB.createCollection(shardedColl.getName()));
assert.commandWorked(shards.s0.adminCommand({shardCollection: shardedColl.getFullName(), key: {_id: 1}}));
assert.commandWorked(shardedColl.insert(data));
deprecationTest(shardedDB, whereDeprecationMsg, whereCmdObj, shards);
deprecationTest(shardedDB, accumulatorDeprecationMsg, accumulatorCmdObj, shards);
deprecationTest(shardedDB, functionDeprecationMsg, functionAggCmdObj, shards);
deprecationTest(shardedDB, functionDeprecationMsg, functionFindCmdObj, shards);
shards.stop();