test: move core coverage to owner boundaries (#124184)

* test: move core coverage to owner boundaries

* ci: lower plugin SDK surface budget
This commit is contained in:
Peter Steinberger
2026-08-15 07:42:53 -07:00
committed by GitHub
parent 9663cc7edc
commit b365f7ec89
9 changed files with 52 additions and 160 deletions
+4 -2
View File
@@ -284,7 +284,8 @@ export function readPluginSdkSurfaceBudgets(env: NodeJS.ProcessEnv = process.env
// +6: load-only bridges for published pre-split plugin artifacts
// (voice-call/matrix runtime-doctor repair names, WhatsApp ack policy,
// Slack progress-draft render) so installed plugins survive upgrade (#124041 class).
4330,
// -1: remove the orphan diagnostic traceparent propagation export.
4329,
env,
),
publicFunctionExports: readPluginSdkSurfaceBudgetEnv(
@@ -357,7 +358,8 @@ export function readPluginSdkSurfaceBudgets(env: NodeJS.ProcessEnv = process.env
// +3: load-only bridges for published pre-split plugin artifacts
// (voice-call/matrix runtime-doctor repair names, WhatsApp ack policy,
// Slack progress-draft render) so installed plugins survive upgrade (#124041 class).
2577,
// -1: remove the orphan diagnostic traceparent propagation export.
2576,
env,
),
publicDeprecatedExports: readPluginSdkSurfaceBudgetEnv(
+12 -4
View File
@@ -360,10 +360,18 @@ describe("agentCliCommand", () => {
expect(zeroTimeoutGatewayRequestMs).toBe(2_147_000_000);
});
it("clamps oversized gateway timeout seconds", () => {
expect(agentViaGatewayTesting.resolveGatewayAgentTimeoutMs(Number.MAX_SAFE_INTEGER)).toBe(
MAX_TIMER_TIMEOUT_MS,
);
it("clamps oversized gateway timeout seconds at the command boundary", async () => {
await withTempStore(async () => {
mockGatewaySuccessReply();
await agentCliCommand(
{ message: "hi", to: "+1555", timeout: String(Number.MAX_SAFE_INTEGER) },
runtime,
);
const request = requireFirstCallArg(callGateway, "gateway") as { timeoutMs?: number };
expect(request.timeoutMs).toBe(MAX_TIMER_TIMEOUT_MS);
});
});
it("rejects partial gateway timeout values", async () => {
-1
View File
@@ -357,7 +357,6 @@ export const agentViaGatewayTesting = {
agentSessionModuleCache.clear();
agentSessionModuleLoader = loader;
},
resolveGatewayAgentTimeoutMs,
setGatewayAbortRetryDelaysMsForTests(delays?: readonly number[]): void {
gatewayAbortRetryDelaysMsForTests = delays;
},
+27 -28
View File
@@ -1,19 +1,22 @@
import { describe, expect, it, vi } from "vitest";
import { probeDockerGatewayHealth, resolveDockerHealthcheckPort } from "./docker-healthcheck.js";
import { probeDockerGatewayHealth } from "./docker-healthcheck.js";
describe("Docker healthcheck", () => {
it("prefers the active Gateway lock port used by --port", async () => {
it("probes the active Gateway lock port used by --port", async () => {
const getRuntimeConfig = vi.fn(() => ({ gateway: { port: 19002 } }));
const resolveGatewayPort = vi.fn(() => 19003);
const fetch = vi.fn(async () => ({ ok: true }) as Response);
await expect(
resolveDockerHealthcheckPort({
probeDockerGatewayHealth({
env: { OPENCLAW_GATEWAY_PORT: "19001" },
fetch,
getRuntimeConfig,
readActiveGatewayLockPort: vi.fn(async () => 19000),
resolveGatewayPort,
}),
).resolves.toBe(19000);
).resolves.toBe(true);
expect(fetch).toHaveBeenCalledWith("http://127.0.0.1:19000/healthz");
expect(getRuntimeConfig).not.toHaveBeenCalled();
expect(resolveGatewayPort).not.toHaveBeenCalled();
});
@@ -31,30 +34,24 @@ describe("Docker healthcheck", () => {
config: { gateway: { port: 19002 } },
expected: 19002,
},
])("falls back to the canonical $name port", async ({ env, config, expected }) => {
await expect(
resolveDockerHealthcheckPort({
env,
getRuntimeConfig: () => config,
readActiveGatewayLockPort: vi.fn(async () => undefined),
}),
).resolves.toBe(expected);
});
])(
"probes the canonical $name port when no active lock exists",
async ({ env, config, expected }) => {
const fetch = vi.fn(async () => ({ ok: true }) as Response);
it("falls back to config when the active lock cannot be read", async () => {
await expect(
resolveDockerHealthcheckPort({
env: {},
getRuntimeConfig: () => ({ gateway: { port: 19002 } }),
readActiveGatewayLockPort: vi.fn(async () => {
throw new Error("lock unavailable");
await expect(
probeDockerGatewayHealth({
env,
fetch,
getRuntimeConfig: () => config,
readActiveGatewayLockPort: vi.fn(async () => undefined),
}),
resolveGatewayPort: (config) => config.gateway?.port ?? 18789,
}),
).resolves.toBe(19002);
});
).resolves.toBe(true);
expect(fetch).toHaveBeenCalledWith(`http://127.0.0.1:${expected}/healthz`);
},
);
it("probes the unauthenticated liveness endpoint on the resolved port", async () => {
it("probes the configured port when the active lock cannot be read", async () => {
const fetch = vi.fn(async () => ({ ok: true }) as Response);
await expect(
@@ -62,11 +59,13 @@ describe("Docker healthcheck", () => {
env: {},
fetch,
getRuntimeConfig: () => ({ gateway: { port: 19002 } }),
readActiveGatewayLockPort: vi.fn(async () => 19000),
resolveGatewayPort: vi.fn(() => 19002),
readActiveGatewayLockPort: vi.fn(async () => {
throw new Error("lock unavailable");
}),
resolveGatewayPort: (config) => config.gateway?.port ?? 18789,
}),
).resolves.toBe(true);
expect(fetch).toHaveBeenCalledWith("http://127.0.0.1:19000/healthz");
expect(fetch).toHaveBeenCalledWith("http://127.0.0.1:19002/healthz");
});
it("reports an unsuccessful or unreachable liveness endpoint as unhealthy", async () => {
+1 -1
View File
@@ -17,7 +17,7 @@ type DockerHealthcheckDeps = Partial<DockerHealthcheckPortDeps> & {
fetch?: typeof globalThis.fetch;
};
export async function resolveDockerHealthcheckPort(
async function resolveDockerHealthcheckPort(
deps: Partial<DockerHealthcheckPortDeps> = {},
): Promise<number> {
const env = deps.env ?? process.env;
+7 -55
View File
@@ -95,8 +95,8 @@ describe("gateway usage helpers", () => {
endDate: string,
) {
const range = expectDateRange(result);
expect(range.startMs).toBe(testApi.parseDateToMs(startDate));
expect(range.endMs).toBe(testApi.parseDateToMs(endDate)! + dayMs - 1);
expect(range.startMs).toBe(Date.parse(`${startDate}T00:00:00.000Z`));
expect(range.endMs).toBe(Date.parse(`${endDate}T00:00:00.000Z`) + dayMs - 1);
}
function expectDateRange(result: ReturnType<typeof testApi.resolveDateRange>) {
@@ -128,26 +128,6 @@ describe("gateway usage helpers", () => {
vi.clearAllMocks();
});
it("parseDateToMs accepts YYYY-MM-DD and rejects invalid input", () => {
expect(testApi.parseDateToMs("2026-02-05")).toBe(Date.UTC(2026, 1, 5));
expect(testApi.parseDateToMs(" 2026-02-05 ")).toBe(Date.UTC(2026, 1, 5));
expect(testApi.parseDateToMs("2026-2-5")).toBeUndefined();
expect(testApi.parseDateToMs("nope")).toBeUndefined();
expect(testApi.parseDateToMs(undefined)).toBeUndefined();
});
it("parseDateToMs rejects out-of-range calendar dates instead of rolling them over", () => {
// Impossible dates that still match the YYYY-MM-DD shape must not silently shift to a real day.
expect(testApi.parseDateToMs("2026-02-30")).toBeUndefined(); // would roll to Mar 2
expect(testApi.parseDateToMs("2026-04-31")).toBeUndefined(); // would roll to May 1
expect(testApi.parseDateToMs("2025-02-29")).toBeUndefined(); // non-leap Feb 29
expect(testApi.parseDateToMs("2026-13-01")).toBeUndefined(); // month too large
expect(testApi.parseDateToMs("2026-00-10")).toBeUndefined(); // month zero
expect(testApi.parseDateToMs("2026-01-00")).toBeUndefined(); // day zero
// Real leap day must stay valid (guard against over-rejection).
expect(testApi.parseDateToMs("2024-02-29")).toBe(Date.UTC(2024, 1, 29));
});
it.each([
[{ startDate: "2026-02-30" }, "invalid startDate"],
[{ endDate: "2026-2-5" }, "invalid endDate"],
@@ -275,34 +255,6 @@ describe("gateway usage helpers", () => {
expect(vi.mocked(discoverAllSessions)).not.toHaveBeenCalled();
});
it("parseUtcOffsetToMinutes supports whole-hour and half-hour offsets", () => {
expect(testApi.parseUtcOffsetToMinutes("UTC-4")).toBe(-240);
expect(testApi.parseUtcOffsetToMinutes("UTC+5:30")).toBe(330);
expect(testApi.parseUtcOffsetToMinutes(" UTC+14 ")).toBe(14 * 60);
});
it("parseUtcOffsetToMinutes rejects invalid offsets", () => {
expect(testApi.parseUtcOffsetToMinutes("UTC+14:30")).toBeUndefined();
expect(testApi.parseUtcOffsetToMinutes("UTC+5:99")).toBeUndefined();
expect(testApi.parseUtcOffsetToMinutes("UTC+25")).toBeUndefined();
expect(testApi.parseUtcOffsetToMinutes("GMT+5")).toBeUndefined();
expect(testApi.parseUtcOffsetToMinutes(undefined)).toBeUndefined();
});
it("parseDays coerces strings/numbers to integers", () => {
expect(testApi.parseDays(7.9)).toBe(7);
expect(testApi.parseDays("30")).toBe(30);
expect(testApi.parseDays("")).toBeUndefined();
expect(testApi.parseDays("nope")).toBeUndefined();
});
it("parseDays caps day counts before Date arithmetic can overflow", () => {
expect(testApi.parseDays(1e300)).toBe(36600);
expect(testApi.parseDays("1e300")).toBe(36600);
expect(testApi.parseDays(Number.MAX_SAFE_INTEGER)).toBe(36600);
expect(testApi.parseDays(366 * 100)).toBe(36600);
});
it("resolveDateRange uses explicit start/end as UTC when mode is missing (backward compatible)", () => {
const result = testApi.resolveDateRange({
startDate: "2026-02-01",
@@ -311,13 +263,13 @@ describe("gateway usage helpers", () => {
expectUtcDateRange(result, "2026-02-01", "2026-02-02");
});
it("resolveDateRange uses explicit UTC mode", () => {
it("resolveDateRange accepts a leap day in explicit UTC mode", () => {
const result = testApi.resolveDateRange({
startDate: "2026-02-01",
endDate: "2026-02-02",
startDate: "2024-02-29",
endDate: "2024-03-01",
mode: "utc",
});
expectUtcDateRange(result, "2026-02-01", "2026-02-02");
expectUtcDateRange(result, "2024-02-29", "2024-03-01");
});
it("resolveDateRange uses specific UTC offset for explicit dates", () => {
@@ -389,7 +341,7 @@ describe("gateway usage helpers", () => {
startDate: "2026-02-01",
endDate: "2026-02-02",
mode: "specific",
utcOffset: "bad-value",
utcOffset: "UTC+14:30",
}),
);
expect(missingOffset.startMs).toBe(Date.UTC(2026, 1, 1));
-18
View File
@@ -522,21 +522,6 @@ const getDateParts = (date: Date, interpretation: DateInterpretation): DateParts
};
};
/**
* Parse a date string (YYYY-MM-DD) to start-of-day timestamp based on interpretation mode.
* Returns undefined if invalid.
*/
const parseDateToMs = (
raw: unknown,
interpretation: DateInterpretation = { mode: "utc" },
): number | undefined => {
const parts = parseDateParts(raw);
if (!parts) {
return undefined;
}
return datePartsToStartMs(parts, interpretation);
};
const formatDateLabel = (ms: number, interpretation: DateInterpretation): string => {
const parts = getDateParts(new Date(ms), interpretation);
return formatDateParts(parts.year, parts.monthIndex, parts.day);
@@ -1141,9 +1126,6 @@ function mergeUsageCacheStatus(
// Exposed for unit tests (kept as a single export to avoid widening the public API surface).
export const testApi = {
parseUtcOffsetToMinutes,
parseDateToMs,
parseDays,
resolveDateRange,
loadCostUsageSummaryCached,
costUsageCache,
-33
View File
@@ -9,7 +9,6 @@ import {
emitTrustedDiagnosticEventWithPrivateData,
emitTrustedSkillUsedDiagnosticEvent,
emitTrustedSecurityEvent,
formatDiagnosticTraceparentForPropagation,
hasPendingInternalDiagnosticEvent,
isInternalDiagnosticEventMetadata,
isDiagnosticsEnabled,
@@ -246,38 +245,6 @@ describe("diagnostic-events", () => {
expect(isInternalDiagnosticEventMetadata({ trusted: false })).toBe(false);
});
it("formats traceparent for propagation only from dispatcher-trusted metadata", () => {
const trace = createDiagnosticTraceContext({
traceId: "4bf92f3577b34da6a3ce929d0e0e4736",
spanId: "00f067aa0ba902b7",
traceFlags: "01",
});
const traceparents: Array<string | undefined> = [];
onInternalDiagnosticEvent((event, metadata) => {
traceparents.push(formatDiagnosticTraceparentForPropagation(event, metadata));
});
emitDiagnosticEvent({
type: "message.queued",
source: "plugin",
trace,
});
emitTrustedDiagnosticEvent({
type: "model.usage",
usage: { total: 1 },
trace,
});
expect(traceparents).toEqual([undefined, `00-${trace.traceId}-${trace.spanId}-01`]);
expect(formatDiagnosticTraceparentForPropagation({ trace }, { trusted: true })).toBeUndefined();
expect(
formatDiagnosticTraceparentForPropagation(
{ trace },
{ trusted: false, trustedTraceContext: true },
),
).toBeUndefined();
});
it("prepares trusted events synchronously without cloning private data", async () => {
const diagnosticTrace = createDiagnosticTraceContext({
traceId: "4bf92f3577b34da6a3ce929d0e0e4736",
+1 -18
View File
@@ -19,7 +19,6 @@ import {
type DiagnosticTraceContext,
} from "./diagnostic-trace-context.js";
import {
formatPropagatedDiagnosticTraceparent,
prepareDiagnosticTracePropagation,
resetDiagnosticTracePropagationForTest,
shouldPrepareDiagnosticTracePropagation,
@@ -959,7 +958,6 @@ type DiagnosticEventsGlobalState = {
const MAX_ASYNC_DIAGNOSTIC_EVENTS = 10_000;
const MAX_ASYNC_DIAGNOSTIC_EVENTS_PER_TURN = 100;
const DIAGNOSTIC_EVENTS_STATE_KEY = Symbol.for("openclaw.diagnosticEvents.state.v1");
const dispatchedTrustedDiagnosticMetadata = new WeakSet<object>();
const ASYNC_DIAGNOSTIC_EVENT_TYPES = new Set<DiagnosticEventPayload["type"]>([
"tool.execution.started",
"tool.execution.completed",
@@ -1145,11 +1143,7 @@ function dispatchDiagnosticEvent(
function createDiagnosticMetadataForListener(
metadata: DiagnosticEventMetadata,
): DiagnosticEventMetadata {
const listenerMetadata = Object.freeze({ ...metadata });
if (listenerMetadata.trusted) {
dispatchedTrustedDiagnosticMetadata.add(listenerMetadata);
}
return listenerMetadata;
return Object.freeze({ ...metadata });
}
function cloneDiagnosticEventForListener(event: DiagnosticEventPayload): DiagnosticEventPayload {
@@ -1585,17 +1579,6 @@ export function onDiagnosticEvent(listener: (evt: DiagnosticEventPayload) => voi
});
}
/** Formats traceparent only for trusted metadata created by the diagnostic dispatcher. */
export function formatDiagnosticTraceparentForPropagation(
event: { trace?: DiagnosticTraceContext },
metadata: DiagnosticEventMetadata,
): string | undefined {
if (!metadata.trusted || !dispatchedTrustedDiagnosticMetadata.has(metadata)) {
return undefined;
}
return formatPropagatedDiagnosticTraceparent(event.trace);
}
/** Returns whether listener metadata marks dispatcher-internal provenance. */
export function isInternalDiagnosticEventMetadata(metadata: DiagnosticEventMetadata): boolean {
return metadata.internal === true;