From 70bcc67925a70974488e46a0e093514ecaadd867 Mon Sep 17 00:00:00 2001 From: cjihrig Date: Thu, 14 Mar 2024 23:58:20 -0400 Subject: [PATCH] test_runner: run top level tests in a microtask This commit updates the test harness to prevent top level tests from executing immediately. This allows certain config data, such as filtering options, to be discovered before running the tests. --- lib/internal/test_runner/harness.js | 13 ++++++++++++- lib/internal/test_runner/runner.js | 1 + lib/internal/test_runner/test.js | 2 +- .../output/source_mapped_locations.snapshot | 3 +++ 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/lib/internal/test_runner/harness.js b/lib/internal/test_runner/harness.js index b13ca112e5c..504cc1e93ac 100644 --- a/lib/internal/test_runner/harness.js +++ b/lib/internal/test_runner/harness.js @@ -25,6 +25,7 @@ const { setupTestReporters, shouldColorizeTestFiles, } = require('internal/test_runner/utils'); +const { queueMicrotask } = require('internal/process/task_queues'); const { bigint: hrtime } = process.hrtime; const testResources = new SafeMap(); @@ -181,6 +182,7 @@ function setup(root) { root.harness = { __proto__: null, + allowTestsToRun: false, bootstrapComplete: false, coverage: FunctionPrototypeBind(collectCoverage, null, root, coverage), counters: { @@ -219,7 +221,16 @@ function getGlobalRoot() { async function startSubtest(subtest) { await reportersSetup; - getGlobalRoot().harness.bootstrapComplete = true; + + const root = getGlobalRoot(); + if (!root.harness.bootstrapComplete) { + root.harness.bootstrapComplete = true; + queueMicrotask(() => { + root.harness.allowTestsToRun = true; + root.processPendingSubtests(); + }); + } + await subtest.start(); } diff --git a/lib/internal/test_runner/runner.js b/lib/internal/test_runner/runner.js index b7ac5756dad..41fbfdab931 100644 --- a/lib/internal/test_runner/runner.js +++ b/lib/internal/test_runner/runner.js @@ -538,6 +538,7 @@ function run(options = kEmptyObject) { } const runFiles = () => { root.harness.bootstrapComplete = true; + root.harness.allowTestsToRun = true; return SafePromiseAllSettledReturnVoid(testFiles, (path) => { const subtest = runTestFile(path, filesWatcher, opts); filesWatcher?.runningSubtests.set(path, subtest); diff --git a/lib/internal/test_runner/test.js b/lib/internal/test_runner/test.js index 1642cfdd15e..0bb714a617c 100644 --- a/lib/internal/test_runner/test.js +++ b/lib/internal/test_runner/test.js @@ -603,7 +603,7 @@ class Test extends AsyncResource { // it. Otherwise, return a Promise to the caller and mark the test as // pending for later execution. this.reporter.enqueue(this.nesting, this.loc, this.name); - if (!this.parent.hasConcurrency()) { + if (!this.root.harness.allowTestsToRun || !this.parent.hasConcurrency()) { const deferred = createDeferredPromise(); deferred.test = this; diff --git a/test/fixtures/test-runner/output/source_mapped_locations.snapshot b/test/fixtures/test-runner/output/source_mapped_locations.snapshot index 24c3ee8d113..29b70fd0d08 100644 --- a/test/fixtures/test-runner/output/source_mapped_locations.snapshot +++ b/test/fixtures/test-runner/output/source_mapped_locations.snapshot @@ -21,6 +21,9 @@ not ok 1 - fails * * * + * + * + * ... 1..1 # tests 1