Files
fusion/scripts/__tests__/content-hash.test.mjs
gsxdsm 211c0fd557 perf(test): cut inner-loop fixed overhead to sub-second on cache-fresh runs
- skill-sync check conditioned on content hash of its inputs (skips ~0.3s spawn)
- ensure-test-artifacts: git-blob content-hash staleness; branch switches no longer trigger spurious ~2.6s tsc rebuilds (mtime fallback when dirty)
- isolation guard: cheap --before-fast reusing prior post-run baseline (~2.1s -> ~0.07s); detection proven preserved via injected-leak failure test
- vitest-setup: CI skips 4040-4045 discovery probe unless FUSION_RESERVED_PORTS set; kill-guard wrapper untouched, asymmetry pinned by port-probe-policy tests
- cache-fresh fast path skips sync/artifacts/HOME-prune entirely (mode line: fast-path=cache-fresh)
2026-06-03 17:57:29 -07:00

154 lines
6.2 KiB
JavaScript

/**
* Unit tests for scripts/lib/content-hash.mjs (U3).
*
* Runner: node --test scripts/__tests__/content-hash.test.mjs
*
* These tests use injectable gitFn/readFn stubs so they never touch the real
* repo or shell out to git.
*/
import test from "node:test";
import assert from "node:assert/strict";
import { computeContentHash } from "../lib/content-hash.mjs";
/**
* Build a fake git runner from a description of the tree.
*
* @param {object} tree
* @param {Record<string,string>} tree.tracked path -> blob sha (clean tracked files)
* @param {string[]} [tree.dirty] tracked paths that are modified in worktree
* @param {string[]} [tree.untracked] untracked-not-ignored paths
*/
function fakeGit(tree) {
const { tracked = {}, dirty = [], untracked = [] } = tree;
return (args) => {
if (args[0] === "ls-files") {
return Object.entries(tracked)
.map(([file, sha]) => `100644 ${sha} 0\t${file}`)
.join("\n");
}
if (args[0] === "status") {
const lines = [];
for (const file of dirty) lines.push(` M ${file}`);
for (const file of untracked) lines.push(`?? ${file}`);
return lines.join("\n");
}
return null;
};
}
const readBytes = (contentByPath) => (absPath) => {
// absPath is rootDir + "/" + relPath; match on suffix.
for (const [rel, content] of Object.entries(contentByPath)) {
if (absPath.endsWith(rel)) return Buffer.from(content);
}
throw Object.assign(new Error("ENOENT"), { code: "ENOENT" });
};
const base = { rootDir: "/repo", inputPaths: ["packages/core/src"] };
test("computeContentHash is stable for identical tracked content", () => {
const git = fakeGit({ tracked: { "packages/core/src/a.ts": "aaa", "packages/core/src/b.ts": "bbb" } });
const h1 = computeContentHash({ ...base, gitFn: git, readFn: readBytes({}) });
const h2 = computeContentHash({ ...base, gitFn: git, readFn: readBytes({}) });
assert.equal(h1, h2);
assert.equal(h1.length, 64);
});
test("computeContentHash busts when a tracked blob sha changes (real source change)", () => {
const before = computeContentHash({
...base,
gitFn: fakeGit({ tracked: { "packages/core/src/a.ts": "aaa" } }),
readFn: readBytes({}),
});
const after = computeContentHash({
...base,
gitFn: fakeGit({ tracked: { "packages/core/src/a.ts": "zzz" } }),
readFn: readBytes({}),
});
assert.notEqual(before, after);
});
test("branch-switch with identical content yields the same hash (mtime-independent)", () => {
// Two 'branches' with the same tracked blob shas → identical hash, even though
// a real checkout would rewrite mtimes. The hash never reads mtime.
const git = fakeGit({ tracked: { "packages/core/src/a.ts": "aaa" } });
const branchA = computeContentHash({ ...base, gitFn: git, readFn: readBytes({}) });
const branchB = computeContentHash({ ...base, gitFn: git, readFn: readBytes({}) });
assert.equal(branchA, branchB);
});
test("dirty tracked file is hashed by working-tree bytes, not the stale index sha", () => {
// Same index blob sha, but the worktree content differs → different hashes.
const clean = computeContentHash({
...base,
gitFn: fakeGit({ tracked: { "packages/core/src/a.ts": "aaa" } }),
readFn: readBytes({ "packages/core/src/a.ts": "ON-DISK-V1" }),
});
const dirty = computeContentHash({
...base,
gitFn: fakeGit({ tracked: { "packages/core/src/a.ts": "aaa" }, dirty: ["packages/core/src/a.ts"] }),
readFn: readBytes({ "packages/core/src/a.ts": "ON-DISK-V2" }),
});
assert.notEqual(clean, dirty);
});
test("two different working-tree contents of a dirty file produce different hashes", () => {
const v1 = computeContentHash({
...base,
gitFn: fakeGit({ tracked: { "packages/core/src/a.ts": "aaa" }, dirty: ["packages/core/src/a.ts"] }),
readFn: readBytes({ "packages/core/src/a.ts": "V1" }),
});
const v2 = computeContentHash({
...base,
gitFn: fakeGit({ tracked: { "packages/core/src/a.ts": "aaa" }, dirty: ["packages/core/src/a.ts"] }),
readFn: readBytes({ "packages/core/src/a.ts": "V2" }),
});
assert.notEqual(v1, v2);
});
test("untracked file is folded into the hash via its bytes", () => {
const without = computeContentHash({
...base,
gitFn: fakeGit({ tracked: { "packages/core/src/a.ts": "aaa" } }),
readFn: readBytes({}),
});
const withUntracked = computeContentHash({
...base,
gitFn: fakeGit({ tracked: { "packages/core/src/a.ts": "aaa" }, untracked: ["packages/core/src/new.ts"] }),
readFn: readBytes({ "packages/core/src/new.ts": "brand new" }),
});
assert.notEqual(without, withUntracked);
});
test("porcelain status parsing tolerates spacing variants (M path vs ' M path')", () => {
// git emits the worktree-modified code in either " M path" or "M path" form
// depending on staged/worktree state; both must be recognized as dirty.
const tracked = { "packages/core/src/a.ts": "aaa" };
const readFn = (absPath) => (absPath.endsWith("a.ts") ? Buffer.from("ON-DISK") : Buffer.from(""));
const variantGit = (statusLine) => (args) => {
if (args[0] === "ls-files") {
return Object.entries(tracked).map(([f, s]) => `100644 ${s} 0\t${f}`).join("\n");
}
if (args[0] === "status") return statusLine;
return null;
};
const clean = computeContentHash({ ...base, gitFn: variantGit(""), readFn: () => Buffer.from("") });
const variantA = computeContentHash({ ...base, gitFn: variantGit(" M packages/core/src/a.ts"), readFn });
const variantB = computeContentHash({ ...base, gitFn: variantGit("M packages/core/src/a.ts"), readFn });
assert.notEqual(clean, variantA, "leading-space variant must register as dirty");
assert.notEqual(clean, variantB, "trailing-space variant must register as dirty");
// Both variants describe the same dirty file/content → identical hash.
assert.equal(variantA, variantB);
});
test("versionPrefix busts the hash so a format bump invalidates all entries", () => {
const git = fakeGit({ tracked: { "packages/core/src/a.ts": "aaa" } });
const v1 = computeContentHash({ ...base, versionPrefix: "v1", gitFn: git, readFn: readBytes({}) });
const v2 = computeContentHash({ ...base, versionPrefix: "v2", gitFn: git, readFn: readBytes({}) });
assert.notEqual(v1, v2);
});