blob: 3b005c960194729dd191208ac31f47a89e4ca0a0 [file] [log] [blame]
# TODO(jayconrod): support shared memory on more platforms.
[!GOOS:darwin] [!GOOS:linux] [!GOOS:windows] skip
# Verify that the fuzzing engine records the actual crashing input, even when
# a worker process terminates without communicating the crashing input back
# to the coordinator.
[short] skip
env GOCACHE=$WORK/cache
# Start fuzzing. The worker crashes after 100 iterations.
# The fuzz function writes the crashing input to "want" before exiting.
# The fuzzing engine reconstructs the crashing input and saves it to testdata.
! exists want
! go test -fuzz=. -parallel=1 -fuzztime=110x -fuzzminimizetime=10x -v
stdout '^\s+fuzzing process hung or terminated unexpectedly: exit status'
stdout 'Failing input written to testdata'
# Run the fuzz target without fuzzing. The fuzz function is called with the
# crashing input in testdata. The test passes if that input is identical to
# the one saved in "want".
exists want
go test -want=want
-- go.mod --
module fuzz
go 1.17
-- fuzz_test.go --
package fuzz
import (
"bytes"
"flag"
"os"
"testing"
)
var wantFlag = flag.String("want", "", "file containing previous crashing input")
func FuzzRepeat(f *testing.F) {
i := 0
f.Fuzz(func(t *testing.T, b []byte) {
i++
if i == 100 {
f, err := os.OpenFile("want", os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0666)
if err != nil {
// Couldn't create the file. Return without crashing, and try
// again.
i--
t.Skip(err)
}
if _, err := f.Write(b); err != nil {
// We already created the file, so if we failed to write it
// there's not much we can do. The test will fail anyway, but
// at least make sure the error is logged to stdout.
t.Fatal(err)
}
if err := f.Close(); err != nil {
t.Fatal(err)
}
os.Exit(1) // crash without communicating
}
if *wantFlag != "" {
want, err := os.ReadFile(*wantFlag)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(want, b) {
t.Fatalf("inputs are not equal!\n got: %q\nwant:%q", b, want)
}
}
})
}