Source file
src/hash/maphash/maphash_test.go
1
2
3
4
5 package maphash
6
7 import (
8 "bytes"
9 "hash"
10 "testing"
11 )
12
13 func TestUnseededHash(t *testing.T) {
14 m := map[uint64]struct{}{}
15 for i := 0; i < 1000; i++ {
16 h := new(Hash)
17 m[h.Sum64()] = struct{}{}
18 }
19 if len(m) < 900 {
20 t.Errorf("empty hash not sufficiently random: got %d, want 1000", len(m))
21 }
22 }
23
24 func TestSeededHash(t *testing.T) {
25 s := MakeSeed()
26 m := map[uint64]struct{}{}
27 for i := 0; i < 1000; i++ {
28 h := new(Hash)
29 h.SetSeed(s)
30 m[h.Sum64()] = struct{}{}
31 }
32 if len(m) != 1 {
33 t.Errorf("seeded hash is random: got %d, want 1", len(m))
34 }
35 }
36
37 func TestHashGrouping(t *testing.T) {
38 b := bytes.Repeat([]byte("foo"), 100)
39 hh := make([]*Hash, 7)
40 for i := range hh {
41 hh[i] = new(Hash)
42 }
43 for _, h := range hh[1:] {
44 h.SetSeed(hh[0].Seed())
45 }
46 hh[0].Write(b)
47 hh[1].WriteString(string(b))
48
49 writeByte := func(h *Hash, b byte) {
50 err := h.WriteByte(b)
51 if err != nil {
52 t.Fatalf("WriteByte: %v", err)
53 }
54 }
55 writeSingleByte := func(h *Hash, b byte) {
56 _, err := h.Write([]byte{b})
57 if err != nil {
58 t.Fatalf("Write single byte: %v", err)
59 }
60 }
61 writeStringSingleByte := func(h *Hash, b byte) {
62 _, err := h.WriteString(string([]byte{b}))
63 if err != nil {
64 t.Fatalf("WriteString single byte: %v", err)
65 }
66 }
67
68 for i, x := range b {
69 writeByte(hh[2], x)
70 writeSingleByte(hh[3], x)
71 if i == 0 {
72 writeByte(hh[4], x)
73 } else {
74 writeSingleByte(hh[4], x)
75 }
76 writeStringSingleByte(hh[5], x)
77 if i == 0 {
78 writeByte(hh[6], x)
79 } else {
80 writeStringSingleByte(hh[6], x)
81 }
82 }
83
84 sum := hh[0].Sum64()
85 for i, h := range hh {
86 if sum != h.Sum64() {
87 t.Errorf("hash %d not identical to a single Write", i)
88 }
89 }
90 }
91
92 func TestHashBytesVsString(t *testing.T) {
93 s := "foo"
94 b := []byte(s)
95 h1 := new(Hash)
96 h2 := new(Hash)
97 h2.SetSeed(h1.Seed())
98 n1, err1 := h1.WriteString(s)
99 if n1 != len(s) || err1 != nil {
100 t.Fatalf("WriteString(s) = %d, %v, want %d, nil", n1, err1, len(s))
101 }
102 n2, err2 := h2.Write(b)
103 if n2 != len(b) || err2 != nil {
104 t.Fatalf("Write(b) = %d, %v, want %d, nil", n2, err2, len(b))
105 }
106 if h1.Sum64() != h2.Sum64() {
107 t.Errorf("hash of string and bytes not identical")
108 }
109 }
110
111 func TestHashHighBytes(t *testing.T) {
112
113 const N = 10
114 m := map[uint64]struct{}{}
115 for i := 0; i < N; i++ {
116 h := new(Hash)
117 h.WriteString("foo")
118 m[h.Sum64()>>32] = struct{}{}
119 }
120 if len(m) < N/2 {
121 t.Errorf("from %d seeds, wanted at least %d different hashes; got %d", N, N/2, len(m))
122 }
123 }
124
125 func TestRepeat(t *testing.T) {
126 h1 := new(Hash)
127 h1.WriteString("testing")
128 sum1 := h1.Sum64()
129
130 h1.Reset()
131 h1.WriteString("testing")
132 sum2 := h1.Sum64()
133
134 if sum1 != sum2 {
135 t.Errorf("different sum after reseting: %#x != %#x", sum1, sum2)
136 }
137
138 h2 := new(Hash)
139 h2.SetSeed(h1.Seed())
140 h2.WriteString("testing")
141 sum3 := h2.Sum64()
142
143 if sum1 != sum3 {
144 t.Errorf("different sum on the same seed: %#x != %#x", sum1, sum3)
145 }
146 }
147
148 func TestSeedFromSum64(t *testing.T) {
149 h1 := new(Hash)
150 h1.WriteString("foo")
151 x := h1.Sum64()
152 h2 := new(Hash)
153 h2.SetSeed(h1.Seed())
154 h2.WriteString("foo")
155 y := h2.Sum64()
156 if x != y {
157 t.Errorf("hashes don't match: want %x, got %x", x, y)
158 }
159 }
160
161 func TestSeedFromSeed(t *testing.T) {
162 h1 := new(Hash)
163 h1.WriteString("foo")
164 _ = h1.Seed()
165 x := h1.Sum64()
166 h2 := new(Hash)
167 h2.SetSeed(h1.Seed())
168 h2.WriteString("foo")
169 y := h2.Sum64()
170 if x != y {
171 t.Errorf("hashes don't match: want %x, got %x", x, y)
172 }
173 }
174
175 func TestSeedFromFlush(t *testing.T) {
176 b := make([]byte, 65)
177 h1 := new(Hash)
178 h1.Write(b)
179 x := h1.Sum64()
180 h2 := new(Hash)
181 h2.SetSeed(h1.Seed())
182 h2.Write(b)
183 y := h2.Sum64()
184 if x != y {
185 t.Errorf("hashes don't match: want %x, got %x", x, y)
186 }
187 }
188
189 func TestSeedFromReset(t *testing.T) {
190 h1 := new(Hash)
191 h1.WriteString("foo")
192 h1.Reset()
193 h1.WriteString("foo")
194 x := h1.Sum64()
195 h2 := new(Hash)
196 h2.SetSeed(h1.Seed())
197 h2.WriteString("foo")
198 y := h2.Sum64()
199 if x != y {
200 t.Errorf("hashes don't match: want %x, got %x", x, y)
201 }
202 }
203
204
205 var _ hash.Hash = &Hash{}
206 var _ hash.Hash64 = &Hash{}
207
208 func benchmarkSize(b *testing.B, size int) {
209 h := &Hash{}
210 buf := make([]byte, size)
211 b.SetBytes(int64(size))
212 b.ResetTimer()
213
214 for i := 0; i < b.N; i++ {
215 h.Reset()
216 h.Write(buf)
217 h.Sum64()
218 }
219 }
220
221 func BenchmarkHash8Bytes(b *testing.B) {
222 benchmarkSize(b, 8)
223 }
224
225 func BenchmarkHash320Bytes(b *testing.B) {
226 benchmarkSize(b, 320)
227 }
228
229 func BenchmarkHash1K(b *testing.B) {
230 benchmarkSize(b, 1024)
231 }
232
233 func BenchmarkHash8K(b *testing.B) {
234 benchmarkSize(b, 8192)
235 }
236
View as plain text