mirror of
https://github.com/zebrajr/node.git
synced 2026-01-15 12:15:26 +00:00
test_runner: graceful termination on --test only
PR-URL: https://github.com/nodejs/node/pull/43977 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Nitzan Uziely <linkgoron@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
This commit is contained in:
@@ -13,9 +13,10 @@ const {
|
||||
ERR_TEST_FAILURE,
|
||||
},
|
||||
} = require('internal/errors');
|
||||
const { getOptionValue } = require('internal/options');
|
||||
const { Test, ItTest, Suite } = require('internal/test_runner/test');
|
||||
|
||||
|
||||
const isTestRunner = getOptionValue('--test');
|
||||
const testResources = new SafeMap();
|
||||
const root = new Test({ __proto__: null, name: '<root>' });
|
||||
let wasRootSetup = false;
|
||||
@@ -134,8 +135,11 @@ function setup(root) {
|
||||
process.on('uncaughtException', exceptionHandler);
|
||||
process.on('unhandledRejection', rejectionHandler);
|
||||
process.on('beforeExit', exitHandler);
|
||||
process.on('SIGINT', terminationHandler);
|
||||
process.on('SIGTERM', terminationHandler);
|
||||
// TODO(MoLow): Make it configurable to hook when isTestRunner === false.
|
||||
if (isTestRunner) {
|
||||
process.on('SIGINT', terminationHandler);
|
||||
process.on('SIGTERM', terminationHandler);
|
||||
}
|
||||
|
||||
root.reporter.pipe(process.stdout);
|
||||
root.reporter.version();
|
||||
|
||||
6
test/fixtures/test-runner/never_ending_async.js
vendored
Normal file
6
test/fixtures/test-runner/never_ending_async.js
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
const test = require('node:test');
|
||||
const { setTimeout } = require('timers/promises');
|
||||
|
||||
// We are using a very large timeout value to ensure that the parent process
|
||||
// will have time to send a SIGINT signal to cancel the test.
|
||||
test('never ending test', () => setTimeout(100_000_000));
|
||||
5
test/fixtures/test-runner/never_ending_sync.js
vendored
Normal file
5
test/fixtures/test-runner/never_ending_sync.js
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
const test = require('node:test');
|
||||
|
||||
test('never ending test', () => {
|
||||
while (true);
|
||||
});
|
||||
@@ -2,8 +2,29 @@
|
||||
const common = require('../common');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const assert = require('assert');
|
||||
const { spawnSync } = require('child_process');
|
||||
const { setTimeout } = require('timers/promises');
|
||||
const { spawnSync, spawn } = require('child_process');
|
||||
const { once } = require('events');
|
||||
const { finished } = require('stream/promises');
|
||||
|
||||
async function runAndKill(file) {
|
||||
if (common.isWindows) {
|
||||
common.printSkipMessage(`signals are not supported in windows, skipping ${file}`);
|
||||
return;
|
||||
}
|
||||
let stdout = '';
|
||||
const child = spawn(process.execPath, ['--test', file]);
|
||||
child.stdout.setEncoding('utf8');
|
||||
child.stdout.on('data', (chunk) => {
|
||||
if (!stdout.length) child.kill('SIGINT');
|
||||
stdout += chunk;
|
||||
});
|
||||
const [code, signal] = await once(child, 'exit');
|
||||
await finished(child.stdout);
|
||||
assert.match(stdout, /not ok 1/);
|
||||
assert.match(stdout, /# cancelled 1\n/);
|
||||
assert.strictEqual(signal, null);
|
||||
assert.strictEqual(code, 1);
|
||||
}
|
||||
|
||||
if (process.argv[2] === 'child') {
|
||||
const test = require('node:test');
|
||||
@@ -17,12 +38,6 @@ if (process.argv[2] === 'child') {
|
||||
test('failing test', () => {
|
||||
assert.strictEqual(true, false);
|
||||
});
|
||||
} else if (process.argv[3] === 'never_ends') {
|
||||
assert.strictEqual(process.argv[3], 'never_ends');
|
||||
test('never ending test', () => {
|
||||
return setTimeout(100_000_000);
|
||||
});
|
||||
process.kill(process.pid, 'SIGINT');
|
||||
} else assert.fail('unreachable');
|
||||
} else {
|
||||
let child = spawnSync(process.execPath, [__filename, 'child', 'pass']);
|
||||
@@ -37,14 +52,6 @@ if (process.argv[2] === 'child') {
|
||||
assert.strictEqual(child.status, 1);
|
||||
assert.strictEqual(child.signal, null);
|
||||
|
||||
child = spawnSync(process.execPath, [__filename, 'child', 'never_ends']);
|
||||
assert.strictEqual(child.status, 1);
|
||||
assert.strictEqual(child.signal, null);
|
||||
if (common.isWindows) {
|
||||
common.printSkipMessage('signals are not supported in windows');
|
||||
} else {
|
||||
const stdout = child.stdout.toString();
|
||||
assert.match(stdout, /not ok 1 - never ending test/);
|
||||
assert.match(stdout, /# cancelled 1/);
|
||||
}
|
||||
runAndKill(fixtures.path('test-runner', 'never_ending_sync.js')).then(common.mustCall());
|
||||
runAndKill(fixtures.path('test-runner', 'never_ending_async.js')).then(common.mustCall());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user