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: include stack trace of uncaughtException and unhandledRejection #44614

Merged
merged 3 commits into from Sep 14, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/internal/test_runner/tap_stream.js
Expand Up @@ -173,7 +173,7 @@ function jsToYaml(indent, name, value) {
}

if (isErrorObj) {
const { kTestCodeFailure, kHookFailure } = lazyLoadTest();
const { kTestCodeFailure, kUnwrapErrors } = lazyLoadTest();
const {
cause,
code,
Expand All @@ -187,7 +187,7 @@ function jsToYaml(indent, name, value) {

// If the ERR_TEST_FAILURE came from an error provided by user code,
// then try to unwrap the original error message and stack.
if (code === 'ERR_TEST_FAILURE' && (failureType === kTestCodeFailure || failureType === kHookFailure)) {
if (code === 'ERR_TEST_FAILURE' && kUnwrapErrors.has(failureType)) {
errStack = cause?.stack ?? errStack;
errCode = cause?.code ?? errCode;
if (failureType === kTestCodeFailure) {
Expand Down
4 changes: 3 additions & 1 deletion lib/internal/test_runner/test.js
Expand Up @@ -13,6 +13,7 @@ const {
PromiseResolve,
ReflectApply,
SafeMap,
SafeSet,
SafePromiseAll,
SafePromiseRace,
Symbol,
Expand Down Expand Up @@ -60,6 +61,7 @@ const testOnlyFlag = !isTestRunner && getOptionValue('--test-only');
const kShouldAbort = Symbol('kShouldAbort');
const kRunHook = Symbol('kRunHook');
const kHookNames = ObjectSeal(['before', 'after', 'beforeEach', 'afterEach']);
const kUnwrapErrors = new SafeSet([kTestCodeFailure, kHookFailure, 'uncaughtException', 'unhandledRejection']);
MoLow marked this conversation as resolved.
Show resolved Hide resolved


function stopTest(timeout, signal) {
Expand Down Expand Up @@ -726,9 +728,9 @@ module.exports = {
ItTest,
kCancelledByParent,
kDefaultIndent,
kHookFailure,
kSubtestsFailed,
kTestCodeFailure,
kUnwrapErrors,
Suite,
Test,
};
1 change: 1 addition & 0 deletions test/message/test_runner_describe_it.out
Expand Up @@ -418,6 +418,7 @@ not ok 49 - callback async throw
code: 'ERR_TEST_FAILURE'
stack: |-
*
*
...
# Subtest: callback async throw after done
ok 50 - callback async throw after done
Expand Down
12 changes: 12 additions & 0 deletions test/message/test_runner_output.js
Expand Up @@ -371,3 +371,15 @@ test('rejected thenable', () => {
},
};
});

test('unfinished test with uncaughtException', async () => {
await new Promise(() => {
setTimeout(() => { throw new Error('foo'); });
});
});

test('unfinished test with unhandledRejection', async () => {
await new Promise(() => {
setTimeout(() => Promise.reject(new Error('bar')));
});
});
33 changes: 29 additions & 4 deletions test/message/test_runner_output.out
Expand Up @@ -463,6 +463,7 @@ not ok 51 - callback async throw
code: 'ERR_TEST_FAILURE'
stack: |-
*
*
...
# Subtest: callback async throw after done
ok 52 - callback async throw after done
Expand Down Expand Up @@ -601,8 +602,32 @@ not ok 62 - rejected thenable
error: 'custom error'
code: 'ERR_TEST_FAILURE'
...
# Subtest: unfinished test with uncaughtException
not ok 63 - unfinished test with uncaughtException
---
duration_ms: *
failureType: 'uncaughtException'
error: 'foo'
code: 'ERR_TEST_FAILURE'
stack: |-
*
*
*
...
# Subtest: unfinished test with unhandledRejection
not ok 64 - unfinished test with unhandledRejection
---
duration_ms: *
failureType: 'unhandledRejection'
error: 'bar'
code: 'ERR_TEST_FAILURE'
stack: |-
*
*
*
...
# Subtest: invalid subtest fail
not ok 63 - invalid subtest fail
not ok 65 - invalid subtest fail
---
duration_ms: *
failureType: 'parentAlreadyFinished'
Expand All @@ -611,16 +636,16 @@ not ok 63 - invalid subtest fail
stack: |-
*
...
1..63
1..65
# Warning: Test "unhandled rejection - passes but warns" generated asynchronous activity after the test ended. This activity created the error "Error: rejected from unhandled rejection fail" and would have caused the test to fail, but instead triggered an unhandledRejection event.
# Warning: Test "async unhandled rejection - passes but warns" generated asynchronous activity after the test ended. This activity created the error "Error: rejected from async unhandled rejection fail" and would have caused the test to fail, but instead triggered an unhandledRejection event.
# Warning: Test "immediate throw - passes but warns" generated asynchronous activity after the test ended. This activity created the error "Error: thrown from immediate throw fail" and would have caused the test to fail, but instead triggered an uncaughtException event.
# Warning: Test "immediate reject - passes but warns" generated asynchronous activity after the test ended. This activity created the error "Error: rejected from immediate reject fail" and would have caused the test to fail, but instead triggered an unhandledRejection event.
# Warning: Test "callback called twice in different ticks" generated asynchronous activity after the test ended. This activity created the error "Error [ERR_TEST_FAILURE]: callback invoked multiple times" and would have caused the test to fail, but instead triggered an uncaughtException event.
# Warning: Test "callback async throw after done" generated asynchronous activity after the test ended. This activity created the error "Error: thrown from callback async throw after done" and would have caused the test to fail, but instead triggered an uncaughtException event.
# tests 63
# tests 65
# pass 27
# fail 19
# fail 21
# cancelled 2
# skipped 10
# todo 5
Expand Down