Compare commits
1 Commits
cdb5efb4a3
...
v0.1.0
| Author | SHA1 | Date | |
|---|---|---|---|
| 56b1982f8a |
@@ -4,4 +4,6 @@ unleash:
|
|||||||
timeout-coefficient: 50
|
timeout-coefficient: 50
|
||||||
|
|
||||||
workers: 4
|
workers: 4
|
||||||
dry-run: false
|
dry-run: false
|
||||||
|
threshold:
|
||||||
|
efficacy: 1.0
|
||||||
@@ -17,6 +17,8 @@ type bucket[K, V any] struct {
|
|||||||
compare EqualFunc[K]
|
compare EqualFunc[K]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// location determines where in the bucket a certain key would be placed. If the
|
||||||
|
// capacity is 0, this will panic.
|
||||||
func (b bucket[K, V]) location(key K) uint64 {
|
func (b bucket[K, V]) location(key K) uint64 {
|
||||||
return b.hash(key) % b.capacity
|
return b.hash(key) % b.capacity
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package cuckoo_test
|
package cuckoo_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"maps"
|
"maps"
|
||||||
"math/rand/v2"
|
"math/rand/v2"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -153,3 +154,88 @@ func TestDropNoItem(t *testing.T) {
|
|||||||
assert.Equal(0, table.Size())
|
assert.Equal(0, table.Size())
|
||||||
assert.False(table.Has(key))
|
assert.False(table.Has(key))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDropItemCapacity(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
key := 0
|
||||||
|
table := cuckoo.NewTable[int, bool](
|
||||||
|
cuckoo.Capacity(64),
|
||||||
|
cuckoo.GrowthFactor(2),
|
||||||
|
)
|
||||||
|
|
||||||
|
startingCapacity := table.TotalCapacity()
|
||||||
|
err := table.Drop(key)
|
||||||
|
endingCapacity := table.TotalCapacity()
|
||||||
|
|
||||||
|
assert.NoError(err)
|
||||||
|
assert.Equal(0, table.Size())
|
||||||
|
assert.Equal(uint64(128), startingCapacity)
|
||||||
|
assert.Equal(uint64(64), endingCapacity)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPutNoCapacity(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
key, value := 0, true
|
||||||
|
table := cuckoo.NewTable[int, bool](
|
||||||
|
cuckoo.Capacity(0),
|
||||||
|
)
|
||||||
|
|
||||||
|
err := table.Put(key, value)
|
||||||
|
|
||||||
|
assert.NoError(err)
|
||||||
|
assert.Equal(1, table.Size())
|
||||||
|
assert.True(table.Has(key))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBadHashCapacity(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
table := cuckoo.NewCustomTable[int, bool](
|
||||||
|
func(int) uint64 { return 0 },
|
||||||
|
func(int) uint64 { return 0 },
|
||||||
|
func(a, b int) bool { return a == b },
|
||||||
|
cuckoo.Capacity(20),
|
||||||
|
)
|
||||||
|
|
||||||
|
err1 := table.Put(0, true)
|
||||||
|
err2 := table.Put(1, true)
|
||||||
|
err3 := table.Put(2, true)
|
||||||
|
|
||||||
|
assert.NoError(err1)
|
||||||
|
assert.NoError(err2)
|
||||||
|
assert.Error(err3)
|
||||||
|
|
||||||
|
assert.Equal(uint64(80), table.TotalCapacity())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDropResizeCapacity(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
table := cuckoo.NewTable[int, bool](
|
||||||
|
cuckoo.Capacity(10),
|
||||||
|
)
|
||||||
|
|
||||||
|
err1 := table.Put(0, true)
|
||||||
|
err2 := table.Put(1, true)
|
||||||
|
err3 := table.Drop(1)
|
||||||
|
|
||||||
|
assert.NoError(errors.Join(err1, err2, err3))
|
||||||
|
assert.Equal(uint64(20), table.TotalCapacity())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewTableBy(t *testing.T) {
|
||||||
|
type User struct {
|
||||||
|
_ func()
|
||||||
|
id string
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
assert := assert.New(t)
|
||||||
|
table := cuckoo.NewTableBy[User, bool](
|
||||||
|
func(u User) string { return u.id },
|
||||||
|
)
|
||||||
|
|
||||||
|
err := table.Put(User{nil, "1", "Robert"}, true)
|
||||||
|
|
||||||
|
assert.NoError(err)
|
||||||
|
assert.Equal(1, table.Size())
|
||||||
|
assert.True(table.Has(User{nil, "1", "Robbie"}))
|
||||||
|
}
|
||||||
|
|||||||
2
go.mod
2
go.mod
@@ -4,6 +4,8 @@ go 1.25.6
|
|||||||
|
|
||||||
require github.com/stretchr/testify v1.11.1
|
require github.com/stretchr/testify v1.11.1
|
||||||
|
|
||||||
|
require github.com/kr/pretty v0.3.1 // indirect
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
|||||||
11
go.sum
11
go.sum
@@ -1,12 +1,21 @@
|
|||||||
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
|
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||||
|
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||||
github.com/trailofbits/go-fuzz-utils v0.0.0-20260318143407-0907cafe7589 h1:UmBZCTPdDYore2IEHN+U4eIqEaRq6METh9pKiPumkqc=
|
github.com/trailofbits/go-fuzz-utils v0.0.0-20260318143407-0907cafe7589 h1:UmBZCTPdDYore2IEHN+U4eIqEaRq6METh9pKiPumkqc=
|
||||||
github.com/trailofbits/go-fuzz-utils v0.0.0-20260318143407-0907cafe7589/go.mod h1:zh+T+w9XT/3o4E0WLEGCdmLJ8Yqx/zY3o538tQY3OjY=
|
github.com/trailofbits/go-fuzz-utils v0.0.0-20260318143407-0907cafe7589/go.mod h1:zh+T+w9XT/3o4E0WLEGCdmLJ8Yqx/zY3o538tQY3OjY=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|||||||
7
table.go
7
table.go
@@ -45,6 +45,9 @@ func (t Table[K, V]) load() float64 {
|
|||||||
return float64(t.Size()) / float64(t.TotalCapacity())
|
return float64(t.Size()) / float64(t.TotalCapacity())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// resize clears all buckets, changes the sizes of them to a specific capacity,
|
||||||
|
// and fills them back up again. It is a helper function for [Table.grow] and
|
||||||
|
// [Table.shrink]; use them instead.
|
||||||
func (t *Table[K, V]) resize(capacity uint64) error {
|
func (t *Table[K, V]) resize(capacity uint64) error {
|
||||||
entries := make([]entry[K, V], 0, t.Size())
|
entries := make([]entry[K, V], 0, t.Size())
|
||||||
for k, v := range t.Entries() {
|
for k, v := range t.Entries() {
|
||||||
@@ -63,6 +66,8 @@ func (t *Table[K, V]) resize(capacity uint64) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// grow increases the table's capacity by the [Table.growthFactor]. If the
|
||||||
|
// capacity is 0, it increases it to 1.
|
||||||
func (t *Table[K, V]) grow() error {
|
func (t *Table[K, V]) grow() error {
|
||||||
var newCapacity uint64
|
var newCapacity uint64
|
||||||
|
|
||||||
@@ -75,6 +80,8 @@ func (t *Table[K, V]) grow() error {
|
|||||||
return t.resize(newCapacity)
|
return t.resize(newCapacity)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// shrink reduces the table's capacity by the [Table.growthFactor]. It may
|
||||||
|
// reduce it down to 0.
|
||||||
func (t *Table[K, V]) shrink() error {
|
func (t *Table[K, V]) shrink() error {
|
||||||
return t.resize(t.bucketA.capacity / t.growthFactor)
|
return t.resize(t.bucketA.capacity / t.growthFactor)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
go test fuzz v1
|
|
||||||
[]byte("B000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000")
|
|
||||||
Reference in New Issue
Block a user