Some checks failed
ClawSweeper Dispatch / dispatch (push) Has been cancelled
CodeQL / Security High (actions) (push) Has been cancelled
CodeQL / Security High (channel-runtime-boundary) (push) Has been cancelled
CodeQL / Security High (core-auth-secrets) (push) Has been cancelled
CodeQL / Security High (mcp-process-tool-boundary) (push) Has been cancelled
CodeQL / Security High (network-ssrf-boundary) (push) Has been cancelled
CodeQL / Security High (plugin-trust-boundary) (push) Has been cancelled
CodeQL / Security High (process-exec-boundary) (push) Has been cancelled
Docs Sync Publish Repo / sync-publish-repo (push) Has been cancelled
Docs / docs (push) Has been cancelled
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Has been cancelled
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Has been cancelled
Workflow Sanity / no-tabs (push) Has been cancelled
Workflow Sanity / actionlint (push) Has been cancelled
Workflow Sanity / generated-doc-baselines (push) Has been cancelled
CI / runner-admission (push) Has been cancelled
CI / preflight (push) Has been cancelled
CI / security-fast (push) Has been cancelled
CI / pnpm-store-warmup (push) Has been cancelled
CI / build-artifacts (push) Has been cancelled
CI / native-i18n (push) Has been cancelled
CI / ${{ matrix.check_name }} (push) Has been cancelled
CI / ${{ matrix.checkName }} (push) Has been cancelled
CI / checks-node-compat-node22 (push) Has been cancelled
CI / check-bundled-channel-config-metadata (push) Has been cancelled
CI / check-dependencies (push) Has been cancelled
CI / check-guards (push) Has been cancelled
CI / check-lint (push) Has been cancelled
CI / check-prod-types (push) Has been cancelled
CI / check-shrinkwrap (push) Has been cancelled
CI / check-test-types (push) Has been cancelled
CI / check-additional-boundaries-a (push) Has been cancelled
CI / check-additional-boundaries-bcd (push) Has been cancelled
CI / check-additional-extension-bundled (push) Has been cancelled
CI / check-additional-extension-channels (push) Has been cancelled
CI / check-additional-extension-package-boundary (push) Has been cancelled
CI / check-additional-runtime-topology-architecture (push) Has been cancelled
CI / check-session-accessor-boundary (push) Has been cancelled
CI / check-session-transcript-reader-boundary (push) Has been cancelled
CI / check-docs (push) Has been cancelled
CI / skills-python (push) Has been cancelled
CI / macos-swift (push) Has been cancelled
CI / ios-build (push) Has been cancelled
CI / ci-timings-summary (push) Has been cancelled
Native App Locale Refresh / Refresh native fa (push) Has been cancelled
Native App Locale Refresh / Refresh native fr (push) Has been cancelled
Native App Locale Refresh / Refresh native hi (push) Has been cancelled
Native App Locale Refresh / Refresh native id (push) Has been cancelled
Native App Locale Refresh / Refresh native it (push) Has been cancelled
Native App Locale Refresh / Refresh native ja-JP (push) Has been cancelled
Control UI Locale Refresh / plan (push) Has been cancelled
Control UI Locale Refresh / Refresh ${{ matrix.locale }} (push) Has been cancelled
Control UI Locale Refresh / Commit control UI locale refresh (push) Has been cancelled
Live Media Runner Image / Build live media runner image (push) Has been cancelled
Native App Locale Refresh / Refresh native ar (push) Has been cancelled
Native App Locale Refresh / Refresh native de (push) Has been cancelled
Native App Locale Refresh / Refresh native es (push) Has been cancelled
Native App Locale Refresh / Refresh native ko (push) Has been cancelled
Native App Locale Refresh / Refresh native nl (push) Has been cancelled
Native App Locale Refresh / Refresh native pl (push) Has been cancelled
Native App Locale Refresh / Refresh native pt-BR (push) Has been cancelled
Native App Locale Refresh / Refresh native ru (push) Has been cancelled
Native App Locale Refresh / Refresh native sv (push) Has been cancelled
Native App Locale Refresh / Refresh native th (push) Has been cancelled
Native App Locale Refresh / Refresh native tr (push) Has been cancelled
Native App Locale Refresh / Refresh native uk (push) Has been cancelled
Native App Locale Refresh / Refresh native vi (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-CN (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-TW (push) Has been cancelled
Native App Locale Refresh / Commit native locale refresh (push) Has been cancelled
Plugin Init Scaffold Validation / Validate provider scaffold (push) Has been cancelled
Plugin NPM Release / preview_plugins_npm (push) Has been cancelled
Plugin NPM Release / Validate release publish approval (push) Has been cancelled
Plugin NPM Release / preview_plugin_pack (push) Has been cancelled
Plugin NPM Release / publish_plugins_npm (push) Has been cancelled
Sandbox Common Smoke / sandbox-common-smoke (push) Has been cancelled
Website Installer Sync / static (push) Has been cancelled
Website Installer Sync / linux-docker (push) Has been cancelled
Website Installer Sync / macos-installer (push) Has been cancelled
Website Installer Sync / windows-installer (push) Has been cancelled
Website Installer Sync / sync-website (push) Has been cancelled
Adolf is a fork/vendored clone of github.com/openclaw/openclaw (v2026.6.11), free to diverge. Tree copied sans upstream .git; upstream remote added for future syncs. Node pinned to 24 (.nvmrc); engines already require >=22.19. Preserves docs/ARCHITECTURE.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LeqyaxJF2nbRXJtae2kNB2
450 lines
14 KiB
TypeScript
450 lines
14 KiB
TypeScript
// Local Heavy Check Runtime tests cover local heavy check runtime script behavior.
|
|
import { execFileSync } from "node:child_process";
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import { describe, expect, it } from "vitest";
|
|
import {
|
|
acquireLocalHeavyCheckLockSync,
|
|
applyLocalOxlintPolicy,
|
|
applyLocalTsgoPolicy,
|
|
resolveLocalHeavyCheckEnv,
|
|
shouldAcquireLocalHeavyCheckLockForOxlint,
|
|
shouldAcquireLocalHeavyCheckLockForTsgo,
|
|
} from "../../scripts/lib/local-heavy-check-runtime.mjs";
|
|
import { createScriptTestHarness } from "./test-helpers.js";
|
|
|
|
const { createTempDir } = createScriptTestHarness();
|
|
const GIB = 1024 ** 3;
|
|
const CONSTRAINED_HOST = {
|
|
totalMemoryBytes: 16 * GIB,
|
|
logicalCpuCount: 8,
|
|
};
|
|
const ROOMY_HOST = {
|
|
totalMemoryBytes: 128 * GIB,
|
|
logicalCpuCount: 16,
|
|
};
|
|
|
|
function makeEnv(overrides: Record<string, string | undefined> = {}) {
|
|
const env = {
|
|
...process.env,
|
|
OPENCLAW_LOCAL_CHECK: "1",
|
|
...overrides,
|
|
};
|
|
if (!Object.hasOwn(overrides, "OPENCLAW_LOCAL_CHECK_MODE")) {
|
|
delete env.OPENCLAW_LOCAL_CHECK_MODE;
|
|
}
|
|
return env;
|
|
}
|
|
|
|
describe("local-heavy-check-runtime", () => {
|
|
it("reenables local heavy-check policy for local wrapper entrypoints", () => {
|
|
expect(resolveLocalHeavyCheckEnv({ OPENCLAW_LOCAL_CHECK: "0", PATH: "/usr/bin" })).toEqual({
|
|
OPENCLAW_LOCAL_CHECK: "1",
|
|
PATH: "/usr/bin",
|
|
});
|
|
expect(resolveLocalHeavyCheckEnv({ OPENCLAW_LOCAL_CHECK: "false", PATH: "/usr/bin" })).toEqual({
|
|
OPENCLAW_LOCAL_CHECK: "1",
|
|
PATH: "/usr/bin",
|
|
});
|
|
});
|
|
|
|
it("preserves local-check disablement in CI", () => {
|
|
expect(
|
|
resolveLocalHeavyCheckEnv({
|
|
CI: "true",
|
|
OPENCLAW_LOCAL_CHECK: "0",
|
|
PATH: "/usr/bin",
|
|
}),
|
|
).toEqual({
|
|
CI: "true",
|
|
OPENCLAW_LOCAL_CHECK: "0",
|
|
PATH: "/usr/bin",
|
|
});
|
|
});
|
|
|
|
it("tightens local tsgo runs on constrained hosts", () => {
|
|
const { args, env } = applyLocalTsgoPolicy([], makeEnv(), CONSTRAINED_HOST);
|
|
|
|
expect(args).toEqual([
|
|
"--declaration",
|
|
"false",
|
|
"--incremental",
|
|
"--tsBuildInfoFile",
|
|
".artifacts/tsgo-cache/root.tsbuildinfo",
|
|
"--singleThreaded",
|
|
"--checkers",
|
|
"1",
|
|
]);
|
|
expect(env.GOGC).toBe("30");
|
|
expect(env.GOMEMLIMIT).toBe("3GiB");
|
|
});
|
|
|
|
it("skips declaration transforms for no-emit tsgo checks", () => {
|
|
const { args } = applyLocalTsgoPolicy([], makeEnv({ OPENCLAW_LOCAL_CHECK: "0" }), ROOMY_HOST);
|
|
|
|
expect(args).toEqual(["--declaration", "false"]);
|
|
});
|
|
|
|
it("keeps explicit tsgo flags and Go env overrides intact when throttled", () => {
|
|
const { args, env } = applyLocalTsgoPolicy(
|
|
["--checkers", "4", "--singleThreaded", "--pprofDir", "/tmp/existing"],
|
|
makeEnv({
|
|
GOGC: "80",
|
|
GOMEMLIMIT: "5GiB",
|
|
OPENCLAW_TSGO_PPROF_DIR: "/tmp/profile",
|
|
}),
|
|
CONSTRAINED_HOST,
|
|
);
|
|
|
|
expect(args).toEqual([
|
|
"--checkers",
|
|
"4",
|
|
"--singleThreaded",
|
|
"--pprofDir",
|
|
"/tmp/existing",
|
|
"--declaration",
|
|
"false",
|
|
]);
|
|
expect(env.GOGC).toBe("80");
|
|
expect(env.GOMEMLIMIT).toBe("5GiB");
|
|
});
|
|
|
|
it("keeps explicit tsgo declaration flags intact", () => {
|
|
const env = makeEnv({ OPENCLAW_LOCAL_CHECK_MODE: "full" });
|
|
const longFlag = applyLocalTsgoPolicy(["--declaration"], env, ROOMY_HOST);
|
|
const shortFlag = applyLocalTsgoPolicy(["-d"], env, ROOMY_HOST);
|
|
|
|
expect(longFlag.args).toEqual(["--declaration"]);
|
|
expect(shortFlag.args).toEqual(["-d"]);
|
|
});
|
|
|
|
it("defaults local tsgo to full-speed mode on roomy hosts", () => {
|
|
const { args, env } = applyLocalTsgoPolicy([], makeEnv(), ROOMY_HOST);
|
|
|
|
expect(args).toEqual([
|
|
"--declaration",
|
|
"false",
|
|
"--incremental",
|
|
"--tsBuildInfoFile",
|
|
".artifacts/tsgo-cache/root.tsbuildinfo",
|
|
]);
|
|
expect(env.GOGC).toBeUndefined();
|
|
expect(env.GOMEMLIMIT).toBeUndefined();
|
|
});
|
|
|
|
it("uses the configured local tsgo build info file", () => {
|
|
const { args } = applyLocalTsgoPolicy(
|
|
[],
|
|
makeEnv({
|
|
OPENCLAW_LOCAL_CHECK_MODE: "full",
|
|
OPENCLAW_TSGO_BUILD_INFO_FILE: ".artifacts/custom/tsgo.tsbuildinfo",
|
|
}),
|
|
ROOMY_HOST,
|
|
);
|
|
|
|
expect(args).toEqual([
|
|
"--declaration",
|
|
"false",
|
|
"--incremental",
|
|
"--tsBuildInfoFile",
|
|
".artifacts/custom/tsgo.tsbuildinfo",
|
|
]);
|
|
});
|
|
|
|
it("avoids incremental cache reuse for ad hoc tsgo runs", () => {
|
|
const { args } = applyLocalTsgoPolicy(
|
|
["--extendedDiagnostics"],
|
|
makeEnv({ OPENCLAW_LOCAL_CHECK_MODE: "full" }),
|
|
ROOMY_HOST,
|
|
);
|
|
|
|
expect(args).toEqual(["--extendedDiagnostics", "--declaration", "false"]);
|
|
});
|
|
|
|
it("allows forcing the throttled tsgo policy on roomy hosts", () => {
|
|
const { args, env } = applyLocalTsgoPolicy(
|
|
[],
|
|
makeEnv({
|
|
OPENCLAW_LOCAL_CHECK_MODE: "throttled",
|
|
}),
|
|
ROOMY_HOST,
|
|
);
|
|
|
|
expect(args).toEqual([
|
|
"--declaration",
|
|
"false",
|
|
"--incremental",
|
|
"--tsBuildInfoFile",
|
|
".artifacts/tsgo-cache/root.tsbuildinfo",
|
|
"--singleThreaded",
|
|
"--checkers",
|
|
"1",
|
|
]);
|
|
expect(env.GOGC).toBe("30");
|
|
expect(env.GOMEMLIMIT).toBe("3GiB");
|
|
});
|
|
|
|
it("allows forcing full-speed tsgo runs on roomy hosts", () => {
|
|
const { args, env } = applyLocalTsgoPolicy(
|
|
[],
|
|
makeEnv({
|
|
OPENCLAW_LOCAL_CHECK_MODE: "full",
|
|
}),
|
|
ROOMY_HOST,
|
|
);
|
|
|
|
expect(args).toEqual([
|
|
"--declaration",
|
|
"false",
|
|
"--incremental",
|
|
"--tsBuildInfoFile",
|
|
".artifacts/tsgo-cache/root.tsbuildinfo",
|
|
]);
|
|
expect(env.GOGC).toBeUndefined();
|
|
expect(env.GOMEMLIMIT).toBeUndefined();
|
|
});
|
|
|
|
it("skips the heavy-check lock for tsgo metadata commands", () => {
|
|
expect(shouldAcquireLocalHeavyCheckLockForTsgo(["--help"])).toBe(false);
|
|
expect(shouldAcquireLocalHeavyCheckLockForTsgo(["-h"])).toBe(false);
|
|
expect(shouldAcquireLocalHeavyCheckLockForTsgo(["--version"])).toBe(false);
|
|
expect(shouldAcquireLocalHeavyCheckLockForTsgo(["-v"])).toBe(false);
|
|
expect(shouldAcquireLocalHeavyCheckLockForTsgo(["--init"])).toBe(false);
|
|
expect(shouldAcquireLocalHeavyCheckLockForTsgo(["--showConfig"])).toBe(false);
|
|
});
|
|
|
|
it("keeps the heavy-check lock for real tsgo runs", () => {
|
|
expect(shouldAcquireLocalHeavyCheckLockForTsgo([])).toBe(true);
|
|
expect(shouldAcquireLocalHeavyCheckLockForTsgo(["--extendedDiagnostics"])).toBe(true);
|
|
});
|
|
|
|
it("allows forcing the tsgo lock back on", () => {
|
|
expect(
|
|
shouldAcquireLocalHeavyCheckLockForTsgo(
|
|
["--help"],
|
|
makeEnv({ OPENCLAW_TSGO_FORCE_LOCK: "1" }),
|
|
),
|
|
).toBe(true);
|
|
});
|
|
|
|
it("serializes local oxlint runs onto one thread on constrained hosts", () => {
|
|
const { args, env } = applyLocalOxlintPolicy([], makeEnv(), CONSTRAINED_HOST);
|
|
|
|
expect(args).toEqual([
|
|
"--type-aware",
|
|
"--tsconfig",
|
|
"config/tsconfig/oxlint.json",
|
|
"--report-unused-disable-directives-severity",
|
|
"error",
|
|
"--threads=1",
|
|
]);
|
|
expect(env.GOGC).toBe("30");
|
|
expect(env.GOMEMLIMIT).toBe("3GiB");
|
|
});
|
|
|
|
it("defaults local oxlint to one thread on roomy hosts", () => {
|
|
const { args, env } = applyLocalOxlintPolicy([], makeEnv(), ROOMY_HOST);
|
|
|
|
expect(args).toEqual([
|
|
"--type-aware",
|
|
"--tsconfig",
|
|
"config/tsconfig/oxlint.json",
|
|
"--report-unused-disable-directives-severity",
|
|
"error",
|
|
"--threads=1",
|
|
]);
|
|
expect(env.GOGC).toBe("30");
|
|
expect(env.GOMEMLIMIT).toBe("3GiB");
|
|
});
|
|
|
|
it("honors an explicit oxlint thread count", () => {
|
|
const { args, env } = applyLocalOxlintPolicy(
|
|
["--threads=8"],
|
|
makeEnv({ GOGC: "80", GOMEMLIMIT: "5GiB" }),
|
|
ROOMY_HOST,
|
|
);
|
|
|
|
expect(args).toEqual([
|
|
"--threads=8",
|
|
"--type-aware",
|
|
"--tsconfig",
|
|
"config/tsconfig/oxlint.json",
|
|
"--report-unused-disable-directives-severity",
|
|
"error",
|
|
]);
|
|
expect(env.GOGC).toBe("80");
|
|
expect(env.GOMEMLIMIT).toBe("5GiB");
|
|
});
|
|
|
|
it("allows forcing full-speed oxlint runs on roomy hosts", () => {
|
|
const { args, env } = applyLocalOxlintPolicy(
|
|
[],
|
|
makeEnv({
|
|
OPENCLAW_LOCAL_CHECK_MODE: "full",
|
|
}),
|
|
ROOMY_HOST,
|
|
);
|
|
|
|
expect(args).toEqual([
|
|
"--type-aware",
|
|
"--tsconfig",
|
|
"config/tsconfig/oxlint.json",
|
|
"--report-unused-disable-directives-severity",
|
|
"error",
|
|
]);
|
|
expect(env.GOGC).toBeUndefined();
|
|
expect(env.GOMEMLIMIT).toBeUndefined();
|
|
});
|
|
|
|
it("skips the heavy-check lock for explicit oxlint file targets", () => {
|
|
const cwd = createTempDir("openclaw-oxlint-lock-skip-");
|
|
const target = path.join(cwd, "sample.ts");
|
|
fs.writeFileSync(target, "export const ok = true;\n", "utf8");
|
|
|
|
expect(
|
|
shouldAcquireLocalHeavyCheckLockForOxlint(["--type-aware", "--", "sample.ts"], { cwd }),
|
|
).toBe(false);
|
|
});
|
|
|
|
it("skips the heavy-check lock for oxlint metadata commands", () => {
|
|
expect(shouldAcquireLocalHeavyCheckLockForOxlint(["--help"])).toBe(false);
|
|
expect(shouldAcquireLocalHeavyCheckLockForOxlint(["-h"])).toBe(false);
|
|
expect(shouldAcquireLocalHeavyCheckLockForOxlint(["--version"])).toBe(false);
|
|
expect(shouldAcquireLocalHeavyCheckLockForOxlint(["-V"])).toBe(false);
|
|
expect(shouldAcquireLocalHeavyCheckLockForOxlint(["--rules"])).toBe(false);
|
|
expect(shouldAcquireLocalHeavyCheckLockForOxlint(["--print-config"])).toBe(false);
|
|
expect(shouldAcquireLocalHeavyCheckLockForOxlint(["--init"])).toBe(false);
|
|
});
|
|
|
|
it("keeps the heavy-check lock for directory targets and broad oxlint runs", () => {
|
|
const cwd = createTempDir("openclaw-oxlint-lock-keep-");
|
|
fs.mkdirSync(path.join(cwd, "src"), { recursive: true });
|
|
fs.writeFileSync(path.join(cwd, "src", "sample.ts"), "export const ok = true;\n", "utf8");
|
|
|
|
expect(shouldAcquireLocalHeavyCheckLockForOxlint(["--type-aware", "--", "src"], { cwd })).toBe(
|
|
true,
|
|
);
|
|
expect(shouldAcquireLocalHeavyCheckLockForOxlint(["--type-aware"], { cwd })).toBe(true);
|
|
});
|
|
|
|
it("allows forcing the oxlint lock back on", () => {
|
|
const cwd = createTempDir("openclaw-oxlint-lock-force-");
|
|
fs.writeFileSync(path.join(cwd, "sample.ts"), "export const ok = true;\n", "utf8");
|
|
|
|
expect(
|
|
shouldAcquireLocalHeavyCheckLockForOxlint(["--type-aware", "--", "sample.ts"], {
|
|
cwd,
|
|
env: makeEnv({ OPENCLAW_OXLINT_FORCE_LOCK: "1" }),
|
|
}),
|
|
).toBe(true);
|
|
});
|
|
|
|
it("reclaims stale local heavy-check locks from dead pids", () => {
|
|
const cwd = createTempDir("openclaw-local-heavy-check-");
|
|
const commonDir = path.join(cwd, ".git");
|
|
const lockDir = path.join(commonDir, "openclaw-local-checks", "heavy-check.lock");
|
|
fs.mkdirSync(lockDir, { recursive: true });
|
|
fs.writeFileSync(
|
|
path.join(lockDir, "owner.json"),
|
|
`${JSON.stringify({
|
|
pid: 999_999_999,
|
|
tool: "tsgo",
|
|
cwd,
|
|
})}\n`,
|
|
"utf8",
|
|
);
|
|
|
|
const release = acquireLocalHeavyCheckLockSync({
|
|
cwd,
|
|
env: makeEnv(),
|
|
toolName: "oxlint",
|
|
});
|
|
|
|
const owner = JSON.parse(fs.readFileSync(path.join(lockDir, "owner.json"), "utf8"));
|
|
expect(owner.pid).toBe(process.pid);
|
|
expect(owner.tool).toBe("oxlint");
|
|
|
|
release();
|
|
expect(fs.existsSync(lockDir)).toBe(false);
|
|
});
|
|
|
|
it("uses a worktree-local heavy-check lock when explicitly requested", () => {
|
|
const repoRoot = createTempDir("openclaw-local-heavy-check-worktree-");
|
|
execFileSync("git", ["init"], { cwd: repoRoot, stdio: "ignore" });
|
|
const cwd = path.join(repoRoot, "nested", "tooling");
|
|
fs.mkdirSync(cwd, { recursive: true });
|
|
const commonLockDir = path.join(repoRoot, ".git", "openclaw-local-checks", "heavy-check.lock");
|
|
const worktreeLockDir = path.join(
|
|
repoRoot,
|
|
".artifacts",
|
|
"openclaw-local-checks",
|
|
"heavy-check.lock",
|
|
);
|
|
const nestedLockDir = path.join(cwd, ".artifacts", "openclaw-local-checks", "heavy-check.lock");
|
|
|
|
const release = acquireLocalHeavyCheckLockSync({
|
|
cwd,
|
|
env: makeEnv({ OPENCLAW_HEAVY_CHECK_LOCK_SCOPE: "worktree" }),
|
|
toolName: "check:changed",
|
|
});
|
|
|
|
const owner = JSON.parse(fs.readFileSync(path.join(worktreeLockDir, "owner.json"), "utf8"));
|
|
expect(owner.tool).toBe("check:changed");
|
|
expect(fs.existsSync(worktreeLockDir)).toBe(true);
|
|
expect(fs.existsSync(commonLockDir)).toBe(false);
|
|
expect(fs.existsSync(nestedLockDir)).toBe(false);
|
|
|
|
release();
|
|
expect(fs.existsSync(worktreeLockDir)).toBe(false);
|
|
});
|
|
|
|
it("rejects malformed heavy-check lock timing env values", () => {
|
|
const cwd = createTempDir("openclaw-local-heavy-check-malformed-env-");
|
|
|
|
expect(() =>
|
|
acquireLocalHeavyCheckLockSync({
|
|
cwd,
|
|
env: makeEnv({ OPENCLAW_HEAVY_CHECK_LOCK_TIMEOUT_MS: "10ms" }),
|
|
toolName: "oxlint",
|
|
}),
|
|
).toThrow("OPENCLAW_HEAVY_CHECK_LOCK_TIMEOUT_MS must be a positive integer; got: 10ms");
|
|
expect(() =>
|
|
acquireLocalHeavyCheckLockSync({
|
|
cwd,
|
|
env: makeEnv({ OPENCLAW_HEAVY_CHECK_LOCK_POLL_MS: "0" }),
|
|
toolName: "oxlint",
|
|
}),
|
|
).toThrow("OPENCLAW_HEAVY_CHECK_LOCK_POLL_MS must be a positive integer; got: 0");
|
|
});
|
|
|
|
it("cleans up stale legacy test locks when acquiring the shared heavy-check lock", () => {
|
|
const cwd = createTempDir("openclaw-local-heavy-check-legacy-");
|
|
const commonDir = path.join(cwd, ".git");
|
|
const locksDir = path.join(commonDir, "openclaw-local-checks");
|
|
const legacyLockDir = path.join(locksDir, "test.lock");
|
|
const heavyCheckLockDir = path.join(locksDir, "heavy-check.lock");
|
|
fs.mkdirSync(legacyLockDir, { recursive: true });
|
|
fs.writeFileSync(
|
|
path.join(legacyLockDir, "owner.json"),
|
|
`${JSON.stringify({
|
|
pid: 999_999_999,
|
|
tool: "test",
|
|
cwd,
|
|
})}\n`,
|
|
"utf8",
|
|
);
|
|
|
|
const release = acquireLocalHeavyCheckLockSync({
|
|
cwd,
|
|
env: makeEnv(),
|
|
toolName: "oxlint",
|
|
});
|
|
|
|
expect(fs.existsSync(legacyLockDir)).toBe(false);
|
|
expect(fs.existsSync(heavyCheckLockDir)).toBe(true);
|
|
|
|
release();
|
|
expect(fs.existsSync(heavyCheckLockDir)).toBe(false);
|
|
});
|
|
});
|