From 6ab0f62b3b7a469bc97bda4aefd43912c1fd90d6 Mon Sep 17 00:00:00 2001 From: Shakker Date: Mon, 30 Mar 2026 21:54:51 +0100 Subject: [PATCH] test: stabilize remaining windows ci timeouts --- src/acp/control-plane/manager.test.ts | 40 +++++++++++++----- src/tasks/task-registry.test.ts | 2 +- src/test-utils/session-state-cleanup.test.ts | 44 +++++++++++++------- 3 files changed, 58 insertions(+), 28 deletions(-) diff --git a/src/acp/control-plane/manager.test.ts b/src/acp/control-plane/manager.test.ts index 8523b867e9a..628956570dd 100644 --- a/src/acp/control-plane/manager.test.ts +++ b/src/acp/control-plane/manager.test.ts @@ -63,6 +63,21 @@ async function withAcpManagerTaskStateDir(run: (root: string) => Promise): }); } +async function waitForAssertion(assertion: () => void, timeoutMs = 2_000, stepMs = 5) { + const startedAt = Date.now(); + for (;;) { + try { + assertion(); + return; + } catch (error) { + if (Date.now() - startedAt >= timeoutMs) { + throw error; + } + await new Promise((resolve) => setTimeout(resolve, stepMs)); + } + } +} + function createRuntime(): { runtime: AcpRuntime; ensureSession: ReturnType; @@ -316,17 +331,20 @@ describe("AcpSessionManager", () => { requestId: "direct-parented-run", }); - expect(findTaskByRunId("direct-parented-run")).toMatchObject({ - runtime: "acp", - requesterSessionKey: "agent:quant:telegram:quant:direct:822430204", - childSessionKey: "agent:codex:acp:child-1", - label: "Quant patch", - task: "Implement the feature and report back", - status: "succeeded", - progressSummary: "Write failed: permission denied for /root/oc-acp-write-should-fail.txt.", - terminalOutcome: "blocked", - terminalSummary: "Permission denied for /root/oc-acp-write-should-fail.txt.", - }); + await waitForAssertion(() => + expect(findTaskByRunId("direct-parented-run")).toMatchObject({ + runtime: "acp", + requesterSessionKey: "agent:quant:telegram:quant:direct:822430204", + childSessionKey: "agent:codex:acp:child-1", + label: "Quant patch", + task: "Implement the feature and report back", + status: "succeeded", + progressSummary: + "Write failed: permission denied for /root/oc-acp-write-should-fail.txt.", + terminalOutcome: "blocked", + terminalSummary: "Permission denied for /root/oc-acp-write-should-fail.txt.", + }), + ); }); }); diff --git a/src/tasks/task-registry.test.ts b/src/tasks/task-registry.test.ts index 15e2ac40f15..e8e1fc16aed 100644 --- a/src/tasks/task-registry.test.ts +++ b/src/tasks/task-registry.test.ts @@ -697,7 +697,7 @@ describe("task-registry", () => { }); it("adopts parent flow linkage when collapsing onto an earlier ACP record", async () => { - await withTempDir({ prefix: "openclaw-task-registry-" }, async (root) => { + await withTaskRegistryTempDir(async (root) => { process.env.OPENCLAW_STATE_DIR = root; resetTaskRegistryForTests(); diff --git a/src/test-utils/session-state-cleanup.test.ts b/src/test-utils/session-state-cleanup.test.ts index c1252927be6..40598519329 100644 --- a/src/test-utils/session-state-cleanup.test.ts +++ b/src/test-utils/session-state-cleanup.test.ts @@ -2,26 +2,36 @@ import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import { resetSessionWriteLockStateForTest } from "../agents/session-write-lock.js"; -import { - clearSessionStoreCacheForTest, - getSessionStoreLockQueueSizeForTest, - withSessionStoreLockForTest, -} from "../config/sessions/store.js"; -import { resetFileLockStateForTest } from "../infra/file-lock.js"; -import { cleanupSessionStateForTest } from "./session-state-cleanup.js"; const acquireSessionWriteLockMock = vi.hoisted(() => vi.fn(async () => ({ release: vi.fn(async () => {}) })), ); -vi.mock("../agents/session-write-lock.js", async (importOriginal) => { - const original = await importOriginal(); - return { - ...original, - acquireSessionWriteLock: acquireSessionWriteLockMock, - }; -}); +let cleanupSessionStateForTest: typeof import("./session-state-cleanup.js").cleanupSessionStateForTest; +let withSessionStoreLockForTest: typeof import("../config/sessions/store.js").withSessionStoreLockForTest; +let getSessionStoreLockQueueSizeForTest: typeof import("../config/sessions/store.js").getSessionStoreLockQueueSizeForTest; +let clearSessionStoreCacheForTest: typeof import("../config/sessions/store.js").clearSessionStoreCacheForTest; +let resetFileLockStateForTest: typeof import("../infra/file-lock.js").resetFileLockStateForTest; +let resetSessionWriteLockStateForTest: typeof import("../agents/session-write-lock.js").resetSessionWriteLockStateForTest; + +async function loadFreshSessionCleanupModules() { + vi.resetModules(); + vi.doMock("../agents/session-write-lock.js", async (importOriginal) => { + const original = await importOriginal(); + return { + ...original, + acquireSessionWriteLock: acquireSessionWriteLockMock, + }; + }); + ({ + withSessionStoreLockForTest, + getSessionStoreLockQueueSizeForTest, + clearSessionStoreCacheForTest, + } = await import("../config/sessions/store.js")); + ({ cleanupSessionStateForTest } = await import("./session-state-cleanup.js")); + ({ resetFileLockStateForTest } = await import("../infra/file-lock.js")); + ({ resetSessionWriteLockStateForTest } = await import("../agents/session-write-lock.js")); +} function createDeferred() { let resolve!: (value: T | PromiseLike) => void; @@ -34,7 +44,8 @@ function createDeferred() { } describe("cleanupSessionStateForTest", () => { - beforeEach(() => { + beforeEach(async () => { + await loadFreshSessionCleanupModules(); vi.useRealTimers(); clearSessionStoreCacheForTest(); resetFileLockStateForTest(); @@ -48,6 +59,7 @@ describe("cleanupSessionStateForTest", () => { resetFileLockStateForTest(); resetSessionWriteLockStateForTest(); vi.restoreAllMocks(); + vi.doUnmock("../agents/session-write-lock.js"); }); it("waits for in-flight session store locks before clearing test state", async () => {