diff --git a/lib/internal/test_runner/harness.js b/lib/internal/test_runner/harness.js index 1bdd6e99ed1c3b..5d0ce337ccd10c 100644 --- a/lib/internal/test_runner/harness.js +++ b/lib/internal/test_runner/harness.js @@ -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: '' }); 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(); diff --git a/test/fixtures/test-runner/never_ending_async.js b/test/fixtures/test-runner/never_ending_async.js new file mode 100644 index 00000000000000..0f26ea9291fd0d --- /dev/null +++ b/test/fixtures/test-runner/never_ending_async.js @@ -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)); diff --git a/test/fixtures/test-runner/never_ending_sync.js b/test/fixtures/test-runner/never_ending_sync.js new file mode 100644 index 00000000000000..efc78757b18852 --- /dev/null +++ b/test/fixtures/test-runner/never_ending_sync.js @@ -0,0 +1,5 @@ +const test = require('node:test'); + +test('never ending test', () => { + while (true); +}); diff --git a/test/parallel/test-runner-exit-code.js b/test/parallel/test-runner-exit-code.js index 638ad9853aeefb..1833fa00f7f7ae 100644 --- a/test/parallel/test-runner-exit-code.js +++ b/test/parallel/test-runner-exit-code.js @@ -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()); }