rea/tests/boundary/cli/analysisViewCli.test.ts

172 lines
5.3 KiB
TypeScript

import { mkdir, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { expect } from "vitest";
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
import { cliTest } from "../../support/cli/cliFixture.js";
import { analysisViewLayoutEvidence } from "../../fixtures/analysisView.js";
import { createEvidence } from "../../../src/domain/evidence.js";
import { ghidraFunctionDossier } from "../../../src/domain/ghidraValues.fixture.js";
cliTest(
"projects one section from a JSON file of inline layout Evidence",
async ({ cli }) => {
const root = await createTestTempDirectory("rea-analysis-view-cli-");
const parent = analysisViewLayoutEvidence();
const request = {
source: { kind: "inline", evidence: parent },
view: {
kind: "item",
collection: "sections",
selector: { name: ".data" },
},
};
const input = join(root, "view.json");
await mkdir(root, { recursive: true });
await writeFile(input, JSON.stringify(request));
const result = await cli.run({
arguments: ["inspect-analysis-view", input, "--json"],
environment: {
HOME: root,
XDG_CONFIG_HOME: root,
XDG_CACHE_HOME: root,
},
});
expect(result.exitCode).toBe(0);
expect(result.json).toMatchObject({
operation: "inspect_analysis_view",
normalized_result: {
kind: "item",
parent_evidence_id: parent.evidence_id,
item: { name: { display: ".data" } },
},
});
},
);
cliTest(
"projects native function pseudocode without requiring Ghidra",
async ({ cli }) => {
const root = await createTestTempDirectory("rea-native-view-cli-");
const parent = createEvidence(
{ path: "/fixtures/native.exe", format: "pe", sha256: "a".repeat(64) },
{ id: "ghidra", name: "Ghidra", version: "12.1.4" },
{
operation: "analyze_function",
parameters: { address: "0x401000" },
result: ghidraFunctionDossier(),
},
);
const input = join(root, "native-view.json");
await writeFile(
input,
JSON.stringify({
source: { kind: "inline", evidence: parent },
view: { kind: "native", facet: "pseudocode", offset: 0, limit: 12 },
}),
);
const result = await cli.run({
arguments: ["inspect-analysis-view", input, "--json"],
environment: { HOME: root, XDG_CONFIG_HOME: root, XDG_CACHE_HOME: root },
});
expect(result.exitCode).toBe(0);
expect(result.json).toMatchObject({
operation: "inspect_analysis_view",
normalized_result: {
kind: "native",
parent_evidence_id: parent.evidence_id,
procedure_address: "0x401000",
item: { text: "int fixture_", unit: "utf16-code-units" },
},
locations: [
{ kind: "artifact-path", path: "/fixtures/native.exe" },
{ kind: "address", address: "0x401000" },
],
});
},
);
cliTest("rejects malformed JSON before projection", async ({ cli }) => {
const root = await createTestTempDirectory("rea-analysis-view-cli-bad-");
const result = await cli.run({
arguments: ["inspect-analysis-view", "{", "--json"],
environment: {
HOME: root,
XDG_CONFIG_HOME: root,
XDG_CACHE_HOME: root,
},
});
expect(result.exitCode).toBe(1);
expect(result.json).toMatchObject({
code: "invalid_request",
category: "invalid_input",
details: { operation: "inspect-analysis-view" },
});
});
cliTest("rejects a request that omits source", async ({ cli }) => {
const root = await createTestTempDirectory("rea-analysis-view-cli-missing-");
const input = join(root, "missing-source.json");
await writeFile(input, JSON.stringify({ view: { kind: "summary" } }));
const result = await cli.run({
arguments: ["inspect-analysis-view", input, "--json"],
environment: {
HOME: root,
XDG_CONFIG_HOME: root,
XDG_CACHE_HOME: root,
},
});
expect(result.exitCode).toBe(1);
expect(result.json).toMatchObject({
code: "invalid_request",
category: "invalid_input",
details: { operation: "inspect-analysis-view" },
});
});
for (const [view, reason] of [
[{ kind: "unknown-view" }, "invalid_value"],
[{}, "missing_argument"],
] as const) {
cliTest(
`reports correction details for ${reason} view kind`,
async ({ cli }) => {
const root = await createTestTempDirectory("rea-view-variant-");
const input = join(root, "view.json");
await writeFile(
input,
JSON.stringify({
source: {
kind: "inline",
evidence: analysisViewLayoutEvidence(),
},
view,
}),
);
const result = await cli.run({
arguments: ["inspect-analysis-view", input, "--json"],
environment: {
HOME: root,
XDG_CONFIG_HOME: root,
XDG_CACHE_HOME: root,
},
});
expect(result.exitCode).toBe(1);
expect(result.json).toMatchObject({
code: "invalid_request",
details: {
issues: [
{
path: ["view", "kind"],
reason,
expected: expect.arrayContaining(["summary", "page"]),
},
],
},
});
expect(JSON.stringify(result.json)).not.toContain("unknown-view");
},
);
}