Skip to content

Commit 0289a02

Browse files
MoLowmarco-ippolito
authored andcommittedJun 17, 2024
test_runner: fix watch mode race condition
PR-URL: #52954 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com> Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
1 parent f82d086 commit 0289a02

File tree

2 files changed

+26
-7
lines changed

2 files changed

+26
-7
lines changed
 

‎lib/internal/test_runner/runner.js

+12-6
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ const { createInterface } = require('readline');
3535
const { deserializeError } = require('internal/error_serdes');
3636
const { Buffer } = require('buffer');
3737
const { FilesWatcher } = require('internal/watch_mode/files_watcher');
38-
const { queueMicrotask } = require('internal/process/task_queues');
3938
const console = require('internal/console/global');
4039
const {
4140
codes: {
@@ -420,10 +419,16 @@ function runTestFile(path, filesWatcher, opts) {
420419
if (watchMode) {
421420
filesWatcher.runningProcesses.delete(path);
422421
filesWatcher.runningSubtests.delete(path);
423-
if (filesWatcher.runningSubtests.size === 0) {
424-
opts.root.reporter[kEmitMessage]('test:watch:drained');
425-
queueMicrotask(() => opts.root.postRun());
426-
}
422+
(async () => {
423+
try {
424+
await subTestEnded;
425+
} finally {
426+
if (filesWatcher.runningSubtests.size === 0) {
427+
opts.root.reporter[kEmitMessage]('test:watch:drained');
428+
opts.root.postRun();
429+
}
430+
}
431+
})();
427432
}
428433

429434
if (code !== 0 || signal !== null) {
@@ -442,7 +447,8 @@ function runTestFile(path, filesWatcher, opts) {
442447
throw err;
443448
}
444449
});
445-
return subtest.start();
450+
const subTestEnded = subtest.start();
451+
return subTestEnded;
446452
}
447453

448454
function watchFiles(testFiles, opts) {

‎test/parallel/test-runner-watch-mode.mjs

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Flags: --expose-internals
22
import * as common from '../common/index.mjs';
33
import { describe, it } from 'node:test';
4+
import assert from 'node:assert';
45
import { spawn } from 'node:child_process';
56
import { writeFileSync } from 'node:fs';
67
import util from 'internal/util';
@@ -36,21 +37,33 @@ async function testWatch({ fileToUpdate, file }) {
3637
['--watch', '--test', file ? fixturePaths[file] : undefined].filter(Boolean),
3738
{ encoding: 'utf8', stdio: 'pipe', cwd: tmpdir.path });
3839
let stdout = '';
40+
let currentRun = '';
41+
const runs = [];
3942

4043
child.stdout.on('data', (data) => {
4144
stdout += data.toString();
42-
const testRuns = stdout.match(/ - test has ran/g);
45+
currentRun += data.toString();
46+
const testRuns = stdout.match(/# duration_ms\s\d+/g);
4347
if (testRuns?.length >= 1) ran1.resolve();
4448
if (testRuns?.length >= 2) ran2.resolve();
4549
});
4650

4751
await ran1.promise;
52+
runs.push(currentRun);
53+
currentRun = '';
4854
const content = fixtureContent[fileToUpdate];
4955
const path = fixturePaths[fileToUpdate];
5056
const interval = setInterval(() => writeFileSync(path, content), common.platformTimeout(1000));
5157
await ran2.promise;
58+
runs.push(currentRun);
5259
clearInterval(interval);
5360
child.kill();
61+
for (const run of runs) {
62+
assert.match(run, /# tests 1/);
63+
assert.match(run, /# pass 1/);
64+
assert.match(run, /# fail 0/);
65+
assert.match(run, /# cancelled 0/);
66+
}
5467
}
5568

5669
describe('test runner watch mode', () => {

0 commit comments

Comments
 (0)
Please sign in to comment.