test_runner: remove redundant bootstrap boolean

The test runner bootstrap process awaits a Promise and then sets
a boolean flag. This commit consolidates the Promise and boolean
into a single value. This commit also ensures that the globalRoot
test is always assigned in createTestTree() in order to better
consolidate the CLI/run() and non-CLI configuration.

PR-URL: https://github.com/nodejs/node/pull/54013
Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
This commit is contained in:
Colin Ihrig 2024-07-27 09:27:03 -04:00 committed by GitHub
parent 7a2f1b9738
commit 14e7eb34f4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 20 additions and 21 deletions

View File

@ -28,18 +28,20 @@ const {
} = require('internal/test_runner/utils'); } = require('internal/test_runner/utils');
const { queueMicrotask } = require('internal/process/task_queues'); const { queueMicrotask } = require('internal/process/task_queues');
const { bigint: hrtime } = process.hrtime; const { bigint: hrtime } = process.hrtime;
const resolvedPromise = PromiseResolve();
const testResources = new SafeMap(); const testResources = new SafeMap();
let globalRoot;
testResources.set(reporterScope.asyncId(), reporterScope); testResources.set(reporterScope.asyncId(), reporterScope);
function createTestTree(options = kEmptyObject) { function createTestTree(options = kEmptyObject) {
return setup(new Test({ __proto__: null, ...options, name: '<root>' })); globalRoot = setup(new Test({ __proto__: null, ...options, name: '<root>' }));
return globalRoot;
} }
function createProcessEventHandler(eventName, rootTest) { function createProcessEventHandler(eventName, rootTest) {
return (err) => { return (err) => {
if (!rootTest.harness.bootstrapComplete) { if (rootTest.harness.bootstrapPromise) {
// Something went wrong during the asynchronous portion of bootstrapping // Something went wrong during the asynchronous portion of bootstrapping
// the test runner. Since the test runner is not setup properly, we can't // the test runner. Since the test runner is not setup properly, we can't
// do anything but throw the error. // do anything but throw the error.
@ -196,7 +198,7 @@ function setup(root) {
root.harness = { root.harness = {
__proto__: null, __proto__: null,
allowTestsToRun: false, allowTestsToRun: false,
bootstrapComplete: false, bootstrapPromise: resolvedPromise,
watching: false, watching: false,
coverage: FunctionPrototypeBind(collectCoverage, null, root, coverage), coverage: FunctionPrototypeBind(collectCoverage, null, root, coverage),
resetCounters() { resetCounters() {
@ -222,33 +224,30 @@ function setup(root) {
return root; return root;
} }
let globalRoot;
let asyncBootstrap;
function lazyBootstrapRoot() { function lazyBootstrapRoot() {
if (!globalRoot) { if (!globalRoot) {
globalRoot = createTestTree({ __proto__: null, entryFile: process.argv?.[1] }); // This is where the test runner is bootstrapped when node:test is used
// without the --test flag or the run() API.
createTestTree({ __proto__: null, entryFile: process.argv?.[1] });
globalRoot.reporter.on('test:fail', (data) => { globalRoot.reporter.on('test:fail', (data) => {
if (data.todo === undefined || data.todo === false) { if (data.todo === undefined || data.todo === false) {
process.exitCode = kGenericUserError; process.exitCode = kGenericUserError;
} }
}); });
asyncBootstrap = setupTestReporters(globalRoot.reporter); globalRoot.harness.bootstrapPromise = setupTestReporters(globalRoot.reporter);
} }
return globalRoot; return globalRoot;
} }
async function startSubtest(subtest) { async function startSubtestAfterBootstrap(subtest) {
if (asyncBootstrap) { if (subtest.root.harness.bootstrapPromise) {
// Only incur the overhead of awaiting the Promise once. // Only incur the overhead of awaiting the Promise once.
await asyncBootstrap; await subtest.root.harness.bootstrapPromise;
asyncBootstrap = undefined; subtest.root.harness.bootstrapPromise = null;
if (!subtest.root.harness.bootstrapComplete) { queueMicrotask(() => {
subtest.root.harness.bootstrapComplete = true; subtest.root.harness.allowTestsToRun = true;
queueMicrotask(() => { subtest.root.processPendingSubtests();
subtest.root.harness.allowTestsToRun = true; });
subtest.root.processPendingSubtests();
});
}
} }
await subtest.start(); await subtest.start();
@ -262,7 +261,7 @@ function runInParentContext(Factory) {
return PromiseResolve(); return PromiseResolve();
} }
return startSubtest(subtest); return startSubtestAfterBootstrap(subtest);
} }
const test = (name, options, fn) => { const test = (name, options, fn) => {

View File

@ -596,7 +596,7 @@ function run(options = kEmptyObject) {
teardown = undefined; teardown = undefined;
} }
const runFiles = () => { const runFiles = () => {
root.harness.bootstrapComplete = true; root.harness.bootstrapPromise = null;
root.harness.allowTestsToRun = true; root.harness.allowTestsToRun = true;
return SafePromiseAllSettledReturnVoid(testFiles, (path) => { return SafePromiseAllSettledReturnVoid(testFiles, (path) => {
const subtest = runTestFile(path, filesWatcher, opts); const subtest = runTestFile(path, filesWatcher, opts);