mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-26 04:15:48 -06:00
test(gateway): restore startup environment after servers (#120137)
* fix(test): restore gateway startup environment * fix(test): centralize gateway startup env cleanup * test(gateway): restore live startup environment * fix(test): complete gateway startup env lifecycle * test(gateway): restore raw server owner environment * test(qa): restore gateway producer environment
This commit is contained in:
committed by
Vincent Koc
parent
576c70e778
commit
fb04abdd0f
@@ -17,6 +17,7 @@ import {
|
||||
disconnectGatewayClient,
|
||||
getFreeGatewayPort,
|
||||
} from "../gateway/test-helpers.e2e.js";
|
||||
import { GATEWAY_STARTUP_MUTATED_ENV_KEYS } from "../gateway/test-helpers.env.js";
|
||||
import { captureEnv, setTestEnvValue } from "../test-utils/env.js";
|
||||
import { GATEWAY_CLIENT_MODES, GATEWAY_CLIENT_NAMES } from "../utils/message-channel.js";
|
||||
import { withTimeout } from "../utils/with-timeout.js";
|
||||
@@ -25,10 +26,10 @@ import type { ExecApprovalFollowupOutcome } from "./bash-tools.exec-types.js";
|
||||
|
||||
const TEST_ENV_KEYS = [
|
||||
"HOME",
|
||||
...GATEWAY_STARTUP_MUTATED_ENV_KEYS,
|
||||
"OPENCLAW_STATE_DIR",
|
||||
"OPENCLAW_CONFIG_PATH",
|
||||
"OPENCLAW_GATEWAY_TOKEN",
|
||||
"OPENCLAW_GATEWAY_PORT",
|
||||
"OPENCLAW_SKIP_CHANNELS",
|
||||
"OPENCLAW_SKIP_GMAIL_WATCHER",
|
||||
"OPENCLAW_SKIP_CRON",
|
||||
|
||||
@@ -47,7 +47,7 @@ const DEFAULT_LIVE_PARENT_MODEL = "openai/gpt-5.4";
|
||||
type LiveAcpAgent = "claude" | "codex" | "droid" | "gemini" | "opencode";
|
||||
|
||||
function snapshotAcpBindLiveEnv(): LiveEnvSnapshot {
|
||||
return snapshotLiveEnv(["CODEX_HOME", "OPENCLAW_GATEWAY_PORT"]);
|
||||
return snapshotLiveEnv(["CODEX_HOME"]);
|
||||
}
|
||||
|
||||
function resolveLiveTimeoutMs(raw: string | undefined, fallback: number): number {
|
||||
|
||||
@@ -41,7 +41,7 @@ const LIVE_TIMEOUT_MS = resolvePositiveInteger(
|
||||
);
|
||||
|
||||
function snapshotAcpSpawnDefaultsLiveEnv(): LiveEnvSnapshot {
|
||||
return snapshotLiveEnv(["CODEX_HOME", "OPENCLAW_GATEWAY_PORT"]);
|
||||
return snapshotLiveEnv(["CODEX_HOME"]);
|
||||
}
|
||||
|
||||
function resolvePositiveInteger(raw: string | undefined, fallback: number): number {
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
*/
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { testing as cliBackendsTesting } from "../agents/cli-backends.test-support.js";
|
||||
import { captureEnv } from "../test-utils/env.js";
|
||||
import { GATEWAY_STARTUP_MUTATED_ENV_KEYS } from "./test-helpers.env.js";
|
||||
|
||||
vi.mock("./client-start-readiness.js", () => ({
|
||||
startGatewayClientWhenEventLoopReady: async (client: { start: () => void }) => {
|
||||
@@ -12,6 +14,7 @@ vi.mock("./client-start-readiness.js", () => ({
|
||||
}));
|
||||
|
||||
describe("gateway cli backend live helpers", () => {
|
||||
const gatewayStartupEnv = captureEnv([...GATEWAY_STARTUP_MUTATED_ENV_KEYS]);
|
||||
let liveHelpers: typeof import("./gateway-cli-backend.live-helpers.js");
|
||||
|
||||
beforeAll(async () => {
|
||||
@@ -24,6 +27,7 @@ describe("gateway cli backend live helpers", () => {
|
||||
|
||||
afterEach(() => {
|
||||
vi.useRealTimers();
|
||||
gatewayStartupEnv.restore();
|
||||
cliBackendsTesting.resetDepsForTest();
|
||||
delete process.env.OPENCLAW_SKIP_CHANNELS;
|
||||
delete process.env.OPENCLAW_SKIP_PROVIDERS;
|
||||
@@ -53,9 +57,15 @@ describe("gateway cli backend live helpers", () => {
|
||||
process.env.OPENCLAW_TEST_MINIMAL_GATEWAY = "old-minimal";
|
||||
process.env.ANTHROPIC_API_KEY = "old-anthropic";
|
||||
process.env.ANTHROPIC_API_KEY_OLD = "old-anthropic-old";
|
||||
process.env.PATH = "old-path";
|
||||
process.env.OPENCLAW_GATEWAY_PORT = "old-port";
|
||||
process.env.OPENCLAW_PATH_BOOTSTRAPPED = "old-bootstrap";
|
||||
|
||||
const snapshot = snapshotCliBackendLiveEnv();
|
||||
applyCliBackendLiveEnv(new Set<string>());
|
||||
process.env.PATH = "gateway-path";
|
||||
process.env.OPENCLAW_GATEWAY_PORT = "gateway-port";
|
||||
process.env.OPENCLAW_PATH_BOOTSTRAPPED = "1";
|
||||
|
||||
expect(process.env.OPENCLAW_SKIP_CHANNELS).toBe("1");
|
||||
expect(process.env.OPENCLAW_SKIP_PROVIDERS).toBe("1");
|
||||
@@ -80,6 +90,9 @@ describe("gateway cli backend live helpers", () => {
|
||||
expect(process.env.OPENCLAW_TEST_MINIMAL_GATEWAY).toBe("old-minimal");
|
||||
expect(process.env.ANTHROPIC_API_KEY).toBe("old-anthropic");
|
||||
expect(process.env.ANTHROPIC_API_KEY_OLD).toBe("old-anthropic-old");
|
||||
expect(process.env.PATH).toBe("old-path");
|
||||
expect(process.env.OPENCLAW_GATEWAY_PORT).toBe("old-port");
|
||||
expect(process.env.OPENCLAW_PATH_BOOTSTRAPPED).toBe("old-bootstrap");
|
||||
});
|
||||
|
||||
it("defaults the model switch probe to Claude Sonnet -> Opus", async () => {
|
||||
|
||||
@@ -26,6 +26,7 @@ import { GATEWAY_CLIENT_MODES, GATEWAY_CLIENT_NAMES } from "../utils/message-cha
|
||||
import { sleep } from "../utils/sleep.js";
|
||||
import { startGatewayClientWhenEventLoopReady } from "./client-start-readiness.js";
|
||||
import { GatewayClient, type GatewayClientOptions } from "./client.js";
|
||||
import { restoreLiveEnv, snapshotLiveEnv, type LiveEnvSnapshot } from "./live-env-test-helpers.js";
|
||||
|
||||
// Aggregate docker live runs can contend on startup enough that the gateway
|
||||
// websocket handshake needs a wider budget than the single-provider reruns.
|
||||
@@ -49,21 +50,7 @@ export type CliBackendLiveModelSelection = {
|
||||
agentRuntime: { id: string };
|
||||
};
|
||||
|
||||
export type CliBackendLiveEnvSnapshot = {
|
||||
configPath?: string;
|
||||
stateDir?: string;
|
||||
token?: string;
|
||||
skipChannels?: string;
|
||||
skipProviders?: string;
|
||||
skipGmail?: string;
|
||||
skipCron?: string;
|
||||
skipCanvas?: string;
|
||||
skipBrowserControl?: string;
|
||||
bundledPluginsDir?: string;
|
||||
minimalGateway?: string;
|
||||
anthropicApiKey?: string;
|
||||
anthropicApiKeyOld?: string;
|
||||
};
|
||||
export type CliBackendLiveEnvSnapshot = LiveEnvSnapshot;
|
||||
|
||||
export const CLI_BACKEND_LIVE_PROVIDER_SKIP_ENV = "OPENCLAW_LIVE_CLI_BACKEND_ALLOW_PROVIDER_SKIP";
|
||||
export const CLI_BACKEND_LIVE_ADVISORY_ENV = "OPENCLAW_LIVE_CLI_BACKEND_ADVISORY";
|
||||
@@ -550,21 +537,13 @@ function isRetryableGatewayConnectError(error: Error): boolean {
|
||||
}
|
||||
|
||||
export function snapshotCliBackendLiveEnv(): CliBackendLiveEnvSnapshot {
|
||||
return {
|
||||
configPath: process.env.OPENCLAW_CONFIG_PATH,
|
||||
stateDir: process.env.OPENCLAW_STATE_DIR,
|
||||
token: process.env.OPENCLAW_GATEWAY_TOKEN,
|
||||
skipChannels: process.env.OPENCLAW_SKIP_CHANNELS,
|
||||
skipProviders: process.env.OPENCLAW_SKIP_PROVIDERS,
|
||||
skipGmail: process.env.OPENCLAW_SKIP_GMAIL_WATCHER,
|
||||
skipCron: process.env.OPENCLAW_SKIP_CRON,
|
||||
skipCanvas: process.env.OPENCLAW_SKIP_CANVAS_HOST,
|
||||
skipBrowserControl: process.env.OPENCLAW_SKIP_BROWSER_CONTROL_SERVER,
|
||||
bundledPluginsDir: process.env.OPENCLAW_BUNDLED_PLUGINS_DIR,
|
||||
minimalGateway: process.env.OPENCLAW_TEST_MINIMAL_GATEWAY,
|
||||
anthropicApiKey: process.env.ANTHROPIC_API_KEY,
|
||||
anthropicApiKeyOld: process.env.ANTHROPIC_API_KEY_OLD,
|
||||
};
|
||||
return snapshotLiveEnv([
|
||||
"OPENCLAW_SKIP_PROVIDERS",
|
||||
"OPENCLAW_BUNDLED_PLUGINS_DIR",
|
||||
"OPENCLAW_TEST_MINIMAL_GATEWAY",
|
||||
"ANTHROPIC_API_KEY",
|
||||
"ANTHROPIC_API_KEY_OLD",
|
||||
]);
|
||||
}
|
||||
|
||||
export function applyCliBackendLiveEnv(preservedEnv: ReadonlySet<string>): void {
|
||||
@@ -584,27 +563,7 @@ export function applyCliBackendLiveEnv(preservedEnv: ReadonlySet<string>): void
|
||||
}
|
||||
|
||||
export function restoreCliBackendLiveEnv(snapshot: CliBackendLiveEnvSnapshot): void {
|
||||
restoreEnvVar("OPENCLAW_CONFIG_PATH", snapshot.configPath);
|
||||
restoreEnvVar("OPENCLAW_STATE_DIR", snapshot.stateDir);
|
||||
restoreEnvVar("OPENCLAW_GATEWAY_TOKEN", snapshot.token);
|
||||
restoreEnvVar("OPENCLAW_SKIP_CHANNELS", snapshot.skipChannels);
|
||||
restoreEnvVar("OPENCLAW_SKIP_PROVIDERS", snapshot.skipProviders);
|
||||
restoreEnvVar("OPENCLAW_SKIP_GMAIL_WATCHER", snapshot.skipGmail);
|
||||
restoreEnvVar("OPENCLAW_SKIP_CRON", snapshot.skipCron);
|
||||
restoreEnvVar("OPENCLAW_SKIP_CANVAS_HOST", snapshot.skipCanvas);
|
||||
restoreEnvVar("OPENCLAW_SKIP_BROWSER_CONTROL_SERVER", snapshot.skipBrowserControl);
|
||||
restoreEnvVar("OPENCLAW_BUNDLED_PLUGINS_DIR", snapshot.bundledPluginsDir);
|
||||
restoreEnvVar("OPENCLAW_TEST_MINIMAL_GATEWAY", snapshot.minimalGateway);
|
||||
restoreEnvVar("ANTHROPIC_API_KEY", snapshot.anthropicApiKey);
|
||||
restoreEnvVar("ANTHROPIC_API_KEY_OLD", snapshot.anthropicApiKeyOld);
|
||||
}
|
||||
|
||||
function restoreEnvVar(name: string, value: string | undefined): void {
|
||||
if (value === undefined) {
|
||||
delete process.env[name];
|
||||
return;
|
||||
}
|
||||
process.env[name] = value;
|
||||
restoreLiveEnv(snapshot);
|
||||
}
|
||||
|
||||
export async function ensurePairedTestGatewayClientIdentity(params?: {
|
||||
|
||||
@@ -80,6 +80,8 @@ import { deleteTestEnvValue, setTestEnvValue } from "../test-utils/env.js";
|
||||
import { getFreePort, isPortFree } from "../test-utils/ports.js";
|
||||
import { GATEWAY_CLIENT_MODES, GATEWAY_CLIENT_NAMES } from "../utils/message-channel.js";
|
||||
import { GatewayClient } from "./client.js";
|
||||
import { restoreLiveEnv, snapshotLiveEnv } from "./live-env-test-helpers.js";
|
||||
import type { GatewayServer } from "./server-public.js";
|
||||
|
||||
type ProviderThinkingModelCompat = {
|
||||
thinkingFormat?: string;
|
||||
@@ -92,7 +94,6 @@ import {
|
||||
shouldRetryExecReadProbe,
|
||||
shouldRetryToolReadProbe,
|
||||
} from "./live-tool-probe.test-helpers.js";
|
||||
import { startGatewayServer } from "./server.impl.js";
|
||||
import { readSessionMessagesAsync } from "./session-transcript-readers.js";
|
||||
import { loadSessionEntry } from "./session-utils.js";
|
||||
|
||||
@@ -4570,25 +4571,19 @@ async function runGatewayModelSuite(params: GatewayModelSuiteParams) {
|
||||
);
|
||||
}
|
||||
const [ultraUpstreamBaseUrl] = [...ultraUpstreamBaseUrls];
|
||||
const previous = {
|
||||
configPath: process.env.OPENCLAW_CONFIG_PATH,
|
||||
token: process.env.OPENCLAW_GATEWAY_TOKEN,
|
||||
skipChannels: process.env.OPENCLAW_SKIP_CHANNELS,
|
||||
skipGmail: process.env.OPENCLAW_SKIP_GMAIL_WATCHER,
|
||||
skipCron: process.env.OPENCLAW_SKIP_CRON,
|
||||
skipCanvas: process.env.OPENCLAW_SKIP_CANVAS_HOST,
|
||||
disableBonjour: process.env.OPENCLAW_DISABLE_BONJOUR,
|
||||
logLevel: process.env.OPENCLAW_LOG_LEVEL,
|
||||
agentDir: process.env.OPENCLAW_AGENT_DIR,
|
||||
stateDir: process.env.OPENCLAW_STATE_DIR,
|
||||
};
|
||||
const previousEnv = snapshotLiveEnv([
|
||||
"OPENCLAW_DISABLE_BONJOUR",
|
||||
"OPENCLAW_LOG_LEVEL",
|
||||
"OPENCLAW_AGENT_DIR",
|
||||
]);
|
||||
const { startGatewayServer } = await import("./server.impl.js");
|
||||
let runtimeEnv: ReturnType<typeof enterProductionEnvForLiveRun> | undefined;
|
||||
let cleanupTempStateDir: string | undefined;
|
||||
let cleanupTempAgentDir: string | undefined;
|
||||
let cleanupToolProbePath: string | undefined;
|
||||
let cleanupTempDir: string | undefined;
|
||||
let ultraWireCapture: OpenAIUltraWireCapture | undefined;
|
||||
let server: Awaited<ReturnType<typeof startGatewayServer>> | undefined;
|
||||
let server: GatewayServer | undefined;
|
||||
let client: GatewayClient | undefined;
|
||||
|
||||
try {
|
||||
@@ -5481,16 +5476,7 @@ async function runGatewayModelSuite(params: GatewayModelSuiteParams) {
|
||||
if (runtimeEnv) {
|
||||
restoreProductionEnvForLiveRun(runtimeEnv);
|
||||
}
|
||||
restoreOptionalEnv("OPENCLAW_CONFIG_PATH", previous.configPath);
|
||||
restoreOptionalEnv("OPENCLAW_GATEWAY_TOKEN", previous.token);
|
||||
restoreOptionalEnv("OPENCLAW_SKIP_CHANNELS", previous.skipChannels);
|
||||
restoreOptionalEnv("OPENCLAW_SKIP_GMAIL_WATCHER", previous.skipGmail);
|
||||
restoreOptionalEnv("OPENCLAW_SKIP_CRON", previous.skipCron);
|
||||
restoreOptionalEnv("OPENCLAW_SKIP_CANVAS_HOST", previous.skipCanvas);
|
||||
restoreOptionalEnv("OPENCLAW_DISABLE_BONJOUR", previous.disableBonjour);
|
||||
restoreOptionalEnv("OPENCLAW_LOG_LEVEL", previous.logLevel);
|
||||
restoreOptionalEnv("OPENCLAW_AGENT_DIR", previous.agentDir);
|
||||
restoreOptionalEnv("OPENCLAW_STATE_DIR", previous.stateDir);
|
||||
restoreLiveEnv(previousEnv);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5747,16 +5733,8 @@ describeLive("gateway live (dev agent, profile keys)", () => {
|
||||
}
|
||||
clearRuntimeConfigSnapshot();
|
||||
const runtimeEnv = enterProductionEnvForLiveRun();
|
||||
const previous = {
|
||||
configPath: process.env.OPENCLAW_CONFIG_PATH,
|
||||
token: process.env.OPENCLAW_GATEWAY_TOKEN,
|
||||
skipChannels: process.env.OPENCLAW_SKIP_CHANNELS,
|
||||
skipGmail: process.env.OPENCLAW_SKIP_GMAIL_WATCHER,
|
||||
skipCron: process.env.OPENCLAW_SKIP_CRON,
|
||||
skipCanvas: process.env.OPENCLAW_SKIP_CANVAS_HOST,
|
||||
agentDir: process.env.OPENCLAW_AGENT_DIR,
|
||||
stateDir: process.env.OPENCLAW_STATE_DIR,
|
||||
};
|
||||
const previousEnv = snapshotLiveEnv(["OPENCLAW_AGENT_DIR"]);
|
||||
const { startGatewayServer } = await import("./server.impl.js");
|
||||
|
||||
process.env.OPENCLAW_SKIP_CHANNELS = "1";
|
||||
process.env.OPENCLAW_SKIP_GMAIL_WATCHER = "1";
|
||||
@@ -5766,7 +5744,7 @@ describeLive("gateway live (dev agent, profile keys)", () => {
|
||||
const token = `test-${randomUUID()}`;
|
||||
process.env.OPENCLAW_GATEWAY_TOKEN = token;
|
||||
|
||||
let server: Awaited<ReturnType<typeof startGatewayServer>> | undefined;
|
||||
let server: GatewayServer | undefined;
|
||||
let client: GatewayClient | undefined;
|
||||
let toolProbePath: string | undefined;
|
||||
let tempDir: string | undefined;
|
||||
@@ -5972,14 +5950,7 @@ describeLive("gateway live (dev agent, profile keys)", () => {
|
||||
});
|
||||
}
|
||||
|
||||
restoreOptionalEnv("OPENCLAW_CONFIG_PATH", previous.configPath);
|
||||
restoreOptionalEnv("OPENCLAW_GATEWAY_TOKEN", previous.token);
|
||||
restoreOptionalEnv("OPENCLAW_SKIP_CHANNELS", previous.skipChannels);
|
||||
restoreOptionalEnv("OPENCLAW_SKIP_GMAIL_WATCHER", previous.skipGmail);
|
||||
restoreOptionalEnv("OPENCLAW_SKIP_CRON", previous.skipCron);
|
||||
restoreOptionalEnv("OPENCLAW_SKIP_CANVAS_HOST", previous.skipCanvas);
|
||||
restoreOptionalEnv("OPENCLAW_AGENT_DIR", previous.agentDir);
|
||||
restoreOptionalEnv("OPENCLAW_STATE_DIR", previous.stateDir);
|
||||
restoreLiveEnv(previousEnv);
|
||||
}
|
||||
}, 180_000);
|
||||
});
|
||||
|
||||
@@ -15,10 +15,12 @@ import {
|
||||
disconnectGatewayClient,
|
||||
getFreeGatewayPort,
|
||||
} from "./test-helpers.e2e.js";
|
||||
import { GATEWAY_STARTUP_MUTATED_ENV_KEYS } from "./test-helpers.env.js";
|
||||
|
||||
const GATEWAY_E2E_TIMEOUT_MS = 90_000;
|
||||
const ENV_KEYS = [
|
||||
"HOME",
|
||||
...GATEWAY_STARTUP_MUTATED_ENV_KEYS,
|
||||
"OPENCLAW_STATE_DIR",
|
||||
"OPENCLAW_CONFIG_PATH",
|
||||
"OPENCLAW_GATEWAY_TOKEN",
|
||||
|
||||
@@ -28,6 +28,7 @@ import {
|
||||
getFreeGatewayPort,
|
||||
startGatewayWithClient,
|
||||
} from "./test-helpers.e2e.js";
|
||||
import { GATEWAY_STARTUP_MUTATED_ENV_KEYS } from "./test-helpers.env.js";
|
||||
import { installOpenAiResponsesMock } from "./test-helpers.openai-mock.js";
|
||||
import { buildMockOpenAiResponsesProvider } from "./test-openai-responses-model.js";
|
||||
|
||||
@@ -36,6 +37,7 @@ const GATEWAY_E2E_TIMEOUT_MS = 90_000;
|
||||
let gatewayTestSeq = 0;
|
||||
const GATEWAY_TEST_ENV_KEYS = [
|
||||
"HOME",
|
||||
...GATEWAY_STARTUP_MUTATED_ENV_KEYS,
|
||||
"OPENCLAW_STATE_DIR",
|
||||
"OPENCLAW_CONFIG_PATH",
|
||||
"OPENCLAW_GATEWAY_TOKEN",
|
||||
@@ -986,17 +988,7 @@ module.exports = {
|
||||
{ timeout: GATEWAY_E2E_TIMEOUT_MS },
|
||||
async () => {
|
||||
const envSnapshot = captureEnv([
|
||||
"HOME",
|
||||
"OPENCLAW_STATE_DIR",
|
||||
"OPENCLAW_CONFIG_PATH",
|
||||
"OPENCLAW_GATEWAY_TOKEN",
|
||||
"OPENCLAW_SKIP_CHANNELS",
|
||||
"OPENCLAW_SKIP_GMAIL_WATCHER",
|
||||
"OPENCLAW_SKIP_CRON",
|
||||
"OPENCLAW_SKIP_CANVAS_HOST",
|
||||
"OPENCLAW_SKIP_BROWSER_CONTROL_SERVER",
|
||||
"OPENCLAW_SKIP_PROVIDERS",
|
||||
"OPENCLAW_BUNDLED_PLUGINS_DIR",
|
||||
...GATEWAY_TEST_ENV_KEYS,
|
||||
"OPENCLAW_TEST_MINIMAL_GATEWAY",
|
||||
"DISCORD_BOT_TOKEN",
|
||||
]);
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
* Environment snapshot helpers for live gateway tests.
|
||||
*/
|
||||
import { deleteTestEnvValue, setTestEnvValue } from "../test-utils/env.js";
|
||||
import { GATEWAY_STARTUP_MUTATED_ENV_KEYS } from "./test-helpers.env.js";
|
||||
|
||||
const COMMON_LIVE_ENV_NAMES = [
|
||||
...GATEWAY_STARTUP_MUTATED_ENV_KEYS,
|
||||
"OPENCLAW_AGENT_RUNTIME",
|
||||
"OPENCLAW_CONFIG_PATH",
|
||||
"OPENCLAW_GATEWAY_TOKEN",
|
||||
|
||||
@@ -24,15 +24,16 @@ import {
|
||||
disconnectGatewayClient,
|
||||
getFreeGatewayPort,
|
||||
} from "./test-helpers.e2e.js";
|
||||
import { GATEWAY_STARTUP_MUTATED_ENV_KEYS } from "./test-helpers.env.js";
|
||||
|
||||
const TEST_ENV_KEYS = [
|
||||
"HOME",
|
||||
...GATEWAY_STARTUP_MUTATED_ENV_KEYS,
|
||||
"OPENCLAW_STATE_DIR",
|
||||
"OPENCLAW_CONFIG_PATH",
|
||||
"OPENCLAW_GATEWAY_URL",
|
||||
"OPENCLAW_GATEWAY_TOKEN",
|
||||
"OPENCLAW_GATEWAY_PASSWORD",
|
||||
"OPENCLAW_GATEWAY_PORT",
|
||||
];
|
||||
|
||||
type Cleanup = () => Promise<void> | void;
|
||||
|
||||
@@ -22,15 +22,16 @@ import {
|
||||
disconnectGatewayClient,
|
||||
getFreeGatewayPort,
|
||||
} from "../test-helpers.e2e.js";
|
||||
import { GATEWAY_STARTUP_MUTATED_ENV_KEYS } from "../test-helpers.env.js";
|
||||
|
||||
const TEST_ENV_KEYS = [
|
||||
"HOME",
|
||||
...GATEWAY_STARTUP_MUTATED_ENV_KEYS,
|
||||
"OPENCLAW_STATE_DIR",
|
||||
"OPENCLAW_CONFIG_PATH",
|
||||
"OPENCLAW_GATEWAY_URL",
|
||||
"OPENCLAW_GATEWAY_TOKEN",
|
||||
"OPENCLAW_GATEWAY_PASSWORD",
|
||||
"OPENCLAW_GATEWAY_PORT",
|
||||
];
|
||||
|
||||
describe("plugin.approval.request delivery routing (real gateway)", () => {
|
||||
|
||||
@@ -11,9 +11,11 @@ import { PROXY_ENV_KEYS } from "../infra/net/proxy-env.js";
|
||||
import { captureEnv, deleteTestEnvValue, setTestEnvValue } from "../test-utils/env.js";
|
||||
import { startGatewayServer } from "./server.js";
|
||||
import { getFreeGatewayPort } from "./test-helpers.e2e.js";
|
||||
import { GATEWAY_STARTUP_MUTATED_ENV_KEYS } from "./test-helpers.env.js";
|
||||
|
||||
const NETWORK_GATEWAY_ENV_KEYS = [
|
||||
"HOME",
|
||||
...GATEWAY_STARTUP_MUTATED_ENV_KEYS,
|
||||
"OPENCLAW_STATE_DIR",
|
||||
"OPENCLAW_CONFIG_PATH",
|
||||
"OPENCLAW_GATEWAY_TOKEN",
|
||||
|
||||
@@ -30,8 +30,6 @@ export async function resetPreparedModelCatalogForTest(): Promise<void> {
|
||||
await resetPreparedModelCatalogForTestLocal();
|
||||
}
|
||||
|
||||
ensureOpenClawCliOnPath();
|
||||
|
||||
const loadGatewayStartupEarlyModule = createLazyRuntimeModule(
|
||||
() => import("./server-startup-early.js"),
|
||||
);
|
||||
@@ -108,6 +106,7 @@ export async function startGatewayServer(
|
||||
port = 18789,
|
||||
opts: GatewayServerOptions = {},
|
||||
): Promise<GatewayServer> {
|
||||
ensureOpenClawCliOnPath();
|
||||
let releasePostReadyWork: () => void = () => {};
|
||||
const postReadyWorkBarrier = new Promise<void>((resolve) => {
|
||||
releasePostReadyWork = resolve;
|
||||
|
||||
@@ -12,8 +12,8 @@ import {
|
||||
signDevicePayload,
|
||||
} from "../infra/device-identity.js";
|
||||
import { buildDeviceAuthPayload } from "./device-auth.js";
|
||||
import { shouldRetainControlUiDeviceAuthMigrationSession } from "./server-public.js";
|
||||
import { CONTROL_UI_CLIENT } from "./server.auth.test-helpers.js";
|
||||
import { shouldRetainControlUiDeviceAuthMigrationSession } from "./server.impl.js";
|
||||
import {
|
||||
connectReq,
|
||||
createGatewaySuiteHarness,
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
signDevicePayload,
|
||||
} from "../infra/device-identity.js";
|
||||
import { rawDataToString } from "../infra/ws.js";
|
||||
import { captureEnv } from "../test-utils/env.js";
|
||||
import { getDeterministicFreePortBlock } from "../test-utils/ports.js";
|
||||
import {
|
||||
GATEWAY_CLIENT_MODES,
|
||||
@@ -25,6 +26,7 @@ import {
|
||||
import { GatewayClient } from "./client.js";
|
||||
import { buildDeviceAuthPayloadV3 } from "./device-auth.js";
|
||||
import { startGatewayServer } from "./server.js";
|
||||
import { GATEWAY_STARTUP_MUTATED_ENV_KEYS } from "./test-helpers.env.js";
|
||||
|
||||
/** Reserve a deterministic free port block for Gateway E2E tests. */
|
||||
export async function getFreeGatewayPort(): Promise<number> {
|
||||
@@ -263,23 +265,47 @@ export async function startGatewayWithClient(params: {
|
||||
token: string;
|
||||
clientDisplayName?: string;
|
||||
}) {
|
||||
await writeFile(params.configPath, `${JSON.stringify(params.cfg, null, 2)}\n`);
|
||||
process.env.OPENCLAW_CONFIG_PATH = params.configPath;
|
||||
clearRuntimeConfigSnapshot();
|
||||
clearConfigCache();
|
||||
clearSessionStoreCacheForTest();
|
||||
const gatewayStartupEnv = captureEnv([...GATEWAY_STARTUP_MUTATED_ENV_KEYS]);
|
||||
let server: Awaited<ReturnType<typeof startGatewayServer>> | undefined;
|
||||
try {
|
||||
await writeFile(params.configPath, `${JSON.stringify(params.cfg, null, 2)}\n`);
|
||||
process.env.OPENCLAW_CONFIG_PATH = params.configPath;
|
||||
clearRuntimeConfigSnapshot();
|
||||
clearConfigCache();
|
||||
clearSessionStoreCacheForTest();
|
||||
|
||||
const port = await getFreeGatewayPort();
|
||||
const server = await startGatewayServer(port, {
|
||||
bind: "loopback",
|
||||
auth: { mode: "token", token: params.token },
|
||||
controlUiEnabled: false,
|
||||
});
|
||||
const client = await connectGatewayClient({
|
||||
url: `ws://127.0.0.1:${port}`,
|
||||
token: params.token,
|
||||
clientDisplayName: params.clientDisplayName,
|
||||
});
|
||||
const port = await getFreeGatewayPort();
|
||||
const startedServer = await startGatewayServer(port, {
|
||||
bind: "loopback",
|
||||
auth: { mode: "token", token: params.token },
|
||||
controlUiEnabled: false,
|
||||
});
|
||||
server = startedServer;
|
||||
const client = await connectGatewayClient({
|
||||
url: `ws://127.0.0.1:${port}`,
|
||||
token: params.token,
|
||||
clientDisplayName: params.clientDisplayName,
|
||||
});
|
||||
|
||||
return { port, server, client };
|
||||
return {
|
||||
port,
|
||||
client,
|
||||
server: {
|
||||
close: async (...args: Parameters<typeof startedServer.close>) => {
|
||||
try {
|
||||
await startedServer.close(...args);
|
||||
} finally {
|
||||
gatewayStartupEnv.restore();
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
} catch (error) {
|
||||
try {
|
||||
await server?.close({ reason: "gateway E2E client setup failed" });
|
||||
} finally {
|
||||
gatewayStartupEnv.restore();
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// Gateway startup rewrites these process-wide values. Manual in-process test
|
||||
// owners must snapshot them so later files never inherit a closed server or stale PATH.
|
||||
export const GATEWAY_STARTUP_MUTATED_ENV_KEYS = [
|
||||
"PATH",
|
||||
"OPENCLAW_GATEWAY_PORT",
|
||||
"OPENCLAW_PATH_BOOTSTRAPPED",
|
||||
] as const;
|
||||
|
||||
/** Captures values that in-process Gateway startup can mutate. */
|
||||
export function snapshotGatewayStartupEnv(): Record<string, string | undefined> {
|
||||
return Object.fromEntries(GATEWAY_STARTUP_MUTATED_ENV_KEYS.map((key) => [key, process.env[key]]));
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
import path from "node:path";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { deleteTestEnvValue, setTestEnvValue } from "../test-utils/env.js";
|
||||
import { disconnectGatewayClient, startGatewayWithClient } from "./test-helpers.e2e.js";
|
||||
import { installGatewayTestHooks, withGatewayServer } from "./test-helpers.server.js";
|
||||
|
||||
const envBeforeSuite = {
|
||||
PATH: process.env.PATH,
|
||||
OPENCLAW_GATEWAY_PORT: process.env.OPENCLAW_GATEWAY_PORT,
|
||||
OPENCLAW_PATH_BOOTSTRAPPED: process.env.OPENCLAW_PATH_BOOTSTRAPPED,
|
||||
};
|
||||
|
||||
installGatewayTestHooks();
|
||||
|
||||
describe("Gateway test environment lifecycle", () => {
|
||||
it("records the process-wide startup environment", async () => {
|
||||
await withGatewayServer(async ({ port }) => {
|
||||
expect(process.env.OPENCLAW_GATEWAY_PORT).toBe(String(port));
|
||||
expect(process.env.OPENCLAW_PATH_BOOTSTRAPPED).toBe("1");
|
||||
});
|
||||
});
|
||||
|
||||
it("restores startup-owned environment before the next test", () => {
|
||||
expect({
|
||||
PATH: process.env.PATH,
|
||||
OPENCLAW_GATEWAY_PORT: process.env.OPENCLAW_GATEWAY_PORT,
|
||||
OPENCLAW_PATH_BOOTSTRAPPED: process.env.OPENCLAW_PATH_BOOTSTRAPPED,
|
||||
}).toEqual(envBeforeSuite);
|
||||
});
|
||||
|
||||
it("restores startup-owned environment when a direct E2E server closes", async () => {
|
||||
const stateDir = process.env.OPENCLAW_STATE_DIR;
|
||||
if (!stateDir) {
|
||||
throw new Error("OPENCLAW_STATE_DIR is required");
|
||||
}
|
||||
setTestEnvValue("PATH", process.env.PATH ?? "");
|
||||
deleteTestEnvValue("OPENCLAW_PATH_BOOTSTRAPPED");
|
||||
const envBeforeServer = {
|
||||
PATH: process.env.PATH,
|
||||
OPENCLAW_GATEWAY_PORT: process.env.OPENCLAW_GATEWAY_PORT,
|
||||
OPENCLAW_PATH_BOOTSTRAPPED: process.env.OPENCLAW_PATH_BOOTSTRAPPED,
|
||||
};
|
||||
const token = "test-gateway-token-1234567890";
|
||||
for (const attempt of ["first", "second"]) {
|
||||
const started = await startGatewayWithClient({
|
||||
cfg: { gateway: { auth: { mode: "token", token } } },
|
||||
configPath: path.join(stateDir, "openclaw.json"),
|
||||
token,
|
||||
});
|
||||
|
||||
try {
|
||||
expect(process.env.OPENCLAW_GATEWAY_PORT).toBe(String(started.port));
|
||||
expect(process.env.OPENCLAW_PATH_BOOTSTRAPPED).toBe("1");
|
||||
} finally {
|
||||
await disconnectGatewayClient(started.client).catch(() => undefined);
|
||||
await started.server.close({
|
||||
reason: `${attempt} direct E2E environment proof complete`,
|
||||
});
|
||||
}
|
||||
|
||||
expect({
|
||||
PATH: process.env.PATH,
|
||||
OPENCLAW_GATEWAY_PORT: process.env.OPENCLAW_GATEWAY_PORT,
|
||||
OPENCLAW_PATH_BOOTSTRAPPED: process.env.OPENCLAW_PATH_BOOTSTRAPPED,
|
||||
}).toEqual(envBeforeServer);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -60,6 +60,7 @@ import { GATEWAY_CLIENT_MODES, GATEWAY_CLIENT_NAMES } from "../utils/message-cha
|
||||
import { buildDeviceAuthPayloadV3 } from "./device-auth.js";
|
||||
import type { GatewayServerOptions } from "./server.js";
|
||||
import { invalidateSessionSharingSnapshot } from "./session-sharing.js";
|
||||
import { GATEWAY_STARTUP_MUTATED_ENV_KEYS } from "./test-helpers.env.js";
|
||||
import { resetTestPluginRegistry } from "./test-helpers.plugin-registry.js";
|
||||
import {
|
||||
agentCommand,
|
||||
@@ -80,6 +81,7 @@ const getServerModule = createLazyRuntimeModule(() => import("./server.js"));
|
||||
const GATEWAY_TEST_ENV_KEYS = [
|
||||
"HOME",
|
||||
"USERPROFILE",
|
||||
...GATEWAY_STARTUP_MUTATED_ENV_KEYS,
|
||||
"OPENCLAW_STATE_DIR",
|
||||
"OPENCLAW_CONFIG_PATH",
|
||||
"OPENCLAW_AGENT_DIR",
|
||||
|
||||
@@ -4,6 +4,10 @@ import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { loadPersistedAuthProfileStore } from "../agents/auth-profiles/persisted.js";
|
||||
import {
|
||||
GATEWAY_STARTUP_MUTATED_ENV_KEYS,
|
||||
snapshotGatewayStartupEnv,
|
||||
} from "../gateway/test-helpers.env.js";
|
||||
import {
|
||||
closeOpenClawAgentDatabaseByPath,
|
||||
openOpenClawAgentDatabase,
|
||||
@@ -12,7 +16,7 @@ import {
|
||||
closeOpenClawStateDatabaseByPath,
|
||||
openOpenClawStateDatabase,
|
||||
} from "../state/openclaw-state-db.js";
|
||||
import { withEnvAsync } from "./env.js";
|
||||
import { setTestEnvValue, withEnvAsync } from "./env.js";
|
||||
import { createOpenClawTestState, withOpenClawTestState } from "./openclaw-test-state.js";
|
||||
|
||||
async function expectPathMissing(targetPath: string): Promise<void> {
|
||||
@@ -31,6 +35,7 @@ describe("openclaw test state", () => {
|
||||
const previousOpenClawHome = process.env.OPENCLAW_HOME;
|
||||
const previousStateDir = process.env.OPENCLAW_STATE_DIR;
|
||||
const previousConfigPath = process.env.OPENCLAW_CONFIG_PATH;
|
||||
const previousGatewayStartupEnv = snapshotGatewayStartupEnv();
|
||||
|
||||
const state = await createOpenClawTestState({
|
||||
label: "unit",
|
||||
@@ -49,6 +54,9 @@ describe("openclaw test state", () => {
|
||||
expect(process.env.HOME).toBe(state.home);
|
||||
expect(process.env.OPENCLAW_HOME).toBe(state.home);
|
||||
expect(JSON.parse(await fs.readFile(state.configPath, "utf8"))).toStrictEqual({});
|
||||
for (const key of GATEWAY_STARTUP_MUTATED_ENV_KEYS) {
|
||||
setTestEnvValue(key, `mutated-${key}`);
|
||||
}
|
||||
} finally {
|
||||
await state.cleanup();
|
||||
}
|
||||
@@ -57,6 +65,7 @@ describe("openclaw test state", () => {
|
||||
expect(process.env.OPENCLAW_HOME).toBe(previousOpenClawHome);
|
||||
expect(process.env.OPENCLAW_STATE_DIR).toBe(previousStateDir);
|
||||
expect(process.env.OPENCLAW_CONFIG_PATH).toBe(previousConfigPath);
|
||||
expect(snapshotGatewayStartupEnv()).toEqual(previousGatewayStartupEnv);
|
||||
await expectPathMissing(state.root);
|
||||
});
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import { resolveAuthProfileDatabasePath } from "../agents/auth-profiles/sqlite.j
|
||||
import { saveAuthProfileStore } from "../agents/auth-profiles/store.js";
|
||||
import type { AuthProfileStore } from "../agents/auth-profiles/types.js";
|
||||
import * as configRuntime from "../config/config.js";
|
||||
import { GATEWAY_STARTUP_MUTATED_ENV_KEYS } from "../gateway/test-helpers.env.js";
|
||||
import { isPathInside } from "../infra/path-guards.js";
|
||||
import {
|
||||
closeOpenClawAgentDatabaseByPath,
|
||||
@@ -72,6 +73,7 @@ const ENV_KEYS = [
|
||||
"USERPROFILE",
|
||||
"HOMEDRIVE",
|
||||
"HOMEPATH",
|
||||
...GATEWAY_STARTUP_MUTATED_ENV_KEYS,
|
||||
"OPENCLAW_HOME",
|
||||
"OPENCLAW_STATE_DIR",
|
||||
"OPENCLAW_CONFIG_PATH",
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
disconnectGatewayClient,
|
||||
getFreeGatewayPort,
|
||||
} from "../../../../src/gateway/test-helpers.e2e.js";
|
||||
import { GATEWAY_STARTUP_MUTATED_ENV_KEYS } from "../../../../src/gateway/test-helpers.env.js";
|
||||
import { closeOpenClawAgentDatabasesForTest } from "../../../../src/state/openclaw-agent-db.js";
|
||||
import { closeOpenClawStateDatabaseForTest } from "../../../../src/state/openclaw-state-db.js";
|
||||
import { createTaskRecord, deleteTaskRecordById } from "../../../../src/tasks/task-registry.js";
|
||||
@@ -120,11 +121,11 @@ vi.mock("../../../../src/gateway/server-request-context.js", async () => {
|
||||
|
||||
const ENV_KEYS = [
|
||||
"HOME",
|
||||
...GATEWAY_STARTUP_MUTATED_ENV_KEYS,
|
||||
"OPENCLAW_STATE_DIR",
|
||||
"OPENCLAW_CONFIG_PATH",
|
||||
"OPENCLAW_GATEWAY_TOKEN",
|
||||
"OPENCLAW_GATEWAY_PASSWORD",
|
||||
"OPENCLAW_GATEWAY_PORT",
|
||||
"OPENCLAW_SKIP_CHANNELS",
|
||||
"OPENCLAW_SKIP_GMAIL_WATCHER",
|
||||
"OPENCLAW_SKIP_CRON",
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
disconnectGatewayClient,
|
||||
getFreeGatewayPort,
|
||||
} from "../../../../src/gateway/test-helpers.e2e.js";
|
||||
import { snapshotGatewayStartupEnv } from "../../../../src/gateway/test-helpers.env.js";
|
||||
import {
|
||||
registerPluginHttpRoute,
|
||||
withPluginHttpRouteRegistry,
|
||||
@@ -139,6 +140,7 @@ describe("Gateway hosted web surfaces", () => {
|
||||
|
||||
await withEnvAsync(
|
||||
{
|
||||
...snapshotGatewayStartupEnv(),
|
||||
HOME: root,
|
||||
OPENCLAW_CONFIG_PATH: configPath,
|
||||
OPENCLAW_DISABLE_BUNDLED_PLUGINS: "1",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { snapshotGatewayStartupEnv } from "../../../../src/gateway/test-helpers.env.js";
|
||||
import {
|
||||
assertGatewayLoopbackLanProof,
|
||||
parseGatewayLoopbackLanOptions,
|
||||
@@ -36,7 +37,9 @@ describe("Gateway loopback and LAN access producer", () => {
|
||||
});
|
||||
|
||||
it("proves real loopback isolation, LAN reachability, and shared-token authentication", async () => {
|
||||
const gatewayStartupEnv = snapshotGatewayStartupEnv();
|
||||
const proof = await runGatewayLoopbackLanProof();
|
||||
expect(snapshotGatewayStartupEnv()).toEqual(gatewayStartupEnv);
|
||||
expect(proof).toEqual({
|
||||
loopback: {
|
||||
authenticatedHealthRpc: true,
|
||||
|
||||
@@ -13,6 +13,7 @@ import { clearSessionStoreCacheForTest } from "../../../../src/config/sessions/s
|
||||
import { pickPrimaryLanIPv4 } from "../../../../src/gateway/net.js";
|
||||
import { startGatewayServer, type GatewayServer } from "../../../../src/gateway/server.js";
|
||||
import { getFreeGatewayPort } from "../../../../src/gateway/test-helpers.e2e.js";
|
||||
import { GATEWAY_STARTUP_MUTATED_ENV_KEYS } from "../../../../src/gateway/test-helpers.env.js";
|
||||
import { resetAgentEventsForTest } from "../../../../src/infra/agent-events.js";
|
||||
import { rawDataToString } from "../../../../src/infra/ws.js";
|
||||
import { captureEnv, deleteTestEnvValue, setTestEnvValue } from "../../../../src/test-utils/env.js";
|
||||
@@ -27,6 +28,7 @@ const SCENARIO_ID = "gateway-loopback-lan-access";
|
||||
const PROBE_TIMEOUT_MS = 10_000;
|
||||
const ENV_KEYS = [
|
||||
"HOME",
|
||||
...GATEWAY_STARTUP_MUTATED_ENV_KEYS,
|
||||
"OPENCLAW_STATE_DIR",
|
||||
"OPENCLAW_CONFIG_PATH",
|
||||
"OPENCLAW_GATEWAY_TOKEN",
|
||||
|
||||
@@ -9,6 +9,7 @@ import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { promisify } from "node:util";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { snapshotGatewayStartupEnv } from "../../../../src/gateway/test-helpers.env.js";
|
||||
import { withEnvAsync } from "../../../../src/test-utils/env.js";
|
||||
import { waitForFile } from "../../../helpers/process-wait.js";
|
||||
import { useAutoCleanupTempDirTracker } from "../../../helpers/temp-dir.js";
|
||||
@@ -171,11 +172,13 @@ describeOnTestbox("Gateway SSH tunnel QA producer", () => {
|
||||
|
||||
it("proves real forwarding, cleanup, and operator diagnostics", async () => {
|
||||
const artifactBase = tempDirs.make("openclaw-gateway-ssh-evidence-");
|
||||
const gatewayStartupEnv = snapshotGatewayStartupEnv();
|
||||
const evidence = await runGatewaySshTunnels({
|
||||
artifactBase,
|
||||
repoRoot: process.cwd(),
|
||||
});
|
||||
|
||||
expect(snapshotGatewayStartupEnv()).toEqual(gatewayStartupEnv);
|
||||
expect(evidence.entries).toHaveLength(1);
|
||||
expect(evidence.entries[0]?.result.status).toBe("pass");
|
||||
const summary = JSON.parse(
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
import { gatewayStatusCommand } from "../../../../src/commands/gateway-status.js";
|
||||
import { clearConfigCache, clearRuntimeConfigSnapshot } from "../../../../src/config/config.js";
|
||||
import { startGatewayServer } from "../../../../src/gateway/server.js";
|
||||
import { snapshotGatewayStartupEnv } from "../../../../src/gateway/test-helpers.env.js";
|
||||
import { formatErrorMessage } from "../../../../src/infra/errors.js";
|
||||
import type { OutputRuntimeEnv } from "../../../../src/runtime.js";
|
||||
import { withEnvAsync } from "../../../../src/test-utils/env.js";
|
||||
@@ -581,6 +582,7 @@ export async function runGatewaySshTunnels(
|
||||
|
||||
const result = await withEnvAsync(
|
||||
{
|
||||
...snapshotGatewayStartupEnv(),
|
||||
HOME: homeDir,
|
||||
OPENCLAW_CONFIG_PATH: configPath,
|
||||
OPENCLAW_DISABLE_BUNDLED_PLUGINS: "1",
|
||||
|
||||
@@ -2,6 +2,7 @@ import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { snapshotGatewayStartupEnv } from "../../../../src/gateway/test-helpers.env.js";
|
||||
import { runGatewayTlsPinningProducer } from "./gateway-tls-pinning.js";
|
||||
|
||||
const tempDirs: string[] = [];
|
||||
@@ -14,12 +15,14 @@ describe("Gateway TLS pinning evidence", () => {
|
||||
it("proves the live listener fingerprint and public client pin policy", async () => {
|
||||
const artifactBase = await fs.mkdtemp(path.join(os.tmpdir(), "gateway-tls-pinning-evidence-"));
|
||||
tempDirs.push(artifactBase);
|
||||
const gatewayStartupEnv = snapshotGatewayStartupEnv();
|
||||
|
||||
const evidence = await runGatewayTlsPinningProducer({
|
||||
artifactBase,
|
||||
repoRoot: process.cwd(),
|
||||
});
|
||||
|
||||
expect(snapshotGatewayStartupEnv()).toEqual(gatewayStartupEnv);
|
||||
expect(evidence.entries[0]?.result.status).toBe("pass");
|
||||
const proof = JSON.parse(
|
||||
await fs.readFile(path.join(artifactBase, "gateway-tls-pinning-summary.json"), "utf8"),
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
} from "../../../../extensions/qa-lab/api.js";
|
||||
import { clearConfigCache, clearRuntimeConfigSnapshot } from "../../../../src/config/config.js";
|
||||
import { startGatewayServer } from "../../../../src/gateway/server.js";
|
||||
import { GATEWAY_STARTUP_MUTATED_ENV_KEYS } from "../../../../src/gateway/test-helpers.env.js";
|
||||
import { formatErrorMessage } from "../../../../src/infra/errors.js";
|
||||
import { normalizeFingerprint } from "../../../../src/infra/tls/fingerprint.js";
|
||||
import { loadGatewayTlsRuntime } from "../../../../src/infra/tls/gateway.js";
|
||||
@@ -24,6 +25,7 @@ const DISCOVERY_PLUGIN_ID = "tls-discovery-proof";
|
||||
const CONNECTION_TIMEOUT_MS = 15_000;
|
||||
const ENV_KEYS = [
|
||||
"HOME",
|
||||
...GATEWAY_STARTUP_MUTATED_ENV_KEYS,
|
||||
"NODE_ENV",
|
||||
"OPENCLAW_CONFIG_PATH",
|
||||
"OPENCLAW_STATE_DIR",
|
||||
|
||||
Reference in New Issue
Block a user