Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 3 additions & 18 deletions assert/assertions.go
Original file line number Diff line number Diff line change
Expand Up @@ -2018,12 +2018,7 @@ func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick t
ticker := time.NewTicker(tick)
defer ticker.Stop()

var tickC <-chan time.Time

// Check the condition once first on the initial call.
go checkCond()

for {
for tickC := ticker.C; ; {
select {
case <-timer.C:
return Fail(t, "Condition never satisfied", msgAndArgs...)
Expand Down Expand Up @@ -2121,12 +2116,7 @@ func EventuallyWithT(t TestingT, condition func(collect *CollectT), waitFor time
ticker := time.NewTicker(tick)
defer ticker.Stop()

var tickC <-chan time.Time

// Check the condition once first on the initial call.
go checkCond()

for {
for tickC := ticker.C; ; {
select {
case <-timer.C:
for _, err := range lastFinishedTickErrs {
Expand Down Expand Up @@ -2165,12 +2155,7 @@ func Never(t TestingT, condition func() bool, waitFor time.Duration, tick time.D
ticker := time.NewTicker(tick)
defer ticker.Stop()

var tickC <-chan time.Time

// Check the condition once first on the initial call.
go checkCond()

for {
for tickC := ticker.C; ; {
select {
case <-timer.C:
return true
Expand Down
70 changes: 58 additions & 12 deletions assert/assertions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"regexp"
"runtime"
"strings"
"sync/atomic"
"testing"
"time"
)
Expand Down Expand Up @@ -3491,6 +3492,54 @@ func TestEventuallyWithTTrue(t *testing.T) {
Equal(t, 2, counter, "Condition is expected to be called 2 times")
}

func TestEventuallyWithT_AvoidsPanic_NilDeref(t *testing.T) {
t.Parallel()

var p atomic.Value
go func() {
time.Sleep(5 * time.Millisecond)
value := 1
p.Store(&value)
}()

// If the condition runs before the first tick, this panics on *p.Load()
True(t, EventuallyWithT(t, func(c *CollectT) {
Equal(c, 1, *p.Load().(*int))
}, 200*time.Millisecond, 50*time.Millisecond))
}

func TestEventually_AvoidsPanic_NilDeref(t *testing.T) {
t.Parallel()

var p atomic.Value
go func() {
time.Sleep(5 * time.Millisecond)
value := 1
p.Store(&value)
}()

// If the condition runs before the first tick, this panics on *p.Load()
True(t, Eventually(t, func() bool {
return *p.Load().(*int) == 1
}, 200*time.Millisecond, 50*time.Millisecond))
}

func TestNever_AvoidsPanic_NilDeref(t *testing.T) {
t.Parallel()

var p atomic.Value
go func() {
time.Sleep(5 * time.Millisecond)
value := 0
p.Store(&value)
}()

// If the condition runs before the first tick, this panics on *p.Load()
True(t, Never(t, func() bool {
return *p.Load().(*int) == 1 // set to 0 above, so this should never == 1
}, 200*time.Millisecond, 50*time.Millisecond))
}

func TestEventuallyWithT_ConcurrencySafe(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -3568,28 +3617,26 @@ func TestEventuallyTimeout(t *testing.T) {
})
}

func TestEventuallySucceedQuickly(t *testing.T) {
func TestEventually_NoImmediateCheckBeforeFirstTick(t *testing.T) {
t.Parallel()

mockT := new(testing.T)

condition := func() bool { return true }

// By making the tick longer than the total duration, we expect that this test would fail if
// we didn't check the condition before the first tick elapses.
True(t, Eventually(mockT, condition, 100*time.Millisecond, time.Second))
// By making the tick longer than the total duration, the condition should not be checked.
False(t, Eventually(mockT, condition, 100*time.Millisecond, time.Second))
}

func TestEventuallyWithTSucceedQuickly(t *testing.T) {
func TestEventuallyWithT_NoImmediateCheckBeforeFirstTick(t *testing.T) {
t.Parallel()

mockT := new(testing.T)

condition := func(t *CollectT) {}

// By making the tick longer than the total duration, we expect that this test would fail if
// we didn't check the condition before the first tick elapses.
True(t, EventuallyWithT(mockT, condition, 100*time.Millisecond, time.Second))
// By making the tick longer than the total duration, the condition should not be checked.
False(t, EventuallyWithT(mockT, condition, 100*time.Millisecond, time.Second))
}

func TestNeverFalse(t *testing.T) {
Expand Down Expand Up @@ -3623,15 +3670,14 @@ func TestNeverTrue(t *testing.T) {
False(t, Never(mockT, condition, 100*time.Millisecond, 20*time.Millisecond))
}

func TestNeverFailQuickly(t *testing.T) {
func TestNever_NoImmediateCheckBeforeFirstTick(t *testing.T) {
t.Parallel()

mockT := new(testing.T)

// By making the tick longer than the total duration, we expect that this test would fail if
// we didn't check the condition before the first tick elapses.
// By making the tick longer than the total duration, the condition should not be checked.
condition := func() bool { return true }
False(t, Never(mockT, condition, 100*time.Millisecond, time.Second))
True(t, Never(mockT, condition, 100*time.Millisecond, time.Second))
}

func Test_validateEqualArgs(t *testing.T) {
Expand Down