package cuckoo_test import ( "maps" "math/rand/v2" "testing" "github.com/stretchr/testify/assert" "git.maximhutz.com/tools/go-cuckoo" ) func TestNewTable(t *testing.T) { assert := assert.New(t) table := cuckoo.NewTable[int, bool]() assert.NotNil(table) assert.Zero(table.Size()) } func TestAddItem(t *testing.T) { assert := assert.New(t) key, value := 0, true table := cuckoo.NewTable[int, bool]() err := table.Put(key, value) assert.NoError(err) assert.Equal(1, table.Size()) assert.True(table.Has(key)) } func TestPutOverwrite(t *testing.T) { assert := assert.New(t) key, value, newValue := 0, 1, 2 table := cuckoo.NewTable[int, int]() (table.Put(key, value)) err := table.Put(key, newValue) assert.NoError(err) assert.Equal(1, table.Size()) assert.True(table.Has(key)) found, _ := table.Get(key) assert.Equal(newValue, found) } func TestSameHash(t *testing.T) { assert := assert.New(t) hash := func(int) uint64 { return 0 } table := cuckoo.NewCustomTable[int, bool](hash, hash, cuckoo.DefaultEqualFunc[int]) errA := table.Put(0, true) errB := table.Put(1, true) errC := table.Put(2, true) assert.NoError(errA) assert.NoError(errB) assert.ErrorContains(errC, "bad hash") } func TestStartingCapacity(t *testing.T) { assert := assert.New(t) table := cuckoo.NewTable[int, bool](cuckoo.Capacity(64)) assert.Equal(uint64(128), table.TotalCapacity()) } func TestResizeCapacity(t *testing.T) { assert := assert.New(t) table := cuckoo.NewTable[int, bool]( cuckoo.Capacity(8), cuckoo.GrowthFactor(2), ) for table.TotalCapacity() == 16 { err := table.Put(rand.Int(), true) assert.NoError(err) } assert.Equal(uint64(32), table.TotalCapacity()) } func TestPutMany(t *testing.T) { assert := assert.New(t) expected, actual := map[int]bool{}, cuckoo.NewTable[int, bool]() for i := range 1_000 { expected[i] = true err := actual.Put(i, true) assert.NoError(err) } assert.Equal(maps.Collect(actual.Entries()), expected) assert.Equal(len(expected), actual.Size()) } func TestGetMany(t *testing.T) { assert := assert.New(t) table := cuckoo.NewTable[int, bool]() for i := range 1_000 { err := table.Put(i, true) assert.NoError(err) } for i := range 2_000 { value, err := table.Get(i) if i < 1_000 { assert.NoError(err) assert.Equal(value, true) } else { assert.Error(err) } } } func TestRemove(t *testing.T) { assert := assert.New(t) table := cuckoo.NewTable[int, bool]() assert.False(table.Has(0)) err := table.Put(0, true) assert.NoError(err) assert.True(table.Has(0)) } func TestDropExistingItem(t *testing.T) { assert := assert.New(t) key, value := 0, true table := cuckoo.NewTable[int, bool]() (table.Put(key, value)) err := table.Drop(key) assert.NoError(err) assert.Equal(0, table.Size()) assert.False(table.Has(key)) } func TestDropNoItem(t *testing.T) { assert := assert.New(t) key := 0 table := cuckoo.NewTable[int, bool]() err := table.Drop(key) assert.NoError(err) assert.Equal(0, table.Size()) assert.False(table.Has(key)) }