test: stabilize gateway suites
This commit is contained in:
@@ -17,7 +17,12 @@ export async function startGatewayDiscovery(params: {
|
||||
logDiscovery: { info: (msg: string) => void; warn: (msg: string) => void };
|
||||
}) {
|
||||
let bonjourStop: (() => Promise<void>) | null = null;
|
||||
const tailnetDns = await resolveTailnetDnsHint();
|
||||
const bonjourEnabled =
|
||||
process.env.CLAWDBOT_DISABLE_BONJOUR !== "1" &&
|
||||
process.env.NODE_ENV !== "test" &&
|
||||
!process.env.VITEST;
|
||||
const needsTailnetDns = bonjourEnabled || params.wideAreaDiscoveryEnabled;
|
||||
const tailnetDns = needsTailnetDns ? await resolveTailnetDnsHint() : undefined;
|
||||
const sshPortEnv = process.env.CLAWDBOT_SSH_PORT?.trim();
|
||||
const sshPortParsed = sshPortEnv ? Number.parseInt(sshPortEnv, 10) : NaN;
|
||||
const sshPort = Number.isFinite(sshPortParsed) && sshPortParsed > 0 ? sshPortParsed : undefined;
|
||||
|
||||
@@ -29,6 +29,10 @@ import {
|
||||
testTailnetIPv4,
|
||||
} from "./test-helpers.mocks.js";
|
||||
|
||||
// Preload the gateway server module once per worker.
|
||||
// Important: `test-helpers.mocks` must run before importing the server so vi.mock hooks apply.
|
||||
const serverModulePromise = import("./server.js");
|
||||
|
||||
let previousHome: string | undefined;
|
||||
let previousUserProfile: string | undefined;
|
||||
let previousStateDir: string | undefined;
|
||||
@@ -105,7 +109,7 @@ export function installGatewayTestHooks() {
|
||||
embeddedRunMock.waitResults.clear();
|
||||
drainSystemEvents(resolveMainSessionKeyFromConfig());
|
||||
resetAgentRunContextForTest();
|
||||
const mod = await import("./server.js");
|
||||
const mod = await serverModulePromise;
|
||||
mod.__resetModelCatalogCacheForTest();
|
||||
piSdkMock.enabled = false;
|
||||
piSdkMock.discoverCalls = 0;
|
||||
@@ -184,7 +188,7 @@ export function onceMessage<T = unknown>(
|
||||
}
|
||||
|
||||
export async function startGatewayServer(port: number, opts?: GatewayServerOptions) {
|
||||
const mod = await import("./server.js");
|
||||
const mod = await serverModulePromise;
|
||||
return await mod.startGatewayServer(port, opts);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,9 @@ function fallbackHostName() {
|
||||
export async function getMachineDisplayName(): Promise<string> {
|
||||
if (cachedPromise) return cachedPromise;
|
||||
cachedPromise = (async () => {
|
||||
if (process.env.VITEST || process.env.NODE_ENV === "test") {
|
||||
return fallbackHostName();
|
||||
}
|
||||
if (process.platform === "darwin") {
|
||||
const computerName = await tryScutil("ComputerName");
|
||||
if (computerName) return computerName;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { type AddressInfo, createServer } from "node:net";
|
||||
import { isMainThread, threadId } from "node:worker_threads";
|
||||
|
||||
async function isPortFree(port: number): Promise<boolean> {
|
||||
if (!Number.isFinite(port) || port <= 0 || port > 65535) return false;
|
||||
@@ -45,7 +46,11 @@ export async function getDeterministicFreePortBlock(params?: {
|
||||
|
||||
const workerIdRaw = process.env.VITEST_WORKER_ID ?? process.env.VITEST_POOL_ID ?? "";
|
||||
const workerId = Number.parseInt(workerIdRaw, 10);
|
||||
const shard = Number.isFinite(workerId) ? Math.max(0, workerId) : Math.abs(process.pid);
|
||||
const shard = Number.isFinite(workerId)
|
||||
? Math.max(0, workerId)
|
||||
: isMainThread
|
||||
? Math.abs(process.pid)
|
||||
: Math.abs(threadId);
|
||||
|
||||
const rangeSize = 1000;
|
||||
const shardCount = 30;
|
||||
@@ -79,4 +84,3 @@ export async function getDeterministicFreePortBlock(params?: {
|
||||
|
||||
throw new Error("failed to acquire a free port block");
|
||||
}
|
||||
|
||||
|
||||
@@ -62,10 +62,16 @@ export function installTestEnv(): { cleanup: () => void; tempHome: string } {
|
||||
{ key: "XDG_CACHE_HOME", value: process.env.XDG_CACHE_HOME },
|
||||
{ key: "CLAWDBOT_STATE_DIR", value: process.env.CLAWDBOT_STATE_DIR },
|
||||
{ key: "CLAWDBOT_CONFIG_PATH", value: process.env.CLAWDBOT_CONFIG_PATH },
|
||||
{ key: "CLAWDBOT_GATEWAY_PORT", value: process.env.CLAWDBOT_GATEWAY_PORT },
|
||||
{ key: "CLAWDBOT_BRIDGE_ENABLED", value: process.env.CLAWDBOT_BRIDGE_ENABLED },
|
||||
{ key: "CLAWDBOT_BRIDGE_HOST", value: process.env.CLAWDBOT_BRIDGE_HOST },
|
||||
{ key: "CLAWDBOT_BRIDGE_PORT", value: process.env.CLAWDBOT_BRIDGE_PORT },
|
||||
{ key: "CLAWDBOT_CANVAS_HOST_PORT", value: process.env.CLAWDBOT_CANVAS_HOST_PORT },
|
||||
{ key: "CLAWDBOT_TEST_HOME", value: process.env.CLAWDBOT_TEST_HOME },
|
||||
{ key: "COPILOT_GITHUB_TOKEN", value: process.env.COPILOT_GITHUB_TOKEN },
|
||||
{ key: "GH_TOKEN", value: process.env.GH_TOKEN },
|
||||
{ key: "GITHUB_TOKEN", value: process.env.GITHUB_TOKEN },
|
||||
{ key: "NODE_OPTIONS", value: process.env.NODE_OPTIONS },
|
||||
];
|
||||
|
||||
const tempHome = fs.mkdtempSync(path.join(os.tmpdir(), "clawdbot-test-home-"));
|
||||
@@ -78,10 +84,18 @@ export function installTestEnv(): { cleanup: () => void; tempHome: string } {
|
||||
delete process.env.CLAWDBOT_CONFIG_PATH;
|
||||
// Prefer deriving state dir from HOME so nested tests that change HOME also isolate correctly.
|
||||
delete process.env.CLAWDBOT_STATE_DIR;
|
||||
// Prefer test-controlled ports over developer overrides (avoid port collisions across tests/workers).
|
||||
delete process.env.CLAWDBOT_GATEWAY_PORT;
|
||||
delete process.env.CLAWDBOT_BRIDGE_ENABLED;
|
||||
delete process.env.CLAWDBOT_BRIDGE_HOST;
|
||||
delete process.env.CLAWDBOT_BRIDGE_PORT;
|
||||
delete process.env.CLAWDBOT_CANVAS_HOST_PORT;
|
||||
// Avoid leaking real GitHub/Copilot tokens into non-live test runs.
|
||||
delete process.env.COPILOT_GITHUB_TOKEN;
|
||||
delete process.env.GH_TOKEN;
|
||||
delete process.env.GITHUB_TOKEN;
|
||||
// Avoid leaking local dev tooling flags into tests (e.g. --inspect).
|
||||
delete process.env.NODE_OPTIONS;
|
||||
|
||||
// Windows: prefer the legacy default state dir so auth/profile tests match real paths.
|
||||
if (process.platform === "win32") {
|
||||
|
||||
Reference in New Issue
Block a user