test: speed up long-running async suites

This commit is contained in:
Peter Steinberger
2026-02-23 05:03:15 +00:00
parent 48f327c206
commit 610863e733
2 changed files with 30 additions and 29 deletions

View File

@@ -8,11 +8,11 @@ import { createExecTool } from "./bash-tools.exec.js";
import { killProcessTree } from "./shell-utils.js"; import { killProcessTree } from "./shell-utils.js";
const BACKGROUND_HOLD_CMD = 'node -e "setTimeout(() => {}, 5000)"'; const BACKGROUND_HOLD_CMD = 'node -e "setTimeout(() => {}, 5000)"';
const ABORT_SETTLE_MS = process.platform === "win32" ? 200 : 40; const ABORT_SETTLE_MS = process.platform === "win32" ? 200 : 25;
const ABORT_WAIT_TIMEOUT_MS = process.platform === "win32" ? 1_500 : 240; const ABORT_WAIT_TIMEOUT_MS = process.platform === "win32" ? 1_500 : 240;
const POLL_INTERVAL_MS = 15; const POLL_INTERVAL_MS = 15;
const FINISHED_WAIT_TIMEOUT_MS = process.platform === "win32" ? 8_000 : 600; const FINISHED_WAIT_TIMEOUT_MS = process.platform === "win32" ? 8_000 : 600;
const BACKGROUND_TIMEOUT_SEC = process.platform === "win32" ? 0.2 : 0.08; const BACKGROUND_TIMEOUT_SEC = process.platform === "win32" ? 0.2 : 0.05;
const TEST_EXEC_DEFAULTS = { const TEST_EXEC_DEFAULTS = {
security: "full" as const, security: "full" as const,
ask: "off" as const, ask: "off" as const,
@@ -151,7 +151,7 @@ test("background exec without explicit timeout ignores default timeout", async (
const result = await tool.execute("toolcall", { command: BACKGROUND_HOLD_CMD, background: true }); const result = await tool.execute("toolcall", { command: BACKGROUND_HOLD_CMD, background: true });
expect(result.details.status).toBe("running"); expect(result.details.status).toBe("running");
const sessionId = (result.details as { sessionId: string }).sessionId; const sessionId = (result.details as { sessionId: string }).sessionId;
const waitMs = Math.max(ABORT_SETTLE_MS + 120, BACKGROUND_TIMEOUT_SEC * 1000 + 120); const waitMs = Math.max(ABORT_SETTLE_MS + 80, BACKGROUND_TIMEOUT_SEC * 1000 + 80);
const startedAt = Date.now(); const startedAt = Date.now();
await expect await expect

View File

@@ -10,6 +10,12 @@ import {
} from "./openclaw-tools.subagents.sessions-spawn.test-harness.js"; } from "./openclaw-tools.subagents.sessions-spawn.test-harness.js";
import { resetSubagentRegistryForTests } from "./subagent-registry.js"; import { resetSubagentRegistryForTests } from "./subagent-registry.js";
const fastModeEnv = vi.hoisted(() => {
const previous = process.env.OPENCLAW_TEST_FAST;
process.env.OPENCLAW_TEST_FAST = "1";
return { previous };
});
vi.mock("./pi-embedded.js", () => ({ vi.mock("./pi-embedded.js", () => ({
isEmbeddedPiRunActive: () => false, isEmbeddedPiRunActive: () => false,
isEmbeddedPiRunStreaming: () => false, isEmbeddedPiRunStreaming: () => false,
@@ -17,6 +23,10 @@ vi.mock("./pi-embedded.js", () => ({
waitForEmbeddedPiRunEnd: async () => true, waitForEmbeddedPiRunEnd: async () => true,
})); }));
vi.mock("./tools/agent-step.js", () => ({
readLatestAssistantReply: async () => "done",
}));
const callGatewayMock = getCallGatewayMock(); const callGatewayMock = getCallGatewayMock();
const RUN_TIMEOUT_SECONDS = 1; const RUN_TIMEOUT_SECONDS = 1;
@@ -93,13 +103,7 @@ async function emitLifecycleEndAndFlush(params: {
} }
describe("openclaw-tools: subagents (sessions_spawn lifecycle)", () => { describe("openclaw-tools: subagents (sessions_spawn lifecycle)", () => {
let previousFastTestEnv: string | undefined;
beforeEach(() => { beforeEach(() => {
if (previousFastTestEnv === undefined) {
previousFastTestEnv = process.env.OPENCLAW_TEST_FAST;
}
vi.stubEnv("OPENCLAW_TEST_FAST", "1");
resetSessionsSpawnConfigOverride(); resetSessionsSpawnConfigOverride();
setSessionsSpawnConfigOverride({ setSessionsSpawnConfigOverride({
session: { session: {
@@ -117,11 +121,11 @@ describe("openclaw-tools: subagents (sessions_spawn lifecycle)", () => {
}); });
afterAll(() => { afterAll(() => {
if (previousFastTestEnv === undefined) { if (fastModeEnv.previous === undefined) {
delete process.env.OPENCLAW_TEST_FAST; delete process.env.OPENCLAW_TEST_FAST;
return; return;
} }
process.env.OPENCLAW_TEST_FAST = previousFastTestEnv; process.env.OPENCLAW_TEST_FAST = fastModeEnv.previous;
}); });
it("sessions_spawn runs cleanup flow after subagent completion", async () => { it("sessions_spawn runs cleanup flow after subagent completion", async () => {
@@ -151,19 +155,12 @@ describe("openclaw-tools: subagents (sessions_spawn lifecycle)", () => {
if (!child.runId) { if (!child.runId) {
throw new Error("missing child runId"); throw new Error("missing child runId");
} }
emitAgentEvent({ await waitFor(
runId: child.runId, () =>
stream: "lifecycle", ctx.waitCalls.some((call) => call.runId === child.runId) &&
data: { patchCalls.some((call) => call.label === "my-task") &&
phase: "end", ctx.calls.filter((call) => call.method === "agent").length >= 2,
startedAt: 1000, );
endedAt: 2000,
},
});
await waitFor(() => ctx.waitCalls.some((call) => call.runId === child.runId));
await waitFor(() => patchCalls.some((call) => call.label === "my-task"));
await waitFor(() => ctx.calls.filter((c) => c.method === "agent").length >= 2);
const childWait = ctx.waitCalls.find((call) => call.runId === child.runId); const childWait = ctx.waitCalls.find((call) => call.runId === child.runId);
expect(childWait?.timeoutMs).toBe(1000); expect(childWait?.timeoutMs).toBe(1000);
@@ -216,8 +213,9 @@ describe("openclaw-tools: subagents (sessions_spawn lifecycle)", () => {
endedAt: 2345, endedAt: 2345,
}); });
await waitFor(() => ctx.calls.filter((call) => call.method === "agent").length >= 2); await waitFor(
await waitFor(() => Boolean(deletedKey)); () => ctx.calls.filter((call) => call.method === "agent").length >= 2 && Boolean(deletedKey),
);
const childWait = ctx.waitCalls.find((call) => call.runId === child.runId); const childWait = ctx.waitCalls.find((call) => call.runId === child.runId);
expect(childWait?.timeoutMs).toBe(1000); expect(childWait?.timeoutMs).toBe(1000);
@@ -277,9 +275,12 @@ describe("openclaw-tools: subagents (sessions_spawn lifecycle)", () => {
if (!child.runId) { if (!child.runId) {
throw new Error("missing child runId"); throw new Error("missing child runId");
} }
await waitFor(() => ctx.waitCalls.some((call) => call.runId === child.runId)); await waitFor(
await waitFor(() => ctx.calls.filter((call) => call.method === "agent").length >= 2); () =>
await waitFor(() => Boolean(deletedKey)); ctx.waitCalls.some((call) => call.runId === child.runId) &&
ctx.calls.filter((call) => call.method === "agent").length >= 2 &&
Boolean(deletedKey),
);
const childWait = ctx.waitCalls.find((call) => call.runId === child.runId); const childWait = ctx.waitCalls.find((call) => call.runId === child.runId);
expect(childWait?.timeoutMs).toBe(1000); expect(childWait?.timeoutMs).toBe(1000);