/** * Gate on the wiring of the environment-fault stop (celilo#1247). * * On 2026-09-03 `cele2e run --all` reported 7 passed, 47 failed. Three were * real. The other 44 were one event: a leaked network held a fixed e2e subnet, * so every suite from the eleventh on died at `docker compose up` in 2 seconds, * and the summary listed each as its own failure. * * The classifier is tested by behaviour in tests/extract-failure.test.ts. What * is pinned here is that the runner ACTS on it: stops the run at the first * suite that could not create its network, and says in the summary that the * rest never ran. The behavioural proof needs a leaked network on the Docker * host, which is the rig's. * * Read the source instead of importing the runner: main() runs at import time * (module top-level), so importing it would execute a docker run. */ import { expect, test } from 'bun:test'; import { readFileSync } from 'node:fs'; import { dirname, join } from 'node:path'; import { fileURLToPath } from 'node:url'; const SRC = readFileSync(join(dirname(fileURLToPath(import.meta.url)), 'runner.ts'), 'utf-8'); /** The per-suite loop body, from its `for` to the timing save that follows it. */ function suiteLoop(): string { return SRC.slice( SRC.indexOf('for (let i = 0; i < testFiles.length; i++)'), SRC.indexOf('saveTiming(history);\n saveBlockTiming(blockTiming);'), ); } /** The end-of-run block, from the results summary to the last-run write. */ function endOfRunBlock(): string { return SRC.slice(SRC.indexOf('saveTiming(history);\n saveBlockTiming(blockTiming);')); } test('a failed suite is classified by networkCreationFault', () => { // .includes, not toContain: a miss would print all of runner.ts as the diff. expect(SRC.includes('environmentFault: networkCreationFault(lines)')).toBe(true); }); test('the run stops at the first suite that could not create its network', () => { // Today the loop had no such branch: it ran every remaining suite into the // same wall and counted each as a failure. const loop = suiteLoop(); const guardAt = loop.indexOf('if (result.environmentFault)'); expect(guardAt).toBeGreaterThan(-1); // The guard is the last statement in the loop body, so a `break` after it is its own. expect(loop.slice(guardAt).includes('break;')).toBe(true); }); test('the stop comes after the suite wrote its own result.json', () => { // The suite that hit the fault DID run and fail. Its record must exist, or // the results dir has a suite directory with a log and no verdict. const loop = suiteLoop(); expect(loop.indexOf("join(logDir, 'result.json')")).toBeGreaterThan(-1); expect(loop.indexOf("join(logDir, 'result.json')")).toBeLessThan( loop.indexOf('if (result.environmentFault)'), ); }); test('the summary reports the suites that never ran as not run, not as failures', () => { const block = endOfRunBlock(); expect(block.includes('not run')).toBe(true); // Durable for a reader that never saw the terminal. const summaryJson = block.slice(block.indexOf("join(resultsDir, 'summary.json')")); expect(summaryJson.slice(0, summaryJson.indexOf('writeLastRun(')).includes('notRun')).toBe(true); expect(block.slice(block.indexOf('writeLastRun(')).includes('environmentFault')).toBe(true); });