Files
rea/tests/boundary/filesystem/verifierCommandOutput.test.ts
T
morluto 2250e67bc2 fix(verifiers): consolidate native client command lifetimes
Migrate the remaining native verifier commands to shared ownership with explicit stdin contracts, command-before-fixture cleanup, and failure receipts. Preserve observed catalog counts and unknowns, retained artifacts, native assertions, and selected launch inputs.

Remove the obsolete raw exec export and share output persistence across native verifiers. Exercise actual entrypoints with authored failed preflights and acknowledged descendants, plus filesystem failures and opaque error preservation.
2026-10-24 19:40:50 +08:00

199 lines
6.1 KiB
TypeScript

import { readFile } from "node:fs/promises";
import { afterEach, expect, it } from "vitest";
import { saveVerifierCommandOutput } from "../../../scripts/lib/verifier-command-output.mjs";
import {
createTestWorkspace,
removeTestWorkspace,
} from "../../support/workspace/workspaceFixture.js";
const workspaces: string[] = [];
afterEach(async () => {
for (const root of workspaces.splice(0)) await removeTestWorkspace(root);
});
const createOutputWorkspace = async () => {
const workspace = await createTestWorkspace("rea-verifier-command-output-");
workspaces.push(workspace.root);
return workspace;
};
const rejection = (operation: Promise<unknown>): Promise<unknown> =>
operation.then(
() => {
throw new Error("Expected command output persistence to reject");
},
(cause: unknown) => cause,
);
it("writes exact Unicode and empty output bytes and returns the original output", async () => {
const workspace = await createOutputWorkspace();
const paths = {
stdout: workspace.path("stdout"),
stderr: workspace.path("stderr"),
};
const output = { stdout: "observed α测试\0\n", stderr: "" };
expect(await saveVerifierCommandOutput(async () => output, paths)).toBe(
output,
);
expect(await readFile(paths.stdout)).toEqual(Buffer.from(output.stdout));
expect(await readFile(paths.stderr)).toEqual(Buffer.alloc(0));
});
it("retains both failed-command streams while preserving its exact cause", async () => {
const workspace = await createOutputWorkspace();
const paths = {
stdout: workspace.path("stdout"),
stderr: workspace.path("stderr"),
};
const cause = Object.assign(new Error("selected command failed"), {
snapshot: {
stdout: { text: "" },
stderr: { text: "partial diagnostics α测试\n" },
},
});
await expect(
saveVerifierCommandOutput(async () => {
throw cause;
}, paths),
).rejects.toBe(cause);
expect(await readFile(paths.stdout)).toEqual(Buffer.alloc(0));
expect(await readFile(paths.stderr)).toEqual(
Buffer.from(cause.snapshot.stderr.text),
);
});
it("writes available partial failure output without replacing unavailable evidence", async () => {
const workspace = await createOutputWorkspace();
const original = Buffer.from("retained caller output\0\n");
const paths = {
stdout: await workspace.write("stdout", original),
stderr: workspace.path("stderr"),
};
const cause = {
snapshot: {
stdout: { text: null },
stderr: { text: "available failure diagnostics\n" },
},
};
await expect(
saveVerifierCommandOutput(async () => {
throw cause;
}, paths),
).rejects.toBe(cause);
expect(await readFile(paths.stdout)).toEqual(original);
expect(await readFile(paths.stderr, "utf8")).toBe(cause.snapshot.stderr.text);
});
it.each([undefined, null])(
"preserves the opaque %s failure and both existing output artifacts",
async (cause) => {
const workspace = await createOutputWorkspace();
const paths = {
stdout: await workspace.write("stdout", "retained stdout\n"),
stderr: await workspace.write("stderr", "retained stderr\n"),
};
await expect(
saveVerifierCommandOutput(async () => {
throw cause;
}, paths),
).rejects.toBe(cause);
expect(await readFile(paths.stdout, "utf8")).toBe("retained stdout\n");
expect(await readFile(paths.stderr, "utf8")).toBe("retained stderr\n");
},
);
it.skipIf(process.platform === "win32")(
"retains the command cause and actual stdout write failure while writing stderr",
async () => {
const workspace = await createOutputWorkspace();
const paths = {
stdout: await workspace.mkdir("stdout-directory"),
stderr: workspace.path("stderr"),
};
const cause = Object.assign(new Error("primary command failure"), {
snapshot: {
stdout: { text: "command stdout" },
stderr: { text: "command stderr\n" },
},
});
const failure = await rejection(
saveVerifierCommandOutput(async () => {
throw cause;
}, paths),
);
expect(failure).toBeInstanceOf(AggregateError);
if (!(failure instanceof AggregateError)) throw failure;
expect(failure.cause).toBe(cause);
expect(failure.errors).toHaveLength(2);
expect(failure.errors[0]).toBe(cause);
expect(failure.errors[1]).toMatchObject({
code: "EISDIR",
path: paths.stdout,
});
expect(await readFile(paths.stderr, "utf8")).toBe(
cause.snapshot.stderr.text,
);
},
);
it.skipIf(process.platform === "win32")(
"attempts stderr persistence after a successful command's stdout write fails",
async () => {
const workspace = await createOutputWorkspace();
const paths = {
stdout: await workspace.mkdir("stdout-directory"),
stderr: workspace.path("stderr"),
};
const output = {
stdout: "successful stdout",
stderr: "successful stderr\n",
};
const failure = await rejection(
saveVerifierCommandOutput(async () => output, paths),
);
expect(failure).not.toBeInstanceOf(AggregateError);
expect(failure).toMatchObject({
code: "EISDIR",
path: paths.stdout,
});
expect(await readFile(paths.stderr, "utf8")).toBe(output.stderr);
},
);
it.skipIf(process.platform === "win32")(
"retains both independent filesystem errors when neither output can be written",
async () => {
const workspace = await createOutputWorkspace();
const paths = {
stdout: await workspace.mkdir("stdout-directory"),
stderr: await workspace.mkdir("stderr-directory"),
};
const failure = await rejection(
saveVerifierCommandOutput(
async () => ({ stdout: "stdout", stderr: "stderr" }),
paths,
),
);
expect(failure).toBeInstanceOf(AggregateError);
if (!(failure instanceof AggregateError)) throw failure;
expect(failure.errors).toHaveLength(2);
expect(failure.errors[0]).toMatchObject({
code: "EISDIR",
path: paths.stdout,
});
expect(failure.errors[1]).toMatchObject({
code: "EISDIR",
path: paths.stderr,
});
expect(failure.cause).toBe(failure.errors[0]);
},
);