mirror of https://github.com/openclaw/openclaw.git
test: fix provider runtime mocks and test planner load shedding
This commit is contained in:
parent
aebdb8f8cf
commit
3059eadca2
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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<LoadOpenClawPlugins>();
|
||||
const loadPluginManifestRegistryMock = vi.fn<LoadPluginManifestRegistry>();
|
||||
const applyPluginAutoEnableMock = vi.fn<ApplyPluginAutoEnable>();
|
||||
|
||||
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<Record<string, unknown>>) {
|
||||
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<LoadOpenClawPlugins>) =>
|
||||
loadOpenClawPluginsMock(...args),
|
||||
}));
|
||||
vi.doMock("../config/plugin-auto-enable.js", () => ({
|
||||
applyPluginAutoEnable: (...args: unknown[]) => applyPluginAutoEnableMock(...args),
|
||||
applyPluginAutoEnable: (...args: Parameters<ApplyPluginAutoEnable>) =>
|
||||
applyPluginAutoEnableMock(...args),
|
||||
}));
|
||||
vi.doMock("./manifest-registry.js", () => ({
|
||||
loadPluginManifestRegistry: (...args: unknown[]) => loadPluginManifestRegistryMock(...args),
|
||||
loadPluginManifestRegistry: (...args: Parameters<LoadPluginManifestRegistry>) =>
|
||||
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",
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -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", () => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue