package cuckoo_test import ( "maps" "testing" "github.com/stretchr/testify/assert" go_fuzz_utils "github.com/trailofbits/go-fuzz-utils" "git.maximhutz.com/tools/go-cuckoo" ) func offsetHash(seed uint32) cuckoo.Hash[uint32] { return func(x uint32) uint64 { v := uint64(x) ^ uint64(seed) v = (v ^ (v >> 30)) * 0xbf58476d1ce4e5b9 v = (v ^ (v >> 27)) * 0x94d049bb133111eb return v ^ (v >> 31) } } type fuzzStep struct { drop bool key, value uint32 } type fuzzScenario struct { seedA, seedB uint32 steps []fuzzStep } func FuzzInsertLookup(f *testing.F) { f.Fuzz(func(t *testing.T, data []byte) { var scenario fuzzScenario assert := assert.New(t) if tp, err := go_fuzz_utils.NewTypeProvider(data); err != nil { return } else if err := tp.Fill(&scenario); err != nil { return } if scenario.seedA == scenario.seedB { return } actual := cuckoo.NewCustomTable[uint32, uint32]( offsetHash(scenario.seedA), offsetHash(scenario.seedB), func(a, b uint32) bool { return a == b }, ) expected := map[uint32]uint32{} for _, step := range scenario.steps { if step.drop { err := actual.Drop(step.key) assert.NoError(err) delete(expected, step.key) _, err = actual.Get(step.key) assert.Error(err) } else { err := actual.Put(step.key, step.value) assert.NoError(err) expected[step.key] = step.value found, err := actual.Get(step.key) assert.NoError(err) assert.Equal(step.value, found) } assert.Equal(expected, maps.Collect(actual.Entries())) } }) }