import { spawnSync } from "node:child_process"; import { readdirSync, mkdtempSync, rmSync } from "node:fs"; import { tmpdir } from "node:os"; import path from "node:path"; import { afterEach, describe, expect, it } from "vitest"; import { testing } from "../../scripts/check-cli-startup-memory.mjs"; const tempRoots: string[] = []; function makeTempRoot(): string { const root = mkdtempSync(path.join(tmpdir(), "openclaw-startup-memory-test-")); tempRoots.push(root); return root; } afterEach(() => { for (const root of tempRoots.splice(0)) { rmSync(root, { recursive: true, force: true }); } }); describe("check-cli-startup-memory", () => { it("keeps the Linux help startup budget tight while allowing macOS RSS overhead", () => { expect(testing.resolveDefaultLimitsMb("linux").help).toBe(100); expect(testing.resolveDefaultLimitsMb("darwin").help).toBeGreaterThan(100); }); it("does not create a temp home before argument validation succeeds", () => { if (process.platform !== "darwin" && process.platform !== "linux") { return; } const tempRoot = makeTempRoot(); const result = spawnSync(process.execPath, ["scripts/check-cli-startup-memory.mjs", "--json"], { cwd: path.resolve(__dirname, "..", ".."), encoding: "utf8", env: { ...process.env, TMPDIR: tempRoot, TEMP: tempRoot, TMP: tempRoot, }, }); expect(result.status).not.toBe(0); expect(readdirSync(tempRoot)).toEqual([]); }); it("times out startup probes instead of hanging indefinitely", () => { if (process.platform !== "darwin" && process.platform !== "linux") { return; } const tempRoot = makeTempRoot(); const seenTimeouts: Array = []; const seenKillSignals: Array = []; const timeoutError = Object.assign(new Error("spawnSync timed out"), { code: "ETIMEDOUT" }); expect(() => testing.runStartupMemoryCheck( [ "--json", path.join(tempRoot, "startup-memory.json"), "--summary", path.join(tempRoot, "summary.md"), ], { platform: "linux", timeoutMs: 1234, spawnSync: ( _command: string, _args: string[], options: { killSignal?: string; timeout?: number }, ) => { seenTimeouts.push(options.timeout); seenKillSignals.push(options.killSignal); return { error: timeoutError, signal: "SIGKILL", status: null, stderr: "", stdout: "", }; }, }, ), ).toThrow("--help timed out after 1234ms"); expect(seenTimeouts).toEqual([1234, 1234, 1234]); expect(seenKillSignals).toEqual(["SIGKILL", "SIGKILL", "SIGKILL"]); }); });