mirror of
https://github.com/morluto/rea.git
synced 2026-11-07 05:56:19 -10:00
test(elf): cover big-endian ABI notes through CLI and MCP (#8803)
This commit is contained in:
1 parent
276d99e787
commit
9a68ce57a0
1 file changed
+113
@@ -0,0 +1,113 @@
|
||||
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);
|
||||
},
|
||||
);
|
||||
Reference in new issue
Block a user