refactor: consolidate free-port test helpers (#99771)

This commit is contained in:
Dallin Romney
2026-07-03 19:53:43 -07:00
committed by GitHub
parent 7acfb63535
commit 7b2c51573f
5 changed files with 8 additions and 92 deletions
+1 -17
View File
@@ -1,26 +1,10 @@
// Chutes OAuth tests cover OAuth endpoints, local callback handling, and fetch preconnect behavior.
import net from "node:net";
import { describe, expect, it, vi } from "vitest";
import { CHUTES_TOKEN_ENDPOINT, CHUTES_USERINFO_ENDPOINT } from "../agents/chutes-oauth.js";
import { withFetchPreconnect } from "../test-utils/fetch-mock.js";
import { getFreePort } from "../test-utils/ports.js";
import { loginChutes } from "./chutes-oauth.js";
async function getFreePort(): Promise<number> {
return await new Promise((resolve, reject) => {
const server = net.createServer();
server.once("error", reject);
server.listen(0, "127.0.0.1", () => {
const address = server.address();
if (!address || typeof address === "string") {
server.close(() => reject(new Error("No TCP address")));
return;
}
const port = address.port;
server.close((err) => (err ? reject(err) : resolve(port)));
});
});
}
const urlToString = (url: Request | URL | string): string => {
if (typeof url === "string") {
return url;
@@ -2,7 +2,6 @@
import { randomBytes, randomUUID } from "node:crypto";
import { writeSync } from "node:fs";
import fs from "node:fs/promises";
import { createServer } from "node:net";
import os from "node:os";
import path from "node:path";
import {
@@ -60,6 +59,7 @@ import { DEFAULT_AGENT_ID } from "../routing/session-key.js";
import { stripAssistantInternalScaffolding } from "../shared/text/assistant-visible-text.js";
import { findFinalTagMatches, stripFinalTags } from "../shared/text/final-tags.js";
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 {
@@ -1948,42 +1948,6 @@ function editDistance(a: string, b: string): number {
return prev[bLen] ?? Number.POSITIVE_INFINITY;
}
async function getFreePort(): Promise<number> {
return await new Promise((resolve, reject) => {
const srv = createServer();
srv.on("error", reject);
srv.listen(0, "127.0.0.1", () => {
const addr = srv.address();
if (!addr || typeof addr === "string") {
srv.close();
reject(new Error("failed to acquire free port"));
return;
}
const port = addr.port;
srv.close((err) => {
if (err) {
reject(err);
} else {
resolve(port);
}
});
});
});
}
async function isPortFree(port: number): Promise<boolean> {
if (!Number.isFinite(port) || port <= 0 || port > 65535) {
return false;
}
return await new Promise((resolve) => {
const srv = createServer();
srv.once("error", () => resolve(false));
srv.listen(port, "127.0.0.1", () => {
srv.close(() => resolve(true));
});
});
}
async function getFreeGatewayPort(): Promise<number> {
// Gateway uses derived ports (browser/canvas). Avoid flaky collisions by
// ensuring the common derived offsets are free too.
+1 -17
View File
@@ -1,29 +1,13 @@
// Provider auth runtime tests cover OAuth callback handling and provider auth flow helpers.
import fs from "node:fs/promises";
import { createServer } from "node:net";
import os from "node:os";
import path from "node:path";
import { describe, expect, it, vi } from "vitest";
import { saveAuthProfileStore } from "../agents/auth-profiles/store.js";
import { MAX_TIMER_TIMEOUT_MS } from "../shared/number-coercion.js";
import { getFreePort } from "../test-utils/ports.js";
import * as providerAuthRuntime from "./provider-auth-runtime.js";
async function getFreePort(): Promise<number> {
return await new Promise((resolve, reject) => {
const server = createServer();
server.once("error", reject);
server.listen(0, "127.0.0.1", () => {
const address = server.address();
if (!address || typeof address === "string") {
server.close(() => reject(new Error("Failed to allocate a local port")));
return;
}
const { port } = address;
server.close((err) => (err ? reject(err) : resolve(port)));
});
});
}
describe("plugin-sdk provider-auth-runtime", () => {
it("exports the runtime-ready auth helper", () => {
expect(providerAuthRuntime.getRuntimeAuthForModel).toBeTypeOf("function");
+3 -3
View File
@@ -2,7 +2,7 @@
import { createServer } from "node:net";
import { isMainThread, threadId } from "node:worker_threads";
async function isPortFree(port: number): Promise<boolean> {
export async function isPortFree(port: number): Promise<boolean> {
if (!Number.isFinite(port) || port <= 0 || port > 65535) {
return false;
}
@@ -15,7 +15,7 @@ async function isPortFree(port: number): Promise<boolean> {
});
}
async function getOsFreePort(): Promise<number> {
export async function getFreePort(): Promise<number> {
return await new Promise((resolve, reject) => {
const server = createServer();
server.once("error", reject);
@@ -80,7 +80,7 @@ export async function getDeterministicFreePortBlock(params?: {
// Fallback: let the OS pick a port block (best effort).
for (let attempt = 0; attempt < 25; attempt += 1) {
const port = await getOsFreePort();
const port = await getFreePort();
const ok = (await Promise.all(offsets.map((offset) => isPortFree(port + offset)))).every(
Boolean,
);
+2 -18
View File
@@ -2,11 +2,11 @@
import { type ChildProcess, spawn, spawnSync } from "node:child_process";
import { once } from "node:events";
import { mkdtemp, rm } from "node:fs/promises";
import net from "node:net";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { setTimeout as delay } from "node:timers/promises";
import { describe, expect, it } from "vitest";
import { getFreePort } from "../../src/test-utils/ports.js";
const mockOpenAiPath = "scripts/e2e/mock-openai-server.mjs";
const webSearchMockPath = "scripts/e2e/lib/openai-web-search-minimal/mock-server.mjs";
@@ -44,22 +44,6 @@ function runScript(scriptPath: string, env: Record<string, string>) {
});
}
async function freePort() {
const server = net.createServer();
await new Promise<void>((resolve, reject) => {
server.once("error", reject);
server.listen(0, "127.0.0.1", resolve);
});
const address = server.address();
await new Promise<void>((resolve, reject) => {
server.close((error) => (error ? reject(error) : resolve()));
});
if (!address || typeof address === "string") {
throw new Error("failed to allocate a local port");
}
return address.port;
}
async function waitForListening(child: ChildProcess, port: number, output: () => string) {
await new Promise<void>((resolve, reject) => {
let settled = false;
@@ -127,7 +111,7 @@ async function withMockServer(
},
) => Promise<void>,
) {
const port = await freePort();
const port = await getFreePort();
let stderr = "";
let stdout = "";
const child = spawn(process.execPath, [scriptPath], {