Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 19cfa31

Browse filesBrowse files
cjihrigtargos
authored andcommitted
test_runner: close and flush destinations on forced exit
This commit updates the test runner to explicitly close and flush all destination file streams when the --test-force-exit flag is used. Fixes: #54327 PR-URL: #55099 Reviewed-By: Chemi Atlow <chemi@atlow.co.il> Reviewed-By: Jake Yuesong Li <jake.yuesong@gmail.com>
1 parent 9aeba48 commit 19cfa31
Copy full SHA for 19cfa31

File tree

Expand file treeCollapse file tree

3 files changed

+74
-4
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

3 files changed

+74
-4
lines changed
Open diff view settings
Collapse file

‎lib/internal/test_runner/test.js‎

Copy file name to clipboardExpand all lines: lib/internal/test_runner/test.js
+21-3Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@ const {
1414
NumberPrototypeToFixed,
1515
ObjectDefineProperty,
1616
ObjectSeal,
17+
Promise,
1718
PromisePrototypeThen,
1819
PromiseResolve,
1920
ReflectApply,
2021
RegExpPrototypeExec,
2122
SafeMap,
2223
SafePromiseAll,
24+
SafePromiseAllReturnVoid,
2325
SafePromisePrototypeFinally,
2426
SafePromiseRace,
2527
SafeSet,
@@ -46,6 +48,7 @@ const {
4648
createDeferredCallback,
4749
countCompletedTest,
4850
isTestFailureError,
51+
reporterScope,
4952
} = require('internal/test_runner/utils');
5053
const {
5154
createDeferredPromise,
@@ -973,10 +976,25 @@ class Test extends AsyncResource {
973976
// any remaining ref'ed handles, then do that now. It is theoretically
974977
// possible that a ref'ed handle could asynchronously create more tests,
975978
// but the user opted into this behavior.
976-
this.reporter.once('close', () => {
977-
process.exit();
978-
});
979+
const promises = [];
980+
981+
for (let i = 0; i < reporterScope.reporters.length; i++) {
982+
const { destination } = reporterScope.reporters[i];
983+
984+
ArrayPrototypePush(promises, new Promise((resolve) => {
985+
destination.on('unpipe', () => {
986+
if (!destination.closed && typeof destination.close === 'function') {
987+
destination.close(resolve);
988+
} else {
989+
resolve();
990+
}
991+
});
992+
}));
993+
}
994+
979995
this.harness.teardown();
996+
await SafePromiseAllReturnVoid(promises);
997+
process.exit();
980998
}
981999
}
9821000

Collapse file

‎lib/internal/test_runner/utils.js‎

Copy file name to clipboardExpand all lines: lib/internal/test_runner/utils.js
+4-1Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,8 @@ function shouldColorizeTestFiles(destinations) {
144144

145145
async function getReportersMap(reporters, destinations) {
146146
return SafePromiseAllReturnArrayLike(reporters, async (name, i) => {
147-
const destination = kBuiltinDestinations.get(destinations[i]) ?? createWriteStream(destinations[i]);
147+
const destination = kBuiltinDestinations.get(destinations[i]) ??
148+
createWriteStream(destinations[i], { __proto__: null, flush: true });
148149

149150
// Load the test reporter passed to --test-reporter
150151
let reporter = tryBuiltinReporter(name);
@@ -301,6 +302,8 @@ function parseCommandLine() {
301302
const { reporter, destination } = reportersMap[i];
302303
compose(rootReporter, reporter).pipe(destination);
303304
}
305+
306+
reporterScope.reporters = reportersMap;
304307
});
305308

306309
globalTestOptions = {
Collapse file
+49Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
'use strict';
2+
require('../common');
3+
const fixtures = require('../common/fixtures');
4+
const tmpdir = require('../common/tmpdir');
5+
const { match, strictEqual } = require('node:assert');
6+
const { spawnSync } = require('node:child_process');
7+
const { readFileSync } = require('node:fs');
8+
const { test } = require('node:test');
9+
10+
function runWithReporter(reporter) {
11+
const destination = tmpdir.resolve(`${reporter}.out`);
12+
const args = [
13+
'--test-force-exit',
14+
`--test-reporter=${reporter}`,
15+
`--test-reporter-destination=${destination}`,
16+
fixtures.path('test-runner', 'reporters.js'),
17+
];
18+
const child = spawnSync(process.execPath, args);
19+
strictEqual(child.stdout.toString(), '');
20+
strictEqual(child.stderr.toString(), '');
21+
strictEqual(child.status, 1);
22+
return destination;
23+
}
24+
25+
tmpdir.refresh();
26+
27+
test('junit reporter', () => {
28+
const output = readFileSync(runWithReporter('junit'), 'utf8');
29+
match(output, /<!-- tests 4 -->/);
30+
match(output, /<!-- pass 2 -->/);
31+
match(output, /<!-- fail 2 -->/);
32+
match(output, /<!-- duration_ms/);
33+
match(output, /<\/testsuites>/);
34+
});
35+
36+
test('spec reporter', () => {
37+
const output = readFileSync(runWithReporter('spec'), 'utf8');
38+
match(output, /tests 4/);
39+
match(output, /pass 2/);
40+
match(output, /fail 2/);
41+
});
42+
43+
test('tap reporter', () => {
44+
const output = readFileSync(runWithReporter('tap'), 'utf8');
45+
match(output, /# tests 4/);
46+
match(output, /# pass 2/);
47+
match(output, /# fail 2/);
48+
match(output, /# duration_ms/);
49+
});

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.