perf(test): slim gateway live connect smoke

This commit is contained in:
Peter Steinberger
2026-04-23 14:45:06 +01:00
parent 7dd37bda4f
commit 4dcd6b8dc4

View File

@@ -1,41 +1,148 @@
import { describe, expect, it } from "vitest";
import fs from "node:fs/promises";
import { createServer } from "node:http";
import type { AddressInfo } from "node:net";
import os from "node:os";
import path from "node:path";
import { afterEach, describe, expect, it } from "vitest";
import { type RawData, WebSocketServer } from "ws";
import { loadOrCreateDeviceIdentity } from "../infra/device-identity.js";
import { connectTestGatewayClient } from "./gateway-cli-backend.live-helpers.js";
import { getFreePort, installGatewayTestHooks, startGatewayServer } from "./test-helpers.js";
import { PROTOCOL_VERSION } from "./protocol/index.js";
const GATEWAY_CONNECT_TIMEOUT_MS = 10_000;
const GATEWAY_CONNECT_TIMEOUT_MS = 5_000;
const tempRoots: string[] = [];
async function createTempDeviceIdentity() {
const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-gateway-connect-"));
tempRoots.push(tempRoot);
return loadOrCreateDeviceIdentity(path.join(tempRoot, "device.json"));
}
async function startMinimalGatewayServer(params: { token: string }) {
const httpServer = createServer();
const wss = new WebSocketServer({ server: httpServer });
const requests: string[] = [];
wss.on("connection", (ws) => {
ws.send(
JSON.stringify({
type: "event",
event: "connect.challenge",
payload: { nonce: "test-nonce" },
}),
);
ws.on("message", (data) => {
const frame = JSON.parse(rawWsDataToString(data)) as {
type?: string;
id?: string;
method?: string;
params?: { auth?: { token?: string }; device?: { nonce?: string } };
};
if (frame.type !== "req" || !frame.id) {
return;
}
requests.push(frame.method ?? "");
if (frame.method === "connect") {
expect(frame.params?.auth?.token).toBe(params.token);
expect(frame.params?.device?.nonce).toBe("test-nonce");
ws.send(
JSON.stringify({
type: "res",
id: frame.id,
ok: true,
payload: {
type: "hello-ok",
protocol: PROTOCOL_VERSION,
server: { version: "test", connId: "conn-1" },
features: { methods: ["health"], events: ["connect.challenge"] },
snapshot: {
presence: [],
health: { ok: true },
stateVersion: { presence: 0, health: 0 },
uptimeMs: 0,
},
policy: {
maxPayload: 1,
maxBufferedBytes: 1,
tickIntervalMs: 60_000,
},
},
}),
);
return;
}
if (frame.method === "health") {
ws.send(JSON.stringify({ type: "res", id: frame.id, ok: true, payload: { ok: true } }));
}
});
});
await new Promise<void>((resolve) => httpServer.listen(0, "127.0.0.1", resolve));
const address = httpServer.address() as AddressInfo;
return {
requests,
url: `ws://127.0.0.1:${address.port}`,
close: async () => {
for (const client of wss.clients) {
client.terminate();
}
await new Promise<void>((resolve, reject) => {
wss.close((error) => (error ? reject(error) : resolve()));
});
await new Promise<void>((resolve, reject) => {
httpServer.close((error) => (error ? reject(error) : resolve()));
});
},
};
}
function rawWsDataToString(data: RawData): string {
if (typeof data === "string") {
return data;
}
if (Buffer.isBuffer(data)) {
return data.toString("utf8");
}
if (Array.isArray(data)) {
return Buffer.concat(data).toString("utf8");
}
return Buffer.from(data).toString("utf8");
}
describe("gateway cli backend connect", () => {
installGatewayTestHooks();
afterEach(async () => {
await Promise.all(
tempRoots.splice(0).map((root) => fs.rm(root, { recursive: true, force: true })),
);
});
it(
"connects a same-process test gateway client in minimal mode",
"connects a test gateway client through the live helper",
async () => {
const token = `test-${Date.now()}`;
const port = await getFreePort();
const server = await startGatewayServer(port, {
bind: "loopback",
auth: { mode: "token", token },
controlUiEnabled: false,
});
const deviceIdentity = await createTempDeviceIdentity();
const server = await startMinimalGatewayServer({ token });
let client: Awaited<ReturnType<typeof connectTestGatewayClient>> | undefined;
try {
client = await connectTestGatewayClient({
url: `ws://127.0.0.1:${port}`,
url: server.url,
token,
timeoutMs: 5_000,
maxAttemptTimeoutMs: 5_000,
requestTimeoutMs: 5_000,
deviceIdentity,
timeoutMs: 1_000,
maxAttemptTimeoutMs: 1_000,
requestTimeoutMs: 1_000,
});
const health = await client.request("health", undefined, {
timeoutMs: 5_000,
timeoutMs: 1_000,
});
expect(health).toMatchObject({
ok: true,
});
expect(server.requests).toEqual(["connect", "health"]);
} finally {
await client?.stopAndWait({ timeoutMs: 1_000 }).catch(() => {});
await server.close({ reason: "gateway connect regression complete" });
await server.close();
}
},
GATEWAY_CONNECT_TIMEOUT_MS,