test: remove timeout-prone windows ci waits

This commit is contained in:
Shakker 2026-03-30 22:57:50 +01:00 committed by Shakker
parent da03d857f9
commit 82695bb24d
5 changed files with 71 additions and 36 deletions

View File

@ -66,18 +66,9 @@ async function withAcpManagerTaskStateDir(run: (root: string) => Promise<void>):
});
}
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));
}
async function flushMicrotasks(rounds = 3): Promise<void> {
for (let index = 0; index < rounds; index += 1) {
await Promise.resolve();
}
}
@ -338,20 +329,19 @@ describe("AcpSessionManager", () => {
requestId: "direct-parented-run",
});
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.",
}),
);
await flushMicrotasks();
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.",
});
});
});

View File

@ -113,7 +113,7 @@ async function connectMcp(params: {
describe("openclaw channel mcp server", () => {
describe("gateway-backed flows", () => {
installGatewayTestHooks();
installGatewayTestHooks({ scope: "suite" });
test("lists conversations, reads messages, and waits for events", async () => {
const storePath = await createSessionStoreFile();

View File

@ -23,11 +23,13 @@ function createFakeServer(): FakeServer {
}
async function expectTaskPending(task: Promise<unknown>) {
const early = await Promise.race([
task.then(() => "resolved"),
new Promise<"pending">((resolve) => setTimeout(() => resolve("pending"), 25)),
]);
expect(early).toBe("pending");
let settled = false;
void task.finally(() => {
settled = true;
});
await Promise.resolve();
await Promise.resolve();
expect(settled).toBe(false);
}
describe("plugin-sdk channel lifecycle helpers", () => {

View File

@ -11,11 +11,17 @@ import {
withSessionStoreLockForTest,
} from "../config/sessions/store.js";
import { resetFileLockStateForTest } from "../infra/file-lock.js";
import { cleanupSessionStateForTest } from "./session-state-cleanup.js";
import {
cleanupSessionStateForTest,
resetSessionStateCleanupRuntimeForTests,
setSessionStateCleanupRuntimeForTests,
} from "./session-state-cleanup.js";
const acquireSessionWriteLockMock = vi.hoisted(() =>
vi.fn(async () => ({ release: vi.fn(async () => {}) })),
);
const drainFileLockStateMock = vi.hoisted(() => vi.fn(async () => undefined));
const drainSessionWriteLockStateMock = vi.hoisted(() => vi.fn(async () => undefined));
function createDeferred<T>() {
let resolve!: (value: T | PromiseLike<T>) => void;
@ -27,6 +33,12 @@ function createDeferred<T>() {
return { promise, resolve, reject };
}
async function flushMicrotasks(rounds = 3): Promise<void> {
for (let index = 0; index < rounds; index += 1) {
await Promise.resolve();
}
}
describe("cleanupSessionStateForTest", () => {
beforeEach(() => {
vi.useRealTimers();
@ -34,7 +46,13 @@ describe("cleanupSessionStateForTest", () => {
resetFileLockStateForTest();
resetSessionWriteLockStateForTest();
acquireSessionWriteLockMock.mockClear();
drainFileLockStateMock.mockClear();
drainSessionWriteLockStateMock.mockClear();
setSessionWriteLockAcquirerForTests(acquireSessionWriteLockMock);
setSessionStateCleanupRuntimeForTests({
drainFileLockStateForTest: drainFileLockStateMock,
drainSessionWriteLockStateForTest: drainSessionWriteLockStateMock,
});
});
afterEach(() => {
@ -43,6 +61,7 @@ describe("cleanupSessionStateForTest", () => {
resetFileLockStateForTest();
resetSessionWriteLockStateForTest();
resetSessionStoreLockRuntimeForTests();
resetSessionStateCleanupRuntimeForTests();
vi.restoreAllMocks();
});
@ -66,14 +85,18 @@ describe("cleanupSessionStateForTest", () => {
settled = true;
});
await new Promise((resolve) => setTimeout(resolve, 25));
await flushMicrotasks();
expect(settled).toBe(false);
expect(drainFileLockStateMock).not.toHaveBeenCalled();
expect(drainSessionWriteLockStateMock).not.toHaveBeenCalled();
release.resolve();
await running;
await cleanupPromise;
expect(getSessionStoreLockQueueSizeForTest()).toBe(0);
expect(drainFileLockStateMock).toHaveBeenCalledTimes(1);
expect(drainSessionWriteLockStateMock).toHaveBeenCalledTimes(1);
} finally {
release.resolve();
await running?.catch(() => undefined);

View File

@ -5,9 +5,29 @@ import {
} from "../config/sessions/store.js";
import { drainFileLockStateForTest } from "../infra/file-lock.js";
let fileLockDrainerForTests: typeof drainFileLockStateForTest | null = null;
let sessionWriteLockDrainerForTests: typeof drainSessionWriteLockStateForTest | null = null;
export function setSessionStateCleanupRuntimeForTests(params: {
drainFileLockStateForTest?: typeof drainFileLockStateForTest | null;
drainSessionWriteLockStateForTest?: typeof drainSessionWriteLockStateForTest | null;
}): void {
if ("drainFileLockStateForTest" in params) {
fileLockDrainerForTests = params.drainFileLockStateForTest ?? null;
}
if ("drainSessionWriteLockStateForTest" in params) {
sessionWriteLockDrainerForTests = params.drainSessionWriteLockStateForTest ?? null;
}
}
export function resetSessionStateCleanupRuntimeForTests(): void {
fileLockDrainerForTests = null;
sessionWriteLockDrainerForTests = null;
}
export async function cleanupSessionStateForTest(): Promise<void> {
await drainSessionStoreLockQueuesForTest();
clearSessionStoreCacheForTest();
await drainFileLockStateForTest();
await drainSessionWriteLockStateForTest();
await (fileLockDrainerForTests ?? drainFileLockStateForTest)();
await (sessionWriteLockDrainerForTests ?? drainSessionWriteLockStateForTest)();
}