Files
rea/tests/boundary/filesystem/referenceSourceImport.test.ts
T

244 lines
8.2 KiB
TypeScript

import fs from "node:fs";
import { mkdir, rm, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { add, commit, init } from "isomorphic-git";
import { describe, expect, it } from "vitest";
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
import {
importReferenceSource,
normalizeHistoricalSourceParseFailures,
} from "../../../src/application/ReferenceSourceImport.js";
import { projectReferenceSourceEntryFailure } from "../../../src/application/ReferenceSourceImportEntries.js";
import {
projectReferenceSourceImportError,
type ReferenceSourceImportError,
} from "../../../src/application/ReferenceSourceImportTypes.js";
import { createHistoricalSourceManifest } from "../../../src/domain/referenceSourceGraph.js";
const fixture = async (parent: string, name: string): Promise<string> => {
const root = join(parent, name);
await mkdir(join(root, "src"), { recursive: true });
await Promise.all([
writeFile(join(root, "src", "main.ts"), 'import "./dep";\n'),
writeFile(join(root, "src", "dep.ts"), "export const value = 1;\n"),
writeFile(join(root, "src", "broken.ts"), "const = ;\n"),
writeFile(join(root, ".env"), "SECRET_SENTINEL=do-not-record\n"),
writeFile(join(root, "package.json"), '{"name":"fixture"}\n'),
]);
return root;
};
const importTree = (root: string, signal?: AbortSignal) =>
importReferenceSource({
root,
caller: "reference-import-test",
policy: {
secretPatterns: [".env", ".env.*"],
},
...(signal === undefined ? {} : { signal }),
});
describe("reference source import error projection", () => {
it("deduplicates exact parse failures without collapsing distinct reasons", () => {
const malformed = {
path: "src/main.ts",
parser: "babel",
reason: "Malformed input",
};
const unexpected = {
path: "src/main.ts",
parser: "babel",
reason: "Unexpected token",
};
expect(
normalizeHistoricalSourceParseFailures([
unexpected,
malformed,
unexpected,
]),
).toEqual([malformed, unexpected]);
});
it("projects entry failures without low-level reader diagnostics", () => {
for (const [kind, code] of [
["directory", "io"],
["symlink", "io"],
["file", "io"],
["file", "cancelled"],
["unknown", "unsupported"],
] as const) {
const message = projectReferenceSourceEntryFailure({
status: "failed",
path: "safe/path",
kind,
code,
message: "SECRET internal diagnostic /private/path",
});
expect(message).not.toContain("SECRET");
expect(message).not.toContain("/private/path");
expect(message).toMatch(/Check|try again|when ready|smaller|supported/u);
}
});
it("projects every import failure without raw parser or policy text", () => {
const expectedCategories = {
cancelled: "cancelled",
"invalid-root": "invalid_input",
io: "execution_failure",
parse: "execution_failure",
} as const;
for (const [code, category] of Object.entries(expectedCategories)) {
const projected = projectReferenceSourceImportError({
tag: "reference-source-import",
code: code as ReferenceSourceImportError["code"],
message: "SECRET parser stack and /private/path",
});
expect(projected.category).toBe(category);
expect(projected.message).not.toContain("SECRET");
expect(projected.message).not.toContain("/private/path");
expect(projected.message).toMatch(/try again|when ready|Check that/u);
}
});
});
describe("reference source import behavior", () => {
it("imports a source file larger than the former 16 MiB ceiling", async () => {
const root = await createTestTempDirectory("rea-reference-large-");
const size = 16 * 1024 * 1024 + 1;
await writeFile(join(root, "large.bin"), Buffer.alloc(size, 0x61));
const result = await importReferenceSource({
root,
caller: "reference-import-test",
policy: { secretPatterns: [] },
});
expect(result.ok).toBe(true);
if (!result.ok) return;
expect(result.value.entries).toContainEqual(
expect.objectContaining({
path: "large.bin",
kind: "file",
size,
content_state: "hashed",
}),
);
});
it("imports more than ten thousand source entries", async () => {
const root = await createTestTempDirectory("rea-reference-many-");
await Promise.all(
Array.from({ length: 10_001 }, (_, index) =>
writeFile(join(root, `entry-${String(index).padStart(5, "0")}`), ""),
),
);
const result = await importReferenceSource({
root,
caller: "reference-import-test",
policy: { secretPatterns: [] },
});
expect(result.ok).toBe(true);
if (!result.ok) return;
expect(result.value.entries).toHaveLength(10_001);
});
it("imports BMP and supplementary filenames in Unicode code point order", async () => {
const root = await createTestTempDirectory("reference-unicode-");
try {
const paths = ["\uE000.ts", "\u{10000}.ts"];
await Promise.all(
paths.map((path) =>
writeFile(join(root, path), "export const value = 1;\n"),
),
);
const result = await importTree(root);
expect(result.ok).toBe(true);
if (!result.ok) return;
expect(result.value.entries.map(({ path }) => path)).toEqual(paths);
const repeated = await importTree(root);
expect(repeated).toEqual(result);
} finally {
await rm(root, { recursive: true, force: true });
}
});
it("is relocation-stable, resolves imports, and excludes secrets before capture", async () => {
const parent = await createTestTempDirectory("rea-reference-import-");
try {
const leftRoot = await fixture(parent, "left");
const rightRoot = await fixture(parent, "right");
const [left, right] = await Promise.all([
importTree(leftRoot),
importTree(rightRoot),
]);
expect(left.ok).toBe(true);
expect(right.ok).toBe(true);
if (!left.ok || !right.ok) throw new Error("expected imports to pass");
expect(createHistoricalSourceManifest(left.value)).toEqual(
createHistoricalSourceManifest(right.value),
);
expect(left.value.relationships).toContainEqual(
expect.objectContaining({
from_path: "src/main.ts",
to: "src/dep.ts",
resolution: "internal",
}),
);
expect(left.value.parse_failures).toHaveLength(1);
expect(left.value.exclusions).toContainEqual({
path: ".env",
reason: "configured-secret",
});
expect(JSON.stringify(left.value)).not.toContain("SECRET_SENTINEL");
expect(JSON.stringify(left.value)).not.toContain(leftRoot);
} finally {
await rm(parent, { recursive: true, force: true });
}
});
it("imports the caller-selected directory and honors cancellation", async () => {
const outside = await createTestTempDirectory("rea-reference-outside-");
try {
const root = await fixture(outside, "tree");
expect(await importTree(root)).toMatchObject({ ok: true });
const controller = new AbortController();
controller.abort();
const cancelled = await importTree(root, controller.signal);
expect(cancelled).toMatchObject({
ok: false,
error: { code: "cancelled" },
});
} finally {
await rm(outside, { recursive: true, force: true });
}
});
it("records bounded local Git state without invoking Git", async () => {
const parent = await createTestTempDirectory("rea-reference-git-");
try {
const root = await fixture(parent, "repo");
await init({ fs, dir: root, defaultBranch: "main" });
for (const filepath of ["package.json", "src/main.ts", "src/dep.ts"])
await add({ fs, dir: root, filepath });
const oid = await commit({
fs,
dir: root,
author: { name: "REA Test", email: "rea@example.invalid" },
message: "fixture",
});
const result = await importTree(root);
expect(result.ok).toBe(true);
if (!result.ok) throw result.error;
expect(result.value.vcs).toEqual({ kind: "git", head: oid, dirty: null });
} finally {
await rm(parent, { recursive: true, force: true });
}
});
});