File size: 1,400 Bytes
3144483 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | 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]]);
});
|