From 780f4e4e439bfbb995c94700e0342835a92abf1d Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Fri, 12 Jun 2026 15:11:12 -0700 Subject: [PATCH] test: give container-awaiting beforeAll hooks a 120s timeout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit describeWithContainer (and the valkey/autobahn tests' direct ensure() callers) await `compose up --wait-timeout 60` plus a `compose build` step inside beforeAll, but the hook had bun:test's default 5s timeout. On a cold or busy machine the hook fired first and the runner's auto-killer SIGTERMed the in-flight compose subprocess; compose then exited non-zero with stderr at whatever progress line it was on, which doUp() reported as `Failed to start service X: Container ... Creating`. There is no docker race — 4 services brought up concurrently from cold all return exit=0. The coordinator (#32033) solved a cross-process race (warmup-ci.ts vs the first test process); within one `bun bd test` process the per-service in-flight dedup at test/docker/index.ts:200-217 already covers same-service calls, and cross-service concurrency is fine in practice. Matches the existing pattern at websocket-proxy.test.ts:602. Verified by 2x `docker compose down` then `bun bd test` of the SQL container suites from cold: 0 hook timeouts, 0 'Failed to start service' across 5 services starting concurrently. --- test/harness.ts | 6 +++++- test/js/valkey/test-utils.ts | 5 ++++- test/js/valkey/valkey.test.ts | 5 ++++- test/js/web/websocket/autobahn.test.ts | 5 ++++- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/test/harness.ts b/test/harness.ts index 1790a9e78ba..a0e615afc31 100644 --- a/test/harness.ts +++ b/test/harness.ts @@ -1046,7 +1046,11 @@ export async function describeWithContainer( _port = info.ports[servicePort]; console.log(`Container ready via docker-compose: ${image} at ${_host}:${_port}`); readyResolver!(); - }); + // Cold container start is bounded by `compose up --wait-timeout 60` plus + // a `compose build` step; the default 5s hook timeout fires first and the + // runner's auto-killer then SIGTERMs the in-flight compose subprocesses, + // surfacing as bogus `Failed to start service X: ... Creating` errors. + }, 120_000); fn(containerDescriptor); }); diff --git a/test/js/valkey/test-utils.ts b/test/js/valkey/test-utils.ts index a04907a1efa..63e82bdeb0e 100644 --- a/test/js/valkey/test-utils.ts +++ b/test/js/valkey/test-utils.ts @@ -436,7 +436,10 @@ if (isEnabled) { // if (!context.initialized) { // console.warn("Test initialization failed - tests may be skipped"); // } - }); + // Cold container start is bounded by `compose up --wait-timeout 60` plus + // a `compose build` step; the default 5s hook timeout fires long before + // that on a cold cache. + }, 120_000); } if (isEnabled) { diff --git a/test/js/valkey/valkey.test.ts b/test/js/valkey/valkey.test.ts index 6f0364d6ca3..6bc3888fe7a 100644 --- a/test/js/valkey/valkey.test.ts +++ b/test/js/valkey/valkey.test.ts @@ -26,7 +26,10 @@ for (const connectionType of [ConnectionType.TLS, ConnectionType.TCP]) { if (!ctx.redis) { ctx.redis = createClient(connectionType); } - }); + // setupDockerContainer() may cold-start the redis_unified container + // (compose up --wait-timeout 60); shielded by the file-level beforeAll's + // cached promise once that has run, but match its timeout for safety. + }, 120_000); beforeEach(async () => { if (!ctx.redis) { diff --git a/test/js/web/websocket/autobahn.test.ts b/test/js/web/websocket/autobahn.test.ts index 12070512be9..0f88f31549e 100644 --- a/test/js/web/websocket/autobahn.test.ts +++ b/test/js/web/websocket/autobahn.test.ts @@ -42,7 +42,10 @@ describe.skipIf(!isDockerEnabled())("autobahn", () => { wsOptions = process.env.BUN_AUTOBAHN_HOST_HEADER ? { headers: { Host: process.env.BUN_AUTOBAHN_HOST_HEADER } } : undefined; - }); + // Cold container start is bounded by `compose up --wait-timeout 60` plus + // a `compose build` step; the default 5s hook timeout fires long before + // that on a cold cache. + }, 120_000); function getCaseStatus(testID: number) { return new Promise((resolve, reject) => {