Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test_runner: cancel on termination #43549

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 18 additions & 5 deletions lib/internal/test_runner/harness.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,14 @@ function setup(root) {
const rejectionHandler =
createProcessEventHandler('unhandledRejection', root);

process.on('uncaughtException', exceptionHandler);
process.on('unhandledRejection', rejectionHandler);
process.on('beforeExit', () => {
const exitHandler = () => {
root.postRun();

let passCount = 0;
let failCount = 0;
let skipCount = 0;
let todoCount = 0;
let cancelledCount = 0;

for (let i = 0; i < root.subtests.length; i++) {
const test = root.subtests[i];
Expand All @@ -94,6 +93,8 @@ function setup(root) {
skipCount++;
} else if (test.isTodo) {
todoCount++;
} else if (test.cancelled) {
cancelledCount++;
} else if (!test.passed) {
failCount++;
} else {
Expand All @@ -110,6 +111,7 @@ function setup(root) {
root.reporter.diagnostic(root.indent, `tests ${root.subtests.length}`);
root.reporter.diagnostic(root.indent, `pass ${passCount}`);
root.reporter.diagnostic(root.indent, `fail ${failCount}`);
root.reporter.diagnostic(root.indent, `cancelled ${cancelledCount}`);
root.reporter.diagnostic(root.indent, `skipped ${skipCount}`);
root.reporter.diagnostic(root.indent, `todo ${todoCount}`);
root.reporter.diagnostic(root.indent, `duration_ms ${process.uptime()}`);
Expand All @@ -119,10 +121,21 @@ function setup(root) {
process.removeListener('unhandledRejection', rejectionHandler);
process.removeListener('uncaughtException', exceptionHandler);

if (failCount > 0) {
if (failCount > 0 || cancelledCount > 0) {
process.exitCode = 1;
}
});
};

const terminationHandler = () => {
exitHandler();
process.exit();
};

process.on('uncaughtException', exceptionHandler);
process.on('unhandledRejection', rejectionHandler);
process.on('beforeExit', exitHandler);
process.on('SIGINT', terminationHandler);
process.on('SIGTERM', terminationHandler);

root.reporter.pipe(process.stdout);
root.reporter.version();
Expand Down
1 change: 1 addition & 0 deletions test/message/test_runner_desctibe_it.out
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,7 @@ not ok 54 - invalid subtest fail
# tests 54
# pass 23
# fail 17
# cancelled 0
# skipped 9
# todo 5
# duration_ms *
3 changes: 2 additions & 1 deletion test/message/test_runner_no_refs.out
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ not ok 1 - does not keep event loop alive
1..1
# tests 1
# pass 0
# fail 1
# fail 0
# cancelled 1
# skipped 0
# todo 0
# duration_ms *
1 change: 1 addition & 0 deletions test/message/test_runner_only_tests.out
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ ok 11 - only = true, with subtests
# tests 11
# pass 1
# fail 0
# cancelled 0
# skipped 10
# todo 0
# duration_ms *
1 change: 1 addition & 0 deletions test/message/test_runner_output.out
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,7 @@ not ok 57 - invalid subtest fail
# tests 57
# pass 24
# fail 18
# cancelled 0
# skipped 10
# todo 5
# duration_ms *
3 changes: 2 additions & 1 deletion test/message/test_runner_unresolved_promise.out
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ not ok 3 - fail
1..3
# tests 3
# pass 1
# fail 2
# fail 0
# cancelled 2
# skipped 0
# todo 0
# duration_ms *
24 changes: 21 additions & 3 deletions test/parallel/test-runner-exit-code.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
'use strict';
require('../common');
const common = require('../common');
const assert = require('assert');
const { spawnSync } = require('child_process');
const { setTimeout } = require('timers/promises');

if (process.argv[2] === 'child') {
const test = require('node:test');
Expand All @@ -10,12 +11,18 @@ if (process.argv[2] === 'child') {
test('passing test', () => {
assert.strictEqual(true, true);
});
} else {
} else if (process.argv[3] === 'fail') {
assert.strictEqual(process.argv[3], 'fail');
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']);
assert.strictEqual(child.status, 0);
Expand All @@ -24,4 +31,15 @@ if (process.argv[2] === 'child') {
child = spawnSync(process.execPath, [__filename, 'child', 'fail']);
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/);
}
}