SERVER-104776: Enforce “no-var” rule in shell's JS unittests (#35928)

GitOrigin-RevId: fb63c7c0b15cd913b986514ef03c5e53e5ad6deb
This commit is contained in:
Steve McClure 2025-05-23 14:14:12 -07:00 committed by MongoDB Bot
parent 6ca3eed314
commit f985c65c77
14 changed files with 63 additions and 55 deletions

View File

@ -389,4 +389,11 @@ export default [
"mongodb/no-tojson-fn": 0, "mongodb/no-tojson-fn": 0,
}, },
}, },
{
// Shell-specific: extra strict!
files: ["jstests/core/js/**", "jstests/noPassthrough/shell/**"],
rules: {
"no-var": 2,
},
},
]; ];

View File

@ -1,9 +1,9 @@
function basic1(key, lookup, shouldFail) { function basic1(key, lookup, shouldFail) {
var m = new BSONAwareMap(); let m = new BSONAwareMap();
m.put(key, 17); m.put(key, 17);
var out = m.get(lookup || key); let out = m.get(lookup || key);
if (!shouldFail) { if (!shouldFail) {
assert.eq(17, out, "basic1 missing: " + tojson(key)); assert.eq(17, out, "basic1 missing: " + tojson(key));

View File

@ -5,13 +5,13 @@
const numLines = 300; const numLines = 300;
const lineContents = "lots of super fun text\n".repeat(numLines).trim(); const lineContents = "lots of super fun text\n".repeat(numLines).trim();
var echoTest = function() { let echoTest = function() {
clearRawMongoProgramOutput(); clearRawMongoProgramOutput();
// This will produce `numLines` + 1 lines of output because echo isn't being called with // This will produce `numLines` + 1 lines of output because echo isn't being called with
// `-n`. This will block until the program exits. // `-n`. This will block until the program exits.
var exitCode = runProgram("echo", lineContents); let exitCode = runProgram("echo", lineContents);
var output = rawMongoProgramOutput(".*"); let output = rawMongoProgramOutput(".*");
assert.eq(0, exitCode); assert.eq(0, exitCode);
@ -22,6 +22,6 @@ var echoTest = function() {
// The motivating failure for the test was a race in runProgram. Empirically, 10 runs has always // The motivating failure for the test was a race in runProgram. Empirically, 10 runs has always
// been sufficient for this to fail. 16 gives the test some leeway. // been sufficient for this to fail. 16 gives the test some leeway.
for (var i = 0; i < 16; i++) { for (let i = 0; i < 16; i++) {
echoTest(); echoTest();
} }

View File

@ -1,10 +1,10 @@
function tryParallelShell() { function tryParallelShell() {
var nevercalled = startParallelShell(""); let nevercalled = startParallelShell("");
// The shell running this function will generate a non-zero exit code // The shell running this function will generate a non-zero exit code
// because nevercalled isn't called. // because nevercalled isn't called.
} }
var ret = startParallelShell(tryParallelShell); let ret = startParallelShell(tryParallelShell);
assert.throws(ret); assert.throws(ret);
// Since ret is called by assert.throws, the shell running this file will // Since ret is called by assert.throws, the shell running this file will

View File

@ -155,7 +155,7 @@ tests.push(function assertShouldThrowExceptionForFalseWithDefaultMessagePrefix()
}); });
tests.push(function assertShouldNotCallMsgFunctionsOnSuccess() { tests.push(function assertShouldNotCallMsgFunctionsOnSuccess() {
var called = false; let called = false;
assert(true, () => { assert(true, () => {
called = true; called = true;
@ -165,7 +165,7 @@ tests.push(function assertShouldNotCallMsgFunctionsOnSuccess() {
}); });
tests.push(function assertShouldCallMsgFunctionsOnFailure() { tests.push(function assertShouldCallMsgFunctionsOnFailure() {
var called = false; let called = false;
assert.throws(() => { assert.throws(() => {
assert(false, () => { assert(false, () => {
@ -211,7 +211,7 @@ tests.push(function eqShouldFailWhenNotEqual() {
}); });
tests.push(function eqShouldNotCallMsgFunctionOnSuccess() { tests.push(function eqShouldNotCallMsgFunctionOnSuccess() {
var called = false; let called = false;
assert.doesNotThrow(() => { assert.doesNotThrow(() => {
assert.eq(3, 3, () => { assert.eq(3, 3, () => {
@ -223,7 +223,7 @@ tests.push(function eqShouldNotCallMsgFunctionOnSuccess() {
}); });
tests.push(function eqShouldCallMsgFunctionOnFailure() { tests.push(function eqShouldCallMsgFunctionOnFailure() {
var called = false; let called = false;
assert.throws(() => { assert.throws(() => {
assert.eq(1, 3, () => { assert.eq(1, 3, () => {
@ -335,7 +335,7 @@ tests.push(function soonFailsIfMethodNeverPasses() {
}); });
tests.push(function soonPassesIfMethodEventuallyPasses() { tests.push(function soonPassesIfMethodEventuallyPasses() {
var count = 0; let count = 0;
assert.doesNotThrow(() => { assert.doesNotThrow(() => {
assert.soon(() => { assert.soon(() => {
count += 1; count += 1;
@ -347,7 +347,7 @@ tests.push(function soonPassesIfMethodEventuallyPasses() {
/* assert.soonNoExcept tests */ /* assert.soonNoExcept tests */
tests.push(function soonNoExceptEventuallyPassesEvenWithExceptions() { tests.push(function soonNoExceptEventuallyPassesEvenWithExceptions() {
var count = 0; let count = 0;
assert.doesNotThrow(() => { assert.doesNotThrow(() => {
assert.soonNoExcept(() => { assert.soonNoExcept(() => {
count += 1; count += 1;
@ -360,7 +360,7 @@ tests.push(function soonNoExceptEventuallyPassesEvenWithExceptions() {
}); });
tests.push(function soonNoExceptFailsIfExceptionAlwaysThrown() { tests.push(function soonNoExceptFailsIfExceptionAlwaysThrown() {
var count = 0; let count = 0;
assert.throws(() => { assert.throws(() => {
assert.soonNoExcept(() => { assert.soonNoExcept(() => {
throw new Error('failed'); throw new Error('failed');
@ -371,7 +371,7 @@ tests.push(function soonNoExceptFailsIfExceptionAlwaysThrown() {
/* assert.retry tests */ /* assert.retry tests */
tests.push(function retryPassesAfterAFewAttempts() { tests.push(function retryPassesAfterAFewAttempts() {
var count = 0; let count = 0;
assert.doesNotThrow(() => { assert.doesNotThrow(() => {
assert.retry(() => { assert.retry(() => {
@ -394,7 +394,7 @@ tests.push(function retryFailsAfterMaxAttempts() {
/* assert.retryNoExcept tests */ /* assert.retryNoExcept tests */
tests.push(function retryNoExceptPassesAfterAFewAttempts() { tests.push(function retryNoExceptPassesAfterAFewAttempts() {
var count = 0; let count = 0;
assert.doesNotThrow(() => { assert.doesNotThrow(() => {
assert.retryNoExcept(() => { assert.retryNoExcept(() => {

View File

@ -39,8 +39,8 @@ tests.push(function rawCommandOk() {
function _assertMsgFunctionExecution( function _assertMsgFunctionExecution(
assertFunc, assertParameter, {expectException: expectException = false} = {}) { assertFunc, assertParameter, {expectException: expectException = false} = {}) {
var msgFunctionCalled = false; let msgFunctionCalled = false;
var expectedAssert = assert.doesNotThrow; let expectedAssert = assert.doesNotThrow;
if (expectException) { if (expectException) {
expectedAssert = assert.throws; expectedAssert = assert.throws;
@ -63,7 +63,7 @@ tests.push(function msgFunctionOnlyCalledOnFailure() {
assert.commandWorkedIgnoringWriteErrors, res, {expectException: false}); assert.commandWorkedIgnoringWriteErrors, res, {expectException: false});
_assertMsgFunctionExecution(assert.commandFailed, res, {expectException: true}); _assertMsgFunctionExecution(assert.commandFailed, res, {expectException: true});
var msgFunctionCalled = false; let msgFunctionCalled = false;
assert.throws(() => assert.commandFailedWithCode(res, 0, () => { assert.throws(() => assert.commandFailedWithCode(res, 0, () => {
msgFunctionCalled = true; msgFunctionCalled = true;
})); }));

View File

@ -4,7 +4,7 @@
// We explicitly declare the global 'db' object since the rest of the test runs with strict-mode // We explicitly declare the global 'db' object since the rest of the test runs with strict-mode
// enabled. // enabled.
var db; var db; // eslint-disable-line no-var
const conn = MongoRunner.runMongod({}); const conn = MongoRunner.runMongod({});
assert.neq(null, conn, "mongod was unable to start up"); assert.neq(null, conn, "mongod was unable to start up");

View File

@ -2,15 +2,15 @@
// appropriate permissions (where relevant). // appropriate permissions (where relevant).
// Use dataPath because it includes the trailing "/" or "\". // Use dataPath because it includes the trailing "/" or "\".
var tmpHome = MongoRunner.dataPath; let tmpHome = MongoRunner.dataPath;
// Ensure it exists and is a dir (eg. if running without resmoke.py and /data/db doesn't exist). // Ensure it exists and is a dir (eg. if running without resmoke.py and /data/db doesn't exist).
mkdir(tmpHome); mkdir(tmpHome);
removeFile(tmpHome + ".dbshell"); removeFile(tmpHome + ".dbshell");
var args = []; let args = [];
var cmdline = "mongo --nodb"; let cmdline = "mongo --nodb";
var redirection = ""; let redirection = "";
var env = {}; let env = {};
if (_isWindows()) { if (_isWindows()) {
args.push("cmd.exe"); args.push("cmd.exe");
args.push("/c"); args.push("/c");
@ -23,14 +23,15 @@ if (_isWindows()) {
// USERPROFILE set to the tmp homedir. // USERPROFILE set to the tmp homedir.
// Since NUL is a character device, isatty() will return true, which means that .mongorc.js // Since NUL is a character device, isatty() will return true, which means that .mongorc.js
// will be created in the HOMEDRIVE + HOMEPATH location, so we must set them also. // will be created in the HOMEDRIVE + HOMEPATH location, so we must set them also.
let tmpHomeDrive, tmpHomePath;
if (tmpHome.match("^[a-zA-Z]:")) { if (tmpHome.match("^[a-zA-Z]:")) {
var tmpHomeDrive = tmpHome.substr(0, 2); tmpHomeDrive = tmpHome.substr(0, 2);
var tmpHomePath = tmpHome.substr(2); tmpHomePath = tmpHome.substr(2);
} else { } else {
var _pwd = pwd(); let _pwd = pwd();
assert(_pwd.match("^[a-zA-Z]:"), "pwd must include drive"); assert(_pwd.match("^[a-zA-Z]:"), "pwd must include drive");
var tmpHomeDrive = _pwd.substr(0, 2); tmpHomeDrive = _pwd.substr(0, 2);
var tmpHomePath = tmpHome; tmpHomePath = tmpHome;
} }
env = {USERPROFILE: tmpHome, HOMEDRIVE: tmpHomeDrive, HOMEPATH: tmpHomePath}; env = {USERPROFILE: tmpHome, HOMEDRIVE: tmpHomeDrive, HOMEPATH: tmpHomePath};
@ -60,16 +61,16 @@ if (_isWindows()) {
cmdline += " " + redirection; cmdline += " " + redirection;
args.push(cmdline); args.push(cmdline);
jsTestLog("Running args:\n " + tojson(args) + "\nwith env:\n " + tojson(env)); jsTestLog("Running args:\n " + tojson(args) + "\nwith env:\n " + tojson(env));
var pid = _startMongoProgram({args, env}); let pid = _startMongoProgram({args, env});
var rc = waitProgram(pid); let rc = waitProgram(pid);
assert.eq(rc, 0); assert.eq(rc, 0);
var files = listFiles(tmpHome); let files = listFiles(tmpHome);
jsTestLog(tojson(files)); jsTestLog(tojson(files));
var findFile = function(baseName) { let findFile = function(baseName) {
for (var i = 0; i < files.length; i++) { for (let i = 0; i < files.length; i++) {
if (files[i].baseName === baseName) { if (files[i].baseName === baseName) {
return files[i]; return files[i];
} }
@ -77,8 +78,8 @@ var findFile = function(baseName) {
return undefined; return undefined;
}; };
var targetFile = ".dbshell"; let targetFile = ".dbshell";
var file = findFile(targetFile); let file = findFile(targetFile);
assert.neq(typeof (file), "undefined", targetFile + " should exist, but it doesn't"); assert.neq(typeof (file), "undefined", targetFile + " should exist, but it doesn't");
assert.eq(file.isDirectory, false, targetFile + " should not be a directory, but it is"); assert.eq(file.isDirectory, false, targetFile + " should not be a directory, but it is");
@ -91,11 +92,11 @@ if (!_isWindows()) {
// `ls -l` is POSIX, so this is the best that we have. // `ls -l` is POSIX, so this is the best that we have.
// Check for exactly "-rw-------". // Check for exactly "-rw-------".
clearRawMongoProgramOutput(); clearRawMongoProgramOutput();
var rc = runProgram("ls", "-l", file.name); let rc = runProgram("ls", "-l", file.name);
assert.eq(rc, 0); assert.eq(rc, 0);
var output = rawMongoProgramOutput(".*"); let output = rawMongoProgramOutput(".*");
var fields = output.split(" "); let fields = output.split(" ");
// First field is the prefix, second field is the `ls -l` permissions. // First field is the prefix, second field is the `ls -l` permissions.
assert.eq(fields[1].substr(0, 10), "-rw-------", targetFile + " has bad permissions"); assert.eq(fields[1].substr(0, 10), "-rw-------", targetFile + " has bad permissions");
} }

View File

@ -3,10 +3,10 @@
if (!_isWindows()) { if (!_isWindows()) {
clearRawMongoProgramOutput(); clearRawMongoProgramOutput();
var rc = runProgram("mongo", "--nodb", "--quiet", "--eval", "print(isInteractive())"); let rc = runProgram("mongo", "--nodb", "--quiet", "--eval", "print(isInteractive())");
assert.eq(rc, 0); assert.eq(rc, 0);
var output = rawMongoProgramOutput(".*"); let output = rawMongoProgramOutput(".*");
var response = (output.split('\n').slice(-2)[0]).split(' ')[1]; let response = (output.split('\n').slice(-2)[0]).split(' ')[1];
assert.eq(response, "false", "Expected 'false' in script mode"); assert.eq(response, "false", "Expected 'false' in script mode");
// now try interactive // now try interactive
clearRawMongoProgramOutput(); clearRawMongoProgramOutput();

View File

@ -6,8 +6,8 @@
// times from the registry // times from the registry
// Verify that an invariant failure doesn't occur in the program registry // Verify that an invariant failure doesn't occur in the program registry
try { try {
var cleanup = startParallelShell("MongoRunner.runningChildPids();", undefined, true); let cleanup = startParallelShell("MongoRunner.runningChildPids();", undefined, true);
var cleanup2 = startParallelShell("MongoRunner.runningChildPids();", undefined, true); let cleanup2 = startParallelShell("MongoRunner.runningChildPids();", undefined, true);
sleep(5000); sleep(5000);
try { try {

View File

@ -1,12 +1,12 @@
var checkShell = function(retCode) { let checkShell = function(retCode) {
var args = [ let args = [
"mongo", "mongo",
"--nodb", "--nodb",
"--eval", "--eval",
"quit(" + retCode + ");", "quit(" + retCode + ");",
]; ];
var actualRetCode = _runMongoProgram.apply(null, args); let actualRetCode = _runMongoProgram.apply(null, args);
assert.eq(retCode, actualRetCode); assert.eq(retCode, actualRetCode);
}; };

View File

@ -44,7 +44,7 @@ tests.push(function checkTestDataWithFunc() {
// We cannot directly compare testData & TestData because the func object // We cannot directly compare testData & TestData because the func object
// has extra whitespace and line control. // has extra whitespace and line control.
assert.eq(Object.keys(TestData), Object.keys(testData)); assert.eq(Object.keys(TestData), Object.keys(testData));
for (var property in TestData) { for (let property in TestData) {
if (TestData.hasOwnProperty(property) && !(TestData.property instanceof Code)) { if (TestData.hasOwnProperty(property) && !(TestData.property instanceof Code)) {
assert.eq(TestData.property, testData.property); assert.eq(TestData.property, testData.property);
} }

View File

@ -11,7 +11,7 @@ rst.initiate();
const collName = "shell_uses_transaction_read_concern"; const collName = "shell_uses_transaction_read_concern";
const primary = rst.getPrimary(); const primary = rst.getPrimary();
const db = primary.getDB("test"); const db = primary.getDB("test");
var coll = db.getCollection(collName); let coll = db.getCollection(collName);
const testDoc = { const testDoc = {
"test": "doc", "test": "doc",
"_id": 0 "_id": 0

View File

@ -33,7 +33,7 @@ function _doFailedWrite(collection) {
/* writeOK tests */ /* writeOK tests */
tests.push(function writeOKSuccessfulWriteDoesNotCallMsgFunction() { tests.push(function writeOKSuccessfulWriteDoesNotCallMsgFunction() {
var msgFunctionCalled = false; let msgFunctionCalled = false;
const result = db.coll.insert({data: "hello world"}); const result = db.coll.insert({data: "hello world"});
assert.doesNotThrow(() => { assert.doesNotThrow(() => {
@ -46,7 +46,7 @@ tests.push(function writeOKSuccessfulWriteDoesNotCallMsgFunction() {
}); });
tests.push(function writeOKUnsuccessfulWriteDoesCallMsgFunction() { tests.push(function writeOKUnsuccessfulWriteDoesCallMsgFunction() {
var msgFunctionCalled = false; let msgFunctionCalled = false;
const failedResult = _doFailedWrite(db.coll); const failedResult = _doFailedWrite(db.coll);
assert.throws(() => { assert.throws(() => {
@ -60,7 +60,7 @@ tests.push(function writeOKUnsuccessfulWriteDoesCallMsgFunction() {
/* writeError tests */ /* writeError tests */
tests.push(function writeErrorSuccessfulWriteDoesCallMsgFunction() { tests.push(function writeErrorSuccessfulWriteDoesCallMsgFunction() {
var msgFunctionCalled = false; let msgFunctionCalled = false;
const result = db.coll.insert({data: "hello world"}); const result = db.coll.insert({data: "hello world"});
assert.throws(() => { assert.throws(() => {
@ -73,7 +73,7 @@ tests.push(function writeErrorSuccessfulWriteDoesCallMsgFunction() {
}); });
tests.push(function writeErrorUnsuccessfulWriteDoesNotCallMsgFunction() { tests.push(function writeErrorUnsuccessfulWriteDoesNotCallMsgFunction() {
var msgFunctionCalled = false; let msgFunctionCalled = false;
const failedResult = _doFailedWrite(db.coll); const failedResult = _doFailedWrite(db.coll);
assert.doesNotThrow(() => { assert.doesNotThrow(() => {