src.elv.sh@v0.21.0-dev.0.20240515223629-06979efb9a2a/pkg/eval/vals/hash_test.go (about) 1 package vals 2 3 import ( 4 "math" 5 "math/big" 6 "os" 7 "testing" 8 "unsafe" 9 10 "src.elv.sh/pkg/persistent/hash" 11 "src.elv.sh/pkg/persistent/hashmap" 12 "src.elv.sh/pkg/tt" 13 ) 14 15 type hasher struct{} 16 17 func (hasher) Hash() uint32 { return 42 } 18 19 type nonHasher struct{} 20 21 func TestHash(t *testing.T) { 22 z := big.NewInt(5) 23 z.Lsh(z, 8*uint(unsafe.Sizeof(int(0)))) 24 z.Add(z, big.NewInt(9)) 25 // z = 5 << wordSize + 9 26 27 tt.Test(t, Hash, 28 Args(false).Rets(uint32(0)), 29 Args(true).Rets(uint32(1)), 30 Args(1).Rets(uint32(1)), 31 Args(z).Rets(hash.DJB(1, 9, 5)), 32 Args(big.NewRat(3, 2)).Rets(hash.DJB(Hash(big.NewInt(3)), Hash(big.NewInt(2)))), 33 Args(1.0).Rets(hash.UInt64(math.Float64bits(1.0))), 34 Args("foo").Rets(hash.String("foo")), 35 Args(os.Stdin).Rets(hash.UIntPtr(os.Stdin.Fd())), 36 Args(MakeList("foo", "bar")).Rets(hash.DJB(Hash("foo"), Hash("bar"))), 37 Args(MakeMap("foo", "bar")). 38 Rets(hash.DJB(Hash("foo"), Hash("bar"))), 39 Args(hasher{}).Rets(uint32(42)), 40 Args(nonHasher{}).Rets(uint32(0)), 41 ) 42 } 43 44 func TestHash_EqualMapsWithDifferentInternal(t *testing.T) { 45 // The internal representation of maps with the same value is not always the 46 // same: when some keys of the map have the same hash, their values are 47 // stored in the insertion order. 48 // 49 // To reliably test this case, we construct maps with a custom hashing 50 // function. 51 m0 := hashmap.New(Equal, func(v any) uint32 { return 0 }) 52 m1 := m0.Assoc("k1", "v1").Assoc("k2", "v2") 53 m2 := m0.Assoc("k2", "v2").Assoc("k1", "v1") 54 if h1, h2 := Hash(m1), Hash(m2); h1 != h2 { 55 t.Errorf("%v != %v", h1, h2) 56 } 57 }