test: deflake test-runner-watch-mode-kill-signal

PR-URL: https://github.com/nodejs/node/pull/58952
Refs: https://github.com/nodejs/reliability/issues/1250
Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Ethan Arrowood <ethan@arrowood.dev>
Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
This commit is contained in:
Dario Piotrowicz 2025-07-07 21:52:53 +01:00 committed by GitHub
parent 9c025a9287
commit 35c85a2249
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,6 +1,5 @@
import * as common from '../common/index.mjs'; import * as common from '../common/index.mjs';
import { describe, it, beforeEach } from 'node:test'; import { describe, it, beforeEach } from 'node:test';
import { once } from 'node:events';
import assert from 'node:assert'; import assert from 'node:assert';
import { spawn } from 'node:child_process'; import { spawn } from 'node:child_process';
import { writeFileSync } from 'node:fs'; import { writeFileSync } from 'node:fs';
@ -19,27 +18,10 @@ if (common.isAIX) {
} }
const indexContents = ` const indexContents = `
const { setTimeout } = require("timers/promises"); process.on('SIGTERM', () => { console.log('__SIGTERM received__'); process.exit(); });
(async () => { process.on('SIGINT', () => { console.log('__SIGINT received__'); process.exit(); });
// Wait a few milliseconds to make sure that the process.send('script ready');
// parent process has time to attach its listeners setTimeout(() => {}, 100_000);
await setTimeout(200);
process.on('SIGTERM', () => {
console.log('__SIGTERM received__');
process.exit(123);
});
process.on('SIGINT', () => {
console.log('__SIGINT received__');
process.exit(124);
});
console.log('ready!');
// Wait for a long time (just to keep the process alive)
await setTimeout(100_000_000);
})();
`; `;
let indexPath = ''; let indexPath = '';
@ -54,60 +36,82 @@ describe('test runner watch mode with --watch-kill-signal', () => {
beforeEach(refresh); beforeEach(refresh);
it('defaults to SIGTERM', async () => { it('defaults to SIGTERM', async () => {
let currentRun = Promise.withResolvers(); const child = spawn(
const child = spawn(process.execPath, ['--watch', indexPath], { process.execPath,
cwd: tmpdir.path, ['--watch', indexPath],
}); {
cwd: tmpdir.path,
stdio: ['pipe', 'pipe', 'pipe', 'ipc'],
}
);
let stdout = ''; let stdout = '';
child.stdout.on('data', (data) => { child.stdout.on('data', (data) => {
stdout += data.toString(); stdout += `${data}`;
currentRun.resolve(); if (/__(SIGINT|SIGTERM) received__/.test(stdout)) {
}); child.kill();
await currentRun.promise;
currentRun = Promise.withResolvers();
writeFileSync(indexPath, indexContents);
await currentRun.promise;
child.kill();
const [exitCode] = await once(child, 'exit');
assert.match(stdout, /__SIGTERM received__/);
assert.strictEqual(exitCode, 123);
});
it('can be overridden (to SIGINT)', async () => {
let currentRun = Promise.withResolvers();
const child = spawn(process.execPath, ['--watch', '--watch-kill-signal', 'SIGINT', indexPath], {
cwd: tmpdir.path,
});
let stdout = '';
child.stdout.on('data', (data) => {
stdout += data.toString();
if (stdout.includes('ready!')) {
currentRun.resolve();
} }
}); });
await currentRun.promise; child.on('message', (msg) => {
if (msg === 'script ready') {
writeFileSync(indexPath, indexContents);
}
});
currentRun = Promise.withResolvers(); await new Promise((resolve) =>
writeFileSync(indexPath, indexContents); child.on('exit', () => {
resolve();
})
);
assert.match(stdout, /__SIGTERM received__/);
assert.doesNotMatch(stdout, /__SIGINT received__/);
});
it('can be overridden (to SIGINT)', async () => {
const child = spawn(
process.execPath,
['--watch', '--watch-kill-signal', 'SIGINT', indexPath],
{
cwd: tmpdir.path,
stdio: ['pipe', 'pipe', 'pipe', 'ipc'],
}
);
let stdout = '';
child.stdout.on('data', (data) => {
stdout += `${data}`;
if (/__(SIGINT|SIGTERM) received__/.test(stdout)) {
child.kill();
}
});
child.on('message', (msg) => {
if (msg === 'script ready') {
writeFileSync(indexPath, indexContents);
}
});
await new Promise((resolve) =>
child.on('exit', () => {
resolve();
})
);
await currentRun.promise;
child.kill();
const [exitCode] = await once(child, 'exit');
assert.match(stdout, /__SIGINT received__/); assert.match(stdout, /__SIGINT received__/);
assert.strictEqual(exitCode, 124); assert.doesNotMatch(stdout, /__SIGTERM received__/);
}); });
it('errors if an invalid signal is provided', async () => { it('errors if an invalid signal is provided', async () => {
const currentRun = Promise.withResolvers(); const currentRun = Promise.withResolvers();
const child = spawn(process.execPath, ['--watch', '--watch-kill-signal', 'invalid_signal', indexPath], { const child = spawn(
cwd: tmpdir.path, process.execPath,
}); ['--watch', '--watch-kill-signal', 'invalid_signal', indexPath],
{
cwd: tmpdir.path,
}
);
let stdout = ''; let stdout = '';
child.stderr.on('data', (data) => { child.stderr.on('data', (data) => {
@ -117,6 +121,11 @@ describe('test runner watch mode with --watch-kill-signal', () => {
await currentRun.promise; await currentRun.promise;
assert.match(stdout, new RegExp(/TypeError \[ERR_UNKNOWN_SIGNAL\]: Unknown signal: invalid_signal/)); assert.match(
stdout,
new RegExp(
/TypeError \[ERR_UNKNOWN_SIGNAL\]: Unknown signal: invalid_signal/
)
);
}); });
}); });