Skip to content

Commit

Permalink
Add RunOnFailure option
Browse files Browse the repository at this point in the history
This adds an Option to run goleak when test runs fail.

Fixes #128.
  • Loading branch information
sywhang committed Oct 1, 2024
1 parent 898a938 commit c12ec8f
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 7 deletions.
3 changes: 3 additions & 0 deletions leaks.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ func Find(options ...Option) error {
if opts.cleanup != nil {
return errors.New("Cleanup can only be passed to VerifyNone or VerifyTestMain")
}
if opts.runOnFailure {
return errors.New("RunOnFailure can only be passed to VerifyTestMain")
}
var stacks []stack.Stack
retry := true
for i := 0; retry; i++ {
Expand Down
18 changes: 14 additions & 4 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,11 @@ type Option interface {
const _defaultRetries = 20

type opts struct {
filters []func(stack.Stack) bool
maxRetries int
maxSleep time.Duration
cleanup func(int)
filters []func(stack.Stack) bool
maxRetries int
maxSleep time.Duration
cleanup func(int)
runOnFailure bool
}

// implement apply so that opts struct itself can be used as
Expand All @@ -51,6 +52,7 @@ func (o *opts) apply(opts *opts) {
opts.maxRetries = o.maxRetries
opts.maxSleep = o.maxSleep
opts.cleanup = o.cleanup
opts.runOnFailure = o.runOnFailure
}

// optionFunc lets us easily write options without a custom type.
Expand Down Expand Up @@ -107,6 +109,14 @@ func IgnoreCurrent() Option {
})
}

// RunOnFailure makes goleak look for leaking goroutines upon test failures.
// By default goleak only looks for leaking goroutines when tests succeed.
func RunOnFailure() Option {
return optionFunc(func(opts *opts) {
opts.runOnFailure = true
})
}

func maxSleep(d time.Duration) Option {
return optionFunc(func(opts *opts) {
opts.maxSleep = d
Expand Down
22 changes: 19 additions & 3 deletions testmain.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,26 @@ func VerifyTestMain(m TestingM, options ...Option) {
}
defer func() { cleanup(exitCode) }()

if exitCode == 0 {
var (
run bool
errorMsg string
)

if !opts.runOnFailure && exitCode == 0 {
errorMsg = "goleak: Errors on successful test run:%v\n"
run = true
} else if opts.runOnFailure {
errorMsg = "goleak: Errors on unsuccessful test run: %v\n"
run = true
}

if run {
if err := Find(opts); err != nil {
fmt.Fprintf(_osStderr, "goleak: Errors on successful test run: %v\n", err)
exitCode = 1
fmt.Fprintf(_osStderr, errorMsg, err)
// rewrite exitCode if test passed and is set to 0.
if exitCode == 0 {
exitCode = 1
}
}
}
}
4 changes: 4 additions & 0 deletions testmain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ func TestVerifyTestMain(t *testing.T) {
assert.Equal(t, 7, <-exitCode, "Exit code should not be modified")
assert.NotContains(t, <-stderr, "goleak: Errors", "Ignore leaks on unsuccessful runs")

VerifyTestMain(dummyTestMain(7), RunOnFailure())
assert.Equal(t, 7, <-exitCode, "Exit code should not be modified")
assert.Contains(t, <-stderr, "goleak: Errors", "Find leaks on unsuccessful runs with RunOnFailure specified")

VerifyTestMain(dummyTestMain(0))
assert.Equal(t, 1, <-exitCode, "Expect error due to leaks on successful runs")
assert.Contains(t, <-stderr, "goleak: Errors", "Find leaks on successful runs")
Expand Down

0 comments on commit c12ec8f

Please sign in to comment.