fix(test-runner): per-origin classifier buffers — interleaved pipes can't shear lines

stdout and stderr are independent pipes; a chunk from one can arrive
between two halves of a line from the other. The single shared
pending-buffer glued those fragments into garbled lines: a sheared
(fail) line went uncounted (defeating the exit-0-with-failures
backstop) and a sheared terminal summary read as truncation.
Counters stay shared; line assembly is now per-stream, and both
runners tag the stream origin. Also drops the dead ChildProcess
type import left by the killProcessGroup move.
This commit is contained in:
Garry Tan
2026-08-15 16:49:38 -07:00
parent f692da35d7
commit 661b3d943f
3 changed files with 58 additions and 19 deletions
+3 -3
View File
@@ -50,7 +50,7 @@
* bun run scripts/test-paid-shards.ts --timeout 600 --jobs 2
*/
import { spawn, type ChildProcess } from 'node:child_process';
import { spawn } from 'node:child_process';
import * as fs from 'node:fs';
import * as path from 'node:path';
import { normalizeRelativePath } from './test-free-shards';
@@ -430,8 +430,8 @@ export async function runPaidShard(
let exitCode: number | null = null;
try {
const streams: Array<Promise<void>> = [];
if (child.stdout) streams.push(forwardAndClassify(child.stdout, sink(process.stdout), classifier));
if (child.stderr) streams.push(forwardAndClassify(child.stderr, sink(process.stderr), classifier));
if (child.stdout) streams.push(forwardAndClassify(child.stdout, sink(process.stdout), classifier, 'stdout'));
if (child.stderr) streams.push(forwardAndClassify(child.stderr, sink(process.stderr), classifier, 'stderr'));
exitCode = await new Promise<number | null>((resolve, reject) => {
child.once('error', reject);
child.once('close', (code) => resolve(code));