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  }