chore: move from tools/dsa
All checks were successful
CI / lint (pull_request) Successful in 51s
CI / unit-test (pull_request) Successful in 25s
CI / mutation-test (pull_request) Successful in 2m44s
CI / fuzz-test (pull_request) Successful in 1m2s

Moved the implementation of this hash table from `tools/dsa` #1.
This commit is contained in:
2026-03-16 21:10:08 -04:00
parent 553117cb30
commit b762417b80
18 changed files with 1022 additions and 0 deletions

130
cuckoo_test.go Normal file
View File

@@ -0,0 +1,130 @@
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.Capacity())
}
func TestResizeCapacity(t *testing.T) {
assert := assert.New(t)
table := cuckoo.NewTable[int, bool](
cuckoo.Capacity(8),
cuckoo.GrowthFactor(2),
)
for table.Capacity() == 16 {
err := table.Put(rand.Int(), true)
assert.NoError(err)
}
assert.Equal(uint64(32), table.Capacity())
}
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))
}