Files
reverse-engineering-anything/tests/boundary/filesystem/analysisSnapshotInput.test.ts
T
gensokyo-devandgensokyo-dev 4ad1eb5beb fix(snapshot): locate entry diagnostics by collection and index
Each snapshot entry is validated alone, so its schema issue path started at
the entry. Prefix it with entries or workflow_entries and the entry index so
the reason names the entry to repair, and match the header case's issue
count without freezing the whole sentence.

Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-11-14 14:06:23 +01:00

161 lines
6.0 KiB
TypeScript

import { readFile, stat, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { describe, expect, it } from "vitest";
import {
readAnalysisSnapshot,
writeAnalysisSnapshot,
} from "../../../src/application/binary/AnalysisSnapshotFiles.js";
import { projectAnalysisError } from "../../../src/domain/analysisErrorProjection.js";
import {
snapshotBinding,
snapshotTarget,
} from "../../../src/domain/analysisSnapshot.js";
import {
ANALYSIS_SNAPSHOT_PROFILE,
ANALYSIS_SNAPSHOT_TARGET,
} from "../../../src/domain/analysisSnapshot.fixture.js";
import { createEvidenceBundle } from "../../../src/domain/evidenceBundle.js";
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
import { withArtifactResourceScope } from "../../fixtures/artifactInventory.js";
describe.each([
{ mode: "native", paddingBytes: 0 },
{ mode: "streamed", paddingBytes: 9 * 1024 * 1024 },
])("analysis snapshot input ($mode)", ({ paddingBytes }) => {
it.each([
{
label: "header",
document: { entries: [], workflow_entries: [] },
field: "target",
},
{
label: "provider entry",
document: { entries: [{}], workflow_entries: [] },
field: "entries.0.query_id",
},
{
label: "workflow entry",
document: { entries: [], workflow_entries: [{}] },
field: "workflow_entries.0.query_id",
},
])(
"retains the first $label schema diagnostic through the file wrapper",
async ({ document, field }) => {
const root = await createTestTempDirectory(
"rea-snapshot-schema-diagnostic-",
);
const path = join(root, "snapshot.json");
const encoded = `${" ".repeat(paddingBytes)}${JSON.stringify(document)}`;
await writeFile(path, encoded);
const loaded = await readAnalysisSnapshot(path);
if (loaded.ok) throw new Error("Expected invalid snapshot refusal");
expect(loaded.error.cause).toMatchObject({ name: "ZodError" });
const projected = projectAnalysisError(loaded.error);
expect(projected).toMatchObject({
code: "evidence_integrity_mismatch",
category: "integrity_mismatch",
retryable: false,
details: { reason: expect.stringContaining(`at ${field}:`) },
});
if (field === "target")
expect(projected.details?.reason).toMatch(
/ at target: .+ \(2 more issues\)$/,
);
expect(projected).not.toHaveProperty("cause");
expect(projected).not.toHaveProperty("stack");
expect(await readFile(path, "utf8")).toBe(encoded);
},
);
it.each(["[]", "null", "5", '"x"', "true"])(
"classifies a readable %s root as invalid content, not an I/O failure",
async (document) => {
const root = await createTestTempDirectory("rea-snapshot-root-");
const path = join(root, "snapshot.json");
const encoded = `${" ".repeat(paddingBytes)}${document}`;
await writeFile(path, encoded);
const loaded = await readAnalysisSnapshot(path);
if (loaded.ok) throw new Error("Expected a non-object root rejection");
const projected = projectAnalysisError(loaded.error);
expect(projected).toMatchObject({
code: "evidence_integrity_mismatch",
details: { reason: "invalid-json" },
});
expect(projected.message).toContain("Repair or recreate");
expect(loaded.error.cause).toMatchObject({
message: "JSON document root must be an object",
});
expect(await readFile(path, "utf8")).toBe(encoded);
},
);
it("retains syntax and snapshot-member validation and loads valid objects", async () => {
const root = await createTestTempDirectory("rea-snapshot-validation-");
const path = join(root, "snapshot.json");
const prefix = " ".repeat(paddingBytes);
await writeFile(path, `${prefix}[`);
expect(await readAnalysisSnapshot(path)).toMatchObject({
ok: false,
error: { _tag: "EvidenceFileError", reason: "invalid-json" },
});
await writeFile(path, `${prefix}{}`);
expect(await readAnalysisSnapshot(path)).toMatchObject({
ok: false,
error: { _tag: "EvidenceIntegrityError" },
});
const snapshot = {
target: snapshotTarget(ANALYSIS_SNAPSHOT_TARGET),
binding: snapshotBinding(ANALYSIS_SNAPSHOT_PROFILE),
entries: [],
workflow_entries: [],
evidence_bundle: createEvidenceBundle([]),
};
await writeFile(path, `${prefix}${JSON.stringify(snapshot)}`);
expect(await readAnalysisSnapshot(path)).toEqual({
ok: true,
value: snapshot,
});
});
});
it("retains serialization schema diagnostics without creating a snapshot file", async () => {
const root = await createTestTempDirectory("rea-snapshot-write-diagnostic-");
const path = join(root, "snapshot.json");
const snapshot = {
target: snapshotTarget(ANALYSIS_SNAPSHOT_TARGET),
binding: snapshotBinding(ANALYSIS_SNAPSHOT_PROFILE),
entries: [],
workflow_entries: [],
evidence_bundle: createEvidenceBundle([]),
};
Reflect.deleteProperty(snapshot, "binding");
const written = await withArtifactResourceScope((resources) =>
writeAnalysisSnapshot(snapshot, path, false, resources),
);
if (written.ok) throw new Error("Expected invalid snapshot refusal");
expect(written.error.cause).toMatchObject({ name: "ZodError" });
expect(projectAnalysisError(written.error)).toMatchObject({
code: "evidence_integrity_mismatch",
details: { reason: expect.stringContaining("at binding:") },
});
await expect(stat(path)).rejects.toMatchObject({ code: "ENOENT" });
});
it("keeps file-selection failures distinct from invalid snapshot contents", async () => {
const root = await createTestTempDirectory("rea-snapshot-selection-");
for (const [path, reason] of [
[join(root, "missing.json"), "missing"],
[root, "not-file"],
] as const) {
const loaded = await readAnalysisSnapshot(path);
if (loaded.ok) throw new Error("Expected a file-selection failure");
expect(projectAnalysisError(loaded.error)).toMatchObject({
code: "invalid_request",
details: { reason },
});
}
});