Files
rea/src/firmware/FirmwareCommand.test.ts
T
2947a77507 fix(engines): keep format ceilings fixed and recover the EVMole deadline (#6088)
* fix(engines): keep format ceilings fixed and recover the EVMole deadline

Promote the owned EVMole worker wall clock to timeout_ms and name it in
recovery. Fixed CPU, byte, and address-space refusals in this theme say
the adjustable deadline does not raise them.

Refs #5910

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(engines): recover the allowance that refused the request

Model capacity recovery follows a structured limit instead of message text,
and the shared header ceiling no longer names Safetensors. Firmware signal
errors keep captured tool output, oversized reports do not suggest an
intermittent rerun, and NativeAOT hydration budget exhaustion explains the
fixed parser allowance on the partial report.

Co-authored-by: morluto <morluto@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <morluto@users.noreply.github.com>
2026-10-22 03:06:59 +08:00

281 lines
8.9 KiB
TypeScript

import { EventEmitter } from "node:events";
import { chmod, mkdir, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { PassThrough } from "node:stream";
import { expect, it as test, vi } from "vitest";
import { createTestTempDirectory } from "../../tests/fixtures/temporaryDirectory.js";
import { AnalysisCapabilityUnavailableError } from "../domain/analysisErrorCore.js";
import { projectAnalysisError } from "../domain/analysisErrorProjection.js";
import { FirmwareFileAccess } from "./FirmwareFiles.js";
import {
resolveFirmwareCommand,
runFirmwareCommand,
} from "./FirmwareCommand.js";
import {
spawnOwnedProviderProcess,
type ProviderProcessHandle,
} from "../process/ProviderProcess.js";
import { AnalysisError } from "../domain/analysisErrorBase.js";
import { ExecFileOutputCancelledError } from "../process/ExecFileOutput.js";
const it = test.skipIf(process.platform !== "linux");
it.each([
{ source: "analysis", wrapped: false },
{ source: "caller", wrapped: false },
{ source: "analysis", wrapped: true },
{ source: "caller", wrapped: true },
] as const)(
"classifies $source cancellation during launcher admission (wrapped: $wrapped)",
async ({ source, wrapped }) => {
const analysis = new AbortController();
const caller = new AbortController();
const reason =
source === "analysis"
? new DOMException("selected deadline", "TimeoutError")
: { caller: "opaque admission cancellation" };
const retainCleanup = vi.fn();
const failure: unknown = await runFirmwareCommand({
engine: "binwalk",
operation: "inspect_firmware_regions",
command: "/usr/bin/true",
limiter: "/usr/bin/true",
args: ["--version"],
cwd: await createTestTempDirectory("rea-firmware-admission-"),
environment: process.env,
signal: AbortSignal.any([analysis.signal, caller.signal]),
deadline: {
phase: "analysis",
signal: analysis.signal,
timeoutMs: 1234,
expiresAtMs: performance.now() + 1234,
},
launcher: async (options) => {
// Real launcher is paused at its first ownership-preparation await;
// it must reject before acquiring a child after this cancellation.
const admission = wrapped
? undefined
: spawnOwnedProviderProcess(options);
(source === "analysis" ? analysis : caller).abort(reason);
if (admission !== undefined) return admission;
throw new ExecFileOutputCancelledError(reason);
},
retainCleanup,
}).catch((cause: unknown) => cause);
expect(failure).toBeInstanceOf(AnalysisError);
if (!(failure instanceof AnalysisError))
throw new Error("Expected typed admission interruption");
expect(failure.cause).toBe(reason);
expect(projectAnalysisError(failure)).toMatchObject(
source === "analysis"
? {
code: "provider_timeout",
details: { timeout_ms: 1234, diagnostics: { phase: "analysis" } },
remediation: {
action: expect.stringContaining("analysis_timeout_ms"),
},
}
: { code: "cancelled" },
);
expect(retainCleanup).not.toHaveBeenCalled();
},
);
it("does not relabel an unrelated launch failure when a deadline also fires", async () => {
const analysis = new AbortController();
const failure = new Error("distinct launch refusal");
await expect(
runFirmwareCommand({
engine: "binwalk",
operation: "inspect_firmware_regions",
command: "/usr/bin/true",
limiter: "/usr/bin/true",
args: [],
cwd: await createTestTempDirectory("rea-firmware-admission-error-"),
environment: process.env,
signal: analysis.signal,
deadline: {
phase: "analysis",
signal: analysis.signal,
timeoutMs: 1234,
expiresAtMs: performance.now() + 1234,
},
launcher: async () => {
analysis.abort();
throw failure;
},
retainCleanup: vi.fn(),
}),
).rejects.toBe(failure);
});
test("names the host and tool requirement of an unconfigured engine", async () => {
const refusal: unknown = await resolveFirmwareCommand(
{},
"binwalk",
"inspect_firmware_regions",
new FirmwareFileAccess(),
).catch((cause: unknown) => cause);
expect(refusal).toMatchObject({
_tag: "AnalysisCapabilityUnavailableError",
});
if (!(refusal instanceof AnalysisCapabilityUnavailableError))
throw new Error("Expected a capability refusal");
expect(projectAnalysisError(refusal)).toMatchObject({
code: "capability_unavailable",
message: refusal.reason,
remediation: { action: refusal.reason },
});
expect(refusal.reason).toContain("REA_BINWALK_COMMAND");
});
it("rejects a directory configured as the firmware engine executable", async () => {
const root = await createTestTempDirectory("rea-firmware-command-");
const command = join(root, "binwalk");
const limiter = await executableFixture(root, "prlimit");
await mkdir(command);
await expect(
resolveFirmwareCommand(
{
REA_BINWALK_COMMAND: command,
REA_FIRMWARE_PRLIMIT_COMMAND: limiter,
},
"binwalk",
"inspect_firmware_regions",
new FirmwareFileAccess(),
),
).rejects.toMatchObject({
_tag: "AnalysisCapabilityUnavailableError",
reason: expect.stringContaining(command),
});
});
it("classifies an unusable firmware engine as an unavailable capability", async () => {
const root = await createTestTempDirectory("rea-firmware-command-");
const command = join(root, "binwalk");
const limiter = await executableFixture(root, "prlimit");
await writeFile(command, "not executable", { mode: 0o600 });
await expect(
resolveFirmwareCommand(
{
REA_BINWALK_COMMAND: command,
REA_FIRMWARE_PRLIMIT_COMMAND: limiter,
},
"binwalk",
"inspect_firmware_regions",
new FirmwareFileAccess(),
),
).rejects.toMatchObject({
_tag: "AnalysisCapabilityUnavailableError",
reason: expect.stringContaining(command),
});
});
it("rejects a directory configured as the resource limiter executable", async () => {
const root = await createTestTempDirectory("rea-firmware-limiter-");
const command = await executableFixture(root, "binwalk");
const limiter = join(root, "prlimit");
await mkdir(limiter);
await expect(
resolveFirmwareCommand(
{
REA_BINWALK_COMMAND: command,
REA_FIRMWARE_PRLIMIT_COMMAND: limiter,
},
"binwalk",
"inspect_firmware_regions",
new FirmwareFileAccess(),
),
).rejects.toMatchObject({
_tag: "AnalysisCapabilityUnavailableError",
reason: expect.stringContaining(limiter),
});
});
it("keeps captured tool output when firmware stops on SIGXCPU", async () => {
const stdout = new PassThrough();
const stderr = new PassThrough();
const emitter = new EventEmitter();
const child: ProviderProcessHandle = {
on: emitter.on.bind(emitter),
once: emitter.once.bind(emitter),
off: emitter.off.bind(emitter),
pid: 4242,
stdout,
stderr,
exitCode: null,
signalCode: "SIGXCPU",
kill: () => false,
};
let ended = 0;
const close = () => {
ended += 1;
if (ended === 2) emitter.emit("close", null, "SIGXCPU");
};
stdout.once("end", close);
stderr.once("end", close);
setTimeout(() => {
stdout.end("partial scan\n");
stderr.end("cpu limit\n");
}, 15);
const analysis = new AbortController();
const failure: unknown = await runFirmwareCommand({
engine: "binwalk",
operation: "inspect_firmware_regions",
command: "/opt/binwalk",
limiter: "/usr/bin/prlimit",
args: ["--quiet"],
cwd: await createTestTempDirectory("rea-firmware-signal-"),
environment: process.env,
signal: analysis.signal,
deadline: {
phase: "analysis",
signal: analysis.signal,
timeoutMs: 30_000,
expiresAtMs: performance.now() + 30_000,
},
launcher: () =>
Promise.resolve({
process: child,
ownership: {
runId: "rea-firmware-signal",
leaderPid: 4242,
processGroupId: 4242,
},
cleanup: () => Promise.resolve({ cleaned: true, signaled: false }),
}),
retainCleanup: vi.fn(),
}).catch((cause: unknown) => cause);
expect(failure).toMatchObject({
_tag: "AnalysisResourceConstraintError",
resource: "cpu",
capturedOutput: {
stdout: "partial scan\n",
stderr: "cpu limit\n",
signal: "SIGXCPU",
exit_code: null,
truncated: false,
},
});
if (!(failure instanceof AnalysisError))
throw new Error("Expected a firmware resource constraint");
expect(projectAnalysisError(failure).details?.captured_output).toMatchObject({
stdout: "partial scan\n",
stderr: "cpu limit\n",
signal: "SIGXCPU",
});
});
const executableFixture = async (root: string, name: string) => {
const path = join(root, name);
await writeFile(path, "#!/bin/sh\n");
await chmod(path, 0o700);
return path;
};