Skip to content

Commit

Permalink
assert: collect.FailNow() should not panic
Browse files Browse the repository at this point in the history
Fixes #1396
Fixes #1457
  • Loading branch information
marshall-lee committed Oct 13, 2023
1 parent 8992013 commit 8bedbde
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 8 deletions.
19 changes: 11 additions & 8 deletions assert/assertions.go
Original file line number Diff line number Diff line change
Expand Up @@ -1864,17 +1864,20 @@ func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick t

// CollectT implements the TestingT interface and collects all errors.
type CollectT struct {
failed bool
errors []error
}

// Errorf collects the error.
func (c *CollectT) Errorf(format string, args ...interface{}) {
c.failed = true
c.errors = append(c.errors, fmt.Errorf(format, args...))
}

// FailNow panics.
func (*CollectT) FailNow() {
panic("Assertion failed")
// FailNow stops the execution by calling runtime.Goexit.
func (c *CollectT) FailNow() {
c.failed = true
runtime.Goexit()
}

// Deprecated: That was a method for internal usage that should not have been published. Now just panics.
Expand Down Expand Up @@ -1911,7 +1914,7 @@ func EventuallyWithT(t TestingT, condition func(collect *CollectT), waitFor time
}

var lastFinishedTickErrs []error
ch := make(chan []error, 1)
ch := make(chan *CollectT, 1)

timer := time.NewTimer(waitFor)
defer timer.Stop()
Expand All @@ -1931,16 +1934,16 @@ func EventuallyWithT(t TestingT, condition func(collect *CollectT), waitFor time
go func() {
collect := new(CollectT)
defer func() {
ch <- collect.errors
ch <- collect
}()
condition(collect)
}()
case errs := <-ch:
if len(errs) == 0 {
case collect := <-ch:
if !collect.failed {
return true
}
// Keep the errors from the last ended condition, so that they can be copied to t if timeout is reached.
lastFinishedTickErrs = errs
lastFinishedTickErrs = collect.errors
tick = ticker.C
}
}
Expand Down
11 changes: 11 additions & 0 deletions assert/assertions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2838,6 +2838,17 @@ func TestEventuallyWithT_ReturnsTheLatestFinishedConditionErrors(t *testing.T) {
Len(t, mockT.errors, 2)
}

func TestEventuallyWithTFailNow(t *testing.T) {
mockT := new(CollectT)

condition := func(collect *CollectT) {
collect.FailNow()
}

False(t, EventuallyWithT(mockT, condition, 100*time.Millisecond, 20*time.Millisecond))
Len(t, mockT.errors, 1)
}

func TestNeverFalse(t *testing.T) {
condition := func() bool {
return false
Expand Down
32 changes: 32 additions & 0 deletions require/requirements_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"errors"
"testing"
"time"

"github.com/stretchr/testify/assert"
)

// AssertionTesterInterface defines an interface to be used for testing assertion methods
Expand Down Expand Up @@ -681,3 +683,33 @@ func TestErrorAssertionFunc(t *testing.T) {
})
}
}

func TestEventuallyWithTFalse(t *testing.T) {
mockT := new(MockT)

condition := func(collect *assert.CollectT) {
True(collect, false)
}

EventuallyWithT(mockT, condition, 100*time.Millisecond, 20*time.Millisecond)
if !mockT.Failed {
t.Error("Check should fail")
}
}

func TestEventuallyWithTTrue(t *testing.T) {
mockT := new(MockT)

state := 0
condition := func(collect *assert.CollectT) {
defer func() {
state += 1
}()
True(collect, state == 2)
}

EventuallyWithT(mockT, condition, 100*time.Millisecond, 20*time.Millisecond)
if mockT.Failed {
t.Error("Check should pass")
}
}

0 comments on commit 8bedbde

Please sign in to comment.