mirror of
https://github.com/morluto/rea.git
synced 2026-10-31 11:56:12 +00:00
98 lines
4.1 KiB
TypeScript
98 lines
4.1 KiB
TypeScript
import { execFile } from "node:child_process";
|
|
import { join, resolve } from "node:path";
|
|
import { promisify } from "node:util";
|
|
import { pathToFileURL } from "node:url";
|
|
|
|
import { expect, it } from "vitest";
|
|
|
|
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
|
|
|
|
const execFileAsync = promisify(execFile);
|
|
const packerUrl = pathToFileURL(
|
|
resolve("scripts/verify-package-pack.mjs"),
|
|
).href;
|
|
const catalogUrl = pathToFileURL(resolve("dist/catalogIdentity.js")).href;
|
|
const bridge = "package/bridge/hopper_bridge.py";
|
|
const members = [
|
|
bridge,
|
|
"package/bridge/cutter/rea_bridge.py",
|
|
"package/bridge/ghidra/ReaGhidraBridge.java",
|
|
"package/bridge/ghidra/ReaGhidraBundleActivator.java",
|
|
"package/bridge/ghidra/ReaGhidraExtensions.java",
|
|
"package/bridge/ghidra/ReaGhidraPrepareCom.java",
|
|
"package/bridge/ghidra/ReaGhidraPrepareRaw.java",
|
|
"package/bridge/ghidra/ReaGhidraPrepareDol.java",
|
|
"package/bridge/ghidra/ReaGhidraApplySeeds.java",
|
|
"package/bridge/ghidra/ReaGhidraAnalysisOptions.java",
|
|
"package/bridge/ghidra/ReaGhidraNoReturnFix.java",
|
|
"package/bridge/ghidra/ReaGhidraMipsSoftFloat.java",
|
|
"package/scripts/lib/cli-process-environment.mjs",
|
|
];
|
|
|
|
async function verifyListing(listing: string) {
|
|
const workspace = await createTestTempDirectory("rea-tar-listing-");
|
|
const { stdout } = await execFileAsync(process.execPath, [
|
|
"--input-type=module",
|
|
"--eval",
|
|
`import { FULL_CATALOG_IDENTITY } from ${JSON.stringify(catalogUrl)};
|
|
let bridgeParsed = false;
|
|
const exec = async (command, args) => {
|
|
let stdout;
|
|
if ((command === "npm" && args[0] === "pack") || (command === process.execPath && args[1] === "pack")) stdout = "fixture.tgz\\n";
|
|
else if (command === "tar" && args[0] === "-tf") stdout = ${JSON.stringify(listing)};
|
|
else if (command === "tar" && args[0] === "-xOf" && args[2] === "package/package.json")
|
|
stdout = JSON.stringify({ bin: { rea: "scripts/rea.mjs", "rea-agents": "scripts/rea.mjs" }, mcpName: "io.github.morluto/rea", dependencies: { "@lydell/node-pty": "1.1.0" } });
|
|
else if (command === "tar" && args[0] === "-xOf" && args[2] === "package/skills/reverse-engineer-anything/SKILL.md")
|
|
stdout = '---\\nname: reverse-engineer-anything\\nmetadata:\\n version: "fixture"\\n tool_count: ' + FULL_CATALOG_IDENTITY.counts.mcp_tools + "\\n---\\n";
|
|
else if (command === "tar" && args[0] === "-xf") stdout = "";
|
|
else if (command === "python3") { bridgeParsed = true; stdout = ""; }
|
|
else throw new Error("Unexpected command: " + command + " " + JSON.stringify(args));
|
|
return { stdout, stderr: "" };
|
|
};
|
|
const commands = { exec, execNpm: (args) => exec("npm", args) };
|
|
const { verifyPackagePack } = await import(${JSON.stringify(packerUrl)});
|
|
try {
|
|
const result = await verifyPackagePack({ root: process.cwd(), workspace: ${JSON.stringify(workspace)}, commands });
|
|
process.stdout.write(JSON.stringify({ ...result, bridgeParsed }));
|
|
} catch (cause) {
|
|
process.stdout.write(JSON.stringify({ error: cause.message, bridgeParsed }));
|
|
}`,
|
|
]);
|
|
return { result: JSON.parse(stdout), workspace };
|
|
}
|
|
|
|
it("preserves a literal trailing CR in an LF-listed member", async () => {
|
|
const listing =
|
|
members.map((path) => (path === bridge ? `${path}\r` : path)).join("\n") +
|
|
"\n";
|
|
const { result } = await verifyListing(listing);
|
|
expect(result).toEqual({
|
|
error: `package omitted ${bridge}`,
|
|
bridgeParsed: false,
|
|
});
|
|
});
|
|
|
|
it("accepts exact bridge entries from a CRLF tar listing and still rejects generated bytecode", async () => {
|
|
const ending = "\r\n";
|
|
const { result, workspace } = await verifyListing(
|
|
members.join(ending) + ending,
|
|
);
|
|
expect(result).toEqual({
|
|
tarball: join(workspace, "pack/fixture.tgz"),
|
|
bridgeParsed: true,
|
|
});
|
|
|
|
const rejected = await verifyListing(
|
|
[...members, "package/bridge/stale.pyc"].join(ending) + ending,
|
|
);
|
|
expect(rejected.result).toEqual({
|
|
error: "package contained generated Python bytecode",
|
|
bridgeParsed: false,
|
|
});
|
|
});
|
|
|
|
it("accepts exact bridge entries from an LF tar listing", async () => {
|
|
const { result } = await verifyListing(members.join("\n") + "\n");
|
|
expect(result.bridgeParsed).toBe(true);
|
|
});
|