mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-15 12:00:43 +00:00
74 lines
2.2 KiB
TypeScript
74 lines
2.2 KiB
TypeScript
import type { ChildProcess } from "node:child_process";
|
|
import { EventEmitter } from "node:events";
|
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
|
|
const spawnMock = vi.hoisted(() => vi.fn());
|
|
|
|
vi.mock("node:child_process", async () => {
|
|
const actual = await vi.importActual<typeof import("node:child_process")>("node:child_process");
|
|
return {
|
|
...actual,
|
|
spawn: spawnMock,
|
|
};
|
|
});
|
|
|
|
import { runCommandWithTimeout } from "./exec.js";
|
|
|
|
function createFakeSpawnedChild() {
|
|
const child = new EventEmitter() as EventEmitter & ChildProcess;
|
|
const stdout = new EventEmitter();
|
|
const stderr = new EventEmitter();
|
|
let killed = false;
|
|
const kill = vi.fn<(signal?: NodeJS.Signals) => boolean>(() => {
|
|
killed = true;
|
|
return true;
|
|
});
|
|
Object.defineProperty(child, "killed", {
|
|
get: () => killed,
|
|
configurable: true,
|
|
});
|
|
Object.defineProperty(child, "pid", {
|
|
value: 12345,
|
|
configurable: true,
|
|
});
|
|
child.stdout = stdout as ChildProcess["stdout"];
|
|
child.stderr = stderr as ChildProcess["stderr"];
|
|
child.stdin = null;
|
|
child.kill = kill as ChildProcess["kill"];
|
|
return { child, stdout, stderr, kill };
|
|
}
|
|
|
|
describe("runCommandWithTimeout no-output timer", () => {
|
|
afterEach(() => {
|
|
vi.useRealTimers();
|
|
vi.restoreAllMocks();
|
|
});
|
|
|
|
it("resets no-output timeout when spawned child keeps emitting stdout", async () => {
|
|
vi.useFakeTimers();
|
|
const fake = createFakeSpawnedChild();
|
|
spawnMock.mockReturnValue(fake.child);
|
|
|
|
const runPromise = runCommandWithTimeout(["node", "-e", "ignored"], {
|
|
timeoutMs: 1_000,
|
|
noOutputTimeoutMs: 80,
|
|
});
|
|
|
|
fake.stdout.emit("data", Buffer.from("."));
|
|
await vi.advanceTimersByTimeAsync(40);
|
|
fake.stdout.emit("data", Buffer.from("."));
|
|
await vi.advanceTimersByTimeAsync(40);
|
|
fake.stdout.emit("data", Buffer.from("."));
|
|
await vi.advanceTimersByTimeAsync(20);
|
|
|
|
fake.child.emit("close", 0, null);
|
|
const result = await runPromise;
|
|
|
|
expect(result.code ?? 0).toBe(0);
|
|
expect(result.termination).toBe("exit");
|
|
expect(result.noOutputTimedOut).toBe(false);
|
|
expect(result.stdout).toBe("...");
|
|
expect(fake.kill).not.toHaveBeenCalled();
|
|
});
|
|
});
|