From 0dfea099d6facb4c317f82869c8d3125a3495db1 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 27 Apr 2026 13:00:39 +0100 Subject: [PATCH] test: speed up focused test setup --- src/acp/control-plane/manager.test.ts | 35 +++----- .../provider-registry.test.ts | 11 +-- src/install-sh-version.test.ts | 2 +- .../audit-config-include-perms.test.ts | 79 +++++++++---------- .../audit-plugin-readonly-scope.test.ts | 8 +- .../provider-registry.test.ts | 11 +-- 6 files changed, 58 insertions(+), 88 deletions(-) diff --git a/src/acp/control-plane/manager.test.ts b/src/acp/control-plane/manager.test.ts index 4b2b313839c..fd845080ab7 100644 --- a/src/acp/control-plane/manager.test.ts +++ b/src/acp/control-plane/manager.test.ts @@ -1,6 +1,6 @@ import { setTimeout as scheduleNativeTimeout } from "node:timers"; import { setTimeout as sleep } from "node:timers/promises"; -import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import type { OpenClawConfig } from "../../config/config.js"; import type { AcpSessionRuntimeOptions, SessionAcpMeta } from "../../config/sessions/types.js"; import { resetHeartbeatWakeStateForTests } from "../../infra/heartbeat-wake.js"; @@ -33,14 +33,17 @@ vi.mock("../runtime/registry.js", () => ({ requireAcpRuntimeBackend: (backendId?: string) => hoisted.requireAcpRuntimeBackendMock(backendId), })); -let AcpSessionManager: typeof import("./manager.js").AcpSessionManager; -let AcpRuntimeError: typeof import("../runtime/errors.js").AcpRuntimeError; -let resetAcpSessionManagerForTests: typeof import("./manager.js").__testing.resetAcpSessionManagerForTests; -let findTaskByRunId: typeof import("../../tasks/task-registry.js").findTaskByRunId; -let resetTaskRegistryForTests: typeof import("../../tasks/task-registry.js").resetTaskRegistryForTests; -let resetTaskFlowRegistryForTests: typeof import("../../tasks/task-flow-registry.js").resetTaskFlowRegistryForTests; -let installInMemoryTaskRegistryRuntime: typeof import("../../test-utils/task-registry-runtime.js").installInMemoryTaskRegistryRuntime; -let configureTaskFlowRegistryRuntime: typeof import("../../tasks/task-flow-registry.store.js").configureTaskFlowRegistryRuntime; +const { + AcpSessionManager, + __testing: { resetAcpSessionManagerForTests }, +} = await import("./manager.js"); +const { AcpRuntimeError } = await import("../runtime/errors.js"); +const { findTaskByRunId, resetTaskRegistryForTests } = await import("../../tasks/task-registry.js"); +const { resetTaskFlowRegistryForTests } = await import("../../tasks/task-flow-registry.js"); +const { configureTaskFlowRegistryRuntime } = + await import("../../tasks/task-flow-registry.store.js"); +const { installInMemoryTaskRegistryRuntime } = + await import("../../test-utils/task-registry-runtime.js"); const baseCfg = { acp: { @@ -208,20 +211,6 @@ function extractRuntimeOptionsFromUpserts(): Array { - beforeAll(async () => { - ({ - AcpSessionManager, - __testing: { resetAcpSessionManagerForTests }, - } = await import("./manager.js")); - ({ AcpRuntimeError } = await import("../runtime/errors.js")); - ({ findTaskByRunId, resetTaskRegistryForTests } = await import("../../tasks/task-registry.js")); - ({ resetTaskFlowRegistryForTests } = await import("../../tasks/task-flow-registry.js")); - ({ configureTaskFlowRegistryRuntime } = - await import("../../tasks/task-flow-registry.store.js")); - ({ installInMemoryTaskRegistryRuntime } = - await import("../../test-utils/task-registry-runtime.js")); - }); - beforeEach(() => { resetAcpSessionManagerForTests(); vi.useRealTimers(); diff --git a/src/image-generation/provider-registry.test.ts b/src/image-generation/provider-registry.test.ts index 4a6bbc1237c..fde4e41c7a8 100644 --- a/src/image-generation/provider-registry.test.ts +++ b/src/image-generation/provider-registry.test.ts @@ -1,4 +1,4 @@ -import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { beforeEach, describe, expect, it, vi } from "vitest"; import type { OpenClawConfig } from "../config/types.js"; import type { ImageGenerationProviderPlugin } from "../plugins/types.js"; @@ -10,8 +10,8 @@ vi.mock("../plugins/capability-provider-runtime.js", () => ({ resolvePluginCapabilityProviders: resolvePluginCapabilityProvidersMock, })); -let getImageGenerationProvider: typeof import("./provider-registry.js").getImageGenerationProvider; -let listImageGenerationProviders: typeof import("./provider-registry.js").listImageGenerationProviders; +const { getImageGenerationProvider, listImageGenerationProviders } = + await import("./provider-registry.js"); function createProvider( params: Pick & Partial, @@ -30,11 +30,6 @@ function createProvider( } describe("image-generation provider registry", () => { - beforeAll(async () => { - ({ getImageGenerationProvider, listImageGenerationProviders } = - await import("./provider-registry.js")); - }); - beforeEach(() => { resolvePluginCapabilityProvidersMock.mockReset(); resolvePluginCapabilityProvidersMock.mockReturnValue([]); diff --git a/src/install-sh-version.test.ts b/src/install-sh-version.test.ts index 442ff041ddc..5c5ff45d1fc 100644 --- a/src/install-sh-version.test.ts +++ b/src/install-sh-version.test.ts @@ -26,7 +26,7 @@ OPENCLAW_BIN=fake_openclaw_decorated resolve_openclaw_version OPENCLAW_BIN=fake_openclaw_raw resolve_openclaw_version ( cd "$1" - bash -s <<'OPENCLAW_STDIN_INSTALLER' + source /dev/stdin <<'OPENCLAW_STDIN_INSTALLER' ${versionHelperSource} fake_openclaw_stdin() { printf '%s\\n' 'OpenClaw 2026.3.10 (abcdef0)'; } OPENCLAW_BIN=fake_openclaw_stdin diff --git a/src/security/audit-config-include-perms.test.ts b/src/security/audit-config-include-perms.test.ts index c55a67989e5..481814f4248 100644 --- a/src/security/audit-config-include-perms.test.ts +++ b/src/security/audit-config-include-perms.test.ts @@ -1,13 +1,24 @@ import fs from "node:fs"; import os from "node:os"; import path from "node:path"; -import { describe, expect, it } from "vitest"; +import { beforeEach, describe, expect, it, vi } from "vitest"; import type { ConfigFileSnapshot } from "../config/types.openclaw.js"; import { collectIncludeFilePermFindings } from "./audit-extra.async.js"; -const isWindows = process.platform === "win32"; +const inspectPathPermissionsMock = vi.hoisted(() => vi.fn()); + +vi.mock("./audit-fs.js", () => ({ + inspectPathPermissions: inspectPathPermissionsMock, + formatPermissionDetail: (targetPath: string) => `${targetPath} mocked-perms`, + formatPermissionRemediation: ({ targetPath }: { targetPath: string }) => + `chmod 600 ${targetPath}`, +})); describe("security audit config include permissions", () => { + beforeEach(() => { + inspectPathPermissionsMock.mockReset(); + }); + it("flags group/world-readable config include files", async () => { const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-include-perms-")); const stateDir = path.join(tmp, "state"); @@ -15,39 +26,24 @@ describe("security audit config include permissions", () => { const includePath = path.join(stateDir, "extra.json5"); fs.writeFileSync(includePath, "{ logging: { redactSensitive: 'off' } }\n", "utf-8"); - if (isWindows) { - const { execSync } = await import("node:child_process"); - execSync(`icacls "${includePath}" /grant Everyone:W`, { stdio: "ignore" }); - } else { - fs.chmodSync(includePath, 0o644); - } - - const configPath = path.join(stateDir, "openclaw.json"); - fs.writeFileSync(configPath, `{ "$include": "./extra.json5" }\n`, "utf-8"); - fs.chmodSync(configPath, 0o600); - - const user = "DESKTOP-TEST\\Tester"; - const execIcacls = isWindows - ? async (_cmd: string, args: string[]) => { - const target = args[0]; - if (target === includePath) { - return { - stdout: `${target} NT AUTHORITY\\SYSTEM:(F)\n BUILTIN\\Users:(W)\n ${user}:(F)\n`, - stderr: "", - }; - } - return { - stdout: `${target} NT AUTHORITY\\SYSTEM:(F)\n ${user}:(F)\n`, - stderr: "", - }; - } - : undefined; + inspectPathPermissionsMock.mockResolvedValue({ + ok: true, + isSymlink: false, + isDir: false, + mode: 0o644, + bits: 0o644, + source: "posix", + worldWritable: false, + groupWritable: false, + worldReadable: true, + groupReadable: true, + }); const configSnapshot: ConfigFileSnapshot = { - path: configPath, + path: path.join(stateDir, "openclaw.json"), exists: true, - raw: `{ "$include": "./extra.json5" }\n`, - parsed: { $include: "./extra.json5" }, + raw: `{ "$include": ${JSON.stringify(includePath)} }\n`, + parsed: { $include: includePath }, sourceConfig: {} as ConfigFileSnapshot["sourceConfig"], resolved: {} as ConfigFileSnapshot["resolved"], valid: true, @@ -60,20 +56,19 @@ describe("security audit config include permissions", () => { const findings = await collectIncludeFilePermFindings({ configSnapshot, - platform: isWindows ? "win32" : undefined, - env: isWindows - ? { ...process.env, USERNAME: "Tester", USERDOMAIN: "DESKTOP-TEST" } - : undefined, - execIcacls, }); - const expectedCheckId = isWindows - ? "fs.config_include.perms_writable" - : "fs.config_include.perms_world_readable"; - + expect(inspectPathPermissionsMock).toHaveBeenCalledWith(includePath, { + env: undefined, + exec: undefined, + platform: undefined, + }); expect(findings).toEqual( expect.arrayContaining([ - expect.objectContaining({ checkId: expectedCheckId, severity: "critical" }), + expect.objectContaining({ + checkId: "fs.config_include.perms_world_readable", + severity: "critical", + }), ]), ); }); diff --git a/src/security/audit-plugin-readonly-scope.test.ts b/src/security/audit-plugin-readonly-scope.test.ts index 73fb85dee94..10dde131653 100644 --- a/src/security/audit-plugin-readonly-scope.test.ts +++ b/src/security/audit-plugin-readonly-scope.test.ts @@ -1,4 +1,4 @@ -import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { beforeEach, describe, expect, it, vi } from "vitest"; const applyPluginAutoEnableMock = vi.hoisted(() => vi.fn()); const getActivePluginRegistryMock = vi.hoisted(() => vi.fn()); @@ -23,7 +23,7 @@ vi.mock("../plugins/runtime/metadata-registry-loader.js", () => ({ loadPluginMetadataRegistrySnapshotMock(...args), })); -let collectPluginSecurityAuditFindings: typeof import("./audit.js").collectPluginSecurityAuditFindings; +const { collectPluginSecurityAuditFindings } = await import("./audit.js"); function createAuditContext(params: { sourceConfig: Parameters[0]["sourceConfig"]; @@ -48,10 +48,6 @@ function createAuditContext(params: { } describe("security audit read-only plugin scope", () => { - beforeAll(async () => { - ({ collectPluginSecurityAuditFindings } = await import("./audit.js")); - }); - beforeEach(() => { applyPluginAutoEnableMock.mockReset(); getActivePluginRegistryMock.mockReset(); diff --git a/src/video-generation/provider-registry.test.ts b/src/video-generation/provider-registry.test.ts index f7931f8e16c..642bb434ffc 100644 --- a/src/video-generation/provider-registry.test.ts +++ b/src/video-generation/provider-registry.test.ts @@ -1,4 +1,4 @@ -import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { beforeEach, describe, expect, it, vi } from "vitest"; import type { VideoGenerationProviderPlugin } from "../plugins/types.js"; const { resolvePluginCapabilityProvidersMock } = vi.hoisted(() => ({ @@ -9,8 +9,8 @@ vi.mock("../plugins/capability-provider-runtime.js", () => ({ resolvePluginCapabilityProviders: resolvePluginCapabilityProvidersMock, })); -let getVideoGenerationProvider: typeof import("./provider-registry.js").getVideoGenerationProvider; -let listVideoGenerationProviders: typeof import("./provider-registry.js").listVideoGenerationProviders; +const { getVideoGenerationProvider, listVideoGenerationProviders } = + await import("./provider-registry.js"); function createProvider( params: Pick & Partial, @@ -26,11 +26,6 @@ function createProvider( } describe("video-generation provider registry", () => { - beforeAll(async () => { - ({ getVideoGenerationProvider, listVideoGenerationProviders } = - await import("./provider-registry.js")); - }); - beforeEach(() => { resolvePluginCapabilityProvidersMock.mockReset(); resolvePluginCapabilityProvidersMock.mockReturnValue([]);