import assert from "node:assert/strict"; import { mkdir, mkdtemp, readFile, rm } from "node:fs/promises"; import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; import test from "node:test"; import { fileURLToPath } from "node:url"; import { CHECK_IDS, canonicalIntegrationBase, cleanupOwnedRun, createOwnedRun, validateRunRoot, } from "./p4-acceptance.mjs"; const roots = []; async function fakeRepository() { const root = await mkdtemp(join(tmpdir(), "p4-acceptance-repo-")); roots.push(root); await mkdir(join(root, ".artifacts", "p4-integration"), { recursive: true }); return root; } test.afterEach(async () => { await Promise.all(roots.splice(0).map((root) => rm(root, { recursive: true, force: true }))); }); test("check ids are stable and unique", () => { assert.equal(new Set(CHECK_IDS).size, CHECK_IDS.length); assert.ok(CHECK_IDS.includes("self_heal_create_missing")); assert.ok(CHECK_IDS.includes("rebuild_recreates_contract")); }); test("run roots are only canonical direct p4 integration children", async () => { const repositoryRoot = await fakeRepository(); const base = canonicalIntegrationBase(repositoryRoot); const id = `p4-${"a".repeat(32)}`; assert.equal(validateRunRoot(repositoryRoot, join(base, id), id), join(base, id)); for (const candidate of [base, join(repositoryRoot, ".artifacts", "p1-integration", id), join(base, id, "nested")]) { assert.throws(() => validateRunRoot(repositoryRoot, candidate, id)); } assert.throws(() => validateRunRoot(repositoryRoot, join(base, `p4-${"A".repeat(32)}`), `p4-${"A".repeat(32)}`)); }); test("createOwnedRun writes a canonical marker and cleanup refuses foreign roots", async () => { const repositoryRoot = await fakeRepository(); const { runId, runRoot } = createOwnedRun(repositoryRoot); assert.match(runId, /^p4-[0-9a-f]{32}$/); const marker = JSON.parse(await readFile(join(runRoot, "run.json"), "utf8")); assert.equal(marker.runId, runId); assert.throws(() => cleanupOwnedRun(repositoryRoot, join(repositoryRoot, "tmp"), runId)); cleanupOwnedRun(repositoryRoot, runRoot, runId); });