diff options
| author | Katie Hockman <katie@golang.org> | 2021-10-14 12:32:58 -0400 |
|---|---|---|
| committer | Katie Hockman <katie@golang.org> | 2021-10-19 15:48:56 +0000 |
| commit | 067d796549242bec2d33226c9da1e67f092a7be2 (patch) | |
| tree | bcf3633c27756e3b5bd26b0c119f50e1785b17e1 /src/testing | |
| parent | 6294207a1c79e318124850155c7b6c23997c8c13 (diff) | |
| download | go-067d796549242bec2d33226c9da1e67f092a7be2.tar.xz | |
testing: write output to buffer when fuzzing
Fixes #48709
Change-Id: Ia6376a2f792946498d6565a53605b3e6c985ea7c
Reviewed-on: https://go-review.googlesource.com/c/go/+/355909
Trust: Katie Hockman <katie@golang.org>
Run-TryBot: Katie Hockman <katie@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Jay Conrod <jayconrod@google.com>
Reviewed-by: Roland Shoemaker <roland@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
Diffstat (limited to 'src/testing')
| -rw-r--r-- | src/testing/fuzz.go | 28 |
1 files changed, 20 insertions, 8 deletions
diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 0429f8243d..d5cb5e853f 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -5,6 +5,7 @@ package testing import ( + "bytes" "errors" "flag" "fmt" @@ -367,14 +368,14 @@ func (f *F) Fuzz(ff interface{}) { // run calls fn on a given input, as a subtest with its own T. // run is analogous to T.Run. The test filtering and cleanup works similarly. // fn is called in its own goroutine. - run := func(e corpusEntry) error { + run := func(captureOut io.Writer, e corpusEntry) (ok bool) { if e.Values == nil { // The corpusEntry must have non-nil Values in order to run the // test. If Values is nil, it is a bug in our code. panic(fmt.Sprintf("corpus file %q was not unmarshaled", e.Path)) } if shouldFailFast() { - return nil + return true } testName := f.name if e.Path != "" { @@ -405,6 +406,10 @@ func (f *F) Fuzz(ff interface{}) { }, context: f.testContext, } + if captureOut != nil { + // t.parent aliases f.common. + t.parent.w = captureOut + } t.w = indenter{&t.common} if t.chatty != nil { // TODO(#48132): adjust this to work with test2json. @@ -426,10 +431,7 @@ func (f *F) Fuzz(ff interface{}) { }) <-t.signal f.inFuzzFn = false - if t.Failed() { - return errors.New(string(f.output)) - } - return nil + return !t.Failed() } switch f.fuzzContext.mode { @@ -466,7 +468,17 @@ func (f *F) Fuzz(ff interface{}) { case fuzzWorker: // Fuzzing is enabled, and this is a worker process. Follow instructions // from the coordinator. - if err := f.fuzzContext.deps.RunFuzzWorker(run); err != nil { + if err := f.fuzzContext.deps.RunFuzzWorker(func(e corpusEntry) error { + // Don't write to f.w (which points to Stdout) if running from a + // fuzz worker. This would become very verbose, particularly during + // minimization. Return the error instead, and let the caller deal + // with the output. + var buf bytes.Buffer + if ok := run(&buf, e); !ok { + return errors.New(buf.String()) + } + return nil + }); err != nil { // Internal errors are marked with f.Fail; user code may call this too, before F.Fuzz. // The worker will exit with fuzzWorkerExitCode, indicating this is a failure // (and 'go test' should exit non-zero) but a crasher should not be recorded. @@ -479,7 +491,7 @@ func (f *F) Fuzz(ff interface{}) { for _, e := range f.corpus { name := fmt.Sprintf("%s/%s", f.name, filepath.Base(e.Path)) if _, ok, _ := f.testContext.match.fullName(nil, name); ok { - run(e) + run(f.w, e) } } } |
