Skip to content

Commit 3e48536

Browse files
cjihrigtargos
authored andcommitted
test_runner: don't parse TAP from stderr
This commit stops the test runner CLI from parsing child process stderr as TAP. Per the TAP spec, TAP can only come from stdout. To avoid losing stderr data, those logs are injected into the parser as unknown tokens so that they are output as comments. PR-URL: #45618 Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
1 parent a6e2cf2 commit 3e48536

4 files changed

Lines changed: 67 additions & 14 deletions

File tree

‎lib/internal/test_runner/runner.js‎

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -241,22 +241,29 @@ function runTestFile(path, root, inspectPort, filesWatcher) {
241241
err=error;
242242
});
243243

244-
if(isUsingInspector()){
245-
constrl=createInterface({input: child.stderr});
246-
rl.on('line',(line)=>{
247-
if(isInspectorMessage(line)){
248-
process.stderr.write(line+'\n');
249-
}
250-
});
251-
}
252-
253-
constparser=newTapParser();
254-
child.stderr.pipe(parser).on('data',(ast)=>{
255-
if(ast.lexeme&&isInspectorMessage(ast.lexeme)){
256-
process.stderr.write(ast.lexeme+'\n');
244+
constrl=createInterface({input: child.stderr});
245+
rl.on('line',(line)=>{
246+
if(isInspectorMessage(line)){
247+
process.stderr.write(line+'\n');
248+
return;
257249
}
250+
251+
// stderr cannot be treated as TAP, per the spec. However, we want to
252+
// surface stderr lines as TAP diagnostics to improve the DX. Inject
253+
// each line into the test output as an unknown token as if it came
254+
// from the TAP parser.
255+
constnode={
256+
kind: TokenKind.UNKNOWN,
257+
node: {
258+
value: line,
259+
},
260+
};
261+
262+
subtest.addToReport(node);
258263
});
259264

265+
constparser=newTapParser();
266+
260267
child.stdout.pipe(parser).on('data',(ast)=>{
261268
subtest.addToReport(ast);
262269
});

‎lib/internal/util/inspector.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const { validatePort } = require('internal/validators');
1616
constkMinPort=1024;
1717
constkMaxPort=65535;
1818
constkInspectArgRegex=/--inspect(?:-brk|-port)?|--debug-port/;
19-
constkInspectMsgRegex=/Debuggerlisteningonws:\/\/\[?(.+?)\]?:(\d+)\/|Debuggerattached|Waitingforthedebuggertodisconnect\.\.\./;
19+
constkInspectMsgRegex=/Debuggerlisteningonws:\/\/\[?(.+?)\]?:(\d+)\/|Forhelp,see:https:\/\/nodejs\.org\/en\/docs\/inspector|Debuggerattached|Waitingforthedebuggertodisconnect\.\.\./;
2020

2121
const_isUsingInspector=newSafeWeakMap();
2222
functionisUsingInspector(execArgv=process.execArgv){
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
'use strict';
2+
consttest=require('node:test');
3+
4+
console.error('stderr',1);
5+
6+
test('a test',async()=>{
7+
console.error('stderr',2);
8+
awaitnewPromise((resolve)=>{
9+
console.log('stdout',3);
10+
setTimeout(()=>{
11+
// This should not be sent to the TAP parser.
12+
console.error('not ok 1 - fake test');
13+
resolve();
14+
console.log('stdout',4);
15+
},2);
16+
});
17+
console.error('stderr',5);
18+
});
19+
20+
console.error('stderr',6);

‎test/parallel/test-runner-cli.js‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,3 +168,29 @@ const testFixtures = fixtures.path('test-runner');
168168
assert.match(stdout,/#pass2/);
169169
assert.match(stdout,/#fail1/);
170170
}
171+
172+
{
173+
// Test user logging in tests.
174+
constargs=[
175+
'--test',
176+
'test/fixtures/test-runner/user-logs.js',
177+
];
178+
constchild=spawnSync(process.execPath,args);
179+
180+
assert.strictEqual(child.status,0);
181+
assert.strictEqual(child.signal,null);
182+
assert.strictEqual(child.stderr.toString(),'');
183+
conststdout=child.stdout.toString();
184+
assert.match(stdout,/#Subtest:.+user-logs\.js/);
185+
assert.match(stdout,/{4}#stderr1/);
186+
assert.match(stdout,/{4}#stderr2/);
187+
assert.match(stdout,/{4}#stdout3/);
188+
assert.match(stdout,/{4}#stderr6/);
189+
assert.match(stdout,/{4}#notok1-faketest/);
190+
assert.match(stdout,/{4}#stderr5/);
191+
assert.match(stdout,/{4}#stdout4/);
192+
assert.match(stdout,/{4}#Subtest:atest/);
193+
assert.match(stdout,/{4}ok1-atest/);
194+
assert.match(stdout,/#tests1/);
195+
assert.match(stdout,/#pass1/);
196+
}

0 commit comments

Comments
 (0)