From b03a4aeaeefe7a413e0f814fe8b4f1c94eae0b66 Mon Sep 17 00:00:00 2001 From: Moshe Atlow Date: Sun, 12 May 2024 11:04:11 +0300 Subject: [PATCH] test_runner: fix watch mode race condition --- lib/internal/test_runner/runner.js | 7 ++++--- test/parallel/test-runner-watch-mode.mjs | 15 ++++++++++++++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/lib/internal/test_runner/runner.js b/lib/internal/test_runner/runner.js index d2eb0cb6abf7a7..1975b5070f99ce 100644 --- a/lib/internal/test_runner/runner.js +++ b/lib/internal/test_runner/runner.js @@ -36,7 +36,6 @@ const { createInterface } = require('readline'); const { deserializeError } = require('internal/error_serdes'); const { Buffer } = require('buffer'); const { FilesWatcher } = require('internal/watch_mode/files_watcher'); -const { queueMicrotask } = require('internal/process/task_queues'); const console = require('internal/console/global'); const { codes: { @@ -382,7 +381,8 @@ function runTestFile(path, filesWatcher, opts) { filesWatcher.runningSubtests.delete(path); if (filesWatcher.runningSubtests.size === 0) { opts.root.reporter[kEmitMessage]('test:watch:drained'); - queueMicrotask(() => opts.root.postRun()); + const postRun = () => opts.root.postRun(); + PromisePrototypeThen(subTestEnded, postRun, postRun); } } @@ -402,7 +402,8 @@ function runTestFile(path, filesWatcher, opts) { throw err; } }); - return subtest.start(); + const subTestEnded = subtest.start(); + return subTestEnded; } function watchFiles(testFiles, opts) { diff --git a/test/parallel/test-runner-watch-mode.mjs b/test/parallel/test-runner-watch-mode.mjs index 5ec847330c2c2c..b210dab1e97142 100644 --- a/test/parallel/test-runner-watch-mode.mjs +++ b/test/parallel/test-runner-watch-mode.mjs @@ -1,6 +1,7 @@ // Flags: --expose-internals import * as common from '../common/index.mjs'; import { describe, it } from 'node:test'; +import assert from 'node:assert'; import { spawn } from 'node:child_process'; import { writeFileSync } from 'node:fs'; import util from 'internal/util'; @@ -36,21 +37,33 @@ async function testWatch({ fileToUpdate, file }) { ['--watch', '--test', file ? fixturePaths[file] : undefined].filter(Boolean), { encoding: 'utf8', stdio: 'pipe', cwd: tmpdir.path }); let stdout = ''; + let currentRun = ''; + const runs = []; child.stdout.on('data', (data) => { stdout += data.toString(); - const testRuns = stdout.match(/ - test has ran/g); + currentRun += data.toString(); + const testRuns = stdout.match(/# duration_ms\s\d+/g); if (testRuns?.length >= 1) ran1.resolve(); if (testRuns?.length >= 2) ran2.resolve(); }); await ran1.promise; + runs.push(currentRun); + currentRun = ''; const content = fixtureContent[fileToUpdate]; const path = fixturePaths[fileToUpdate]; const interval = setInterval(() => writeFileSync(path, content), common.platformTimeout(1000)); await ran2.promise; + runs.push(currentRun); clearInterval(interval); child.kill(); + for (const run of runs) { + assert.match(run, /# tests 1/); + assert.match(run, /# pass 1/); + assert.match(run, /# fail 0/); + assert.match(run, /# cancelled 0/); + } } describe('test runner watch mode', () => {