-
Notifications
You must be signed in to change notification settings - Fork 113
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update fuzz tests to use go fuzz features #148
Changes from all commits
5c470e8
bdf7f55
4825e91
223f01f
26aacc5
f8b5c5b
34e6f46
007c5b0
c435a87
343a276
6fa51f6
8641b02
ecd8f50
2206317
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,10 +23,7 @@ package uuid | |
|
||
import ( | ||
"bytes" | ||
"flag" | ||
"fmt" | ||
"os" | ||
"path/filepath" | ||
"regexp" | ||
"strings" | ||
"testing" | ||
) | ||
|
@@ -403,28 +400,110 @@ func BenchmarkParseV4(b *testing.B) { | |
} | ||
} | ||
|
||
var seedFuzzCorpus = flag.Bool("seed_fuzz_corpus", false, "seed fuzz test corpus") | ||
const uuidPattern = "[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}" | ||
|
||
func TestSeedFuzzCorpus(t *testing.T) { | ||
// flag.Parse() is called for us by the test binary. | ||
if !*seedFuzzCorpus { | ||
t.Skip("seeding fuzz test corpus only on demand") | ||
var fromBytesCorpus = [][]byte{ | ||
{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}, | ||
{4, 8, 15, 16, 23, 42}, | ||
} | ||
|
||
// FuzzFromBytesFunc is a fuzz testing suite that exercises the FromBytes function | ||
func FuzzFromBytesFunc(f *testing.F) { | ||
for _, seed := range fromBytesCorpus { | ||
f.Add(seed) | ||
} | ||
corpusDir := filepath.Join(".", "testdata", "corpus") | ||
writeSeedFile := func(name, data string) error { | ||
path := filepath.Join(corpusDir, name) | ||
return os.WriteFile(path, []byte(data), os.ModePerm) | ||
uuidRegexp, err := regexp.Compile(uuidPattern) | ||
if err != nil { | ||
f.Fatal("uuid regexp failed to compile") | ||
} | ||
for _, fst := range fromStringTests { | ||
name := "seed_valid_" + fst.variant | ||
if err := writeSeedFile(name, fst.input); err != nil { | ||
t.Fatal(err) | ||
f.Fuzz(func(t *testing.T, payload []byte) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the general logic for this pair is that if the payload was not 16 bytes, we fail the fuzz if fan error was not returned (or put another way, we verify that the function returns an error when the payload is 16 bytes). Otherwise, if an error was not returned, we make sure it's not a Nil uuid, and we make sure it matched the uuid pattern |
||
u, err := FromBytes(payload) | ||
if len(payload) != Size && err == nil { | ||
t.Errorf("%v did not result in an error", payload) | ||
} | ||
if len(payload) == Size && u == Nil { | ||
t.Errorf("%v resulted in Nil uuid", payload) | ||
} | ||
if len(payload) == Size && !uuidRegexp.MatchString(u.String()) { | ||
dylan-bourque marked this conversation as resolved.
Show resolved
Hide resolved
|
||
t.Errorf("%v resulted in invalid uuid %s", payload, u.String()) | ||
} | ||
// otherwise, allow to pass if no panic | ||
}) | ||
} | ||
|
||
// FuzzFromBytesOrNilFunc is a fuzz testing suite that exercises the FromBytesOrNil function | ||
func FuzzFromBytesOrNilFunc(f *testing.F) { | ||
for _, seed := range fromBytesCorpus { | ||
f.Add(seed) | ||
} | ||
for i, s := range invalidFromStringInputs { | ||
name := fmt.Sprintf("seed_invalid_%d", i) | ||
if err := writeSeedFile(name, s); err != nil { | ||
t.Fatal(err) | ||
uuidRegexp, err := regexp.Compile(uuidPattern) | ||
if err != nil { | ||
f.Error("uuid regexp failed to compile") | ||
} | ||
f.Fuzz(func(t *testing.T, payload []byte) { | ||
u := FromBytesOrNil(payload) | ||
if len(payload) != Size && u != Nil { | ||
t.Errorf("%v resulted in non Nil uuid %s", payload, u.String()) | ||
} | ||
if len(payload) == Size && u == Nil { | ||
t.Errorf("%v resulted Nil uuid", payload) | ||
} | ||
if len(payload) == Size && !uuidRegexp.MatchString(u.String()) { | ||
t.Errorf("%v resulted in invalid uuid %s", payload, u.String()) | ||
} | ||
// otherwise, allow to pass if no panic | ||
}) | ||
} | ||
|
||
var fromStringCorpus = []string{ | ||
"6ba7b810-9dad-11d1-80b4-00c04fd430c8", | ||
"6BA7B810-9DAD-11D1-80B4-00C04FD430C8", | ||
"{6BA7B810-9DAD-11D1-80B4-00C04FD430C8}", | ||
"urn:uuid:6BA7B810-9DAD-11D1-80B4-00C04FD430C8", | ||
"6BA7B8109DAD11D180B400C04FD430C8", | ||
"{6BA7B8109DAD11D180B400C04FD430C8}", | ||
"urn:uuid:6BA7B8109DAD11D180B400C04FD430C8", | ||
} | ||
|
||
// FuzzFromStringFunc is a fuzz testing suite that exercises the FromString function | ||
func FuzzFromStringFunc(f *testing.F) { | ||
for _, seed := range fromStringCorpus { | ||
f.Add(seed) | ||
} | ||
uuidRegexp, err := regexp.Compile(uuidPattern) | ||
if err != nil { | ||
f.Fatal("uuid regexp failed to compile") | ||
} | ||
f.Fuzz(func(t *testing.T, payload string) { | ||
u, err := FromString(payload) | ||
if err != nil { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the general logic for this pair is that if the function didn't return an error, we make sure the uuid matches a regex for uuids. Otherwise, we assume the error was correct for the input. This implicitly fails the fuzz test on a panic. |
||
if u == Nil { | ||
t.Errorf("%s resulted in Nil uuid", payload) | ||
} | ||
if !uuidRegexp.MatchString(u.String()) { | ||
t.Errorf("%s resulted in invalid uuid %s", payload, u.String()) | ||
} | ||
} | ||
// otherwise, allow to pass if no panic | ||
}) | ||
} | ||
|
||
// FuzzFromStringOrNil is a fuzz testing suite that exercises the FromStringOrNil function | ||
func FuzzFromStringOrNilFunc(f *testing.F) { | ||
for _, seed := range fromStringCorpus { | ||
f.Add(seed) | ||
} | ||
uuidRegexp, err := regexp.Compile(uuidPattern) | ||
if err != nil { | ||
f.Error("uuid regexp failed to compile") | ||
} | ||
f.Fuzz(func(t *testing.T, payload string) { | ||
u := FromStringOrNil(payload) | ||
if u != Nil { | ||
if !uuidRegexp.MatchString(u.String()) { | ||
t.Errorf("%s resulted in invalid uuid %s", payload, u.String()) | ||
} | ||
} | ||
// otherwise, allow to pass if no panic | ||
}) | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -611,6 +611,7 @@ func testNewV7(t *testing.T) { | |
t.Run("FaultyRand", makeTestNewV7FaultyRand()) | ||
t.Run("FaultyRandWithOptions", makeTestNewV7FaultyRandWithOptions()) | ||
t.Run("ShortRandomRead", makeTestNewV7ShortRandomRead()) | ||
t.Run("ShortRandomReadWithOptions", makeTestNewV7ShortRandomReadWithOptions()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While I was here I noticed that one of the v7 test functions weren't being run, so I added it here. |
||
t.Run("KSortable", makeTestNewV7KSortable()) | ||
t.Run("ClockSequence", makeTestNewV7ClockSequence()) | ||
} | ||
|
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed harden in places that I missed it.