What fuzzing does
Fuzz testing feeds random inputs to your code and watches for crashes, panics, or assertion failures. It finds bugs that humans do not think to test for, such as malformed UTF-8, integer overflows, and nil pointer dereferences. Go has built-in fuzzing since Go 1.18. Unkey fuzz tests must usepkg/fuzz on top of Go’s native fuzzing API. pkg/fuzz provides deterministic seeds and converts fuzzer-controlled byte slices into typed values without hiding inputs from the coverage-guided fuzzer.
Every fuzz test must call fuzz.Seed(f), accept data []byte, create a fuzz.Consumer with fuzz.New(t, data), and derive generated values from that consumer. Do not fuzz typed parameters directly, and do not use math/rand or ad hoc byte slicing inside fuzz tests.
When the fuzzer finds a failure, Go saves that input so the bug becomes a regression test.
When to write fuzz tests
Fuzz tests are best for code that processes untrusted input: parsing, encoding, decoding, validation, and cryptographic operations. They are less useful for business logic with complex preconditions.Writing your first fuzz test
Start a fuzz test by naming the property it protects. Seed inputs are examples of the property, not the property itself. Add a docstring when the property is a security boundary, parser invariant, or regression from a production bug.Skipping invalid inputs
Uset.Skip() for inputs that do not meet required preconditions. pkg/fuzz also calls t.Skip() when the consumer runs out of bytes, which keeps every generated value tied to fuzzer-controlled input.
Testing security properties
Use fuzzing to validate tamper detection and authentication guarantees. Document security properties in the fuzz test docstring. A future reader must know whether the fuzzer protects parser safety, signature verification, canonical encoding, authorization boundaries, or another guarantee.Running fuzz tests
During normal test runs, fuzz tests execute only with their seed corpus:testdata/fuzz/<TestName>/ so it becomes part of the seed corpus.
What to do when fuzzing finds a bug
Write a deterministic unit test for the failing input, then fix the bug. Keep the fuzz corpus intestdata to prevent regressions.
Bazel configuration
Fuzz tests live in regulargo_test targets. Add //pkg/fuzz to the target dependencies, and include the fuzz corpus with data = glob(["testdata/**"]) when the test has saved failure inputs.
