test: add independent P1.1 acceptance and manual tooling
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { createHash } from "node:crypto";
|
||||
import { access, lstat, readFile, rm } from "node:fs/promises";
|
||||
import { join } from "node:path";
|
||||
import test from "node:test";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { dirname, resolve } from "node:path";
|
||||
|
||||
import {
|
||||
cleanupManual,
|
||||
prepareManual,
|
||||
readManualOwnership,
|
||||
serveManual,
|
||||
stopManual,
|
||||
} from "./p11-manual-acceptance.mjs";
|
||||
|
||||
const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), "../..");
|
||||
const fixedRoot = join(repoRoot, ".artifacts", "manual-acceptance", "p11");
|
||||
|
||||
async function safeCleanup() {
|
||||
try {
|
||||
const owned = await readManualOwnership({ repositoryRoot: repoRoot });
|
||||
if (owned.status === "RUNNING") await stopManual({ repositoryRoot: repoRoot }).catch(() => {});
|
||||
await cleanupManual({ repositoryRoot: repoRoot }).catch(() => {});
|
||||
} catch {
|
||||
await rm(fixedRoot, { recursive: true, force: true }).catch(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
test.beforeEach(async () => {
|
||||
await safeCleanup();
|
||||
});
|
||||
|
||||
test.afterEach(async () => {
|
||||
await safeCleanup();
|
||||
});
|
||||
|
||||
test("prepare creates an independent pending lab without verdict", { concurrency: false }, async () => {
|
||||
const root = await prepareManual({ repositoryRoot: repoRoot });
|
||||
assert.equal(root, fixedRoot);
|
||||
const owned = await readManualOwnership({ repositoryRoot: repoRoot });
|
||||
assert.equal(owned.kind, "p11-manual-acceptance");
|
||||
assert.equal(owned.status, "PENDING");
|
||||
await access(join(root, "GUIDE.md"));
|
||||
await access(join(root, "author", "thoth-workspaces.yaml"));
|
||||
await access(join(root, "author", "p11-filesystem", "evidence", "guide.md"));
|
||||
await access(join(root, "requests", "validate-p11-filesystem.json"));
|
||||
await access(join(root, "commands", "http-01-status.sh"));
|
||||
await access(join(root, "commands", "render-1.sh"));
|
||||
await assert.rejects(access(join(root, "VERDICT.md")));
|
||||
const guide = await readFile(join(root, "GUIDE.md"), "utf8");
|
||||
assert.match(guide, /VERDICT\.md/);
|
||||
assert.match(guide, /read-only/);
|
||||
});
|
||||
|
||||
test("serve, stop, and cleanup manage the owned backend and frontend listeners", { concurrency: false }, async () => {
|
||||
await prepareManual({ repositoryRoot: repoRoot });
|
||||
const running = await serveManual({ repositoryRoot: repoRoot });
|
||||
assert.equal(running.status, "RUNNING");
|
||||
assert.equal(typeof running.backend.pid, "number");
|
||||
assert.equal(typeof running.frontend.pid, "number");
|
||||
const status = await fetch("http://127.0.0.1:8791/workspace-registry/status");
|
||||
assert.equal(status.status, 200);
|
||||
const frontend = await fetch("http://127.0.0.1:8792/");
|
||||
assert.equal(frontend.status, 200);
|
||||
await assert.rejects(cleanupManual({ repositoryRoot: repoRoot }), /still live/);
|
||||
const stopped = await stopManual({ repositoryRoot: repoRoot });
|
||||
assert.equal(stopped.status, "STOPPED");
|
||||
await cleanupManual({ repositoryRoot: repoRoot });
|
||||
await assert.rejects(lstat(fixedRoot));
|
||||
});
|
||||
|
||||
test("stop fails closed when ownership is tampered", { concurrency: false }, async () => {
|
||||
await prepareManual({ repositoryRoot: repoRoot });
|
||||
const running = await serveManual({ repositoryRoot: repoRoot });
|
||||
const ownershipPath = join(fixedRoot, "ownership.json");
|
||||
const digestPath = join(fixedRoot, "ownership.sha256");
|
||||
const original = JSON.parse(await readFile(ownershipPath, "utf8"));
|
||||
const tampered = { ...original, backend: { ...original.backend, pid: original.backend.pid + 1 } };
|
||||
await rm(ownershipPath);
|
||||
await readFile(join(fixedRoot, "logs", "backend.log"));
|
||||
await import("node:fs/promises").then(({ writeFile }) => writeFile(ownershipPath, `${JSON.stringify(tampered, null, 2)}
|
||||
`));
|
||||
await assert.rejects(stopManual({ repositoryRoot: repoRoot }), /manual ownership digest mismatch/);
|
||||
const restored = `${JSON.stringify(running, null, 2)}
|
||||
`;
|
||||
const restoredDigest = `${createHash("sha256").update(restored).digest("hex")}
|
||||
`;
|
||||
await import("node:fs/promises").then(({ writeFile }) => Promise.all([writeFile(ownershipPath, restored), writeFile(digestPath, restoredDigest)]));
|
||||
await stopManual({ repositoryRoot: repoRoot });
|
||||
});
|
||||
Reference in New Issue
Block a user