mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-04 07:14:05 +00:00
90 lines
2.5 KiB
TypeScript
90 lines
2.5 KiB
TypeScript
import { EventEmitter } from "node:events";
|
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
import { runWatchMain } from "../../scripts/watch-node.mjs";
|
|
|
|
class FakeProcess extends EventEmitter {
|
|
execPath = process.execPath;
|
|
pid = 12345;
|
|
stderr = {
|
|
write: () => true,
|
|
};
|
|
}
|
|
|
|
class FakeChild extends EventEmitter {
|
|
signals: string[] = [];
|
|
|
|
kill(signal: string): boolean {
|
|
this.signals.push(signal);
|
|
if (signal === "SIGKILL") {
|
|
this.emit("exit", null, "SIGKILL");
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
describe("watch-node shutdown cleanup", () => {
|
|
afterEach(() => {
|
|
vi.useRealTimers();
|
|
});
|
|
|
|
it("waits for the child and escalates when interrupted children ignore SIGTERM", async () => {
|
|
vi.useFakeTimers();
|
|
const fakeProcess = new FakeProcess();
|
|
const child = new FakeChild();
|
|
let resolvedCode: number | undefined;
|
|
|
|
const run = runWatchMain({
|
|
args: ["gateway"],
|
|
createWatcher: () => ({ close: async () => {}, on: () => {} }),
|
|
lockDisabled: true,
|
|
process: fakeProcess as unknown as NodeJS.Process,
|
|
spawn: () => child as never,
|
|
}).then((code) => {
|
|
resolvedCode = code;
|
|
return code;
|
|
});
|
|
|
|
fakeProcess.emit("SIGTERM");
|
|
await vi.advanceTimersByTimeAsync(4_999);
|
|
expect(resolvedCode).toBeUndefined();
|
|
expect(child.signals).toEqual(["SIGTERM"]);
|
|
|
|
await vi.advanceTimersByTimeAsync(1);
|
|
await expect(run).resolves.toBe(143);
|
|
expect(child.signals).toEqual(["SIGTERM", "SIGKILL"]);
|
|
});
|
|
|
|
it("waits for the auto-doctor child when interrupted during repair", async () => {
|
|
vi.useFakeTimers();
|
|
const fakeProcess = new FakeProcess();
|
|
const runner = new FakeChild();
|
|
const doctor = new FakeChild();
|
|
const children = [runner, doctor];
|
|
let resolvedCode: number | undefined;
|
|
|
|
const run = runWatchMain({
|
|
args: ["gateway"],
|
|
createWatcher: () => ({ close: async () => {}, on: () => {} }),
|
|
env: {},
|
|
lockDisabled: true,
|
|
process: fakeProcess as unknown as NodeJS.Process,
|
|
spawn: () => children.shift() as never,
|
|
}).then((code) => {
|
|
resolvedCode = code;
|
|
return code;
|
|
});
|
|
|
|
runner.emit("exit", 1, null);
|
|
expect(children).toHaveLength(0);
|
|
|
|
fakeProcess.emit("SIGTERM");
|
|
await vi.advanceTimersByTimeAsync(4_999);
|
|
expect(resolvedCode).toBeUndefined();
|
|
expect(doctor.signals).toEqual(["SIGTERM"]);
|
|
|
|
await vi.advanceTimersByTimeAsync(1);
|
|
await expect(run).resolves.toBe(143);
|
|
expect(doctor.signals).toEqual(["SIGTERM", "SIGKILL"]);
|
|
});
|
|
});
|