import assert from "node:assert/strict"; import { EventEmitter } from "node:events"; import { SpawnOptions } from "node:child_process"; import test from "node:test"; import { killProcessTree } from "../main/nodecg/process-killer"; test("killProcessTree validates pid before building Windows taskkill command", () => { const spawnCalls: Array<{ command: string; args: string[]; options: SpawnOptions }> = []; const killed = killProcessTree(Number.NaN, "SIGTERM", { platform: "win32", spawnProcess: (command, args, options) => { spawnCalls.push({ command, args, options }); return new EventEmitter() as import("node:child_process").ChildProcess; }, killProcess: () => undefined, log: () => undefined, }); assert.equal(killed, false); assert.deepEqual(spawnCalls, []); }); test("killProcessTree builds a narrow Windows taskkill invocation", () => { const spawnCalls: Array<{ command: string; args: string[]; options: SpawnOptions }> = []; const killed = killProcessTree(1234, "SIGKILL", { platform: "win32", spawnProcess: (command, args, options) => { spawnCalls.push({ command, args, options }); return new EventEmitter() as import("node:child_process").ChildProcess; }, killProcess: () => undefined, log: () => undefined, }); assert.equal(killed, true); assert.equal(spawnCalls[0]?.command, "taskkill"); assert.deepEqual(spawnCalls[0]?.args, ["/pid", "1234", "/T", "/F"]); assert.equal(spawnCalls[0]?.options.shell, false); assert.equal(spawnCalls[0]?.options.windowsHide, true); }); test("killProcessTree falls back from POSIX process group to child pid", () => { const killCalls: Array<{ pid: number; signal: NodeJS.Signals }> = []; const killed = killProcessTree(1234, "SIGTERM", { platform: "linux", spawnProcess: () => new EventEmitter() as import("node:child_process").ChildProcess, killProcess: (pid, signal) => { killCalls.push({ pid, signal }); if (pid < 0) { throw new Error("process group unavailable"); } }, log: () => undefined, }); assert.equal(killed, true); assert.deepEqual(killCalls, [ { pid: -1234, signal: "SIGTERM" }, { pid: 1234, signal: "SIGTERM" }, ]); });