...

Source file src/hash/maphash/maphash_test.go

Documentation: hash/maphash

		 1  // Copyright 2019 The Go Authors. All rights reserved.
		 2  // Use of this source code is governed by a BSD-style
		 3  // license that can be found in the LICENSE file.
		 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  	// See issue 34925.
	 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() // seed generated here
	 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() // seed generated here
	 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) // seed generated here
	 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() // seed generated here
	 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  // Make sure a Hash implements the hash.Hash and hash.Hash64 interfaces.
	 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