test: stabilize gateway windows sigterm

This commit is contained in:
Peter Steinberger 2026-01-19 16:16:13 +00:00
parent 079c29ceb8
commit 3690be9419
2 changed files with 31 additions and 39 deletions

View File

@ -3,6 +3,7 @@ import fs from "node:fs";
import net from "node:net"; import net from "node:net";
import os from "node:os"; import os from "node:os";
import path from "node:path"; import path from "node:path";
import { pathToFileURL } from "node:url";
import { afterEach, describe, expect, it } from "vitest"; import { afterEach, describe, expect, it } from "vitest";
const waitForPortOpen = async ( const waitForPortOpen = async (
@ -108,37 +109,28 @@ describe("gateway SIGTERM", () => {
CLAWDBOT_BRIDGE_HOST: "127.0.0.1", CLAWDBOT_BRIDGE_HOST: "127.0.0.1",
CLAWDBOT_BRIDGE_PORT: "0", CLAWDBOT_BRIDGE_PORT: "0",
}; };
let childArgs: string[]; const bootstrapPath = path.join(stateDir, "clawdbot-entry-bootstrap.mjs");
if (process.platform === "win32") { const runMainPath = path.resolve("src/cli/run-main.ts");
const bootstrapPath = path.join(stateDir, "clawdbot-entry-bootstrap.mjs"); fs.writeFileSync(
fs.writeFileSync( bootstrapPath,
bootstrapPath, [
[ 'import { pathToFileURL } from "node:url";',
'import { pathToFileURL } from "node:url";', 'const rawArgs = process.env.CLAWDBOT_ENTRY_ARGS ?? "[]";',
"const entry = process.env.CLAWDBOT_ENTRY_PATH;", "let entryArgs = [];",
'const rawArgs = process.env.CLAWDBOT_ENTRY_ARGS ?? "[]";', "try {",
"if (!entry) {", " entryArgs = JSON.parse(rawArgs);",
' console.error("Missing CLAWDBOT_ENTRY_PATH");', "} catch (err) {",
" process.exit(1);", ' console.error("Failed to parse CLAWDBOT_ENTRY_ARGS", err);',
"}", " process.exit(1);",
"let entryArgs = [];", "}",
"try {", `const runMainUrl = ${JSON.stringify(pathToFileURL(runMainPath).href)};`,
" entryArgs = JSON.parse(rawArgs);", "const { runCli } = await import(runMainUrl);",
"} catch (err) {", "await runCli([process.execPath, \"clawdbot\", ...entryArgs]);",
' console.error("Failed to parse CLAWDBOT_ENTRY_ARGS", err);', ].join("\n"),
" process.exit(1);", "utf8",
"}", );
"process.argv = [process.argv[0], entry, ...entryArgs];", const childArgs = ["--import", "tsx", bootstrapPath];
"await import(pathToFileURL(entry).href);", env.CLAWDBOT_ENTRY_ARGS = JSON.stringify(entryArgs);
].join("\n"),
"utf8",
);
childArgs = ["--import", "tsx", bootstrapPath];
env.CLAWDBOT_ENTRY_PATH = path.resolve("src/entry.ts");
env.CLAWDBOT_ENTRY_ARGS = JSON.stringify(entryArgs);
} else {
childArgs = ["--import", "tsx", "src/entry.ts", ...entryArgs];
}
child = spawn(nodeBin, childArgs, { child = spawn(nodeBin, childArgs, {
cwd: process.cwd(), cwd: process.cwd(),

View File

@ -1,5 +1,4 @@
import { describe, expect, test, vi } from "vitest"; import { describe, expect, test, vi } from "vitest";
import fs from "node:fs/promises";
import { WebSocket } from "ws"; import { WebSocket } from "ws";
import { PROTOCOL_VERSION } from "./protocol/index.js"; import { PROTOCOL_VERSION } from "./protocol/index.js";
import { HANDSHAKE_TIMEOUT_MS } from "./server-constants.js"; import { HANDSHAKE_TIMEOUT_MS } from "./server-constants.js";
@ -16,13 +15,14 @@ import {
installGatewayTestHooks(); installGatewayTestHooks();
async function waitForWsClose(ws: WebSocket, timeoutMs: number): Promise<boolean> { async function waitForWsClose(ws: WebSocket, timeoutMs: number): Promise<boolean> {
const deadline = process.hrtime.bigint() + BigInt(timeoutMs) * 1_000_000n; if (ws.readyState === WebSocket.CLOSED) return true;
while (process.hrtime.bigint() < deadline) { return await new Promise((resolve) => {
if (ws.readyState === WebSocket.CLOSED) return true; const timer = setTimeout(() => resolve(ws.readyState === WebSocket.CLOSED), timeoutMs);
// Yield to the event loop without relying on timers (fake timers can leak). ws.once("close", () => {
await fs.stat(process.cwd()).catch(() => {}); clearTimeout(timer);
} resolve(true);
return ws.readyState === WebSocket.CLOSED; });
});
} }
describe("gateway server auth/connect", () => { describe("gateway server auth/connect", () => {