Files
rea/tests/boundary/cli/commandEvidenceDelivery.test.ts
gensokyo-dev 17f581ff75 perf(reverse): add retained GDB and objdump summaries (#5614)
Add opt-in retained GDB and objdump summaries using the shared analysis-view layer. Preserve default complete Evidence, ordered records, provenance and completion facts.

Validate real Bash disassembly, whole-client context costs, CLI publication and cleanup; retain the original measured cohorts and explicit coverage limitations.

Closes #5584.
2026-10-21 01:20:52 +08:00

210 lines
7.2 KiB
TypeScript

import { Cli, z } from "incur";
import pino from "pino";
import { readFile, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { expect, it, onTestFinished, vi } from "vitest";
import { registerReverseEngineeringCommands } from "../../../src/cli/reverseEngineeringCommands.js";
import type { CliInstance } from "../../../src/cli/types.js";
import { CLI_COMMANDS } from "../../../src/cliCommandNames.js";
import {
createEvidence,
parseEvidence,
evidenceSchema,
} from "../../../src/domain/evidence.js";
import { ok } from "../../../src/domain/result.js";
import { GdbSessionManager } from "../../../src/gdb/GdbSessionManager.js";
import { TestReverseEngineeringService } from "../../support/reverseEngineeringService.js";
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
const kinds = ["objdump", "architectures", "gdb"] as const;
const fixture = async (kind: (typeof kinds)[number]) => {
const directory = await createTestTempDirectory("rea-command-delivery-");
const path = join(directory, "input.bin");
await writeFile(path, "local CLI publication fixture");
const runProvider = vi.fn(async () => ({
stdout: "opaque provider output\n",
stderr: "provider diagnostic\n",
}));
const service = new TestReverseEngineeringService({
environment: {},
run: runProvider,
});
const closeService = vi.spyOn(service, "close");
const manager = new GdbSessionManager({ platform: "linux", environment: {} });
const sessionId = "00000000-0000-4000-8000-000000000001";
const report = {
command: "show architecture",
mi: "5^done",
records: ['~"architecture\\n"', "unknown record", "5^done"],
console: '~"architecture\\n"',
target: "",
log: "",
completion_status: "complete" as const,
output_truncated: false,
};
const parent = createEvidence(
undefined,
{ id: "gdb", name: "GDB", version: null },
{
operation: "gdb_console",
parameters: { session_id: sessionId, command: report.command },
result: report,
rawResult: report,
},
);
const start = vi
.spyOn(manager, "start")
.mockResolvedValue(ok({ session_id: sessionId, mi_version: "mi3" }));
vi.spyOn(manager, "execute").mockResolvedValue(
ok({ result: report, evidence: parent }),
);
const close = vi
.spyOn(manager, "close")
.mockResolvedValue(ok({ target_state: "none_observed" }));
const closeAll = vi.spyOn(manager, "closeAll").mockResolvedValue(undefined);
const createManager = vi.fn(() => manager);
const cli = Cli.create("rea-cli-delivery-test", {
version: "1",
sync: false,
});
registerReverseEngineeringCommands(
cli as unknown as CliInstance,
pino({ enabled: false }),
{},
createManager,
() => service,
);
onTestFinished(async () => {
await service.close();
await manager.closeAll();
});
const commandName =
kind === "gdb"
? CLI_COMMANDS.debugWithGdb
: kind === "objdump"
? CLI_COMMANDS.inspectWithObjdump
: CLI_COMMANDS.listObjdumpArchitectures;
const command = Cli.toCommands.get(cli)?.get(commandName);
if (command === undefined) throw new Error("CLI command was not registered");
const argsSchema = Reflect.get(command, "args");
const optionsSchema = Reflect.get(command, "options");
const execute = Reflect.get(command, "run");
if (
!(argsSchema instanceof z.ZodObject) ||
!(optionsSchema instanceof z.ZodObject) ||
typeof execute !== "function"
)
throw new Error("Missing CLI command schemas or callback");
const args =
kind === "gdb"
? { command: report.command }
: kind === "objdump"
? { path, operation: "file_headers" }
: {};
const invoke = async (options: Record<string, unknown>): Promise<unknown> =>
execute({
args: argsSchema.parse(args),
options: optionsSchema.parse({
...(kind === "gdb" ? { inferiorTty: "/dev/pts/caller-fixture" } : {}),
...options,
}),
});
return {
directory,
invoke,
runProvider,
createManager,
start,
close,
closeAll,
closeService,
parent,
report,
};
};
it.each(kinds)(
"publishes %s summaries with exact complete parents",
async (kind) => {
const f = await fixture(kind);
const destination = join(f.directory, "complete.json");
const output = z
.object({
summary: evidenceSchema,
evidence_bundle: z.object({ path: z.string(), bytes: z.number() }),
})
.parse(
await f.invoke({ detail: "summary", evidence_output: destination }),
);
const selected = parseEvidence(output.summary);
const serialized = await readFile(destination, "utf8");
const bundle = JSON.parse(serialized);
expect(output.evidence_bundle.bytes).toBe(Buffer.byteLength(serialized));
expect(bundle.records).toHaveLength(1);
const parent = parseEvidence(bundle.records[0]);
expect(parent.raw_result).toEqual(parent.normalized_result);
expect(selected.normalized_result).toMatchObject({
parent_evidence_id: parent.evidence_id,
source_parameters: parent.parameters,
source_provider: parent.provider,
});
expect(selected.raw_result).toBeNull();
expect(output.evidence_bundle.path).toBe(destination);
if (kind === "gdb") {
expect(parent).toEqual(f.parent);
expect(selected.normalized_result).toMatchObject({
artifact: null,
summary: { records: f.report.records },
});
expect(f.close).toHaveBeenCalledOnce();
expect(f.closeAll).toHaveBeenCalledOnce();
} else {
expect(selected.normalized_result).toMatchObject({
summary: parent.normalized_result,
});
expect(f.runProvider).toHaveBeenCalledOnce();
expect(f.closeService).toHaveBeenCalledOnce();
}
if (kind !== "objdump") {
expect(parent.subject).toBeNull();
expect(selected.subject).toBeNull();
expect(selected.normalized_result).toMatchObject({ artifact: null });
}
},
);
it.each(kinds)(
"rejects %s summary without a destination before provider work",
async (kind) => {
const f = await fixture(kind);
const output = await f.invoke({ detail: "summary" });
expect(output).toMatchObject({ code: "invalid_request" });
expect(JSON.stringify(output)).toContain("evidence_output");
expect(f.createManager).not.toHaveBeenCalled();
expect(f.start).not.toHaveBeenCalled();
expect(f.runProvider).not.toHaveBeenCalled();
},
);
it.each(kinds)(
"preserves an existing %s destination and reports publication failure with source Evidence",
async (kind) => {
const f = await fixture(kind);
const destination = join(f.directory, "existing.json");
const original = Buffer.from("caller-selected content\n");
await writeFile(destination, original);
const output = await f.invoke({
detail: "summary",
evidence_output: destination,
});
expect(await readFile(destination)).toEqual(original);
expect(output).toHaveProperty("code");
expect(output).not.toHaveProperty("summary");
expect(output).toHaveProperty("details.partial_observation.evidence_id");
if (kind === "gdb") {
expect(f.close).toHaveBeenCalledOnce();
expect(f.closeAll).toHaveBeenCalledOnce();
} else expect(f.closeService).toHaveBeenCalledOnce();
},
);