mirror of
https://github.com/morluto/rea.git
synced 2026-11-09 00:07:18 +00:00
* test: focus configuration diagnostics on their owners Preserve shape errors, selected paths, recovery guidance, and unchanged-file behavior across parser, setup, and uninstall boundaries. * test: focus artifact and evidence checks on behavior Retain format, identity, malformed-input, and cleanup coverage while removing fixed prose and closing the admitted test source. * refactor(debugger): use configured session admission limits * test: focus evidence and diagnostics on behavior * fix(test): restore verifier export and formatting * test(config): verify debugger limit ranges * test(rizin): keep fixture executable authoritative * test(rizin): isolate debugger fixture environment
121 lines
4.1 KiB
TypeScript
121 lines
4.1 KiB
TypeScript
import { createHash } from "node:crypto";
|
|
import { writeFile } from "node:fs/promises";
|
|
import { join } from "node:path";
|
|
import { build } from "plist";
|
|
import { expect, it } from "vitest";
|
|
import { createTestTempDirectory } from "../../tests/fixtures/temporaryDirectory.js";
|
|
import { scanCanonicalArtifactInventory } from "../../tests/fixtures/artifactInventory.js";
|
|
import {
|
|
NativeDmgArtifactReader,
|
|
type NativeDmgHost,
|
|
} from "./NativeDmgArtifactReader.js";
|
|
import { translateArtifactFailure } from "./ArtifactOperationFailure.js";
|
|
import { projectAnalysisError } from "../domain/analysisErrorProjection.js";
|
|
|
|
it.each(["same", "other", "missing-path", "no-path", "empty-group"] as const)(
|
|
"retains DMG root facts and limits existing-attachment guidance to a resolved image path: %s",
|
|
async (listed) => {
|
|
const root = await createTestTempDirectory("rea-dmg-unavailable-root-");
|
|
const path = join(root, "image.dmg");
|
|
const bytes = Buffer.alloc(1024);
|
|
bytes.write("koly", bytes.length - 512, "ascii");
|
|
await writeFile(path, bytes);
|
|
const other = join(root, "other.dmg");
|
|
await writeFile(other, bytes);
|
|
const calls: string[] = [];
|
|
const host: NativeDmgHost = {
|
|
run: async (args) => {
|
|
calls.push(args[0] ?? "");
|
|
if (args[0] === "verify") return { stdout: "", exitCode: 0 };
|
|
if (args[0] === "info")
|
|
return {
|
|
stdout: build({
|
|
images: [
|
|
{
|
|
...(listed === "no-path"
|
|
? {}
|
|
: {
|
|
"image-path":
|
|
listed === "same" || listed === "empty-group"
|
|
? path
|
|
: listed === "other"
|
|
? other
|
|
: join(root, "missing.dmg"),
|
|
}),
|
|
"system-entities":
|
|
listed === "empty-group"
|
|
? []
|
|
: [
|
|
{
|
|
"dev-entry": "/dev/disk800",
|
|
"mount-point": join(root, "preexisting"),
|
|
},
|
|
],
|
|
},
|
|
],
|
|
}),
|
|
exitCode: 0,
|
|
};
|
|
if (args[0] === "attach")
|
|
return {
|
|
stdout: "",
|
|
stderr: "hdiutil: attach failed - Resource busy",
|
|
exitCode: 1,
|
|
};
|
|
throw new Error(`Unexpected command ${String(args[0])}`);
|
|
},
|
|
};
|
|
let failure: unknown;
|
|
try {
|
|
await scanCanonicalArtifactInventory(
|
|
path,
|
|
{},
|
|
() => new NativeDmgArtifactReader(path, {}, host),
|
|
);
|
|
} catch (cause: unknown) {
|
|
failure = cause;
|
|
}
|
|
const projected = projectAnalysisError(
|
|
translateArtifactFailure("inspect_artifact", failure),
|
|
);
|
|
expect(projected).toMatchObject({
|
|
category: "unavailable",
|
|
details: {
|
|
partial_observation: {
|
|
kind: "artifact-inventory",
|
|
inventory: {
|
|
manifest: {
|
|
root_sha256: createHash("sha256").update(bytes).digest("hex"),
|
|
root_format: "dmg",
|
|
},
|
|
coverage: { status: "unknown" },
|
|
occurrences: [{ logical_path: "." }],
|
|
provenance: [
|
|
{ arguments: ["verify", path], exit_code: 0 },
|
|
{
|
|
arguments: expect.arrayContaining(["attach", path]),
|
|
exit_code: 1,
|
|
},
|
|
],
|
|
},
|
|
},
|
|
},
|
|
});
|
|
expect(projected.details?.partial_observation).toEqual(
|
|
expect.objectContaining({ kind: "artifact-inventory" }),
|
|
);
|
|
if (listed === "same") {
|
|
expect(projected.message).toMatch(
|
|
/hdiutil.*existing attachment.*owner.*release.*retry.*does not borrow or detach/iu,
|
|
);
|
|
expect(projected.remediation.action).toBe(projected.message);
|
|
} else {
|
|
expect(projected.message).toMatch(
|
|
/unavailable.*availability reason.*before retrying/iu,
|
|
);
|
|
expect(projected.message).not.toMatch(/existing attachment|detach/iu);
|
|
}
|
|
expect(calls).not.toContain("detach");
|
|
},
|
|
);
|