Skip to content

Commit

Permalink
Add RunOnFailure option (uber-go#129)
Browse files Browse the repository at this point in the history
This adds an Option to run goleak when test runs fail.

Fixes uber-go#128.
  • Loading branch information
sywhang authored Oct 1, 2024
1 parent 898a938 commit 7452c70
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 7452c70

Please sign in to comment.