diff options
| author | Katie Hockman <katie@golang.org> | 2020-10-07 14:08:53 -0400 |
|---|---|---|
| committer | Filippo Valsorda <filippo@golang.org> | 2020-12-04 19:17:29 +0100 |
| commit | 0a6f004cb1ed99bc225f4fe3cba5c2c5b901b442 (patch) | |
| tree | c2e15074ba2c6838d5f108ffc5e1a40e2f199898 /src/testing | |
| parent | 555797058ae41e3cc0825831520dee7fb77b3ce5 (diff) | |
| download | go-0a6f004cb1ed99bc225f4fe3cba5c2c5b901b442.tar.xz | |
[dev.fuzz] testing: exit after f.Fuzz function
This change causes f.Fuzz to call runtime.GoExit
when it has finished running. This would mean that
any code after an f.Fuzz function within a fuzz
target would not be executed.
In the future, vet should fail if someone tries to
do this.
This change also adds the missing code that would
execute any cleanup functions added by f.Cleanup.
Change-Id: Ib4d1e6bcafbe189986d0667a1e87dabae67ee621
Reviewed-on: https://go-review.googlesource.com/c/go/+/260338
Run-TryBot: Katie Hockman <katie@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Katie Hockman <katie@golang.org>
Trust: Jay Conrod <jayconrod@google.com>
Reviewed-by: Jay Conrod <jayconrod@google.com>
Diffstat (limited to 'src/testing')
| -rw-r--r-- | src/testing/fuzz.go | 33 |
1 files changed, 17 insertions, 16 deletions
diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 01895e8d7d..11bbd8fb16 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -9,6 +9,7 @@ import ( "flag" "fmt" "os" + "runtime" "time" ) @@ -28,12 +29,11 @@ type InternalFuzzTarget struct { // F is a type passed to fuzz targets for fuzz testing. type F struct { common - context *fuzzContext - corpus []corpusEntry // corpus is the in-memory corpus - result FuzzResult // result is the result of running the fuzz target - fuzzFunc func(f *F) // fuzzFunc is the function which makes up the fuzz target - fuzz bool // fuzz indicates whether the fuzzing engine should run - fuzzCalled bool // fuzzCalled indicates whether f.Fuzz has been called for this target + context *fuzzContext + corpus []corpusEntry // corpus is the in-memory corpus + result FuzzResult // result is the result of running the fuzz target + fuzzFunc func(f *F) // fuzzFunc is the function which makes up the fuzz target + fuzz bool // fuzz indicates whether the fuzzing engine should run } // corpus corpusEntry @@ -61,21 +61,20 @@ func (f *F) Add(args ...interface{}) { } } -// Fuzz runs the fuzz function, ff, for fuzz testing. It runs ff in a separate -// goroutine. Only the first call to Fuzz will be executed, and any subsequent -// calls will panic. If ff fails for a set of arguments, those arguments will be -// added to the seed corpus. +// Fuzz runs the fuzz function, ff, for fuzz testing. If ff fails for a set of +// arguments, those arguments will be added to the seed corpus. +// +// This is a terminal function which will terminate the currently running fuzz +// target by calling runtime.Goexit. To run any code after this function, use +// Cleanup. func (f *F) Fuzz(ff interface{}) { - if f.fuzzCalled { - panic("testing: found more than one call to Fuzz, will skip") - } - f.fuzzCalled = true - fn, ok := ff.(func(*T, []byte)) if !ok { panic("testing: Fuzz function must have type func(*testing.T, []byte)") } + defer runtime.Goexit() // exit after this function + var errStr string run := func(t *T, b []byte) { defer func() { @@ -118,6 +117,7 @@ func (f *F) Fuzz(ff interface{}) { errStr += string(t.output) } } + f.finished = true if f.Failed() { f.result = FuzzResult{Error: errors.New(errStr)} return @@ -169,12 +169,13 @@ func (f *F) runTarget(fn func(*F)) { } if err != nil { f.Fail() - f.result = FuzzResult{Error: fmt.Errorf("%s", err)} + f.result = FuzzResult{Error: fmt.Errorf(" %s", err)} } f.report() f.setRan() f.signal <- true // signal that the test has finished }() + defer f.runCleanup(normalPanic) fn(f) f.finished = true } |
