Files
reverse-engineering-anything/src/mcpDoctor.cleanup.test.ts
T
gensokyo-devandClaude Opus 5.5 d412569293 fix(mcp-doctor): close only through the owned transport
The owned transport is the doctor's only cleanup owner, and Client.close
only delegates to it. Close it once and report its typed failure instead
of aggregating a duplicate SDK close and clearing that failure after a
retry. Pass the filtered caller environment as the launcher's base only,
and name the doctor operation in transport cleanup errors.

Cover a descendant in its own session, which only the token sweep can
reach, and a late cleanup denial that keeps the startup diagnostic and
reports the retained run. Bound the fixture descendant's lifetime so a
failing run cannot leak it. Document the doctor's process-family
ownership and output bound.

Co-Authored-By: gensokyo-dev <gensokyo-dev@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-14 05:36:23 +01:00

60 lines
1.9 KiB
TypeScript

import { resolve } from "node:path";
import { expect, it, vi } from "vitest";
const cleanupDenial = vi.hoisted(() => ({
reason: undefined as string | undefined,
}));
// Keep real process-group cleanup, then report the selected denial so the
// doctor's late cleanup failure is observed without leaking the fixture.
vi.mock("./process/ProcessOwnership.js", async (importOriginal) => {
const original =
await importOriginal<typeof import("./process/ProcessOwnership.js")>();
return {
...original,
cleanupOwnedProcessGroup: async (
...parameters: Parameters<typeof original.cleanupOwnedProcessGroup>
) => {
const released = await original.cleanupOwnedProcessGroup(...parameters);
return cleanupDenial.reason === undefined
? released
: { cleaned: false as const, reason: cleanupDenial.reason };
},
};
});
import { runProductionMcpDoctor } from "./mcpDoctor.js";
it("keeps the startup diagnostic and reports retained resources when cleanup fails", async () => {
cleanupDenial.reason = "fixture process group remained alive";
try {
const result = await runProductionMcpDoctor({
command: process.execPath,
args: [resolve("tests/fixtures/mcpDoctorExit.mjs")],
cwd: process.cwd(),
environment: { ...process.env, REA_MCP_DOCTOR_DEADLINE_MS: "5000" },
});
expect(result).toMatchObject({
healthy: false,
checks: [
{ name: "transport", ok: false },
{
name: "cleanup",
ok: false,
detail: expect.stringMatching(
/^MCP stdio cleanup failed: Provider mcp-doctor adapter failed during mcp_doctor \(fixture process group remained alive\); retained resources: [0-9a-f-]{36}$/u,
),
},
],
diagnostics: {
stderr: "fixture MCP startup exit\n",
stderr_truncated: false,
},
});
} finally {
cleanupDenial.reason = undefined;
}
});