fix(test): disconnect Hopper fixture IPC on SIGTERM

This commit is contained in:
morluto 2026-10-07 12:28:43 +08:00
parent f72931d9dd
commit b912b117f0
3 changed files with 46 additions and 9 deletions

View File

@ -127,6 +127,34 @@ describe("HopperClient cleanup", () => {
await first;
});
it("exits an IPC-backed fixture cleanly after cancelling active work", async () => {
const launcher = new FixtureLauncher();
const client = await startClient(launcher);
const controller = new AbortController();
const pending = client.callTool(
"echo",
{ gate: "cancel-and-close" },
{
signal: controller.signal,
},
);
await launcher.waitForRequest("echo", "cancel-and-close");
controller.abort();
await expect(pending).resolves.toMatchObject({
ok: false,
error: { _tag: "HopperCancelledError" },
});
await client.close();
const child = launcher.processes.at(-1);
expect({
exitCode: child?.exitCode,
signalCode: child?.signalCode,
}).toEqual({
exitCode: 0,
signalCode: null,
});
});
it("reports unconfirmed unowned document cleanup as a typed close failure", async () => {
const client = new HopperClient({
launcher: new UnconfirmedFixtureLauncher(),

View File

@ -113,6 +113,17 @@ describe("HopperClient protocol", () => {
requestId: (await launcher.waitForRequest(method)).id,
});
}
if (expectedTag === "HopperProtocolError") {
await client.close();
const child = launcher.processes.at(-1);
expect({
exitCode: child?.exitCode,
signalCode: child?.signalCode,
}).toEqual({
exitCode: 0,
signalCode: null,
});
}
});
it("preserves a sanitized bridge exception diagnostic", async () => {

View File

@ -184,14 +184,7 @@ const server = createServer((socket) => {
request.method === "shutdown_document"
) {
send({ id: request.id, result: shutdownResult() });
if (shutdownMode !== "cleanup-required")
setTimeout(
() =>
server.close(() => {
if (process.connected) process.disconnect();
}),
2,
);
if (shutdownMode !== "cleanup-required") setTimeout(closeServer, 2);
} else if (request.method === "hang") {
// Deliberately leave the request pending.
} else if (request.method === "exit") {
@ -234,5 +227,10 @@ const server = createServer((socket) => {
});
});
const closeServer = () =>
server.close(() => {
if (process.connected) process.disconnect();
});
server.listen(socketPath);
process.on("SIGTERM", () => server.close());
process.on("SIGTERM", closeServer);