diff --git a/src/lib/shields/index.test.ts b/src/lib/shields/index.test.ts index 82d8a23e898..d6b49278d84 100644 --- a/src/lib/shields/index.test.ts +++ b/src/lib/shields/index.test.ts @@ -592,42 +592,23 @@ describe("shields — unit logic", () => { expect(appliedPolicy).not.toContain("mcp_bridge_alpha"); }); - it("auto-restore applies a snapshot with no managed MCP entries when policy staging is unavailable (#7952)", async () => { - const sandboxName = "openclaw"; - const processToken = "d".repeat(32); - const snapshotPath = path.join(stateDir(), "policy-snapshot-no-managed-mcp.yaml"); - fs.mkdirSync(stateDir(), { recursive: true }); - fs.writeFileSync(snapshotPath, "version: 1\nnetwork_policies:\n restrictive_baseline: {}\n"); - writeState(sandboxName, { - shieldsDown: true, - shieldsPolicySnapshotPath: snapshotPath, - shieldsManagedMcpPolicyKeys: [], - }); - writeMarker(sandboxName, { - pid: 2_147_483_647, - sandboxName, - snapshotPath, - restoreAt: new Date(Date.now() - 1_000).toISOString(), - processToken, - }); - vi.spyOn(process, "kill").mockImplementation(routeProcessKill); - const { applyShieldsPolicySnapshot } = await loadShieldsModule(); - const { buildPolicySetCommand } = await import("../policy"); - const createTempDirectory = vi.spyOn(fs, "mkdtempSync").mockImplementation(() => { - throw Object.assign(new Error("ENOSPC: simulated temporary storage full"), { - code: "ENOSPC", - }); + it("reuses the snapshot without staging when the snapshot and current policy have no managed MCP entries (#7952)", async () => { + const snapshotPath = "/state/policy-snapshot-no-managed-mcp.yaml"; + const snapshotYaml = "version: 1\nnetwork_policies:\n restrictive_baseline: {}\n"; + const writeTempPolicy = vi.fn(() => { + throw new Error("policy staging is unavailable"); }); + const { buildDeadlineRuntimeManagedMcpPolicy } = await import("./permissive-runtime"); - const result = applyShieldsPolicySnapshot(sandboxName, snapshotPath, { - transitionProcessToken: processToken, - deadlineAuthoritative: true, - expiredTimerRecovery: true, + const result = buildDeadlineRuntimeManagedMcpPolicy(snapshotPath, { + managedMcpPolicies: [], + snapshotManagedPolicyKeys: [], + readBasePolicy: () => snapshotYaml, + writeTempPolicy, }); - expect(result.status).toBe(0); - expect(createTempDirectory).not.toHaveBeenCalled(); - expect(buildPolicySetCommand).toHaveBeenCalledWith(snapshotPath, sandboxName); + expect(result).toEqual({ path: snapshotPath, omissions: [] }); + expect(writeTempPolicy).not.toHaveBeenCalled(); }); it("shieldsStatus warns and stays DOWN when inline recovery fails", async () => { diff --git a/src/lib/tunnel/services.test.ts b/src/lib/tunnel/services.test.ts index c2d666e016b..2d30241a52a 100644 --- a/src/lib/tunnel/services.test.ts +++ b/src/lib/tunnel/services.test.ts @@ -14,7 +14,7 @@ import { } from "node:fs"; import { tmpdir } from "node:os"; import { join, resolve } from "node:path"; -import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; +import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; // Import source directly so tests cannot pass against a stale build. import { registerTunnelOrigin } from "./allowed-origins"; @@ -445,9 +445,7 @@ describe("stopAll", () => { let spawnSyncCalls: Array<{ command: string; args: readonly string[] }>; let originalSpawnSync: typeof childProcess.spawnSync; - beforeEach(() => { - pidDir = mkdtempSync(join(tmpdir(), "nemoclaw-svc-test-")); - spawnSyncCalls = []; + beforeAll(() => { originalSpawnSync = childProcess.spawnSync; // @ts-expect-error — partial mock signature is intentional. childProcess.spawnSync = (command: string, args: readonly string[]) => { @@ -468,16 +466,24 @@ describe("stopAll", () => { return reply; }; // The Ollama proxy source module destructures `spawnSync` at - // require time, so to make `stopAll` pick up the patched function we - // bust its cache. `services.ts` requires the proxy lazily, so the - // next call sees the freshly-loaded module. + // require time. Load it once with the stable suite-level mock instead of + // re-evaluating the large module under coverage for every stopAll test. delete require.cache[require.resolve(ollamaProxySourcePath)]; + require(ollamaProxySourcePath); + }); + + beforeEach(() => { + pidDir = mkdtempSync(join(tmpdir(), "nemoclaw-svc-test-")); + spawnSyncCalls = []; }); afterEach(() => { + rmSync(pidDir, { recursive: true, force: true }); + }); + + afterAll(() => { childProcess.spawnSync = originalSpawnSync; delete require.cache[require.resolve(ollamaProxySourcePath)]; - rmSync(pidDir, { recursive: true, force: true }); }); // A scripted ProcessControl models PID identity/liveness/signalling without