2019-04-20 00:40:45 +08:00
|
|
|
package vals
|
|
|
|
|
|
|
|
import (
|
|
|
|
"math"
|
2021-06-28 00:01:12 +08:00
|
|
|
"math/big"
|
2019-04-20 00:40:45 +08:00
|
|
|
"os"
|
|
|
|
"testing"
|
2021-06-28 00:01:12 +08:00
|
|
|
"unsafe"
|
2019-04-20 00:40:45 +08:00
|
|
|
|
2021-05-04 05:17:46 +08:00
|
|
|
"src.elv.sh/pkg/persistent/hash"
|
2023-07-15 05:01:32 +08:00
|
|
|
"src.elv.sh/pkg/persistent/hashmap"
|
2022-03-25 10:41:49 +08:00
|
|
|
"src.elv.sh/pkg/tt"
|
2019-04-20 00:40:45 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
type hasher struct{}
|
|
|
|
|
|
|
|
func (hasher) Hash() uint32 { return 42 }
|
|
|
|
|
|
|
|
type nonHasher struct{}
|
|
|
|
|
|
|
|
func TestHash(t *testing.T) {
|
2021-06-28 00:01:12 +08:00
|
|
|
z := big.NewInt(5)
|
|
|
|
z.Lsh(z, 8*uint(unsafe.Sizeof(int(0))))
|
|
|
|
z.Add(z, big.NewInt(9))
|
|
|
|
// z = 5 << wordSize + 9
|
|
|
|
|
2024-01-11 23:42:43 +08:00
|
|
|
tt.Test(t, Hash,
|
2019-04-20 00:40:45 +08:00
|
|
|
Args(false).Rets(uint32(0)),
|
|
|
|
Args(true).Rets(uint32(1)),
|
2021-06-28 00:01:12 +08:00
|
|
|
Args(1).Rets(uint32(1)),
|
|
|
|
Args(z).Rets(hash.DJB(1, 9, 5)),
|
|
|
|
Args(big.NewRat(3, 2)).Rets(hash.DJB(Hash(big.NewInt(3)), Hash(big.NewInt(2)))),
|
2019-04-20 00:40:45 +08:00
|
|
|
Args(1.0).Rets(hash.UInt64(math.Float64bits(1.0))),
|
|
|
|
Args("foo").Rets(hash.String("foo")),
|
|
|
|
Args(os.Stdin).Rets(hash.UIntPtr(os.Stdin.Fd())),
|
|
|
|
Args(MakeList("foo", "bar")).Rets(hash.DJB(Hash("foo"), Hash("bar"))),
|
2019-04-20 01:26:27 +08:00
|
|
|
Args(MakeMap("foo", "bar")).
|
2019-04-20 00:40:45 +08:00
|
|
|
Rets(hash.DJB(Hash("foo"), Hash("bar"))),
|
|
|
|
Args(hasher{}).Rets(uint32(42)),
|
|
|
|
Args(nonHasher{}).Rets(uint32(0)),
|
2024-01-11 23:42:43 +08:00
|
|
|
)
|
2019-04-20 00:40:45 +08:00
|
|
|
}
|
2023-07-15 05:01:32 +08:00
|
|
|
|
|
|
|
func TestHash_EqualMapsWithDifferentInternal(t *testing.T) {
|
|
|
|
// The internal representation of maps with the same value is not always the
|
|
|
|
// same: when some keys of the map have the same hash, their values are
|
|
|
|
// stored in the insertion order.
|
|
|
|
//
|
|
|
|
// To reliably test this case, we construct maps with a custom hashing
|
|
|
|
// function.
|
|
|
|
m0 := hashmap.New(Equal, func(v any) uint32 { return 0 })
|
|
|
|
m1 := m0.Assoc("k1", "v1").Assoc("k2", "v2")
|
|
|
|
m2 := m0.Assoc("k2", "v2").Assoc("k1", "v1")
|
|
|
|
if h1, h2 := Hash(m1), Hash(m2); h1 != h2 {
|
|
|
|
t.Errorf("%v != %v", h1, h2)
|
|
|
|
}
|
|
|
|
}
|