From 56e7fa828fe4b35a20748843465005bac67f86c7 Mon Sep 17 00:00:00 2001 From: Joseph Mearman Date: Sun, 13 Sep 2026 14:59:07 +0100 Subject: [PATCH] fix(test): stop the sea e2e test's own timeout race from swallowing diagnostics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sea (macos-26-intel) failed a second time, burning through the whole SEA_BINARY_STARTUP_TIMEOUT_MS budget with zero success — but the outer test() timeout was set equal to that same budget, so vitest's own abort raced this test's catch block and won, discarding every byte of captured stderr and leaving nothing to diagnose from. Logs stderr as it arrives instead of only from the catch block, tracks the child's own exit/spawn-error state, and gives the outer test() timeout real headroom over the inner poll deadline so this test's own diagnostic Error is what actually surfaces as the failure. --- test/sea.e2e.test.ts | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/test/sea.e2e.test.ts b/test/sea.e2e.test.ts index f567b05..f79e83d 100644 --- a/test/sea.e2e.test.ts +++ b/test/sea.e2e.test.ts @@ -15,6 +15,9 @@ const BINARY = process.env.CC_PEER_SEA_BINARY; /** How often waitForPort re-probes the binary's own health endpoint while it is still starting up. */ const POLL_INTERVAL_MS = 100; +/** Headroom over SEA_BINARY_STARTUP_TIMEOUT_MS for the outer test() timeout, so waitForPort's own deadline always elapses and this test's own diagnostic Error (captured stderr, process exit info) is what surfaces as the failure — not vitest's generic "Test timed out" abort, which would win the race and discard it if the two timeouts were equal. */ +const TEST_TIMEOUT_HEADROOM_MS = 10_000; + async function freePort(): Promise { return new Promise((resolve, reject) => { const probe = createServer(); @@ -78,8 +81,20 @@ describe.skipIf(BINARY === undefined)("packaged SEA binary", () => { { stdio: ["ignore", "ignore", "pipe"] }, ); let stderr = ""; + let exitInfo = "process is still running"; child.stderr.on("data", (chunk: Buffer) => { - stderr += chunk.toString("utf8"); + const text = chunk.toString("utf8"); + stderr += text; + // Logged as it arrives, not only from the catch block below: vitest's own test-level timeout can abort this test before that block ever runs, which would otherwise discard every diagnostic this test exists to capture. + console.error(`[sea-e2e stderr] ${text}`); + }); + child.once("exit", (code, signal) => { + exitInfo = `process exited: code=${String(code)} signal=${String(signal)}`; + console.error(`[sea-e2e] ${exitInfo}`); + }); + child.once("error", (error) => { + exitInfo = `process failed to spawn: ${error.message}`; + console.error(`[sea-e2e] ${exitInfo}`); }); try { await waitForPort(port, SEA_BINARY_STARTUP_TIMEOUT_MS); @@ -103,13 +118,13 @@ describe.skipIf(BINARY === undefined)("packaged SEA binary", () => { expect(sessions.status).toBe(200); } catch (error) { throw new Error( - `SEA binary smoke test failed; captured stderr:\n${stderr}`, + `SEA binary smoke test failed (${exitInfo}); captured stderr:\n${stderr}`, { cause: error }, ); } finally { child.kill(); } }, - SEA_BINARY_STARTUP_TIMEOUT_MS, + SEA_BINARY_STARTUP_TIMEOUT_MS + TEST_TIMEOUT_HEADROOM_MS, ); });