diff --git a/src/cron/service.issue-regressions.test.ts b/src/cron/service.issue-regressions.test.ts index fdc097f6c..28891765c 100644 --- a/src/cron/service.issue-regressions.test.ts +++ b/src/cron/service.issue-regressions.test.ts @@ -115,7 +115,7 @@ function createIsolatedRegressionJob(params: { } async function writeCronJobs(storePath: string, jobs: CronJob[]) { - await fs.writeFile(storePath, JSON.stringify({ version: 1, jobs }, null, 2), "utf-8"); + await fs.writeFile(storePath, JSON.stringify({ version: 1, jobs }), "utf-8"); } async function startCronForStore(params: { @@ -665,7 +665,7 @@ describe("Cron issue regressions", () => { if (targetJob?.delivery?.channel === "telegram") { targetJob.delivery.to = rewrittenTarget; } - await fs.writeFile(store.storePath, JSON.stringify(persisted, null, 2), "utf-8"); + await fs.writeFile(store.storePath, JSON.stringify(persisted), "utf-8"); return { status: "ok" as const, summary: "done", delivered: true }; }); @@ -736,11 +736,7 @@ describe("Cron issue regressions", () => { ]; for (const { id, state } of terminalStates) { const job: CronJob = { id, ...baseJob, state }; - await fs.writeFile( - store.storePath, - JSON.stringify({ version: 1, jobs: [job] }, null, 2), - "utf-8", - ); + await fs.writeFile(store.storePath, JSON.stringify({ version: 1, jobs: [job] }), "utf-8"); const enqueueSystemEvent = vi.fn(); const cron = await startCronForStore({ storePath: store.storePath, @@ -1410,7 +1406,7 @@ describe("Cron issue regressions", () => { const second = createDueIsolatedJob({ id: "batch-second", nowMs: dueAt, nextRunAtMs: dueAt }); await fs.writeFile( store.storePath, - JSON.stringify({ version: 1, jobs: [first, second] }, null, 2), + JSON.stringify({ version: 1, jobs: [first, second] }), "utf-8", ); @@ -1460,7 +1456,7 @@ describe("Cron issue regressions", () => { }); await fs.writeFile( store.storePath, - JSON.stringify({ version: 1, jobs: [first, second] }, null, 2), + JSON.stringify({ version: 1, jobs: [first, second] }), "utf-8", ); @@ -1524,9 +1520,9 @@ describe("Cron issue regressions", () => { const store = await makeStorePath(); const scheduledAt = Date.parse("2026-02-15T13:00:00.000Z"); - // Use a short but observable timeout: 300 ms. - // Before the fix, premature timeout would fire at ~100 ms (1/3 of 300 ms). - const timeoutSeconds = 0.3; + // Keep this short for suite speed while still separating expected timeout + // from the 1/3-regression timeout. + const timeoutSeconds = 0.16; const cronJob = createIsolatedRegressionJob({ id: "timeout-fraction-29774", name: "timeout fraction regression", @@ -1537,10 +1533,10 @@ describe("Cron issue regressions", () => { }); await writeCronJobs(store.storePath, [cronJob]); - const tempFile = path.join(os.tmpdir(), `cron-29774-${Date.now()}.txt`); let now = scheduledAt; const wallStart = Date.now(); let abortWallMs: number | undefined; + let started = false; const state = createCronServiceState({ cronEnabled: true, @@ -1550,8 +1546,7 @@ describe("Cron issue regressions", () => { enqueueSystemEvent: vi.fn(), requestHeartbeatNow: vi.fn(), runIsolatedAgentJob: vi.fn(async ({ abortSignal }: { abortSignal?: AbortSignal }) => { - // Real side effect: confirm the job actually started. - await fs.writeFile(tempFile, "started", "utf-8"); + started = true; await new Promise((resolve) => { if (!abortSignal) { resolve(); @@ -1578,15 +1573,12 @@ describe("Cron issue regressions", () => { await onTimer(state); - // Confirm job started (real side effect). - await expect(fs.readFile(tempFile, "utf-8")).resolves.toBe("started"); - await fs.unlink(tempFile).catch(() => {}); + expect(started).toBe(true); - // The outer cron timeout fires at timeoutSeconds * 1000 = 300 ms. - // The abort must not have fired at ~100 ms (the 1/3 regression value). - // Allow generous lower bound (80%) to keep the test stable on loaded CI runners. + // The abort must not fire at the old ~1/3 regression value. + // Keep the lower bound conservative for loaded CI runners. const elapsedMs = (abortWallMs ?? Date.now()) - wallStart; - expect(elapsedMs).toBeGreaterThanOrEqual(timeoutSeconds * 1000 * 0.8); + expect(elapsedMs).toBeGreaterThanOrEqual(timeoutSeconds * 1000 * 0.7); const job = state.store?.jobs.find((entry) => entry.id === "timeout-fraction-29774"); expect(job?.state.lastStatus).toBe("error"); diff --git a/src/plugins/loader.test.ts b/src/plugins/loader.test.ts index 1802f33ab..3c2c69218 100644 --- a/src/plugins/loader.test.ts +++ b/src/plugins/loader.test.ts @@ -234,21 +234,6 @@ describe("loadOpenClawPlugins", () => { const bundled = registry.plugins.find((entry) => entry.id === "bundled"); expect(bundled?.status).toBe("disabled"); - - const enabledRegistry = loadOpenClawPlugins({ - cache: false, - config: { - plugins: { - allow: ["bundled"], - entries: { - bundled: { enabled: true }, - }, - }, - }, - }); - - const enabled = enabledRegistry.plugins.find((entry) => entry.id === "bundled"); - expect(enabled?.status).toBe("loaded"); }); it("loads bundled telegram plugin when enabled", () => { diff --git a/src/process/exec.test.ts b/src/process/exec.test.ts index f76d9137f..e985fb927 100644 --- a/src/process/exec.test.ts +++ b/src/process/exec.test.ts @@ -6,8 +6,8 @@ import { withEnvAsync } from "../test-utils/env.js"; import { attachChildProcessBridge } from "./child-process-bridge.js"; import { runCommandWithTimeout, shouldSpawnWithShell } from "./exec.js"; -const CHILD_READY_TIMEOUT_MS = 4_000; -const CHILD_EXIT_TIMEOUT_MS = 4_000; +const CHILD_READY_TIMEOUT_MS = 2_000; +const CHILD_EXIT_TIMEOUT_MS = 2_000; function waitForLine( stream: NodeJS.ReadableStream, @@ -79,10 +79,10 @@ describe("runCommandWithTimeout", () => { it("kills command when no output timeout elapses", async () => { const result = await runCommandWithTimeout( - [process.execPath, "-e", "setTimeout(() => {}, 40)"], + [process.execPath, "-e", "setTimeout(() => {}, 80)"], { timeoutMs: 500, - noOutputTimeoutMs: 20, + noOutputTimeoutMs: 25, }, ); @@ -101,24 +101,24 @@ describe("runCommandWithTimeout", () => { "let count = 0;", 'const ticker = setInterval(() => { process.stdout.write(".");', "count += 1;", - "if (count === 6) {", + "if (count === 3) {", "clearInterval(ticker);", "process.exit(0);", "}", - "}, 25);", + "}, 15);", ].join(" "), ], { timeoutMs: 3_000, - // Keep a healthy margin above the emit interval while avoiding a 1s+ test delay. - noOutputTimeoutMs: 400, + // Keep a healthy margin above the emit interval while avoiding long idle waits. + noOutputTimeoutMs: 120, }, ); expect(result.code ?? 0).toBe(0); expect(result.termination).toBe("exit"); expect(result.noOutputTimedOut).toBe(false); - expect(result.stdout.length).toBeGreaterThanOrEqual(7); + expect(result.stdout.length).toBeGreaterThanOrEqual(4); }); it("reports global timeout termination when overall timeout elapses", async () => { diff --git a/src/process/supervisor/supervisor.test.ts b/src/process/supervisor/supervisor.test.ts index c0070d9a7..dd0a7ab80 100644 --- a/src/process/supervisor/supervisor.test.ts +++ b/src/process/supervisor/supervisor.test.ts @@ -4,7 +4,7 @@ import { createProcessSupervisor } from "./supervisor.js"; type ProcessSupervisor = ReturnType; type SpawnOptions = Parameters[0]; type ChildSpawnOptions = Omit, "backendId" | "mode">; -const OUTPUT_DELAY_MS = 40; +const OUTPUT_DELAY_MS = 15; async function spawnChild(supervisor: ProcessSupervisor, options: ChildSpawnOptions) { return supervisor.spawn({ @@ -38,9 +38,9 @@ describe("process supervisor", () => { const supervisor = createProcessSupervisor(); const run = await spawnChild(supervisor, { sessionId: "s1", - argv: [process.execPath, "-e", "setTimeout(() => {}, 40)"], + argv: [process.execPath, "-e", "setTimeout(() => {}, 30)"], timeoutMs: 500, - noOutputTimeoutMs: 20, + noOutputTimeoutMs: 12, stdinMode: "pipe-closed", }); const exit = await run.wait(); @@ -84,7 +84,7 @@ describe("process supervisor", () => { const supervisor = createProcessSupervisor(); const run = await spawnChild(supervisor, { sessionId: "s-timeout", - argv: [process.execPath, "-e", "setTimeout(() => {}, 40)"], + argv: [process.execPath, "-e", "setTimeout(() => {}, 20)"], timeoutMs: 1, stdinMode: "pipe-closed", });