@@ -4,6 +4,7 @@ import { EventEmitter } from "node:events";
|
4 | 4 | import process from "node:process"; |
5 | 5 | import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; |
6 | 6 | import { OPENCLAW_CLI_ENV_VALUE } from "../infra/openclaw-exec-env.js"; |
| 7 | +import { MAX_TIMER_TIMEOUT_MS } from "../shared/number-coercion.js"; |
7 | 8 | |
8 | 9 | const spawnMock = vi.hoisted(() => vi.fn()); |
9 | 10 | |
@@ -259,6 +260,49 @@ describe("runCommandWithTimeout", () => {
|
259 | 260 | }, |
260 | 261 | ); |
261 | 262 | |
| 263 | +it.runIf(process.platform !== "win32")( |
| 264 | +"caps oversized process timeouts before arming timers", |
| 265 | +async () => { |
| 266 | +vi.useFakeTimers(); |
| 267 | +const timeoutSpy = vi.spyOn(globalThis, "setTimeout"); |
| 268 | +const child = createKilledChild(); |
| 269 | +spawnMock.mockReturnValue(child); |
| 270 | +await loadExecModules({ mockSpawn: true }); |
| 271 | + |
| 272 | +const resultPromise = runCommandWithTimeout(createSilentIdleArgv(), { |
| 273 | +timeoutMs: Number.MAX_SAFE_INTEGER, |
| 274 | +}); |
| 275 | + |
| 276 | +expect(timeoutSpy).toHaveBeenCalledWith(expect.any(Function), MAX_TIMER_TIMEOUT_MS); |
| 277 | +child.emit("exit", 0, null); |
| 278 | +child.emit("close", 0, null); |
| 279 | +const result = await resultPromise; |
| 280 | +expect(result.termination).toBe("exit"); |
| 281 | +}, |
| 282 | +); |
| 283 | + |
| 284 | +it.runIf(process.platform !== "win32")( |
| 285 | +"caps oversized no-output timeouts before arming timers", |
| 286 | +async () => { |
| 287 | +vi.useFakeTimers(); |
| 288 | +const timeoutSpy = vi.spyOn(globalThis, "setTimeout"); |
| 289 | +const child = createKilledChild(); |
| 290 | +spawnMock.mockReturnValue(child); |
| 291 | +await loadExecModules({ mockSpawn: true }); |
| 292 | + |
| 293 | +const resultPromise = runCommandWithTimeout(createSilentIdleArgv(), { |
| 294 | +timeoutMs: 1_000, |
| 295 | +noOutputTimeoutMs: Number.MAX_SAFE_INTEGER, |
| 296 | +}); |
| 297 | + |
| 298 | +expect(timeoutSpy).toHaveBeenCalledWith(expect.any(Function), MAX_TIMER_TIMEOUT_MS); |
| 299 | +child.emit("exit", 0, null); |
| 300 | +child.emit("close", 0, null); |
| 301 | +const result = await resultPromise; |
| 302 | +expect(result.termination).toBe("exit"); |
| 303 | +}, |
| 304 | +); |
| 305 | + |
262 | 306 | it.runIf(process.platform !== "win32")( |
263 | 307 | "swallows stdin EPIPE when child exits before input is consumed (#75438)", |
264 | 308 | { timeout: 5_000 }, |
|