diff --git a/server/src/services/native-runtime/native-workspace-lock-keepalive.test.ts b/server/src/services/native-runtime/native-workspace-lock-keepalive.test.ts index 04877796404..9369ca8e6ff 100644 --- a/server/src/services/native-runtime/native-workspace-lock-keepalive.test.ts +++ b/server/src/services/native-runtime/native-workspace-lock-keepalive.test.ts @@ -1,13 +1,40 @@ import { setImmediate } from "node:timers/promises"; +import * as timers from "node:timers/promises"; import { expect, it, vi } from "vitest"; import type { Db } from "@paperclipai/db"; import { withWorkspaceLockKeepalive } from "./native-workspace-lock-keepalive.js"; +vi.mock("node:timers/promises", async importOriginal => { + const actual = await importOriginal(); + return { ...actual, setTimeout: vi.fn(actual.setTimeout) }; +}); + it.each([0, -1, NaN, Infinity])("does not probe when the idle timeout is %s", async timeout => { const execute = vi.fn(); const value = {}; - await expect(withWorkspaceLockKeepalive({ execute } as unknown as Db, timeout, async () => value)).resolves.toBe(value); - expect(execute).not.toHaveBeenCalled(); + let finish!: (value: object) => void; + const pending = new Promise(resolve => { finish = resolve; }); + vi.useFakeTimers(); + const sleep = vi.mocked(timers.setTimeout); + const originalSleep = sleep.getMockImplementation()!; + sleep.mockClear().mockImplementation((_delay, result, options) => new Promise((resolve, reject) => { + const timer = setTimeout(() => resolve(result), 30_000); + options?.signal?.addEventListener("abort", () => { + clearTimeout(timer); + reject(new Error("aborted")); + }, { once: true }); + })); + const result = withWorkspaceLockKeepalive({ execute } as unknown as Db, timeout, () => pending); + try { + await vi.advanceTimersByTimeAsync(60_001); + expect(execute).not.toHaveBeenCalled(); + expect(sleep).not.toHaveBeenCalled(); + } finally { + finish(value); + await expect(result).resolves.toBe(value); + sleep.mockImplementation(originalSleep); + vi.useRealTimers(); + } }); it("joins an in-flight probe before releasing the lock scope", async () => {