aboutsummaryrefslogtreecommitdiff
path: root/src/testing
diff options
context:
space:
mode:
authorKatie Hockman <katie@golang.org>2020-10-07 14:08:53 -0400
committerFilippo Valsorda <filippo@golang.org>2020-12-04 19:17:29 +0100
commit0a6f004cb1ed99bc225f4fe3cba5c2c5b901b442 (patch)
treec2e15074ba2c6838d5f108ffc5e1a40e2f199898 /src/testing
parent555797058ae41e3cc0825831520dee7fb77b3ce5 (diff)
downloadgo-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.go33
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
}