@@ -9,28 +9,10 @@ vi.mock("node:child_process", async () => {
99 } ;
1010} ) ;
1111
12- const tryListenOnPortMock = vi . hoisted ( ( ) => vi . fn ( ) ) ;
12+ const probePortUsageMock = vi . hoisted ( ( ) => vi . fn ( ) ) ;
1313
1414vi . mock ( "../infra/ports-probe.js" , ( ) => ( {
15- tryListenOnPort : ( ...args : unknown [ ] ) => tryListenOnPortMock ( ...args ) ,
16- probePortUsage : async ( port : number ) => {
17- let sawUnknown = false ;
18- for ( const host of [ "127.0.0.1" , "0.0.0.0" , "::1" , "::" ] ) {
19- try {
20- await tryListenOnPortMock ( { port, host, exclusive : true } ) ;
21- } catch ( err : unknown ) {
22- const code = ( err as { code ?: unknown } ) . code ;
23- if ( code === "EADDRINUSE" ) {
24- return "busy" ;
25- }
26- if ( code === "EADDRNOTAVAIL" || code === "EAFNOSUPPORT" ) {
27- continue ;
28- }
29- sawUnknown = true ;
30- }
31- }
32- return sawUnknown ? "unknown" : "free" ;
33- } ,
15+ probePortUsage : ( ...args : unknown [ ] ) => probePortUsageMock ( ...args ) ,
3416} ) ) ;
3517
3618import { execFileSync } from "node:child_process" ;
@@ -51,10 +33,8 @@ describe("gateway --force helpers", () => {
5133 vi . clearAllMocks ( ) ;
5234 originalKill = process . kill . bind ( process ) ;
5335 originalPlatform = process . platform ;
54- tryListenOnPortMock . mockReset ( ) ;
55- tryListenOnPortMock . mockRejectedValue (
56- Object . assign ( new Error ( "in use" ) , { code : "EADDRINUSE" } ) ,
57- ) ;
36+ probePortUsageMock . mockReset ( ) ;
37+ probePortUsageMock . mockResolvedValue ( "busy" ) ;
5838 // Pin to linux so all lsof tests are platform-invariant.
5939 Object . defineProperty ( process , "platform" , { value : "linux" , configurable : true } ) ;
6040 } ) ;
@@ -83,7 +63,7 @@ describe("gateway --force helpers", () => {
8363 } ) ;
8464
8565 it ( "skips lsof when the port is already bindable" , async ( ) => {
86- tryListenOnPortMock . mockResolvedValue ( undefined ) ;
66+ probePortUsageMock . mockResolvedValue ( "free" ) ;
8767
8868 const result = await forceFreePortAndWait ( 18789 , { timeoutMs : 500 , intervalMs : 100 } ) ;
8969
@@ -217,9 +197,7 @@ describe("gateway --force helpers", () => {
217197 }
218198 return "18789/tcp: 4242\n" ;
219199 } ) ;
220- tryListenOnPortMock
221- . mockRejectedValueOnce ( Object . assign ( new Error ( "in use" ) , { code : "EADDRINUSE" } ) )
222- . mockResolvedValue ( undefined ) ;
200+ probePortUsageMock . mockResolvedValueOnce ( "busy" ) . mockResolvedValue ( "free" ) ;
223201
224202 const result = await forceFreePortAndWait ( 18789 , { timeoutMs : 500 , intervalMs : 100 } ) ;
225203
@@ -249,15 +227,12 @@ describe("gateway --force helpers", () => {
249227 return "" ;
250228 } ) ;
251229
252- const busyErr = Object . assign ( new Error ( "in use" ) , { code : "EADDRINUSE" } ) ;
253- // Each probePortUsage call probes up to 4 hosts; the last check needs all
254- // hosts free, so use permanent mockResolvedValue instead of once.
255- tryListenOnPortMock
256- . mockRejectedValueOnce ( busyErr )
257- . mockRejectedValueOnce ( busyErr )
258- . mockRejectedValueOnce ( busyErr )
259- . mockRejectedValueOnce ( busyErr )
260- . mockResolvedValue ( undefined ) ;
230+ probePortUsageMock
231+ . mockResolvedValueOnce ( "busy" )
232+ . mockResolvedValueOnce ( "busy" )
233+ . mockResolvedValueOnce ( "busy" )
234+ . mockResolvedValueOnce ( "busy" )
235+ . mockResolvedValue ( "free" ) ;
261236
262237 const promise = forceFreePortAndWait ( 18789 , {
263238 timeoutMs : 300 ,
@@ -279,9 +254,7 @@ describe("gateway --force helpers", () => {
279254
280255 it ( "throws when lsof is unavailable and fuser is missing" , async ( ) => {
281256 // An inconclusive four-host probe must continue into the cleanup tools.
282- tryListenOnPortMock . mockRejectedValue (
283- Object . assign ( new Error ( "probe failed" ) , { code : "EIO" } ) ,
284- ) ;
257+ probePortUsageMock . mockResolvedValue ( "unknown" ) ;
285258 ( execFileSync as unknown as Mock ) . mockImplementation ( ( cmd : string ) => {
286259 const err = new Error ( `spawnSync ${ cmd } ENOENT` ) as NodeJS . ErrnoException ;
287260 err . code = "ENOENT" ;
0 commit comments