mirror of
https://github.com/morluto/rea.git
synced 2026-11-06 14:56:32 +00:00
114 lines
4.0 KiB
TypeScript
114 lines
4.0 KiB
TypeScript
import { createHash } from "node:crypto";
|
|
import { readFile, writeFile } from "node:fs/promises";
|
|
import { join } from "node:path";
|
|
import { expect } from "vitest";
|
|
|
|
import { toolContract } from "../../src/contracts/toolContracts.js";
|
|
import {
|
|
elfNote,
|
|
elfNoteFixture,
|
|
} from "../../src/native/elf/ElfNotes.fixture.js";
|
|
import { createTestTempDirectory } from "../fixtures/temporaryDirectory.js";
|
|
import { cliTest } from "../support/cli/cliFixture.js";
|
|
|
|
// Literal big-endian descriptors keep the expected values independent of the
|
|
// fixture's integer writers and the parser's byte-order branch.
|
|
const knownAbi = Buffer.from("00000000010203041020304080010203", "hex");
|
|
const unknownAbi = Buffer.from("01000000010203041020304080010203", "hex");
|
|
const extendedAbi = Buffer.concat([knownAbi, Buffer.from("01020304", "hex")]);
|
|
const shortAbi = knownAbi.subarray(0, 12);
|
|
const descriptorHash = (bytes: Buffer): string =>
|
|
createHash("sha256").update(bytes).digest("hex");
|
|
|
|
for (const { bits, ownership, machine } of [
|
|
{ bits: 32, ownership: "program", machine: 20 },
|
|
{ bits: 64, ownership: "section", machine: 21 },
|
|
] as const)
|
|
cliTest(
|
|
`preserves big-endian ELF${String(bits)} ABI facts through CLI and stdio MCP`,
|
|
async ({ cli }) => {
|
|
const root = await createTestTempDirectory("rea-elf-abi-endian-");
|
|
const path = join(root, "selected.elf");
|
|
const descriptors = [
|
|
knownAbi,
|
|
unknownAbi,
|
|
shortAbi,
|
|
extendedAbi,
|
|
knownAbi,
|
|
];
|
|
const notes = Buffer.concat([
|
|
...descriptors
|
|
.slice(0, 4)
|
|
.map((bytes) => elfNote("GNU", 1, bytes, false)),
|
|
elfNote("OTHER", 1, knownAbi, false),
|
|
]);
|
|
const bytes = elfNoteFixture({
|
|
bits,
|
|
ownership,
|
|
machine,
|
|
little: false,
|
|
notes,
|
|
});
|
|
await writeFile(path, bytes);
|
|
|
|
const output = await cli.sharedCliRun!({
|
|
arguments: ["inspect-elf-notes", path, "--json"],
|
|
});
|
|
expect(output.exitCode, output.stderr).toBe(0);
|
|
const call = await cli.sharedMcpCall!();
|
|
const response = await call("inspect_elf_notes", { path });
|
|
expect(response.isError, JSON.stringify(response.content)).not.toBe(true);
|
|
|
|
const schema = toolContract("inspect_elf_notes").outputSchema;
|
|
const reports = [output.json, response.structuredContent].map((value) => {
|
|
const evidence = schema.parse(value);
|
|
expect(evidence.subject).toMatchObject({
|
|
local_path: path,
|
|
digest: { sha256: descriptorHash(bytes) },
|
|
});
|
|
const report = evidence.normalized_result;
|
|
expect(report).toMatchObject({
|
|
format: `elf${String(bits)}`,
|
|
byte_order: "big",
|
|
machine,
|
|
coverage: {
|
|
status: "complete",
|
|
examined_tables: 1,
|
|
examined_entries: 5,
|
|
},
|
|
});
|
|
expect(report.entries).toHaveLength(5);
|
|
expect(report.entries[0]?.gnu?.abi_tag).toEqual({
|
|
os: 0,
|
|
os_name: "linux",
|
|
major: 0x01020304,
|
|
minor: 0x10203040,
|
|
subminor: 0x80010203,
|
|
});
|
|
expect(report.entries[1]?.gnu?.abi_tag).toEqual({
|
|
os: 0x01000000,
|
|
os_name: null,
|
|
major: 0x01020304,
|
|
minor: 0x10203040,
|
|
subminor: 0x80010203,
|
|
});
|
|
// Unexpected lengths stay raw; no ABI values are invented or truncated.
|
|
for (const index of [2, 3])
|
|
expect(report.entries[index]?.gnu?.abi_tag).toBeNull();
|
|
expect(report.entries[4]).toMatchObject({
|
|
owner: "OTHER",
|
|
type_name: "unknown",
|
|
gnu: null,
|
|
});
|
|
for (const [index, descriptor] of descriptors.entries())
|
|
expect(report.entries[index]?.descriptor).toMatchObject({
|
|
bytes: descriptor.length,
|
|
sha256: descriptorHash(descriptor),
|
|
});
|
|
return report;
|
|
});
|
|
expect(reports[0]).toEqual(reports[1]);
|
|
expect((await readFile(path)).equals(bytes)).toBe(true);
|
|
},
|
|
);
|