Files
Jyotisha/frontend/tests/postgres-fixture-contract.test.ts
T
Jesse_ChenandClaude Opus 5.5 52d14e8fef
Independent Staging Quality Gate / validate (push) Successful in 14m10s
Independent Staging Quality Gate / publish (push) Successful in 4m3s
fix(test): wait for a PostgreSQL fixture slot while the queue moves (BUG-1254)
The slot wait was a fixed 5 minutes from the moment a file started queueing.
With 46 fixture files sharing 2 slots the queue outlasted that, so whichever
file came last failed the gate at random (runs 1742 and 1746). The deadline
now restarts whenever a slot changes hands; only 10 minutes with no slot
changing hands (a hung holder) fails. The 2-slot cap from BUG-281 stays.

Full suite 4967 / fail 24, identical to 171a3f25; tsc 0; lint 0 errors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
2026-10-06 23:21:48 +08:00

69 lines
3.1 KiB
TypeScript

import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import test from "node:test";
import { fileURLToPath } from "node:url";
import { FIXTURE_SLOT_STALL_MS, nextFixtureSlotDeadline } from "./helpers/postgres-fixture.ts";
const fixtureSource = readFileSync(
fileURLToPath(new URL("./helpers/postgres-fixture.ts", import.meta.url)),
"utf8",
);
test("postgres fixtures cap concurrent compose networks so Docker address pools cannot be exhausted", () => {
assert.match(fixtureSource, /JYOTISHA_POSTGRES_MAX_FIXTURES/);
assert.match(fixtureSource, /DEFAULT_MAX_CONCURRENT_POSTGRES_FIXTURES = 2/);
assert.match(fixtureSource, /function acquireFixtureSlot\(/);
assert.match(fixtureSource, /process\.kill\(\s*pid,\s*0\s*\)/);
assert.match(
fixtureSource,
/export function startPostgresFixture\(\)[\s\S]*acquireFixtureSlot\(\)/,
);
assert.match(
fixtureSource,
/timed out waiting for a PostgreSQL fixture slot/,
);
});
test("postgres fixture start failure and stop both release the compose-network slot", () => {
assert.match(
fixtureSource,
/catch \(error\) \{[\s\S]*releasePort\(portReservation\)[\s\S]*slot\.release\(\)/,
);
assert.match(
fixtureSource,
/stop\(\) \{[\s\S]*releasePort\(portReservation\)[\s\S]*slot\.release\(\)/,
);
});
test("large PostgreSQL scripts use stdin without changing shared -c helpers", () => {
assert.match(fixtureSource, /psqlScriptAs\(role, password, sql\)/);
assert.match(fixtureSource, /psqlScriptAs[\s\S]*input: sql/);
assert.match(fixtureSource, /psqlScriptAs[\s\S]*maxBuffer: 16 \* 1024 \* 1024/);
assert.match(fixtureSource, /psqlScriptAs[\s\S]*"--single-transaction"[\s\S]*"-f"[\s\S]*"-"/);
assert.match(fixtureSource, /psql\(sql\)[\s\S]*"-Atc",\s*sql/);
assert.match(fixtureSource, /psqlAs\(role, password, sql\)[\s\S]*"-Atc",\s*sql/);
});
test("a waiter keeps waiting while the slot queue moves and gives up only when it stalls (BUG-1254)", () => {
// Fixed 5-minute waits failed the gate at random once 46 fixture files
// queued for 2 slots: the queue itself outlasted the wait.
assert.doesNotMatch(fixtureSource, /FIXTURE_SLOT_WAIT_MS/);
assert.equal(FIXTURE_SLOT_STALL_MS, 10 * 60 * 1000);
const start = 1_000_000;
const deadline = start + FIXTURE_SLOT_STALL_MS;
// Nobody released or claimed a slot: the deadline does not move.
assert.equal(nextFixtureSlotDeadline("0:11|1:12", "0:11|1:12", deadline, start + 60_000), deadline);
// A slot changed hands: a full stall window from now.
const later = start + 9 * 60_000;
assert.equal(nextFixtureSlotDeadline("0:11|1:12", "0:13|1:12", deadline, later), later + FIXTURE_SLOT_STALL_MS);
// A slot was released and is momentarily free: that is progress too.
assert.equal(nextFixtureSlotDeadline("0:11|1:12", "0:|1:12", deadline, later), later + FIXTURE_SLOT_STALL_MS);
// The acquire loop recomputes the deadline from the owners after every poll.
assert.match(
fixtureSource,
/function acquireFixtureSlot\(\)[\s\S]*slotOwnersSnapshot\(limit\)[\s\S]*deadline = nextFixtureSlotDeadline\(owners, current, deadline, Date\.now\(\)\)/,
);
assert.match(fixtureSource, /no slot changed hands for/);
});