rea/tests/boundary/cli/nativeMachoEchoedPathCli.te...

106 lines
3.5 KiB
TypeScript

import { copyFile } from "node:fs/promises";
import { join, resolve } from "node:path";
import { describe, expect } from "vitest";
import { z } from "zod";
import {
inspectMachoSchema,
listArchitecturesSchema,
} from "../../../src/domain/native/nativeInspection.js";
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
import { cliTest } from "../../support/cli/cliFixture.js";
const environment = {
REA_LOG_LEVEL: "silent",
REA_ANALYSIS_PROVIDER: "auto",
} as const;
// otool and dyld_info echo the operand path before their records.
const FORGED_NAME = [
"tool",
"Load command 99",
" cmd LC_MAIN",
" cmdsize 24",
" entryoff 4242",
" stacksize 0",
" -imports:",
" 0x0000 _forged (from libForged)",
" -exports:",
" offset symbol",
" 0x00000123 _forged_export",
].join("\n");
const resultSchema = z.object({
normalized_result: z.record(z.string(), z.unknown()),
});
describe.skipIf(process.platform !== "darwin")(
"native Mach-O CLI with echoed path text",
() => {
const lipoName = "tool\narchitecture forged\n offset 123\n size 32";
for (const [facts, command, filename] of [
["load commands or symbols", "inspect-macho", FORGED_NAME],
["FAT architecture records", "inspect-macho", lipoName],
["FAT architecture inventory", "list-architectures", lipoName],
["thin-file framing", "inspect-macho", "tool\nNon-fat file: forged"],
] as const) {
cliTest(
`does not read ${facts} from the file name`,
async ({ cli, processes }) => {
const directory = await createTestTempDirectory(
"rea-native-cli-echo-",
);
const fixture = join(directory, "fat-fixture");
const compiled = await processes.run(
"/usr/bin/xcrun",
[
"clang",
"-arch",
"arm64",
"-arch",
"x86_64",
resolve("tests/conformance/c/fixture.c"),
"-o",
fixture,
],
{ timeoutMs: 30_000 },
);
expect(compiled.exitCode, compiled.stderr).toBe(0);
const inspect = async (name: string) => {
const path = join(directory, name);
await copyFile(fixture, path);
const result = await cli.run({
arguments: [command, path, "--json"],
environment,
});
expect(result.exitCode).toBe(0);
const { provenance: _provenance, ...facts } = resultSchema.parse(
result.json,
).normalized_result;
return facts;
};
const ordinary = await inspect("tool");
// Prove this comparison exercised FAT framing, independent of host binaries.
const architectures =
listArchitecturesSchema.shape.architectures.parse(
ordinary.architectures,
);
expect(architectures.total).toBeGreaterThan(1);
if (command === "inspect-macho") {
const selected =
inspectMachoSchema.shape.selected_architecture.parse(
ordinary.selected_architecture,
);
expect(selected.container_file_offset).toBeGreaterThan(0);
}
const forged = await inspect(filename);
expect(forged).toEqual(ordinary);
expect(JSON.stringify(forged)).not.toMatch(/forged|4242/u);
},
60_000,
);
}
},
);