Files
rea/src/application/binary/AnalysisClientCleanup.test.ts
T
Kaoru0822andClaude Opus 5.5 b79d379c25 fix(ghidra): keep and name a runtime directory that close could not remove
When removing Ghidra's private runtime directory failed, close_binary
reported only a generic `provider-client` resource, and a later close,
after the permission was restored, returned success while the directory
and its contents remained. The client dropped its reference to the root
before removing it, and PrivateRuntimeRoot cached the rejected removal.

Keep each runtime or socket root until its removal succeeds, report a
failure as a ProviderCleanupError naming the leftover paths, let
PrivateRuntimeRoot retry a failed removal, and pass such typed cleanup
failures through closeAnalysisClient instead of replacing them.

Fixes #1190

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 04:19:10 +00:00

46 lines
1.5 KiB
TypeScript

import { expect, it } from "vitest";
import { projectAnalysisError } from "../../domain/analysisErrorProjection.js";
import { ProviderCleanupError } from "../../domain/providerCleanupError.js";
import { err } from "../../domain/result.js";
import type { AnalysisClient } from "../AnalysisProvider.js";
import { closeAnalysisClient } from "./AnalysisClientCleanup.js";
const clientClosingWith = (cause: unknown): AnalysisClient => ({
execute: () => Promise.resolve(err(new ProviderCleanupError("x", [], {}))),
close: () => Promise.reject(cause),
});
it("keeps the leftover resources a typed cleanup failure names", async () => {
const leftover = "/tmp/rea-ghidra-fixture";
const failure = new ProviderCleanupError("ghidra", [leftover], {
reason: "runtime directory retained",
});
const closed = await closeAnalysisClient(
clientClosingWith(failure),
"ghidra",
);
expect(closed.ok).toBe(false);
if (!closed.ok)
expect(projectAnalysisError(closed.error)).toMatchObject({
code: "cleanup_incomplete",
details: { resources: [leftover] },
});
});
it("still reports an untyped close rejection as the provider client", async () => {
const closed = await closeAnalysisClient(
clientClosingWith(new Error("unexpected")),
"ghidra",
);
expect(closed.ok).toBe(false);
if (!closed.ok)
expect(projectAnalysisError(closed.error)).toMatchObject({
code: "cleanup_incomplete",
details: { resources: ["provider-client"] },
});
});