From 085930170ed6c9ea9d88162d3b6ad5f663efb630 Mon Sep 17 00:00:00 2001 From: "A. Mahoney-Fernandes" <83057795+0xPlayerOne@users.noreply.github.com> Date: Wed, 21 Oct 2026 03:35:19 -0400 Subject: [PATCH 1/2] fix(testing): load the isolated postgres fixture from an owned temporary file The isolated postgres fixture was bundled and then imported from a data:text/javascript;base64 URL. The coverage reporter of the pinned Bun 1.4.3 cannot report a module loaded that way: it aborts the whole coverage run with "panic: range end index 1884 out of range for slice of length 1024" before it prints a summary, so every coverage run that included packages/testing/src/postgres.test.mjs died at the reporting step. The bundle is now written to a temporary file the test owns and imported from there. The bytes are the ones the build produced, the fixture behaves the same, and the directory is removed when the run ends and when the fixture cannot be loaded at all. The file lives in a dist/ directory because it is generated output, which the repository's coverage configuration already ignores, so the coverage report keeps exactly the rows it had. Three regressions cover the new path: the fixture loads from the temporary file with the bundle's own bytes, the owned directory is removed, and a fixture that cannot be loaded leaves nothing behind either. --- packages/testing/src/postgres.test.mjs | 84 ++++++++++++++++++++++++-- 1 file changed, 80 insertions(+), 4 deletions(-) diff --git a/packages/testing/src/postgres.test.mjs b/packages/testing/src/postgres.test.mjs index aa85c20f6..247cc59c5 100644 --- a/packages/testing/src/postgres.test.mjs +++ b/packages/testing/src/postgres.test.mjs @@ -1,5 +1,9 @@ -import { expect, test } from 'bun:test' -import { fileURLToPath } from 'node:url' +import { afterAll, expect, test } from 'bun:test' +import { existsSync } from 'node:fs' +import { mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises' +import { tmpdir } from 'node:os' +import { join } from 'node:path' +import { fileURLToPath, pathToFileURL } from 'node:url' // Bundle the real wrapper with private, synthetic dependency modules. Unlike // mock.module, these stubs cannot replace database modules in other test files. @@ -36,9 +40,57 @@ const built = await Bun.build({ ], }) if (!built.success) throw new AggregateError(built.logs, 'Fixture test bundle failed') -const { configure, createIsolatedPostgres, withIsolatedPostgres } = await import( - `data:text/javascript;base64,${Buffer.from(await built.outputs[0].text()).toString('base64')}` + +// The bundle is loaded from a temporary file this test owns. +// +// A module imported from a data: URL is not reportable by the coverage reporter +// of the pinned Bun 1.4.3: it aborts the whole coverage run with "panic: range +// end index 1884 out of range for slice of length 1024" before any summary is +// printed. The file holds the bundle's bytes exactly as the build produced them, +// so the fixture under test is unchanged, and the directory is removed when the +// run ends and when the fixture cannot be loaded at all. + +/** The directory that holds the fixture file, created empty and owned by the test. */ +async function createFixtureDirectory() { + const directory = await mkdtemp(join(tmpdir(), 'control-plane-postgres-fixture-')) + // The bundle is generated output, so it is written into a dist/ directory: the + // repository's coverage configuration already ignores generated output, and the + // coverage report keeps the rows it had before. + await mkdir(join(directory, 'dist')) + return directory +} + +/** The path of the fixture file inside an owned directory. */ +function fixtureFilePath(directory) { + return join(directory, 'dist', 'postgres-fixture.mjs') +} + +/** Removes an owned directory and everything in it. */ +async function removeFixtureDirectory(directory) { + await rm(directory, { recursive: true, force: true }) +} + +/** Writes the fixture and loads it, leaving nothing behind when the load fails. */ +async function loadFixtureModule(directory, source) { + await writeFile(fixtureFilePath(directory), source) + try { + return await import(pathToFileURL(fixtureFilePath(directory)).href) + } catch (error) { + await removeFixtureDirectory(directory) + throw error + } +} + +const fixtureSource = await built.outputs[0].text() +const fixtureDirectory = await createFixtureDirectory() +const fixtureFile = fixtureFilePath(fixtureDirectory) +const { configure, createIsolatedPostgres, withIsolatedPostgres } = await loadFixtureModule( + fixtureDirectory, + fixtureSource ) +afterAll(async () => { + await removeFixtureDirectory(fixtureDirectory) +}) function fixture({ migrationError, cleanupError, creationError } = {}) { const calls = [] @@ -129,3 +181,27 @@ test('operation failure still disposes exactly once', async () => { ).rejects.toBe(error) expect(calls).toEqual(['migrate', 'operation', 'dispose']) }) + +test('loads the fixture from the temporary file this test owns', async () => { + expect(existsSync(fixtureFile)).toBe(true) + expect(await readFile(fixtureFile, 'utf8')).toBe(fixtureSource) + expect(fixtureDirectory.startsWith(tmpdir())).toBe(true) + expect(typeof configure).toBe('function') +}) + +test('removes the temporary fixture directory it owns', async () => { + const directory = await createFixtureDirectory() + const file = fixtureFilePath(directory) + await writeFile(file, 'export const probe = 1\n') + + expect(existsSync(file)).toBe(true) + await removeFixtureDirectory(directory) + expect(existsSync(directory)).toBe(false) +}) + +test('removes the temporary fixture directory when the fixture cannot be loaded', async () => { + const directory = await createFixtureDirectory() + + await expect(loadFixtureModule(directory, 'export const broken = (')).rejects.toThrow() + expect(existsSync(directory)).toBe(false) +}) From 75c2f498d953cc5e9457c7534174c641e7159f7a Mon Sep 17 00:00:00 2001 From: "A. Mahoney-Fernandes" <83057795+0xPlayerOne@users.noreply.github.com> Date: Wed, 21 Oct 2026 06:33:01 -0400 Subject: [PATCH 2/2] fix(testing): remove the owned fixture directory on every failure after its allocation The fixture directory is allocated, then filled, then written and then imported, and each of those steps can fail. Only the import was guarded: a directory that was allocated and then not filled, or a file that could not be written, stayed behind in the temporary directory, and the removal was registered only after a successful load. The allocation and the directory creation are now one guarded step, the write is guarded as well as the import, and the removal is registered before the fixture is loaded. The failure that caused the cleanup is kept as it is; a cleanup that fails too is reported beside it rather than in place of it, so the original error is never lost. Four regressions cover the paths: a directory that cannot be created, a file that cannot be written and a fixture that cannot be imported each leave no directory behind, a cleanup that fails is reported next to the failure that caused it, and a directory the test does not own is left untouched. The bundle bytes and the coverage thresholds are unchanged. --- packages/testing/src/postgres.test.mjs | 182 ++++++++++++++++++++++--- 1 file changed, 160 insertions(+), 22 deletions(-) diff --git a/packages/testing/src/postgres.test.mjs b/packages/testing/src/postgres.test.mjs index 247cc59c5..d41a9feef 100644 --- a/packages/testing/src/postgres.test.mjs +++ b/packages/testing/src/postgres.test.mjs @@ -47,18 +47,13 @@ if (!built.success) throw new AggregateError(built.logs, 'Fixture test bundle fa // of the pinned Bun 1.4.3: it aborts the whole coverage run with "panic: range // end index 1884 out of range for slice of length 1024" before any summary is // printed. The file holds the bundle's bytes exactly as the build produced them, -// so the fixture under test is unchanged, and the directory is removed when the -// run ends and when the fixture cannot be loaded at all. - -/** The directory that holds the fixture file, created empty and owned by the test. */ -async function createFixtureDirectory() { - const directory = await mkdtemp(join(tmpdir(), 'control-plane-postgres-fixture-')) - // The bundle is generated output, so it is written into a dist/ directory: the - // repository's coverage configuration already ignores generated output, and the - // coverage report keeps the rows it had before. - await mkdir(join(directory, 'dist')) - return directory -} +// so the fixture under test is unchanged. +// +// Every step after the directory is allocated can fail, and no failure may leave +// the directory behind: the allocation and the directory creation are one guarded +// step, the write is guarded as well as the import, and the removal is registered +// before the fixture is loaded. A removal that fails is reported next to the +// failure that caused it instead of replacing it. /** The path of the fixture file inside an owned directory. */ function fixtureFilePath(directory) { @@ -70,27 +65,97 @@ async function removeFixtureDirectory(directory) { await rm(directory, { recursive: true, force: true }) } -/** Writes the fixture and loads it, leaving nothing behind when the load fails. */ -async function loadFixtureModule(directory, source) { - await writeFile(fixtureFilePath(directory), source) +/** + * The error a failure is reported as. + * + * The failure that caused the cleanup is kept, and a cleanup that failed too is + * reported beside it rather than in place of it. + */ +function fixtureFailure(error, cleanupError) { + if (!cleanupError) return error + return new AggregateError( + [error, cleanupError], + 'the fixture failed and its cleanup failed too', + { + cause: error, + } + ) +} + +/** + * Runs a step that owns a directory, and removes that directory when the step fails. + */ +async function owningDirectory(directory, step, remove = removeFixtureDirectory) { try { - return await import(pathToFileURL(fixtureFilePath(directory)).href) + return await step() } catch (error) { - await removeFixtureDirectory(directory) + try { + await remove(directory) + } catch (cleanupError) { + throw fixtureFailure(error, cleanupError) + } throw error } } +/** + * The directory that holds the fixture file. + * + * The allocation and the directory creation are one guarded step: a directory that + * was allocated and then not filled is removed instead of being left behind. + */ +async function createFixtureDirectory({ + allocate = mkdtemp, + mkdir: makeDirectory = mkdir, + remove = removeFixtureDirectory, +} = {}) { + const directory = await allocate(join(tmpdir(), 'control-plane-postgres-fixture-')) + return owningDirectory( + directory, + async () => { + // The bundle is generated output, so it is written into a dist/ directory: the + // repository's coverage configuration already ignores generated output, and the + // coverage report keeps the rows it had before. + await makeDirectory(join(directory, 'dist')) + return directory + }, + remove + ) +} + +/** + * Writes the fixture and loads it. + * + * The write is inside the guard too: a file that cannot be written leaves the owned + * directory behind unless the directory is removed here. + */ +async function loadFixtureModule( + directory, + source, + { writeFile: write = writeFile, remove = removeFixtureDirectory } = {} +) { + return owningDirectory( + directory, + async () => { + await write(fixtureFilePath(directory), source) + return import(pathToFileURL(fixtureFilePath(directory)).href) + }, + remove + ) +} + const fixtureSource = await built.outputs[0].text() const fixtureDirectory = await createFixtureDirectory() const fixtureFile = fixtureFilePath(fixtureDirectory) +// The removal is registered before the fixture is loaded, so a failure while the +// fixture is written or imported still has a registered cleanup. +afterAll(async () => { + await removeFixtureDirectory(fixtureDirectory) +}) const { configure, createIsolatedPostgres, withIsolatedPostgres } = await loadFixtureModule( fixtureDirectory, fixtureSource ) -afterAll(async () => { - await removeFixtureDirectory(fixtureDirectory) -}) function fixture({ migrationError, cleanupError, creationError } = {}) { const calls = [] @@ -199,9 +264,82 @@ test('removes the temporary fixture directory it owns', async () => { expect(existsSync(directory)).toBe(false) }) -test('removes the temporary fixture directory when the fixture cannot be loaded', async () => { +test('removes the owned directory when the fixture directory cannot be created', async () => { + const allocated = [] + const failure = new Error('the fixture directory could not be created') + const error = await createFixtureDirectory({ + allocate: async (prefix) => { + const directory = await mkdtemp(prefix) + allocated.push(directory) + return directory + }, + mkdir: async () => { + throw failure + }, + }).catch((thrown) => thrown) + + expect(error).toBe(failure) + expect(allocated).toHaveLength(1) + expect(existsSync(allocated[0])).toBe(false) +}) + +test('removes the owned directory when the fixture file cannot be written', async () => { + const directory = await createFixtureDirectory() + const failure = new Error('the fixture file could not be written') + const error = await loadFixtureModule(directory, 'export const probe = 1\n', { + writeFile: async () => { + throw failure + }, + }).catch((thrown) => thrown) + + expect(error).toBe(failure) + expect(existsSync(directory)).toBe(false) +}) + +test('removes the owned directory when the fixture cannot be imported', async () => { const directory = await createFixtureDirectory() + const error = await loadFixtureModule(directory, 'export const broken = (').catch( + (thrown) => thrown + ) + + expect(error).toBeInstanceOf(Error) + expect(existsSync(directory)).toBe(false) +}) + +test('keeps the original failure when the cleanup fails too', async () => { + const directory = await createFixtureDirectory() + const failure = new Error('the fixture file could not be written') + const cleanupFailure = new Error('the owned directory could not be removed') + const error = await loadFixtureModule(directory, 'export const probe = 1\n', { + writeFile: async () => { + throw failure + }, + remove: async () => { + throw cleanupFailure + }, + }).catch((thrown) => thrown) + + expect(error).toBeInstanceOf(AggregateError) + expect(error.errors[0]).toBe(failure) + expect(error.errors[1]).toBe(cleanupFailure) + expect(error.cause).toBe(failure) + // The injected cleanup could not remove the directory, so the test removes it. + await removeFixtureDirectory(directory) + expect(existsSync(directory)).toBe(false) +}) + +test('leaves directories it does not own untouched', async () => { + const neighbour = await createFixtureDirectory() + const directory = await createFixtureDirectory() + const failure = new Error('the fixture file could not be written') + + await loadFixtureModule(directory, 'export const probe = 1\n', { + writeFile: async () => { + throw failure + }, + }).catch(() => {}) - await expect(loadFixtureModule(directory, 'export const broken = (')).rejects.toThrow() + expect(existsSync(neighbour)).toBe(true) expect(existsSync(directory)).toBe(false) + await removeFixtureDirectory(neighbour) })