aboutsummaryrefslogtreecommitdiff
path: root/src/testing/fuzz.go
diff options
context:
space:
mode:
authorJay Conrod <jayconrod@google.com>2021-02-09 17:32:08 -0500
committerJay Conrod <jayconrod@google.com>2021-02-10 18:33:14 +0000
commit25bd2e962e33d15922111464311c4a94ec910773 (patch)
tree9585dd8ea2f58078275239839129fccc6f0d697a /src/testing/fuzz.go
parent1b5cf71ccf0dc95f121830cfdad8280c4f6c1f28 (diff)
downloadgo-25bd2e962e33d15922111464311c4a94ec910773.tar.xz
[dev.fuzz] testing: move inFuzzFn checks from common to F
inFuzzFn is set when the fuzz function is called. While it's set, F methods that have side effects like Skip and Fail may not be called. Previously, (CL 259657) inFuzzFn was in common, and we checked it in the common implementation of those methods. This causes problems in CL 290693 for recursive methods like common.Fail. If T.Fail is called by the fuzz function, it calls common.Fail on the parent F's common. That should not panic. Change-Id: I841b12f77d9c77f5021370d03313e71b4ef50102 Reviewed-on: https://go-review.googlesource.com/c/go/+/290811 Trust: Jay Conrod <jayconrod@google.com> Trust: Katie Hockman <katie@golang.org> Reviewed-by: Katie Hockman <katie@golang.org>
Diffstat (limited to 'src/testing/fuzz.go')
-rw-r--r--src/testing/fuzz.go121
1 files changed, 121 insertions, 0 deletions
diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go
index 196b4cf7ab..f64629bcd4 100644
--- a/src/testing/fuzz.go
+++ b/src/testing/fuzz.go
@@ -43,11 +43,14 @@ type InternalFuzzTarget struct {
type F struct {
common
context *fuzzContext
+ inFuzzFn bool // set to true when fuzz function is running
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
}
+var _ TB = (*F)(nil)
+
// corpusEntry is an alias to the same type as internal/fuzz.CorpusEntry.
// We use a type alias because we don't want to export this type, and we can't
// importing internal/fuzz from testing.
@@ -56,6 +59,124 @@ type corpusEntry = struct {
Data []byte
}
+// Cleanup registers a function to be called when the test and all its
+// subtests complete. Cleanup functions will be called in last added,
+// first called order.
+func (f *F) Cleanup(fn func()) {
+ if f.inFuzzFn {
+ panic("testing: f.Cleanup was called inside the f.Fuzz function")
+ }
+ f.common.Cleanup(fn)
+}
+
+// Error is equivalent to Log followed by Fail.
+func (f *F) Error(args ...interface{}) {
+ if f.inFuzzFn {
+ panic("testing: f.Error was called inside the f.Fuzz function")
+ }
+ f.common.Error(args...)
+}
+
+// Errorf is equivalent to Logf followed by Fail.
+func (f *F) Errorf(format string, args ...interface{}) {
+ if f.inFuzzFn {
+ panic("testing: f.Errorf was called inside the f.Fuzz function")
+ }
+ f.common.Errorf(format, args...)
+}
+
+// Fail marks the function as having failed but continues execution.
+func (f *F) Fail() {
+ if f.inFuzzFn {
+ panic("testing: f.Fail was called inside the f.Fuzz function")
+ }
+ f.common.Fail()
+}
+
+// FailNow marks the function as having failed and stops its execution
+// by calling runtime.Goexit (which then runs all deferred calls in the
+// current goroutine).
+// Execution will continue at the next test or benchmark.
+// FailNow must be called from the goroutine running the
+// test or benchmark function, not from other goroutines
+// created during the test. Calling FailNow does not stop
+// those other goroutines.
+func (f *F) FailNow() {
+ if f.inFuzzFn {
+ panic("testing: f.FailNow was called inside the f.Fuzz function")
+ }
+ f.common.FailNow()
+}
+
+// Fatal is equivalent to Log followed by FailNow.
+func (f *F) Fatal(args ...interface{}) {
+ if f.inFuzzFn {
+ panic("testing: f.Fatal was called inside the f.Fuzz function")
+ }
+ f.common.Fatal(args...)
+}
+
+// Fatalf is equivalent to Logf followed by FailNow.
+func (f *F) Fatalf(format string, args ...interface{}) {
+ if f.inFuzzFn {
+ panic("testing: f.Fatalf was called inside the f.Fuzz function")
+ }
+ f.common.Fatalf(format, args...)
+}
+
+// Helper marks the calling function as a test helper function.
+// When printing file and line information, that function will be skipped.
+// Helper may be called simultaneously from multiple goroutines.
+func (f *F) Helper() {
+ if f.inFuzzFn {
+ panic("testing: f.Helper was called inside the f.Fuzz function")
+ }
+ f.common.Helper()
+}
+
+// Skip is equivalent to Log followed by SkipNow.
+func (f *F) Skip(args ...interface{}) {
+ if f.inFuzzFn {
+ panic("testing: f.Skip was called inside the f.Fuzz function")
+ }
+ f.common.Skip(args...)
+}
+
+// SkipNow marks the test as having been skipped and stops its execution
+// by calling runtime.Goexit.
+// If a test fails (see Error, Errorf, Fail) and is then skipped,
+// it is still considered to have failed.
+// Execution will continue at the next test or benchmark. See also FailNow.
+// SkipNow must be called from the goroutine running the test, not from
+// other goroutines created during the test. Calling SkipNow does not stop
+// those other goroutines.
+func (f *F) SkipNow() {
+ if f.inFuzzFn {
+ panic("testing: f.SkipNow was called inside the f.Fuzz function")
+ }
+ f.common.SkipNow()
+}
+
+// Skipf is equivalent to Logf followed by SkipNow.
+func (f *F) Skipf(format string, args ...interface{}) {
+ if f.inFuzzFn {
+ panic("testing: f.Skipf was called inside the f.Fuzz function")
+ }
+ f.common.Skipf(format, args...)
+}
+
+// TempDir returns a temporary directory for the test to use.
+// The directory is automatically removed by Cleanup when the test and
+// all its subtests complete.
+// Each subsequent call to t.TempDir returns a unique directory;
+// if the directory creation fails, TempDir terminates the test by calling Fatal.
+func (f *F) TempDir() string {
+ if f.inFuzzFn {
+ panic("testing: f.TempDir was called inside the f.Fuzz function")
+ }
+ return f.common.TempDir()
+}
+
// Add will add the arguments to the seed corpus for the fuzz target. This will
// be a no-op if called after or within the Fuzz function. The args must match
// those in the Fuzz function.