import { STDIO_DEFAULT_MAX_BUFFER_SIZE } from "@modelcontextprotocol/server"; import { access, mkdir, readFile, writeFile } from "node:fs/promises"; import { expect, it as test, vi } from "vitest"; import { firmwareFixture, assertFirmwareCleanup, } from "../../fixtures/firmware/provider.js"; import { firmwareResultSchemas } from "../../../src/domain/firmware/firmwareAnalysis.js"; import { FirmwareAnalysisService } from "../../../src/application/firmware/FirmwareAnalysisService.js"; import { FirmwareProvider } from "../../../src/firmware/FirmwareProvider.js"; import { projectAnalysisError } from "../../../src/domain/analysisErrorProjection.js"; import { AnalysisError } from "../../../src/domain/analysisErrorBase.js"; import { toolContract } from "../../../src/contracts/toolContracts.js"; import { ToolResultDelivery } from "../../../src/server/toolResult.js"; import { SafeOutputTree } from "../../../src/artifacts/SafeOutputTree.js"; import { SafeOutputTreeCreationFailure } from "../../../src/artifacts/SafeOutputTreeCreationFailure.js"; // Assert recovery behavior through the public reference table, while keeping // row identity expectations independent of the instruction's digest. const gapsWithContinuations = ( result: ReturnType, ) => { const instructions = new Map( result.extraction_continuations.map(({ id, instruction }) => [ id, instruction, ]), ); return result.extraction_gaps.map(({ continuation_id, ...gap }) => { const instruction = instructions.get(continuation_id); if (instruction === undefined) throw new Error("Missing recovery instruction"); return { ...gap, continuation: instruction }; }); }; const directoryCloseFailure = vi.hoisted(() => ({ mode: "off" as "off" | "transient" | "persistent", attempts: 0, })); vi.mock("node:fs/promises", async (importOriginal) => { const filesystem = await importOriginal(); return { ...filesystem, open: async (...args: Parameters) => { const handle = await filesystem.open(...args); if ( directoryCloseFailure.mode !== "off" && (await handle.stat()).isDirectory() ) { const close = handle.close.bind(handle); let attempted = false; handle.close = async () => { directoryCloseFailure.attempts += 1; if ( directoryCloseFailure.mode === "persistent" || (directoryCloseFailure.mode === "transient" && !attempted) ) { attempted = true; throw new Error("injected published directory close failure"); } await close(); }; } return handle; }, }; }); const delivery = new ToolResultDelivery(STDIO_DEFAULT_MAX_BUFFER_SIZE); const it = test.skipIf(process.platform !== "linux"); it("keeps cleanup-failure state local to the selected factory instance", async () => { const failed = await firmwareFixture("cleanup-failure"); const healthy = await firmwareFixture(); const failure = await failed.service.execute("inspect_firmware_regions", { path: failed.path, }); expect(failure).toMatchObject({ ok: false, error: { cleanupIncomplete: true }, }); const result = await healthy.service.execute("inspect_firmware_regions", { path: healthy.path, }); expect(result.ok).toBe(true); await assertFirmwareCleanup(healthy.launches); }); it("binds region observations to exact bytes and preserves provider-reported uncertainty", async () => { const fixture = await firmwareFixture(); const result = await fixture.service.execute("inspect_firmware_regions", { path: fixture.path, }); if (!result.ok) throw result.error; const normalized = firmwareResultSchemas.inspect_firmware_regions.parse( result.value.normalized_result, ); expect(normalized.regions[0]).toMatchObject({ offset: 2, reported_size: 4, size_basis: "provider_reported_validation_unknown", }); expect(result.value.subject?.local_path).toBe(fixture.path); expect(result.value.subject?.format).toBe("file"); expect(result.value.raw_result).toMatchObject({ report: [{ Analysis: { file_map: [{ id: "hit" }] } }], }); expect(fixture.launches[1]?.args).toEqual( expect.arrayContaining(["--as=1073741824", "--threads", "1"]), ); await assertFirmwareCleanup(fixture.launches); }); it.each(["wrong-input", "bounds"])( "rejects a mismatched or out-of-bounds inspection: %s", async (mode) => { const fixture = await firmwareFixture(mode); const result = await fixture.service.execute("inspect_firmware_regions", { path: fixture.path, }); expect(result).toMatchObject({ ok: false, error: { _tag: "AnalysisOutputError" }, }); await assertFirmwareCleanup(fixture.launches); }, ); it("extracts a selected interval with verified file identity and parent-byte lineage", async () => { const fixture = await firmwareFixture(); const result = await fixture.service.execute("extract_firmware", { path: fixture.path, output_directory: fixture.output, range: { offset: 2, length: 4 }, }); if (!result.ok) throw result.error; const normalized = firmwareResultSchemas.extract_firmware.parse( result.value.normalized_result, ); expect(normalized.selection).toMatchObject({ offset: 2, length: 4 }); expect(normalized.files[0]).toMatchObject({ relative_path: "rootfs/config", size: 14, original_file_range: null, runtime_address: null, }); expect(normalized.chunks[0]?.root_file_range).toEqual({ offset: 2, length: 4, }); expect(normalized.derivations[0]).toMatchObject({ parent_path: "$input", child_path: "$output/rootfs/config", handler: "gzip", parent_file_range: { offset: 0, length: 4 }, }); expect(await readFile(normalized.files[0]?.path ?? "", "utf8")).toBe( "firmware=true\n", ); expect(fixture.launches[1]?.args).toEqual( expect.arrayContaining(["--process-num", "1", "--randomness-depth", "0"]), ); expect(fixture.launches[1]?.args).not.toContain("--no-sandbox"); await assertFirmwareCleanup(fixture.launches); }); it("retains a setup-failed publication tree for provider cleanup retry", async () => { const fixture = await firmwareFixture(); const createTree = SafeOutputTree.create.bind(SafeOutputTree); let cleanupAttempts = 0; let retained: AnalysisError | undefined; const create = vi .spyOn(SafeOutputTree, "create") .mockImplementationOnce(async (outputRoot, platform) => { const tree = await createTree(outputRoot, platform); const rollbackTree = tree.rollback.bind(tree); vi.spyOn(tree, "rollback").mockImplementation(async () => { cleanupAttempts += 1; if (cleanupAttempts === 1) throw new Error("injected first cleanup failure"); return rollbackTree(); }); throw new SafeOutputTreeCreationFailure( new Error("injected post-acquisition setup failure"), tree, ); }); try { const result = await fixture.service.execute("extract_firmware", { path: fixture.path, output_directory: fixture.output, range: { offset: 2, length: 4 }, }); expect(result).toMatchObject({ ok: false, error: { cleanupIncomplete: true, cleanupResources: expect.arrayContaining([fixture.output]), }, }); if (result.ok) throw new Error("Expected retained publication cleanup"); retained = result.error; expect(projectAnalysisError(retained).code).toBe("cleanup_incomplete"); expect(JSON.stringify(projectAnalysisError(retained))).toContain( "injected post-acquisition setup failure", ); await expect(access(fixture.output)).resolves.toBeUndefined(); } finally { create.mockRestore(); } await fixture.close(); expect(cleanupAttempts).toBe(2); expect(retained?.cleanupIncomplete).toBe(false); await expect(access(fixture.output)).rejects.toMatchObject({ code: "ENOENT", }); }); it("returns firmware output after a transient published-directory close failure", async () => { const fixture = await firmwareFixture(); const closeFailure = injectPublishedDirectoryCloseFailure(false); try { const result = await fixture.service.execute("extract_firmware", { path: fixture.path, output_directory: fixture.output, range: { offset: 2, length: 4 }, }); if (!result.ok) throw result.error; const normalized = firmwareResultSchemas.extract_firmware.parse( result.value.normalized_result, ); expect(normalized.output_directory).toBe(fixture.output); expect(await readFile(normalized.files[0]?.path ?? "", "utf8")).toBe( "firmware=true\n", ); expect(closeFailure.attempts()).toBeGreaterThanOrEqual(4); } finally { closeFailure.restore(); } }); it("retains the complete firmware result when published output cleanup stays uncertain", async () => { const fixture = await firmwareFixture(); let retained: AnalysisError | undefined; const closeFailure = injectPublishedDirectoryCloseFailure(true); try { const result = await fixture.service.execute("extract_firmware", { path: fixture.path, output_directory: fixture.output, range: { offset: 2, length: 4 }, }); expect(result).toMatchObject({ ok: false, error: { cleanupIncomplete: true, partialObservation: { kind: "firmware", result: { output_directory: fixture.output, files: [ expect.objectContaining({ relative_path: "rootfs/config", size: 14, }), ], }, }, }, }); if (result.ok) throw new Error("Expected unresolved descriptor cleanup"); expect(result.error).toBeInstanceOf(AnalysisError); retained = result.error; expect(projectAnalysisError(result.error)).toMatchObject({ code: "cleanup_incomplete", details: { partial_observation: { kind: "firmware", result: { output_directory: fixture.output }, }, }, }); expect(await readFile(`${fixture.output}/rootfs/config`, "utf8")).toBe( "firmware=true\n", ); expect(closeFailure.attempts()).toBeGreaterThanOrEqual(4); } finally { closeFailure.restore(); } await fixture.close(); expect(retained?.cleanupIncomplete).toBe(false); expect(await readFile(`${fixture.output}/rootfs/config`, "utf8")).toBe( "firmware=true\n", ); }); it("shares recovery prose across distinct unknown chunk identities", async () => { const fixture = await firmwareFixture("many-unknown"); const result = await fixture.service.execute("extract_firmware", { path: fixture.path, output_directory: fixture.output, }); if (!result.ok) throw result.error; const normalized = firmwareResultSchemas.extract_firmware.parse( result.value.normalized_result, ); expect(normalized.extraction_gaps).toHaveLength(1000); expect( new Set(normalized.extraction_gaps.map(({ provider_id }) => provider_id)) .size, ).toBe(1000); expect(normalized.extraction_continuations).toHaveLength(1); const [instruction] = normalized.extraction_continuations; expect(instruction?.instruction).toContain("inspect_firmware_regions"); expect( normalized.extraction_gaps.every( (gap) => gap.continuation_id === instruction?.id, ), ).toBe(true); }); it("retains a task dependency failure when the producer names no executable", async () => { const fixture = await firmwareFixture("unnamed-dependency"); const result = await fixture.service.execute("extract_firmware", { path: fixture.path, output_directory: fixture.output, }); if (!result.ok) throw result.error; const normalized = firmwareResultSchemas.extract_firmware.parse( result.value.normalized_result, ); expect(gapsWithContinuations(normalized)).toEqual([ { kind: "missing-extractor-dependency", input_path: "$input", relative_path: null, handler: null, provider_id: null, range: null, root_file_range: null, dependencies: [], continuation: expect.stringContaining("identity is unavailable"), }, ]); }); it("preserves an unnamed dependency failure on its owning chunk", async () => { const fixture = await firmwareFixture("unnamed-chunk-dependency"); const result = await fixture.service.execute("extract_firmware", { path: fixture.path, output_directory: fixture.output, }); if (!result.ok) throw result.error; const normalized = firmwareResultSchemas.extract_firmware.parse( result.value.normalized_result, ); expect(gapsWithContinuations(normalized)).toEqual([ { kind: "missing-extractor-dependency", input_path: "$input", relative_path: null, handler: "gzip", provider_id: "gzip-id", range: { offset: 0, length: 18 }, root_file_range: { offset: 0, length: 18 }, dependencies: [], continuation: expect.stringContaining("identity is unavailable"), }, ]); }); it("routes a nested unknown chunk through its published child", async () => { const fixture = await firmwareFixture("nested-unknown"); const result = await fixture.service.execute("extract_firmware", { path: fixture.path, output_directory: fixture.output, }); if (!result.ok) throw result.error; const normalized = firmwareResultSchemas.extract_firmware.parse( result.value.normalized_result, ); expect(gapsWithContinuations(normalized)).toEqual( expect.arrayContaining([ expect.objectContaining({ kind: "unknown-chunk-handler", input_path: "$output/rootfs/config", provider_id: "unknown-id", range: { offset: 0, length: 14 }, root_file_range: null, continuation: expect.stringContaining( "published child named by this gap's input_path", ), }), ]), ); expect(gapsWithContinuations(normalized)[0]?.continuation).toContain( "only if Binwalk is configured with REA_BINWALK_COMMAND", ); expect(gapsWithContinuations(normalized)[0]?.continuation).toContain( "unavailable without configured Binwalk", ); }); it("retains every eligible child in a maximum-depth continuation", async () => { const fixture = await firmwareFixture("depth-reentry"); const result = await fixture.service.execute("extract_firmware", { path: fixture.path, output_directory: fixture.output, max_depth: 10, }); if (!result.ok) throw result.error; const normalized = firmwareResultSchemas.extract_firmware.parse( result.value.normalized_result, ); const gap = gapsWithContinuations(normalized).find( ({ kind, input_path }) => kind === "depth-limited" && input_path === "$output/rootfs/config", ); expect(gap?.continuation).toContain( JSON.stringify(`${fixture.output}/rootfs/config/inner.gz`), ); expect(gap?.continuation).toContain( JSON.stringify(`${fixture.output}/rootfs/config/second.gz`), ); }); it("withholds the nested rerun advice when the published child exceeds the input limit", async () => { const fixture = await firmwareFixture("nested-unknown-oversized"); const result = await fixture.service.execute("extract_firmware", { path: fixture.path, output_directory: fixture.output, }); if (!result.ok) throw result.error; const normalized = firmwareResultSchemas.extract_firmware.parse( result.value.normalized_result, ); expect(gapsWithContinuations(normalized)).toEqual([ { kind: "unknown-chunk-handler", input_path: "$output/rootfs/config", relative_path: null, handler: null, provider_id: "unknown-id", range: { offset: 0, length: 14 }, root_file_range: null, dependencies: [], continuation: expect.stringContaining( "cannot accept it as a fresh input", ), }, ]); }); it.each([ ["depth", 10, "rerun extract_firmware"], ["depth-orphan", 10, "cannot be restarted"], ] as const)( "bounds the maximum-depth continuation by a usable published child (%s)", async (mode, maxDepth, expected) => { const fixture = await firmwareFixture(mode); const result = await fixture.service.execute("extract_firmware", { path: fixture.path, output_directory: fixture.output, max_depth: maxDepth, }); if (!result.ok) throw result.error; const normalized = firmwareResultSchemas.extract_firmware.parse( result.value.normalized_result, ); expect(normalized.depth_limited_paths.length).toBeGreaterThan(0); expect( gapsWithContinuations(normalized).filter( (gap) => gap.kind === "depth-limited", ), ).toEqual( expect.arrayContaining([ expect.objectContaining({ kind: "depth-limited", continuation: expect.stringContaining(expected), }), ]), ); }, ); it("reports a failed multi-file stage as an extractor-failure gap", async () => { const fixture = await firmwareFixture("multi-file-failure"); const result = await fixture.service.execute("extract_firmware", { path: fixture.path, output_directory: fixture.output, }); if (!result.ok) throw result.error; const normalized = firmwareResultSchemas.extract_firmware.parse( result.value.normalized_result, ); expect(gapsWithContinuations(normalized)).toEqual( expect.arrayContaining([ expect.objectContaining({ kind: "extractor-failure", input_path: "$input", handler: "tar", provider_id: "mf-id", range: null, root_file_range: null, }), ]), ); }); it("carries the owning multi-file stage on a task-level dependency gap", async () => { const fixture = await firmwareFixture("multi-file-dependency"); const result = await fixture.service.execute("extract_firmware", { path: fixture.path, output_directory: fixture.output, }); if (!result.ok) throw result.error; const normalized = firmwareResultSchemas.extract_firmware.parse( result.value.normalized_result, ); expect(gapsWithContinuations(normalized)).toEqual([ { kind: "missing-extractor-dependency", input_path: "$input", relative_path: null, handler: "squashfs", provider_id: "sq-id", range: null, root_file_range: null, dependencies: ["sasquatch"], continuation: expect.stringContaining("installs nothing"), }, ]); expect(normalized.diagnostics).toEqual([ expect.objectContaining({ stage: "squashfs" }), ]); }); const injectPublishedDirectoryCloseFailure = (persistent: boolean) => { directoryCloseFailure.attempts = 0; const commit = SafeOutputTree.prototype.commit; const spy = vi .spyOn(SafeOutputTree.prototype, "commit") .mockImplementation(async function (this: SafeOutputTree) { directoryCloseFailure.mode = persistent ? "persistent" : "transient"; await commit.call(this); }); return { attempts: () => directoryCloseFailure.attempts, restore: () => { directoryCloseFailure.mode = "off"; spy.mockRestore(); }, }; }; it.each(["depth", "dependency", "link"])( "reports partial extraction for %s without losing inline results", async (mode) => { const fixture = await firmwareFixture(mode); const result = await fixture.service.execute("extract_firmware", { path: fixture.path, output_directory: fixture.output, }); if (!result.ok) throw result.error; const normalized = firmwareResultSchemas.extract_firmware.parse( result.value.normalized_result, ); expect(normalized.coverage).toBe("partial"); expect(normalized.files).toHaveLength(1); if (mode === "depth") expect(normalized.depth_limited_paths).toEqual(["$output/rootfs/config"]); if (mode === "depth") expect(gapsWithContinuations(normalized)).toEqual([ { kind: "depth-limited", input_path: "$output/rootfs/config", relative_path: null, handler: null, provider_id: null, range: null, root_file_range: null, dependencies: [], continuation: expect.stringMatching( /max_depth.*fresh output_directory/u, ), }, ]); if (mode === "dependency") expect(normalized.diagnostics).toEqual([ { input_path: "$input", stage: "gzip", missing_dependencies: ["sasquatch"], report: { __typename__: "ExtractorDependencyNotFoundReport", severity: "ERROR", dependencies: ["sasquatch"], }, }, ]); if (mode === "dependency") expect(gapsWithContinuations(normalized)).toEqual([ { kind: "missing-extractor-dependency", input_path: "$input", relative_path: null, handler: "gzip", provider_id: "gzip-id", range: { offset: 0, length: 18 }, root_file_range: { offset: 0, length: 18 }, dependencies: ["sasquatch"], continuation: expect.stringContaining("installs nothing"), }, ]); if (mode === "link") { expect(normalized.unpublished_entries).toEqual([ { relative_path: "escape", kind: "symlink", link_target: "/etc/passwd", }, ]); expect(gapsWithContinuations(normalized)).toEqual([ { kind: "unpublished-entry", input_path: "$output/escape", relative_path: "escape", handler: null, provider_id: null, range: null, root_file_range: null, dependencies: [], continuation: expect.stringContaining("metadata"), }, ]); await expect(access(`${fixture.output}/escape`)).rejects.toMatchObject({ code: "ENOENT", }); } await assertFirmwareCleanup(fixture.launches); }, ); it("distinguishes a real output file named $input from the selected original", async () => { const fixture = await firmwareFixture("reserved-name"); const outcome = await fixture.service.execute("extract_firmware", { path: fixture.path, output_directory: fixture.output, }); if (!outcome.ok) throw outcome.error; const result = firmwareResultSchemas.extract_firmware.parse( outcome.value.normalized_result, ); expect(result.files[0]?.relative_path).toBe("$input"); expect(result.derivations[0]).toMatchObject({ parent_path: "$input", child_path: "$output/$input", }); expect(await readFile(`${fixture.output}/$input`, "utf8")).toBe( "firmware=true\n", ); await assertFirmwareCleanup(fixture.launches); }); it.each(["hash", "malformed", "budget", "missing-file"])( "rejects invalid or over-budget extraction and rolls back output: %s", async (mode) => { const fixture = await firmwareFixture(mode); const result = await fixture.service.execute("extract_firmware", { path: fixture.path, output_directory: fixture.output, ...(mode === "budget" ? { max_output_bytes: 1000 } : {}), }); expect(result.ok).toBe(false); await expect(access(fixture.output)).rejects.toMatchObject({ code: "ENOENT", }); await assertFirmwareCleanup(fixture.launches); }, ); it("preserves existing output and rejects invalid intervals before invoking extraction", async () => { const fixture = await firmwareFixture(); await mkdir(fixture.output); await writeFile(`${fixture.output}/existing`, "keep"); const existing = await fixture.service.execute("extract_firmware", { path: fixture.path, output_directory: fixture.output, }); expect(existing.ok).toBe(false); expect(await readFile(`${fixture.output}/existing`, "utf8")).toBe("keep"); const previous = fixture.launches.length; const invalid = await fixture.service.execute("extract_firmware", { path: fixture.path, output_directory: fixture.output, range: { offset: 100, length: 1 }, }); expect(invalid).toMatchObject({ ok: false, error: { _tag: "AnalysisInputError" }, }); expect(fixture.launches).toHaveLength(previous); await assertFirmwareCleanup(fixture.launches); }); it("retains startup stderr when Unblob exits 1 without a report", async () => { const fixture = await firmwareFixture("startup"); const result = await fixture.service.execute("extract_firmware", { path: fixture.path, output_directory: fixture.output, }); if (result.ok) throw new Error("Expected startup failure"); const details = { diagnostics: { stderr: expect.stringContaining("Landlock sandbox is not available"), exit_code: 1, }, }; expect(projectAnalysisError(result.error)).toMatchObject({ details }); expect( delivery.toCallToolResult(result, toolContract("extract_firmware")) .structuredContent, ).toMatchObject({ error: { details } }); expect(result).toMatchObject({ ok: false, error: { _tag: "ProviderAdapterError", diagnostics: { exit_code: 1, stderr: expect.stringContaining("Landlock sandbox is not available"), report_state: "missing", }, }, }); await expect(access(fixture.output)).rejects.toMatchObject({ code: "ENOENT", }); await assertFirmwareCleanup(fixture.launches); }); it.each([ { operation: "inspect_firmware_regions", engine: "binwalk" }, { operation: "extract_firmware", engine: "unblob" }, ] as const)( "keeps $engine's missing report after exit 0 distinct from an empty result", async ({ operation, engine }) => { const fixture = await firmwareFixture("missing-report"); const result = await fixture.service.execute(operation, { path: fixture.path, ...(operation === "extract_firmware" ? { output_directory: fixture.output } : {}), }); if (result.ok) throw new Error("Expected missing-report failure"); const error = { code: "unreadable_output", retryable: false, message: expect.stringContaining("not an empty or complete result"), details: { reason: `${engine} exited 0 without a usable report: Report was not created`, diagnostics: { report_state: "missing", report_path: expect.stringMatching(/report\.json$/), command: expect.any(String), args: expect.any(Array), exit_code: 0, signal: null, stderr: "Producer forgot its report\n", }, }, remediation: { action: expect.stringContaining("did not retry or substitute"), }, }; expect(projectAnalysisError(result.error)).toMatchObject(error); expect(projectAnalysisError(result.error).message).not.toContain( "rea doctor", ); expect( delivery.toCallToolResult(result, toolContract(operation)) .structuredContent, ).toMatchObject({ error }); await assertFirmwareCleanup(fixture.launches); }, ); it("cancels an owned active process and permits the next queued operation", async () => { const fixture = await firmwareFixture("stall"); const controller = new AbortController(); const pending = fixture.service.execute( "inspect_firmware_regions", { path: fixture.path }, { signal: controller.signal }, ); await expect.poll(() => fixture.launches.length).toBe(2); controller.abort(); expect(await pending).toMatchObject({ ok: false, error: { _tag: "AnalysisCancelledError" }, }); const cancelled = await fixture.service.execute( "inspect_firmware_regions", { path: fixture.path }, { signal: AbortSignal.abort() }, ); expect(cancelled).toMatchObject({ ok: false, error: { _tag: "AnalysisCancelledError" }, }); expect(fixture.launches).toHaveLength(2); await assertFirmwareCleanup(fixture.launches); }); it("cancels a waiting request promptly while keeping later launches behind the active operation", async () => { const fixture = await firmwareFixture("stall"); const activeController = new AbortController(); const active = fixture.service.execute( "inspect_firmware_regions", { path: fixture.path }, { signal: activeController.signal }, ); await expect.poll(() => fixture.launches.length).toBe(2); const queuedController = new AbortController(); const queued = fixture.service.execute( "inspect_firmware_regions", { path: fixture.path }, { signal: queuedController.signal }, ); queuedController.abort(); expect(await queued).toMatchObject({ ok: false, error: { _tag: "AnalysisCancelledError" }, }); expect(fixture.launches).toHaveLength(2); activeController.abort(); expect((await active).ok).toBe(false); await assertFirmwareCleanup(fixture.launches); }); it("retains an uncertain worker's workspace and blocks later launches", async () => { const fixture = await firmwareFixture("cleanup-failure"); const first = await fixture.service.execute("inspect_firmware_regions", { path: fixture.path, }); expect(first).toMatchObject({ ok: false, error: { cleanupIncomplete: true }, }); const workspace = fixture.launches[0]?.cwd; expect(workspace).toBeDefined(); if (workspace === undefined) throw new Error("Expected retained workspace"); await access(workspace); const originalLaunches = [...fixture.launches]; const next = await fixture.service.execute("inspect_firmware_regions", { path: fixture.path, }); expect(next).toMatchObject({ ok: false, error: { cleanupIncomplete: true } }); expect(fixture.launches).toEqual(originalLaunches); await access(workspace); fixture.restoreCleanup(); const resumed = await fixture.service.execute("inspect_firmware_regions", { path: fixture.path, }); if (!resumed.ok) throw resumed.error; expect(resumed.value.subject?.local_path).toBe(fixture.path); await assertFirmwareCleanup(fixture.launches); }); it("accepts another build on the verified release line and reports it", async () => { const fixture = await firmwareFixture("normal", "binwalk 3.1.2"); const result = await fixture.service.execute("inspect_firmware_regions", { path: fixture.path, }); if (!result.ok) throw result.error; expect(result.value.provider.version).toBe("3.1.2"); expect(result.value.limitations.join("\n")).toContain( "verified against 3.1.0", ); expect(result.value.normalized_result).toMatchObject({ engine: { version: "3.1.2" }, }); await assertFirmwareCleanup(fixture.launches); }); it("names the accepted release line when the banner is another line", async () => { const fixture = await firmwareFixture("normal", "binwalk 3.2.0"); const result = await fixture.service.execute("inspect_firmware_regions", { path: fixture.path, }); expect(result).toMatchObject({ ok: false, error: { _tag: "AnalysisCapabilityUnavailableError", reason: expect.stringContaining("Binwalk 3.1.x"), }, }); await assertFirmwareCleanup(fixture.launches); }); it("rejects absent or unsupported engines without installing anything", async () => { const missing = await new FirmwareAnalysisService( new FirmwareProvider({}), ).execute("inspect_firmware_regions", { path: "/tmp/unused" }); expect(missing).toMatchObject({ ok: false, error: { _tag: "AnalysisCapabilityUnavailableError" }, }); const fixture = await firmwareFixture("version"); const result = await fixture.service.execute("inspect_firmware_regions", { path: fixture.path, }); expect(result).toMatchObject({ ok: false, error: { _tag: "AnalysisCapabilityUnavailableError" }, }); await assertFirmwareCleanup(fixture.launches); });