| # TODO(jayconrod): support shared memory on more platforms. |
| [!darwin] [!linux] [!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 |
| |
| # 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 |
| stdout 'fuzzing process terminated unexpectedly' |
| stdout 'Crash 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, probably because it already exists, |
| // and we're minimizing now. Return without crashing. |
| return |
| } |
| f.Write(b) |
| f.Close() |
| 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) |
| } |
| } |
| }) |
| } |