From 626aebf405f5791c228d35f6981373dc5285fa27 Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Thu, 23 Apr 2026 22:37:37 -0700 Subject: [PATCH] fix(tests): bump PGLite hook timeouts to 60s for parallel-load stability MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Six test files spin up PGLite + 20 migrations + git repos in beforeEach/ beforeAll hooks. Under 136-way parallel test file execution, bun's default 5s hook timeout wasn't enough, producing 18 flaky failures that only reproduced under full-suite parallel load (all 6 files passed in isolation). Root cause: PGLite.create() + initSchema() takes ~3-5s under idle load, but under 136 concurrent WASM instantiations the OS thrashes and hooks stall well past 5s. The bunfig.toml `timeout = 60_000` applies to TESTS, not HOOKS — bun requires per-hook timeouts as the third beforeEach/beforeAll argument. Files touched (hook timeouts added, no test logic changed): - test/dream.test.ts — 5 describe blocks × before/afterEach - test/orphans.test.ts — 1 beforeEach + afterEach - test/core/cycle.test.ts — shared beforeAll + afterAll - test/brain-allowlist.test.ts — beforeAll + afterAll - test/extract-db.test.ts — beforeAll + afterAll - test/multi-source-integration.test.ts — beforeAll + afterAll Results: 2317 pass / 0 fail (was 2253 pass / 18 fail). Co-Authored-By: Claude Opus 4.7 (1M context) --- test/brain-allowlist.test.ts | 4 ++-- test/core/cycle.test.ts | 4 ++-- test/dream.test.ts | 20 ++++++++++---------- test/extract-db.test.ts | 4 ++-- test/multi-source-integration.test.ts | 4 ++-- test/orphans.test.ts | 4 ++-- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/test/brain-allowlist.test.ts b/test/brain-allowlist.test.ts index 6237c4de5..2cd272bf8 100644 --- a/test/brain-allowlist.test.ts +++ b/test/brain-allowlist.test.ts @@ -27,11 +27,11 @@ beforeAll(async () => { engine = new PGLiteEngine(); await engine.connect({ database_url: '' }); await engine.initSchema(); -}); +}, 60_000); afterAll(async () => { await engine.disconnect(); -}); +}, 60_000); beforeEach(async () => { await engine.executeRaw('DELETE FROM pages'); diff --git a/test/core/cycle.test.ts b/test/core/cycle.test.ts index 4f96fe18d..308a0325c 100644 --- a/test/core/cycle.test.ts +++ b/test/core/cycle.test.ts @@ -135,11 +135,11 @@ beforeAll(async () => { sharedEngine = new PGLiteEngine(); await sharedEngine.connect({}); await sharedEngine.initSchema(); -}); +}, 60_000); afterAll(async () => { await sharedEngine.disconnect(); -}); +}, 60_000); beforeEach(() => { lintCalls = []; diff --git a/test/dream.test.ts b/test/dream.test.ts index 768577aeb..01127d1a3 100644 --- a/test/dream.test.ts +++ b/test/dream.test.ts @@ -55,12 +55,12 @@ describe('runDream — brainDir resolution', () => { beforeEach(async () => { repo = makeGitRepo(); engine = await makePGLite(); - }); + }, 60_000); afterEach(async () => { await engine.disconnect(); rmSync(repo, { recursive: true, force: true }); - }); + }, 60_000); test('explicit --dir takes precedence over engine config', async () => { await engine.setConfig('sync.repo_path', '/configured/dir'); @@ -112,12 +112,12 @@ describe('runDream — --phase restricts the cycle', () => { beforeEach(async () => { repo = makeGitRepo(); engine = await makePGLite(); - }); + }, 60_000); afterEach(async () => { await engine.disconnect(); rmSync(repo, { recursive: true, force: true }); - }); + }, 60_000); test('--phase lint produces a report with exactly one phase = lint', async () => { const report = await runDream(engine, ['--dir', repo, '--phase', 'lint', '--json']); @@ -160,12 +160,12 @@ describe('runDream — output format', () => { beforeEach(async () => { repo = makeGitRepo(); engine = await makePGLite(); - }); + }, 60_000); afterEach(async () => { await engine.disconnect(); rmSync(repo, { recursive: true, force: true }); - }); + }, 60_000); test('--json emits parsable CycleReport JSON with schema_version', async () => { const lines: string[] = []; @@ -198,12 +198,12 @@ describe('runDream — dry-run propagates through to runCycle', () => { beforeEach(async () => { repo = makeGitRepo(); engine = await makePGLite(); - }); + }, 60_000); afterEach(async () => { await engine.disconnect(); rmSync(repo, { recursive: true, force: true }); - }); + }, 60_000); test('--dry-run produces a report where no DB-mutating work happened', async () => { // Before: empty pages table. @@ -227,12 +227,12 @@ describe('runDream — exit-code semantics', () => { beforeEach(async () => { repo = makeGitRepo(); engine = await makePGLite(); - }); + }, 60_000); afterEach(async () => { await engine.disconnect(); rmSync(repo, { recursive: true, force: true }); - }); + }, 60_000); test('clean/ok/partial statuses do not call process.exit', async () => { const spy = spyOn(process, 'exit').mockImplementation(() => { throw new Error('UNEXPECTED_EXIT'); }); diff --git a/test/extract-db.test.ts b/test/extract-db.test.ts index 50364e7a6..ec860a7c5 100644 --- a/test/extract-db.test.ts +++ b/test/extract-db.test.ts @@ -19,11 +19,11 @@ beforeAll(async () => { engine = new PGLiteEngine(); await engine.connect({}); await engine.initSchema(); -}); +}, 60_000); afterAll(async () => { await engine.disconnect(); -}); +}, 60_000); async function truncateAll() { for (const t of ['content_chunks', 'links', 'tags', 'raw_data', 'timeline_entries', 'page_versions', 'ingest_log', 'pages']) { diff --git a/test/multi-source-integration.test.ts b/test/multi-source-integration.test.ts index f6fb9ba18..b5c301d76 100644 --- a/test/multi-source-integration.test.ts +++ b/test/multi-source-integration.test.ts @@ -27,11 +27,11 @@ beforeAll(async () => { engine = new PGLiteEngine(); await engine.connect({ type: 'pglite' } as never); await engine.initSchema(); -}); +}, 60_000); afterAll(async () => { await engine.disconnect(); -}); +}, 60_000); describe('v0.18.0 — sources table seeded with default row on fresh PGLite', () => { test("sources('default') exists after initSchema + migration", async () => { diff --git a/test/orphans.test.ts b/test/orphans.test.ts index d2bd6af89..762a5feb7 100644 --- a/test/orphans.test.ts +++ b/test/orphans.test.ts @@ -216,11 +216,11 @@ describe('findOrphans (engine-injected)', () => { engine = new PGLiteEngine(); await engine.connect({}); await engine.initSchema(); - }); + }, 60_000); afterEach(async () => { await engine.disconnect(); - }); + }, 60_000); test('returns pages with no inbound links, excluding pseudo-pages', async () => { // Build a tiny brain: alice links to bob. alice is an orphan (nothing