github.com/arr-ai/hash@v0.8.0/hash_test.go (about) 1 package hash 2 3 import ( 4 "math" 5 "math/rand" 6 "testing" 7 "unsafe" 8 9 "github.com/stretchr/testify/assert" 10 ) 11 12 func TestHash64(t *testing.T) { 13 if Interface(uint64(0), 0) == 0 { 14 t.Error() 15 } 16 } 17 18 func TestHash64String(t *testing.T) { 19 if Interface("hello", 0) == 0 { 20 t.Error() 21 } 22 } 23 24 func TestHashMatchesEquality(t *testing.T) { 25 t.Logf("%d unique elements", len(cornucopia)) 26 total := 0 27 falsePositives := 0 28 for _, seeds := range [][2]uintptr{{0, 0}, {0, 1}, {0, 2}, {1, 1}, {1, 2}} { 29 aSeed := seeds[0] 30 bSeed := seeds[1] 31 for _, a := range cornucopia { 32 for _, b := range cornucopia { 33 if aSeed == bSeed && a == b { 34 assert.Equal(t, Interface(a, aSeed), Interface(b, bSeed), 35 "a=%v b=%v hash(a)=%v hash(b)=%v", 36 a, b, Interface(a, aSeed), Interface(b, aSeed)) 37 } else if Interface(a, aSeed) == Interface(b, bSeed) { 38 h := Interface(a, aSeed) 39 _ = Interface(b, bSeed) 40 t.Logf("\nhash(%#v %[1]T, %v) ==\nhash(%#v %[3]T, %v) == %d", 41 a, aSeed, b, bSeed, h) 42 falsePositives++ 43 } 44 total++ 45 } 46 } 47 } 48 assert.LessOrEqual(t, falsePositives, total/100, total) 49 } 50 51 func BenchmarkHash(b *testing.B) { 52 r := rand.New(rand.NewSource(0)) 53 for i := 0; i < b.N; i++ { 54 Interface(cornucopia[r.Int()%len(cornucopia)], 0) 55 } 56 } 57 58 var cornucopia = func() []interface{} { 59 x := 42 60 result := []interface{}{ 61 false, 62 true, 63 &x, 64 &[]int{43}[0], 65 &[]string{"hello"}[0], 66 uintptr(unsafe.Pointer(&x)), 67 unsafe.Pointer(nil), 68 unsafe.Pointer(&x), 69 unsafe.Pointer(uintptr(unsafe.Pointer(&x))), 70 [...]int{}, 71 [...]int{1, 2, 3, 4, 5}, 72 [...]int{5, 4, 3, 2, 1}, 73 } 74 75 // The following number lists are massive overkill, but it can't hurt. 76 77 for _, i := range []int64{ 78 -43, -42, -10, -1, 0, 1, 10, 42, 79 math.MaxInt64, math.MaxInt64 - 1, 80 math.MinInt64, math.MinInt64 + 1, 81 } { 82 result = append(result, int(i), int8(i), int16(i), int32(i), i) 83 } 84 85 for _, i := range []uint64{0, 42} { 86 result = append(result, uint(i), uint8(i), uint16(i), uint32(i), i) 87 } 88 89 floats := []float64{ 90 0, 42, math.Pi, 91 math.MaxFloat32, math.SmallestNonzeroFloat32, 92 math.MaxFloat64, math.SmallestNonzeroFloat64, 93 } 94 95 for _, f := range floats { 96 result = append(result, float32(f), f) 97 } 98 99 for _, re := range floats { 100 for _, im := range floats { 101 result = append(result, complex(float32(re), float32(im))) 102 result = append(result, complex(re, im)) 103 } 104 } 105 106 for _, s := range []string{ 107 "", 108 "a", 109 "b", 110 "hello", 111 "-------------------------------------------------------", 112 "--------------------------------------------------------", 113 "--------------------------------------------------------\000", 114 } { 115 result = append(result, s) 116 } 117 118 // Dedupe 119 m := map[interface{}]struct{}{} 120 for _, i := range result { 121 m[i] = struct{}{} 122 } 123 124 for i := range m { 125 result = append(result, i) 126 } 127 128 return result 129 }()