From 3059eadca20c0f22f92c573eceea0b5c5f75c263 Mon Sep 17 00:00:00 2001 From: Ayaan Zaidi Date: Tue, 31 Mar 2026 11:02:33 +0530 Subject: [PATCH] test: fix provider runtime mocks and test planner load shedding --- scripts/test-planner/runtime-profile.mjs | 18 ++++-- src/plugins/providers.test.ts | 72 +++++++++++++++++------- test/scripts/test-planner.test.ts | 8 +-- test/vitest-config.test.ts | 4 +- 4 files changed, 70 insertions(+), 32 deletions(-) diff --git a/scripts/test-planner/runtime-profile.mjs b/scripts/test-planner/runtime-profile.mjs index 188a6f3f187..79c5814efae 100644 --- a/scripts/test-planner/runtime-profile.mjs +++ b/scripts/test-planner/runtime-profile.mjs @@ -87,6 +87,14 @@ const scaleConcurrencyForLoad = (value, loadBand) => { return Math.max(1, Math.floor(value * scale)); }; +const scaleBatchTargetForLoad = (value, loadBand) => { + if (value === null || value === undefined || value <= 0) { + return value; + } + const scale = loadBand === "busy" ? 0.75 : loadBand === "saturated" ? 0.5 : 1; + return Math.max(5_000, Math.floor(value * scale)); +}; + const LOCAL_MEMORY_BUDGETS = { constrained: { vitestCap: 2, @@ -341,12 +349,10 @@ export function resolveExecutionBudget(runtimeCapabilities) { baseBudget.topLevelParallelLimitIsolated, runtime.loadBand, ), - unitFastBatchTargetMs: - runtime.loadBand === "busy" - ? Math.max(baseBudget.unitFastBatchTargetMs, 60_000) - : runtime.loadBand === "saturated" - ? Math.max(baseBudget.unitFastBatchTargetMs, 90_000) - : baseBudget.unitFastBatchTargetMs, + unitFastBatchTargetMs: scaleBatchTargetForLoad( + baseBudget.unitFastBatchTargetMs, + runtime.loadBand, + ), deferredRunConcurrency: runtime.loadBand === "busy" ? Math.max(1, (baseBudget.deferredRunConcurrency ?? 1) - 1) diff --git a/src/plugins/providers.test.ts b/src/plugins/providers.test.ts index e31a8a1c7e6..50cfce6977c 100644 --- a/src/plugins/providers.test.ts +++ b/src/plugins/providers.test.ts @@ -1,8 +1,18 @@ -import { beforeEach, describe, expect, it, vi } from "vitest"; +import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import type { OpenClawConfig } from "../config/config.js"; +import type { PluginAutoEnableResult } from "../config/plugin-auto-enable.js"; +import type { PluginManifestRecord } from "./manifest-registry.js"; +import { createEmptyPluginRegistry } from "./registry-empty.js"; +import type { ProviderPlugin } from "./types.js"; -const loadOpenClawPluginsMock = vi.fn(); -const loadPluginManifestRegistryMock = vi.fn(); -const applyPluginAutoEnableMock = vi.fn(); +type LoadOpenClawPlugins = typeof import("./loader.js").loadOpenClawPlugins; +type LoadPluginManifestRegistry = + typeof import("./manifest-registry.js").loadPluginManifestRegistry; +type ApplyPluginAutoEnable = typeof import("../config/plugin-auto-enable.js").applyPluginAutoEnable; + +const loadOpenClawPluginsMock = vi.fn(); +const loadPluginManifestRegistryMock = vi.fn(); +const applyPluginAutoEnableMock = vi.fn(); let resolveOwningPluginIdsForProvider: typeof import("./providers.js").resolveOwningPluginIdsForProvider; let resolvePluginProviders: typeof import("./providers.runtime.js").resolvePluginProviders; @@ -11,15 +21,22 @@ function createManifestProviderPlugin(params: { id: string; providerIds: string[]; origin?: "bundled" | "workspace"; -}) { +}): PluginManifestRecord { return { id: params.id, + channels: [], + cliBackends: [], providers: params.providerIds, + skills: [], + hooks: [], origin: params.origin ?? "bundled", + rootDir: `/tmp/${params.id}`, + source: params.origin ?? "bundled", + manifestPath: `/tmp/${params.id}/openclaw.plugin.json`, }; } -function setManifestPlugins(plugins: Array>) { +function setManifestPlugins(plugins: PluginManifestRecord[]) { loadPluginManifestRegistryMock.mockReturnValue({ plugins, diagnostics: [], @@ -91,10 +108,10 @@ function createBundledProviderCompatOptions(params?: { onlyPluginIds?: readonly } function createAutoEnabledProviderConfig() { - const rawConfig = { + const rawConfig: OpenClawConfig = { plugins: {}, }; - const autoEnabledConfig = { + const autoEnabledConfig: OpenClawConfig = { ...rawConfig, plugins: { entries: { @@ -151,29 +168,42 @@ function expectBundledProviderLoad(params?: { config?: unknown; env?: NodeJS.Pro } describe("resolvePluginProviders", () => { - beforeEach(async () => { + beforeAll(async () => { vi.resetModules(); vi.doMock("./loader.js", () => ({ - loadOpenClawPlugins: (...args: unknown[]) => loadOpenClawPluginsMock(...args), + loadOpenClawPlugins: (...args: Parameters) => + loadOpenClawPluginsMock(...args), })); vi.doMock("../config/plugin-auto-enable.js", () => ({ - applyPluginAutoEnable: (...args: unknown[]) => applyPluginAutoEnableMock(...args), + applyPluginAutoEnable: (...args: Parameters) => + applyPluginAutoEnableMock(...args), })); vi.doMock("./manifest-registry.js", () => ({ - loadPluginManifestRegistry: (...args: unknown[]) => loadPluginManifestRegistryMock(...args), + loadPluginManifestRegistry: (...args: Parameters) => + loadPluginManifestRegistryMock(...args), })); ({ resolveOwningPluginIdsForProvider } = await import("./providers.js")); ({ resolvePluginProviders } = await import("./providers.runtime.js")); + }); + + beforeEach(() => { loadOpenClawPluginsMock.mockReset(); - loadOpenClawPluginsMock.mockReturnValue({ - providers: [{ pluginId: "google", provider: { id: "demo-provider" } }], - }); + const provider: ProviderPlugin = { + id: "demo-provider", + label: "Demo Provider", + auth: [], + }; + const registry = createEmptyPluginRegistry(); + registry.providers.push({ pluginId: "google", provider, source: "bundled" }); + loadOpenClawPluginsMock.mockReturnValue(registry); loadPluginManifestRegistryMock.mockReset(); applyPluginAutoEnableMock.mockReset(); - applyPluginAutoEnableMock.mockImplementation((params: { config: unknown }) => ({ - config: params.config, - changes: [], - })); + applyPluginAutoEnableMock.mockImplementation( + (params): PluginAutoEnableResult => ({ + config: params.config, + changes: [], + }), + ); setManifestPlugins([ createManifestProviderPlugin({ id: "google", providerIds: ["google"] }), createManifestProviderPlugin({ id: "browser", providerIds: [] }), @@ -196,7 +226,9 @@ describe("resolvePluginProviders", () => { env, }); - expectResolvedProviders(providers, [{ id: "demo-provider", pluginId: "google" }]); + expectResolvedProviders(providers, [ + { id: "demo-provider", label: "Demo Provider", auth: [], pluginId: "google" }, + ]); expect(loadOpenClawPluginsMock).toHaveBeenCalledWith( expect.objectContaining({ workspaceDir: "/workspace/explicit", diff --git a/test/scripts/test-planner.test.ts b/test/scripts/test-planner.test.ts index 1640f22421c..89a1f421f59 100644 --- a/test/scripts/test-planner.test.ts +++ b/test/scripts/test-planner.test.ts @@ -150,12 +150,12 @@ describe("test planner", () => { expect(plan.executionBudget.unitIsolatedWorkers).toBe(1); expect(plan.executionBudget.topLevelParallelLimitNoIsolate).toBe(4); expect(plan.executionBudget.topLevelParallelLimitIsolated).toBe(1); - expect(plan.topLevelParallelLimit).toBe(3); + expect(plan.topLevelParallelLimit).toBe(4); expect(plan.deferredRunConcurrency).toBe(1); artifacts.cleanupTempArtifacts(); }); - it("coalesces saturated high-memory local unit bursts into fewer shared batches", () => { + it("splits saturated high-memory local unit bursts into smaller shared batches", () => { const env = { RUNNER_OS: "macOS", OPENCLAW_TEST_HOST_CPU_COUNT: "16", @@ -200,9 +200,9 @@ describe("test planner", () => { expect(plan.runtimeCapabilities.memoryBand).toBe("high"); expect(plan.runtimeCapabilities.loadBand).toBe("saturated"); - expect(sharedUnitBatches.length).toBeLessThan(baselineSharedUnitBatches.length); + expect(sharedUnitBatches.length).toBeGreaterThan(baselineSharedUnitBatches.length); expect(plan.executionBudget.unitIsolatedWorkers).toBe(1); - expect(plan.executionBudget.unitFastBatchTargetMs).toBe(90_000); + expect(plan.executionBudget.unitFastBatchTargetMs).toBe(22_500); artifacts.cleanupTempArtifacts(); }); diff --git a/test/vitest-config.test.ts b/test/vitest-config.test.ts index 58f370e7ae9..fffea9c11a5 100644 --- a/test/vitest-config.test.ts +++ b/test/vitest-config.test.ts @@ -149,7 +149,7 @@ describe("resolveLocalVitestMaxWorkers", () => { expect(budget.deferredRunConcurrency).toBe(1); }); - it("backs off isolated workers and enlarges unit batches on saturated high-memory locals", () => { + it("backs off isolated workers and shrinks unit batches on saturated high-memory locals", () => { const runtime = resolveRuntimeCapabilities( { RUNNER_OS: "macOS", @@ -167,7 +167,7 @@ describe("resolveLocalVitestMaxWorkers", () => { expect(runtime.memoryBand).toBe("high"); expect(runtime.loadBand).toBe("saturated"); expect(budget.unitIsolatedWorkers).toBe(1); - expect(budget.unitFastBatchTargetMs).toBe(90_000); + expect(budget.unitFastBatchTargetMs).toBe(22_500); }); it("keeps CI windows policy constrained independently of host load", () => {