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/); });