mirror of
https://github.com/morluto/rea
synced 2026-10-25 22:08:11 -04:00
c374c2fe72
Preserve listing-backed facts and explicit unavailable decompiler facets when one function fails. Retain Evidence while excluding transient failures and derived workflows from snapshot reuse; keep healthy cache reuse and owned cleanup semantics. Fixes #4644.
113 lines
4.1 KiB
TypeScript
113 lines
4.1 KiB
TypeScript
import { mkdir, readdir, readFile, writeFile } from "node:fs/promises";
|
|
import { join } from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
import { expect } from "vitest";
|
|
|
|
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
|
|
import { processTest } from "../../support/process/processFixture.js";
|
|
|
|
processTest
|
|
.skipIf(
|
|
!["linux", "darwin"].includes(process.platform) ||
|
|
!["x64", "arm64"].includes(process.arch),
|
|
)
|
|
.for([
|
|
{ outcome: "stopped", retained: false },
|
|
{ outcome: "incomplete", retained: true },
|
|
{ outcome: "unknown", retained: true },
|
|
])(
|
|
"preserves the compiler failure and respects $outcome cleanup ownership",
|
|
async ({ outcome, retained }, { processes }) => {
|
|
const root = await createTestTempDirectory("rea-decompiler-cleanup-test-");
|
|
const temporary = join(root, "temporary");
|
|
await mkdir(temporary);
|
|
const commandUrl = new URL(
|
|
"../../../dist/process/OwnedCommand.js",
|
|
import.meta.url,
|
|
).href;
|
|
const installationUrl = new URL(
|
|
"../../../scripts/lib/ghidra-installation-inspection.mjs",
|
|
import.meta.url,
|
|
).href;
|
|
const policyUrl = new URL(
|
|
"../../../dist/ghidra/GhidraReleasePolicy.js",
|
|
import.meta.url,
|
|
).href;
|
|
// Execute the production entry point and its real filesystem cleanup.
|
|
// Substitute only the two external prerequisites; no Ghidra is launched.
|
|
const commandSource = `
|
|
export * from ${JSON.stringify(`${commandUrl}?cleanup-test-original`)};
|
|
import { OwnedCommandFailure } from ${JSON.stringify(`${commandUrl}?cleanup-test-original`)};
|
|
import { writeFile } from "node:fs/promises";
|
|
export async function runOwnedCommand(command) {
|
|
await writeFile(command.arguments.at(-1), "partial compiler output");
|
|
if (${JSON.stringify(outcome)} === "unknown") throw new Error("opaque compiler failure");
|
|
throw new OwnedCommandFailure("process", "controlled compiler failure", null,
|
|
${JSON.stringify(outcome)} === "incomplete" ? "cleanup refused" : null,
|
|
undefined, [], ${JSON.stringify(outcome)} === "incomplete" ? { retained: true } : undefined);
|
|
}
|
|
`;
|
|
const installationSource = `
|
|
import { SUPPORTED_GHIDRA_VERSION } from ${JSON.stringify(policyUrl)};
|
|
export async function inspectVerifierGhidraInstallation() {
|
|
return { status: "available", providerVersion: SUPPORTED_GHIDRA_VERSION };
|
|
}
|
|
`;
|
|
const loader = join(root, "loader.mjs");
|
|
await writeFile(
|
|
loader,
|
|
`import { registerHooks } from "node:module";
|
|
registerHooks({ load(url, context, nextLoad) {
|
|
if (url === ${JSON.stringify(commandUrl)}) return { format: "module", shortCircuit: true, source: ${JSON.stringify(commandSource)} };
|
|
if (url === ${JSON.stringify(installationUrl)}) return { format: "module", shortCircuit: true, source: ${JSON.stringify(installationSource)} };
|
|
return nextLoad(url, context);
|
|
}});`,
|
|
);
|
|
const result = await processes.run(
|
|
process.execPath,
|
|
[
|
|
"--import",
|
|
loader,
|
|
fileURLToPath(
|
|
new URL(
|
|
"../../../scripts/verify-real-ghidra-decompiler-failure.mjs",
|
|
import.meta.url,
|
|
),
|
|
),
|
|
],
|
|
{
|
|
env: {
|
|
...process.env,
|
|
TMPDIR: temporary,
|
|
TMP: temporary,
|
|
TEMP: temporary,
|
|
},
|
|
timeoutMs: 15_000,
|
|
},
|
|
);
|
|
expect(result.exitCode, result.stderr).toBe(1);
|
|
expect(result.stderr).toContain(
|
|
outcome === "unknown"
|
|
? "opaque compiler failure"
|
|
: "controlled compiler failure",
|
|
);
|
|
const workspaces = await readdir(temporary);
|
|
expect(workspaces).toHaveLength(retained ? 1 : 0);
|
|
if (retained) {
|
|
expect(workspaces[0]).toMatch(/^rea-ghidra-decompiler-/u);
|
|
expect(
|
|
await readFile(
|
|
join(
|
|
temporary,
|
|
workspaces[0]!,
|
|
process.platform === "darwin"
|
|
? "cross-format.dylib"
|
|
: "cross-format.so",
|
|
),
|
|
"utf8",
|
|
),
|
|
).toBe("partial compiler output");
|
|
}
|
|
},
|
|
);
|