@@ -14,6 +14,7 @@ import (
1414 "regexp"
1515 "runtime"
1616 "strings"
17+ "sync/atomic"
1718 "testing"
1819 "time"
1920 "unsafe"
@@ -2760,32 +2761,74 @@ func TestEventuallyTrue(t *testing.T) {
27602761 True (t , Eventually (t , condition , 100 * time .Millisecond , 20 * time .Millisecond ))
27612762}
27622763
2764+ // errorsCapturingT is a mock implementation of TestingT that captures errors reported with Errorf.
2765+ type errorsCapturingT struct {
2766+ errors []error
2767+ }
2768+
2769+ func (t * errorsCapturingT ) Errorf (format string , args ... interface {}) {
2770+ t .errors = append (t .errors , fmt .Errorf (format , args ... ))
2771+ }
2772+
2773+ func (t * errorsCapturingT ) Helper () {}
2774+
27632775func TestEventuallyWithTFalse (t * testing.T ) {
2764- mockT := new (CollectT )
2776+ mockT := new (errorsCapturingT )
27652777
27662778 condition := func (collect * CollectT ) {
2767- True (collect , false )
2779+ Fail (collect , "condition fixed failure" )
27682780 }
27692781
27702782 False (t , EventuallyWithT (mockT , condition , 100 * time .Millisecond , 20 * time .Millisecond ))
27712783 Len (t , mockT .errors , 2 )
27722784}
27732785
27742786func TestEventuallyWithTTrue (t * testing.T ) {
2775- mockT := new (CollectT )
2787+ mockT := new (errorsCapturingT )
27762788
2777- state := 0
2789+ var state atomic. Int32
27782790 condition := func (collect * CollectT ) {
27792791 defer func () {
2780- state += 1
2792+ state . Add ( 1 )
27812793 }()
2782- True (collect , state == 2 )
2794+ True (collect , state . Load () == 2 )
27832795 }
27842796
27852797 True (t , EventuallyWithT (mockT , condition , 100 * time .Millisecond , 20 * time .Millisecond ))
27862798 Len (t , mockT .errors , 0 )
27872799}
27882800
2801+ func TestEventuallyWithT_ConcurrencySafe (t * testing.T ) {
2802+ mockT := new (errorsCapturingT )
2803+
2804+ condition := func (collect * CollectT ) {
2805+ Fail (collect , "condition fixed failure" )
2806+ }
2807+
2808+ // To trigger race conditions, we run EventuallyWithT with a nanosecond tick.
2809+ False (t , EventuallyWithT (mockT , condition , 100 * time .Millisecond , time .Nanosecond ))
2810+ Len (t , mockT .errors , 2 )
2811+ }
2812+
2813+ func TestEventuallyWithT_ReturnsTheLatestFinishedConditionErrors (t * testing.T ) {
2814+ var calledOnce atomic.Bool
2815+ condition := func (collect * CollectT ) {
2816+ if calledOnce .Load () {
2817+ // Sleep to ensure that the second condition runs longer than timeout.
2818+ time .Sleep (time .Second )
2819+ return
2820+ }
2821+
2822+ // The first condition will fail. We expect to get this error as a result.
2823+ Fail (collect , "condition fixed failure" )
2824+ calledOnce .Store (true )
2825+ }
2826+
2827+ mockT := new (errorsCapturingT )
2828+ False (t , EventuallyWithT (mockT , condition , 100 * time .Millisecond , 20 * time .Millisecond ))
2829+ Len (t , mockT .errors , 2 )
2830+ }
2831+
27892832func TestNeverFalse (t * testing.T ) {
27902833 condition := func () bool {
27912834 return false
0 commit comments