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

This test has been timing out in the CI with no information about
why. Splitting it into multiple files to at least show which test
case is timing out.

Drive-by: name the test as test-watch-mode-kill-signal-* as the
tests aren't testing the test runner and are just testing
--watch-kill-signal.

PR-URL: https://github.com/nodejs/node/pull/60298
Refs: https://github.com/nodejs/node/issues/60297
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Pietro Marchini <pietro.marchini94@gmail.com>
Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
This commit is contained in:
Joyee Cheung 2025-10-19 16:20:09 +02:00 committed by GitHub
parent 580bdbd024
commit da5df1dd0a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 150 additions and 131 deletions

16
test/common/watch.js Normal file
View File

@ -0,0 +1,16 @@
'use strict';
const common = require('./index.js');
exports.skipIfNoWatchModeSignals = function() {
if (common.isWindows) {
common.skip('no signals on Windows');
}
if (common.isIBMi) {
common.skip('IBMi does not support `fs.watch()`');
}
if (common.isAIX) {
common.skip('folder watch capability is limited in AIX.');
}
};

View File

@ -0,0 +1,4 @@
process.on('SIGTERM', () => { console.log('__SIGTERM received__'); process.exit(); });
process.on('SIGINT', () => { console.log('__SIGINT received__'); process.exit(); });
process.send('script ready');
setTimeout(() => {}, 100_000);

View File

@ -1,131 +0,0 @@
import * as common from '../common/index.mjs';
import { describe, it, beforeEach } from 'node:test';
import assert from 'node:assert';
import { spawn } from 'node:child_process';
import { writeFileSync } from 'node:fs';
import tmpdir from '../common/tmpdir.js';
if (common.isWindows) {
common.skip('no signals on Windows');
}
if (common.isIBMi) {
common.skip('IBMi does not support `fs.watch()`');
}
if (common.isAIX) {
common.skip('folder watch capability is limited in AIX.');
}
const indexContents = `
process.on('SIGTERM', () => { console.log('__SIGTERM received__'); process.exit(); });
process.on('SIGINT', () => { console.log('__SIGINT received__'); process.exit(); });
process.send('script ready');
setTimeout(() => {}, 100_000);
`;
let indexPath = '';
function refresh() {
tmpdir.refresh();
indexPath = tmpdir.resolve('index.js');
writeFileSync(indexPath, indexContents);
}
describe('test runner watch mode with --watch-kill-signal', () => {
beforeEach(refresh);
it('defaults to SIGTERM', async () => {
const child = spawn(
process.execPath,
['--watch', 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();
})
);
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();
})
);
assert.match(stdout, /__SIGINT received__/);
assert.doesNotMatch(stdout, /__SIGTERM received__/);
});
it('errors if an invalid signal is provided', async () => {
const currentRun = Promise.withResolvers();
const child = spawn(
process.execPath,
['--watch', '--watch-kill-signal', 'invalid_signal', indexPath],
{
cwd: tmpdir.path,
}
);
let stdout = '';
child.stderr.on('data', (data) => {
stdout += data.toString();
currentRun.resolve();
});
await currentRun.promise;
assert.match(
stdout,
new RegExp(
/TypeError \[ERR_UNKNOWN_SIGNAL\]: Unknown signal: invalid_signal/
)
);
});
});

View File

@ -0,0 +1,45 @@
// Test that the kill signal sent by --watch defaults to SIGTERM.
import '../common/index.mjs';
import assert from 'node:assert';
import { writeFileSync } from 'node:fs';
import { spawn } from 'node:child_process';
import { once } from 'node:events';
import tmpdir from '../common/tmpdir.js';
import fixtures from '../common/fixtures.js';
import { skipIfNoWatchModeSignals } from '../common/watch.js';
skipIfNoWatchModeSignals();
tmpdir.refresh();
const indexPath = tmpdir.resolve('kill-signal-for-watch.js');
const indexContents = fixtures.readSync('kill-signal-for-watch.js', 'utf8');
writeFileSync(indexPath, indexContents);
const child = spawn(
process.execPath,
['--watch', indexPath],
{
cwd: tmpdir.path,
stdio: ['inherit', 'pipe', 'inherit', '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 once(child, 'exit');
assert.match(stdout, /__SIGTERM received__/);
assert.doesNotMatch(stdout, /__SIGINT received__/);

View File

@ -0,0 +1,39 @@
// Test that --watch-kill-signal errors when an invalid kill signal is provided.
import '../common/index.mjs';
import assert from 'node:assert';
import { writeFileSync } from 'node:fs';
import { spawn } from 'node:child_process';
import tmpdir from '../common/tmpdir.js';
import fixtures from '../common/fixtures.js';
import { skipIfNoWatchModeSignals } from '../common/watch.js';
skipIfNoWatchModeSignals();
tmpdir.refresh();
const indexPath = tmpdir.resolve('kill-signal-for-watch.js');
const indexContents = fixtures.readSync('kill-signal-for-watch.js', 'utf8');
writeFileSync(indexPath, indexContents);
const currentRun = Promise.withResolvers();
const child = spawn(
process.execPath,
['--watch', '--watch-kill-signal', 'invalid_signal', indexPath],
{
cwd: tmpdir.path,
stdio: ['inherit', 'inherit', 'pipe'],
}
);
let stderr = '';
child.stderr.on('data', (data) => {
stderr += data.toString();
currentRun.resolve();
});
await currentRun.promise;
assert.match(
stderr,
/TypeError \[ERR_UNKNOWN_SIGNAL\]: Unknown signal: invalid_signal/
);

View File

@ -0,0 +1,46 @@
// Test that the kill signal sent by --watch can be overridden to SIGINT
// by using --watch-kill-signal.
import '../common/index.mjs';
import assert from 'node:assert';
import { writeFileSync } from 'node:fs';
import { spawn } from 'node:child_process';
import { once } from 'node:events';
import tmpdir from '../common/tmpdir.js';
import fixtures from '../common/fixtures.js';
import { skipIfNoWatchModeSignals } from '../common/watch.js';
skipIfNoWatchModeSignals();
tmpdir.refresh();
const indexPath = tmpdir.resolve('kill-signal-for-watch.js');
const indexContents = fixtures.readSync('kill-signal-for-watch.js', 'utf8');
writeFileSync(indexPath, indexContents);
const child = spawn(
process.execPath,
['--watch', '--watch-kill-signal', 'SIGINT', indexPath],
{
cwd: tmpdir.path,
stdio: ['inherit', 'pipe', 'inherit', '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 once(child, 'exit');
assert.match(stdout, /__SIGINT received__/);
assert.doesNotMatch(stdout, /__SIGTERM received__/);