openclaw / src /process /child-process-tree.reaping.test.ts
SaylorTwift's picture
SaylorTwift HF Staff
Add files using upload-large-folder tool
3144483 verified
Raw History Blame Contribute Delete
1.4 kB
import { ChildProcess } from "node:child_process";
import { afterEach, expect, it, vi } from "vitest";
import { signalChildProcessTree } from "./child-process-tree.js";
const nativeWait = vi.hoisted(() => vi.fn<(pid: number) => number>((pid) => pid));
vi.mock("./kill-tree.js", () => ({ signalProcessTree: vi.fn() }));
vi.mock("node:module", () => ({
createRequire: () => () => ({ load: () => ({ func: () => nativeWait }) }),
}));
vi.mock("node:fs", () => ({
readdirSync: () => ["400", "401", "402"],
readFileSync: (path: string) => {
const pid = Number(path.split("/")[2]);
const group = pid === 402 ? 900 : 400;
return `${pid} (fixture) Z ${process.pid} ${group} 0 0 0`;
},
}));
const originalPlatform = process.platform;
afterEach(() => {
vi.useRealTimers();
Object.defineProperty(process, "platform", { value: originalPlatform });
});
it("tree termination reaps adopted zombies after root exit without consuming other children", () => {
Object.defineProperty(process, "platform", { value: "linux" });
vi.useFakeTimers();
const child = new ChildProcess();
Object.defineProperty(child, "pid", { value: 400 });
signalChildProcessTree(child, "SIGTERM");
vi.advanceTimersByTime(100);
expect(nativeWait).not.toHaveBeenCalled();
child.emit("exit", null, "SIGTERM");
vi.advanceTimersByTime(25);
expect(nativeWait.mock.calls).toEqual([[401, null, 1]]);
});