@@ -632,6 +632,52 @@ func BenchmarkDoWithDataNoErrors(b *testing.B) {
632632 }
633633}
634634
635+ type attemptsForErrorTestError struct {}
636+
637+ func (attemptsForErrorTestError ) Error () string { return "test error" }
638+
639+ func TestAttemptsForErrorNoDelayAfterFinalAttempt (t * testing.T ) {
640+ var count uint64
641+ var timestamps []time.Time
642+
643+ startTime := time .Now ()
644+
645+ err := Do (
646+ func () error {
647+ count ++
648+ timestamps = append (timestamps , time .Now ())
649+ return attemptsForErrorTestError {}
650+ },
651+ Attempts (3 ),
652+ Delay (200 * time .Millisecond ),
653+ DelayType (FixedDelay ),
654+ AttemptsForError (2 , attemptsForErrorTestError {}),
655+ LastErrorOnly (true ),
656+ Context (context .Background ()),
657+ )
658+
659+ endTime := time .Now ()
660+
661+ assert .Error (t , err )
662+ assert .Equal (t , uint64 (2 ), count , "should attempt exactly 2 times" )
663+ assert .Len (t , timestamps , 2 , "should have 2 timestamps" )
664+
665+ // Verify timing: first attempt at ~0ms, second at ~200ms, end immediately after second attempt
666+ firstAttemptTime := timestamps [0 ].Sub (startTime )
667+ secondAttemptTime := timestamps [1 ].Sub (startTime )
668+ totalTime := endTime .Sub (startTime )
669+
670+ // First attempt should be immediate
671+ assert .Less (t , firstAttemptTime , 50 * time .Millisecond , "first attempt should be immediate" )
672+
673+ // Second attempt should be after delay
674+ assert .Greater (t , secondAttemptTime , 150 * time .Millisecond , "second attempt should be after delay" )
675+ assert .Less (t , secondAttemptTime , 250 * time .Millisecond , "second attempt should not be too delayed" )
676+
677+ // Total time should not include delay after final attempt
678+ assert .Less (t , totalTime , 300 * time .Millisecond , "should not delay after final attempt" )
679+ }
680+
635681func TestIsRecoverable (t * testing.T ) {
636682 err := errors .New ("err" )
637683 assert .True (t , IsRecoverable (err ))
0 commit comments