import { afterEach, expect, test, vi } from "vitest" import { CoordinationAbortError, CoordinationTimeoutError, CountDownLatch, } from "#Source/orchestration/index.ts" afterEach(() => { vi.clearAllTimers() vi.useRealTimers() }) test("CountDownLatch opens when the count reaches zero and resolves waiters", async () => { const countDownLatch = new CountDownLatch(2) const firstWait = countDownLatch.wait() const secondWait = countDownLatch.wait() expect(countDownLatch.isOpen()).toBe(false) expect(countDownLatch.tryWait()).toBe(false) expect(countDownLatch.getRemainingCount()).toBe(2) expect(countDownLatch.getPendingCount()).toBe(2) expect(countDownLatch.countDown()).toBe(1) expect(countDownLatch.arrive()).toBe(0) await Promise.all([firstWait, secondWait]) expect(countDownLatch.isOpen()).toBe(true) expect(countDownLatch.tryWait()).toBe(true) expect(countDownLatch.getRemainingCount()).toBe(0) expect(countDownLatch.getPendingCount()).toBe(0) await expect(countDownLatch.wait()).resolves.toBeUndefined() }) test("CountDownLatch wait rejects on timeout and abort without leaking pending entries", async () => { vi.useFakeTimers() const countDownLatch = new CountDownLatch(1) const timeoutPromise = countDownLatch.wait({ timeout: 30 }) const timeoutExpectation = expect(timeoutPromise).rejects.toBeInstanceOf(CoordinationTimeoutError) expect(countDownLatch.getPendingCount()).toBe(1) await vi.advanceTimersByTimeAsync(30) await timeoutExpectation expect(countDownLatch.getPendingCount()).toBe(0) const abortController = new AbortController() const abortPromise = countDownLatch.wait({ abortSignal: abortController.signal }) const abortExpectation = expect(abortPromise).rejects.toBeInstanceOf(CoordinationAbortError) expect(countDownLatch.getPendingCount()).toBe(1) abortController.abort("cancelled") await abortExpectation expect(countDownLatch.getPendingCount()).toBe(0) }) test("CountDownLatch ignores further countdowns after opening", () => { const countDownLatch = new CountDownLatch(1) expect(countDownLatch.countDown()).toBe(0) expect(countDownLatch.countDown()).toBe(0) expect(countDownLatch.arrive()).toBe(0) expect(countDownLatch.isOpen()).toBe(true) })