From 54102fbc53b9183fae54d4d83daf2ada8b7bf8d8 Mon Sep 17 00:00:00 2001 From: Claude Bot Date: Sat, 24 Jan 2026 16:08:12 +0000 Subject: [PATCH] test(net): use await using and AbortSignal for disposal/timeouts Address additional CodeRabbit review feedback: - Use `await using` for automatic server disposal instead of try/finally - Use `once()` from node:events for cleaner event waiting - Replace setTimeout-based timeout with AbortSignal.timeout() - Simplify helper functions Co-Authored-By: Claude Opus 4.5 --- test/regression/issue/026418.test.ts | 119 ++++++++++----------------- 1 file changed, 44 insertions(+), 75 deletions(-) diff --git a/test/regression/issue/026418.test.ts b/test/regression/issue/026418.test.ts index b5d7479728..0af77eb0fe 100644 --- a/test/regression/issue/026418.test.ts +++ b/test/regression/issue/026418.test.ts @@ -1,12 +1,14 @@ import { describe, it } from "bun:test"; -import { connect, createServer, Server, Socket } from "node:net"; +import { once } from "node:events"; +import type { AddressInfo } from "node:net"; +import { connect, createServer, Socket } from "node:net"; import { Duplex, Writable } from "node:stream"; describe("issue/026418", () => { it("net.Socket data events fire when socket is piped to another stream", async () => { const { promise: dataPromise, resolve: dataResolve } = Promise.withResolvers(); - const server = createServer((socket: Socket) => { + await using server = createServer((socket: Socket) => { socket.on("data", () => { dataResolve(); }); @@ -19,24 +21,20 @@ describe("issue/026418", () => { socket.pipe(writable); }); - try { - const port = await listenOnRandomPort(server); - const client = connect({ host: "127.0.0.1", port }); + await once(server.listen(0, "127.0.0.1"), "listening"); + const { port } = server.address() as AddressInfo; - try { - await waitForConnect(client); + const client = connect({ host: "127.0.0.1", port }); - // Send data - client.write("HELLO"); + await once(client, "connect"); - // Wait for data to be received with timeout - await Promise.race([dataPromise, rejectAfterTimeout(1000, "data event not received")]); - } finally { - client.destroy(); - } - } finally { - await closeServer(server); - } + // Send data + client.write("HELLO"); + + // Wait for data to be received with AbortSignal timeout + await Promise.race([dataPromise, abortAfterTimeout(1000, "data event not received")]); + + client.destroy(); }); it("net.Socket bidirectional pipe works (SSH tunnel pattern)", async () => { @@ -58,7 +56,7 @@ describe("issue/026418", () => { }); } - const server = createServer((socket: Socket) => { + await using server = createServer((socket: Socket) => { socket.on("data", () => { dataResolve(); }); @@ -72,70 +70,41 @@ describe("issue/026418", () => { }); }); - try { - const port = await listenOnRandomPort(server); - const client = connect({ host: "127.0.0.1", port }); + await once(server.listen(0, "127.0.0.1"), "listening"); + const { port } = server.address() as AddressInfo; - try { - await waitForConnect(client); + const client = connect({ host: "127.0.0.1", port }); - client.on("data", (chunk: Buffer) => { - if (chunk.toString().includes("RESPONSE:")) { - responseResolve(); - } - }); + await once(client, "connect"); - // Wait for forward stream to be set up - await Promise.race([pipeReadyPromise, rejectAfterTimeout(1000, "pipe setup timeout")]); - - // Send data - client.write("REQUEST"); - - // Wait for data and response with timeout - await Promise.race([ - Promise.all([dataPromise, responsePromise]), - rejectAfterTimeout(1000, "data/response not received"), - ]); - } finally { - client.destroy(); + client.on("data", (chunk: Buffer) => { + if (chunk.toString().includes("RESPONSE:")) { + responseResolve(); } - } finally { - await closeServer(server); - } + }); + + // Wait for forward stream to be set up + await Promise.race([pipeReadyPromise, abortAfterTimeout(1000, "pipe setup timeout")]); + + // Send data + client.write("REQUEST"); + + // Wait for data and response with timeout + await Promise.race([ + Promise.all([dataPromise, responsePromise]), + abortAfterTimeout(1000, "data/response not received"), + ]); + + client.destroy(); }); }); -// Helper functions - -function listenOnRandomPort(server: Server): Promise { - return new Promise((resolve, reject) => { - server.on("error", reject); - server.listen(0, "127.0.0.1", () => { - const addr = server.address(); - if (addr && typeof addr === "object") { - resolve(addr.port); - } else { - reject(new Error("Failed to get server port")); - } +// Helper to create a promise that rejects after timeout using AbortSignal +function abortAfterTimeout(ms: number, message: string): Promise { + const signal = AbortSignal.timeout(ms); + return new Promise((_, reject) => { + signal.addEventListener("abort", () => { + reject(new Error(message)); }); }); } - -function waitForConnect(client: Socket): Promise { - return new Promise((resolve, reject) => { - client.on("connect", resolve); - client.on("error", reject); - }); -} - -function closeServer(server: Server): Promise { - return new Promise(resolve => { - server.close(() => resolve()); - }); -} - -function rejectAfterTimeout(ms: number, message: string): Promise { - return new Promise((_, reject) => { - setTimeout(() => reject(new Error(message)), ms); - }); -}