@@ -520,3 +520,83 @@ it('should not fail to update mtime when we are over the threshold but mtime is
520
520
} , 1000 ) ;
521
521
await pDelay ( 5000 ) ;
522
522
} , 16000 ) ;
523
+
524
+ it ( 'should allow truncated second precision mtime' , async ( ) => {
525
+ fs . writeFileSync ( `${ tmpDir } /foo` , '' ) ;
526
+
527
+ const customFs = {
528
+ ...fs ,
529
+ stat ( path , cb ) {
530
+ fs . stat ( path , ( err , stat ) => {
531
+ if ( err ) {
532
+ return cb ( err ) ;
533
+ }
534
+
535
+ // Make second precision if not already
536
+ stat . mtime = new Date ( Math . trunc ( stat . mtime . getTime ( ) / 1000 ) * 1000 ) ;
537
+ cb ( null , stat ) ;
538
+ } ) ;
539
+ } ,
540
+ } ;
541
+
542
+ const deferred = pDefer ( ) ;
543
+
544
+ // If the module does not detect second precision for mtime, the mtime
545
+ // comparison will cause the lock to appear compromised.
546
+ const handleCompromised = ( err ) => {
547
+ clearTimeout ( successTimeoutId ) ;
548
+ deferred . reject ( err ) ;
549
+ } ;
550
+
551
+ await lockfile . lock ( `${ tmpDir } /foo` , {
552
+ fs : customFs ,
553
+ update : 1000 ,
554
+ onCompromised : handleCompromised ,
555
+ } ) ;
556
+
557
+ // First update is fine because we `stat` after we `mkdir`, it'll fail on
558
+ // the second update when we use `utimes` and do not `stat` for the `mtime`
559
+ const successTimeoutId = setTimeout ( deferred . resolve , 3000 ) ;
560
+
561
+ await deferred . promise ;
562
+ } ) ;
563
+
564
+ it ( 'should allow rounded second precision mtime' , async ( ) => {
565
+ fs . writeFileSync ( `${ tmpDir } /foo` , '' ) ;
566
+
567
+ const customFs = {
568
+ ...fs ,
569
+ stat ( path , cb ) {
570
+ fs . stat ( path , ( err , stat ) => {
571
+ if ( err ) {
572
+ return cb ( err ) ;
573
+ }
574
+
575
+ // Make second precision if not already
576
+ stat . mtime = new Date ( Math . round ( stat . mtime . getTime ( ) / 1000 ) * 1000 ) ;
577
+ cb ( null , stat ) ;
578
+ } ) ;
579
+ } ,
580
+ } ;
581
+
582
+ const deferred = pDefer ( ) ;
583
+
584
+ // If the module does not detect second precision for mtime, the mtime
585
+ // comparison will cause the lock to appear compromised.
586
+ const handleCompromised = ( err ) => {
587
+ clearTimeout ( successTimeoutId ) ;
588
+ deferred . reject ( err ) ;
589
+ } ;
590
+
591
+ await lockfile . lock ( `${ tmpDir } /foo` , {
592
+ fs : customFs ,
593
+ update : 1000 ,
594
+ onCompromised : handleCompromised ,
595
+ } ) ;
596
+
597
+ // First update is fine because we `stat` after we `mkdir`, it'll fail on
598
+ // the second update when we use `utimes` and do not `stat` for the `mtime`
599
+ const successTimeoutId = setTimeout ( deferred . resolve , 3000 ) ;
600
+
601
+ await deferred . promise ;
602
+ } ) ;
0 commit comments