From bf2c32162636b23a14d0ed3628333397aef457c2 Mon Sep 17 00:00:00 2001 From: Shang Chieh Tseng Date: Wed, 17 Dec 2025 17:48:20 +0800 Subject: [PATCH] Fix double-resolve bug in LogCollector.stop() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - stop() could resolve promise twice (from close event AND timeout) - Add resolved flag to ensure single resolution - Add comment about parallel execution limitation in executor 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- tests/src/executor.ts | 3 +++ tests/src/log-collector.ts | 16 +++++++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/tests/src/executor.ts b/tests/src/executor.ts index 73597c28..096237be 100644 --- a/tests/src/executor.ts +++ b/tests/src/executor.ts @@ -19,6 +19,9 @@ export class TestExecutor { private totalTests: number = 0 private currentTest: number = 0 private logCollector: LogCollector | null = null + // Note: currentTestId is shared state - LogCollector only works correctly + // with sequential execution (concurrency=1). Parallel execution will have + // inaccurate log boundaries. private currentTestId: string | null = null constructor(workingDir: string = process.cwd(), logCollector?: LogCollector) { diff --git a/tests/src/log-collector.ts b/tests/src/log-collector.ts index b7eb8ca9..06e17052 100644 --- a/tests/src/log-collector.ts +++ b/tests/src/log-collector.ts @@ -99,10 +99,16 @@ export class LogCollector { } return new Promise((resolve) => { - this.process!.on("close", () => { - this.isRunning = false; - resolve(); - }); + let resolved = false; + const doResolve = () => { + if (!resolved) { + resolved = true; + this.isRunning = false; + resolve(); + } + }; + + this.process!.on("close", doResolve); this.process!.kill("SIGTERM"); @@ -111,7 +117,7 @@ export class LogCollector { if (this.isRunning && this.process) { this.process.kill("SIGKILL"); } - resolve(); + doResolve(); }, 5000); }); }