diff options
| author | Roland Shoemaker <roland@golang.org> | 2021-05-01 18:46:22 -0700 |
|---|---|---|
| committer | Roland Shoemaker <roland@golang.org> | 2021-05-07 14:24:10 +0000 |
| commit | 510e711dd36999f1800678909bb7fdb448aa074f (patch) | |
| tree | f0b530310fabc4cc01f0f9a3a4f59f8c5d58fefe /src/testing | |
| parent | af3237eaf9cf46e6a02a3b53447e49c55abd4f00 (diff) | |
| download | go-510e711dd36999f1800678909bb7fdb448aa074f.tar.xz | |
[dev.fuzz] testing,internal/fuzz: prevent unbounded memory growth
Usage of f.testContext.match.fullName to generate the test name causes
unbounded memory growth, eventually causing the fuzzer to slow down
as memory pressure increases.
Each time fuzzFn is invoked it generates a unique string and stores it
in a map. With the fuzzer running at around 100k executions per second
this consumed around ~30GB of memory in a handful of minutes.
Instead just use the base name of the test for mutated inputs, a special
name for seeded inputs, and the filename for inputs from the input
corpus.
Change-Id: I083f47df7e82f0c6b0bda244f158233784a13029
Reviewed-on: https://go-review.googlesource.com/c/go/+/316030
Trust: Roland Shoemaker <roland@golang.org>
Trust: Katie Hockman <katie@golang.org>
Run-TryBot: Roland Shoemaker <roland@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Katie Hockman <katie@golang.org>
Diffstat (limited to 'src/testing')
| -rw-r--r-- | src/testing/fuzz.go | 14 |
1 files changed, 6 insertions, 8 deletions
diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 70e1b414a8..7afd24d258 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -226,7 +226,7 @@ func (f *F) Add(args ...interface{}) { } values = append(values, args[i]) } - f.corpus = append(f.corpus, corpusEntry{Values: values}) + f.corpus = append(f.corpus, corpusEntry{Values: values, Name: fmt.Sprintf("seed#%d", len(f.corpus))}) } // supportedTypes represents all of the supported types which can be fuzzed. @@ -298,21 +298,19 @@ func (f *F) Fuzz(ff interface{}) { // fn is called in its own goroutine. // // TODO(jayconrod,katiehockman): dedupe testdata corpus with entries from f.Add - // TODO(jayconrod,katiehockman): improve output when running the subtest. - // e.g. instead of - // --- FAIL: FuzzSomethingError/#00 (0.00s) - // do - // --- FAIL: FuzzSomethingError/<hash> (0.00s) run := func(e corpusEntry) error { if e.Values == nil { // Every code path should have already unmarshaled Data into Values. // It's our fault if it didn't. panic(fmt.Sprintf("corpus file %q was not unmarshaled", e.Name)) } - testName, ok, _ := f.testContext.match.fullName(&f.common, e.Name) - if !ok || shouldFailFast() { + if shouldFailFast() { return nil } + testName := f.common.name + if e.Name != "" { + testName = fmt.Sprintf("%s/%s", testName, e.Name) + } // Record the stack trace at the point of this call so that if the subtest // function - which runs in a separate stack - is marked as a helper, we can // continue walking the stack into the parent test. |
