1 package xxhash
2
3 import (
4 "bytes"
5 "encoding/binary"
6 "fmt"
7 "strings"
8 "testing"
9 )
10
11 func TestAll(t *testing.T) {
12 for _, tt := range []struct {
13 name string
14 input string
15 want uint64
16 }{
17 {"empty", "", 0xef46db3751d8e999},
18 {"a", "a", 0xd24ec4f1a98c6e5b},
19 {"as", "as", 0x1c330fb2d66be179},
20 {"asd", "asd", 0x631c37ce72a97393},
21 {"asdf", "asdf", 0x415872f599cea71e},
22 {
23 "len=63",
24
25 "Call me Ishmael. Some years ago--never mind how long precisely-",
26 0x02a2e85470d6fd96,
27 },
28 } {
29 lastChunkSize := len(tt.input)
30 if lastChunkSize == 0 {
31 lastChunkSize = 1
32 }
33 for chunkSize := 1; chunkSize <= lastChunkSize; chunkSize++ {
34 name := fmt.Sprintf("%s,chunkSize=%d", tt.name, chunkSize)
35 t.Run(name, func(t *testing.T) {
36 testDigest(t, tt.input, chunkSize, tt.want)
37 })
38 }
39 t.Run(tt.name, func(t *testing.T) { testSum(t, tt.input, tt.want) })
40 }
41 }
42
43 func testDigest(t *testing.T, input string, chunkSize int, want uint64) {
44 d := New()
45 ds := New()
46 for i := 0; i < len(input); i += chunkSize {
47 chunk := input[i:]
48 if len(chunk) > chunkSize {
49 chunk = chunk[:chunkSize]
50 }
51 n, err := d.Write([]byte(chunk))
52 if err != nil || n != len(chunk) {
53 t.Fatalf("Digest.Write: got (%d, %v); want (%d, nil)", n, err, len(chunk))
54 }
55 n, err = ds.WriteString(chunk)
56 if err != nil || n != len(chunk) {
57 t.Fatalf("Digest.WriteString: got (%d, %v); want (%d, nil)", n, err, len(chunk))
58 }
59 }
60 if got := d.Sum64(); got != want {
61 t.Fatalf("Digest.Sum64: got 0x%x; want 0x%x", got, want)
62 }
63 if got := ds.Sum64(); got != want {
64 t.Fatalf("Digest.Sum64 (WriteString): got 0x%x; want 0x%x", got, want)
65 }
66 var b [8]byte
67 binary.BigEndian.PutUint64(b[:], want)
68 if got := d.Sum(nil); !bytes.Equal(got, b[:]) {
69 t.Fatalf("Sum: got %v; want %v", got, b[:])
70 }
71 }
72
73 func testSum(t *testing.T, input string, want uint64) {
74 if got := Sum64([]byte(input)); got != want {
75 t.Fatalf("Sum64: got 0x%x; want 0x%x", got, want)
76 }
77 if got := Sum64String(input); got != want {
78 t.Fatalf("Sum64String: got 0x%x; want 0x%x", got, want)
79 }
80 }
81
82 func TestReset(t *testing.T) {
83 parts := []string{"The quic", "k br", "o", "wn fox jumps", " ov", "er the lazy ", "dog."}
84 d := New()
85 for _, part := range parts {
86 d.Write([]byte(part))
87 }
88 h0 := d.Sum64()
89
90 d.Reset()
91 d.Write([]byte(strings.Join(parts, "")))
92 h1 := d.Sum64()
93
94 if h0 != h1 {
95 t.Errorf("0x%x != 0x%x", h0, h1)
96 }
97 }
98
99 func TestBinaryMarshaling(t *testing.T) {
100 d := New()
101 d.WriteString("abc")
102 b, err := d.MarshalBinary()
103 if err != nil {
104 t.Fatal(err)
105 }
106 d = New()
107 d.WriteString("junk")
108 if err := d.UnmarshalBinary(b); err != nil {
109 t.Fatal(err)
110 }
111 d.WriteString("def")
112 if got, want := d.Sum64(), Sum64String("abcdef"); got != want {
113 t.Fatalf("after MarshalBinary+UnmarshalBinary, got 0x%x; want 0x%x", got, want)
114 }
115
116 d0 := New()
117 d1 := New()
118 for i := 0; i < 64; i++ {
119 b, err := d0.MarshalBinary()
120 if err != nil {
121 t.Fatal(err)
122 }
123 d0 = new(Digest)
124 if err := d0.UnmarshalBinary(b); err != nil {
125 t.Fatal(err)
126 }
127 if got, want := d0.Sum64(), d1.Sum64(); got != want {
128 t.Fatalf("after %d Writes, unmarshaled Digest gave sum 0x%x; want 0x%x", i, got, want)
129 }
130
131 d0.Write([]byte{'a'})
132 d1.Write([]byte{'a'})
133 }
134 }
135
136 var sink uint64
137
138 func TestAllocs(t *testing.T) {
139 const shortStr = "abcdefghijklmnop"
140
141
142
143 t.Run("Sum64", func(t *testing.T) {
144 testAllocs(t, func() {
145 sink = Sum64([]byte(shortStr))
146 })
147 })
148
149
150
151 t.Run("Digest", func(t *testing.T) {
152 b := []byte("asdf")
153 testAllocs(t, func() {
154 d := New()
155 d.Write(b)
156 sink = d.Sum64()
157 })
158 })
159 }
160
161 func testAllocs(t *testing.T, fn func()) {
162 t.Helper()
163 if allocs := int(testing.AllocsPerRun(10, fn)); allocs > 0 {
164 t.Fatalf("got %d allocation(s) (want zero)", allocs)
165 }
166 }
167
View as plain text