Fuzzing and Property-Style Tests
Fuzzing and Property-Style Tests
Overview
Fuzzing feeds random inputs to find panics and logic bugs. Go’s built-in fuzzing (go test -fuzz) is ideal for parsers, validators, and codecs.
Fuzz target
func FuzzParsePort(f *testing.F) {
f.Add("8080")
f.Add("0")
f.Add("65535")
f.Fuzz(func(t *testing.T, s string) {
n, err := strconv.Atoi(s)
if err != nil {
return
}
if n < 0 {
t.Fatalf("negative: %d", n)
}
// property: round-trip for valid ports
if n >= 0 && n <= 65535 {
if strconv.Itoa(n) != s && !strings.HasPrefix(s, "0") && s != "0" {
// allow leading zeros mismatch — define your contract
}
}
})
}go test -fuzz=FuzzParsePort -fuzztime=10sSeed corpus
f.Add seeds interesting cases; failing inputs land in testdata/fuzz/.
Good fuzz targets
| Good | Poor |
|---|---|
| JSON/decode, path clean, URL parse wrappers | Tests needing full DB |
| Pure functions | Non-deterministic time without injection |
Property ideas
- Round-trip:
decode(encode(x)) == x
- Idempotent clean:
clean(clean(p)) == clean(p)
- Never panics on any byte slice
Rules of thumb
| Do | Don’t |
|---|---|
| Fix corpus failures as tests | Delete corpus to “go green” |
| Bound work in fuzz body | Sleep/network in fuzz |
Run in CI with -fuzztime short |
Only fuzz manually once |
Try next
- Fuzz your
safeJoin— should never escape root.
- Fuzz JSON validator.
- Commit a minimized failing corpus once fixed.