github.com/geraldss/go/src@v0.0.0-20210511222824-ac7d0ebfc235/hash/maphash/maphash_test.go (about)

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