@@ -378,34 +378,33 @@ describe("gateway lock", () => {
378378 } ) ;
379379
380380 it ( "closes handle and removes lock file when writeFile fails after open succeeds" , async ( ) => {
381- // When fs.open succeeds but the subsequent writeFile fails (e.g. disk full),
382- // the file handle must be closed and the partial lock file removed before
383- // re-throwing to avoid a file descriptor leak.
384381 vi . useRealTimers ( ) ;
385382 const env = await makeEnv ( ) ;
386383 const { lockPath } = resolveLockPath ( env ) ;
387384
388385 const writeError = Object . assign ( new Error ( "ENOSPC: no space left on device" ) , {
389386 code : "ENOSPC" ,
390387 } ) ;
391- const closeMock = vi . fn < ( ) => Promise < void > > ( ) . mockResolvedValue ( undefined ) ;
388+ const close = vi . fn < ( ) => Promise < void > > ( ) . mockResolvedValue ( undefined ) ;
392389 const mockHandle = {
393- writeFile : vi . fn ( ) . mockRejectedValue ( writeError ) ,
394- close : closeMock ,
390+ writeFile : vi . fn ( ) . mockImplementation ( async ( ) => {
391+ await fs . writeFile ( lockPath , "partial" , "utf8" ) ;
392+ throw writeError ;
393+ } ) ,
394+ close,
395395 } ;
396396
397397 const openSpy = vi . spyOn ( fs , "open" ) . mockResolvedValueOnce ( mockHandle as never ) ;
398- const rmSpy = vi . spyOn ( fs , "rm" ) ;
399398
400- await expect ( acquireForTest ( env ) ) . rejects . toBeInstanceOf ( GatewayLockError ) ;
399+ await expect ( acquireForTest ( env ) ) . rejects . toMatchObject ( {
400+ name : "GatewayLockError" ,
401+ cause : writeError ,
402+ } ) ;
401403
402- // The handle must be closed so the file descriptor is not leaked.
403- expect ( closeMock ) . toHaveBeenCalledTimes ( 1 ) ;
404- // The partially-written lock file must be removed so no stale lock lingers.
405- expect ( rmSpy ) . toHaveBeenCalledWith ( lockPath , { force : true } ) ;
404+ expect ( close ) . toHaveBeenCalledTimes ( 1 ) ;
405+ await expect ( fs . access ( lockPath ) ) . rejects . toMatchObject ( { code : "ENOENT" } ) ;
406406
407407 openSpy . mockRestore ( ) ;
408- rmSpy . mockRestore ( ) ;
409408 } ) ;
410409
411410 it ( "clears stale lock on win32 when process cmdline is not a gateway" , async ( ) => {
0 commit comments