1package multihash
2
3import (
4	"bytes"
5	"encoding/hex"
6	"fmt"
7	"runtime"
8	"testing"
9)
10
11type SumTestCase struct {
12	code   uint64
13	length int
14	input  string
15	hex    string
16}
17
18var sumTestCases = []SumTestCase{
19	{ID, 3, "foo", "0003666f6f"},
20	{ID, -1, "foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoo", "0030666f6f666f6f666f6f666f6f666f6f666f6f666f6f666f6f666f6f666f6f666f6f666f6f666f6f666f6f666f6f666f6f"},
21	{SHA1, -1, "foo", "11140beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"},
22	{SHA1, 10, "foo", "110a0beec7b5ea3f0fdbc95d"},
23	{SHA2_256, -1, "foo", "12202c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae"},
24	{SHA2_256, 31, "foo", "121f2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7"},
25	{SHA2_256, 32, "foo", "12202c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae"},
26	{SHA2_256, 16, "foo", "12102c26b46b68ffc68ff99b453c1d304134"},
27	{SHA2_512, -1, "foo", "1340f7fbba6e0636f890e56fbbf3283e524c6fa3204ae298382d624741d0dc6638326e282c41be5e4254d8820772c5518a2c5a8c0c7f7eda19594a7eb539453e1ed7"},
28	{SHA2_512, 32, "foo", "1320f7fbba6e0636f890e56fbbf3283e524c6fa3204ae298382d624741d0dc663832"},
29	{SHA3, 32, "foo", "14204bca2b137edc580fe50a88983ef860ebaca36c857b1f492839d6d7392452a63c"},
30	{SHA3_512, 16, "foo", "14104bca2b137edc580fe50a88983ef860eb"},
31	{SHA3_512, -1, "foo", "14404bca2b137edc580fe50a88983ef860ebaca36c857b1f492839d6d7392452a63c82cbebc68e3b70a2a1480b4bb5d437a7cba6ecf9d89f9ff3ccd14cd6146ea7e7"},
32	{SHA3_224, -1, "beep boop", "171c0da73a89549018df311c0a63250e008f7be357f93ba4e582aaea32b8"},
33	{SHA3_224, 16, "beep boop", "17100da73a89549018df311c0a63250e008f"},
34	{SHA3_256, -1, "beep boop", "1620828705da60284b39de02e3599d1f39e6c1df001f5dbf63c9ec2d2c91a95a427f"},
35	{SHA3_256, 16, "beep boop", "1610828705da60284b39de02e3599d1f39e6"},
36	{SHA3_384, -1, "beep boop", "153075a9cff1bcfbe8a7025aa225dd558fb002769d4bf3b67d2aaf180459172208bea989804aefccf060b583e629e5f41e8d"},
37	{SHA3_384, 16, "beep boop", "151075a9cff1bcfbe8a7025aa225dd558fb0"},
38	{DBL_SHA2_256, 32, "foo", "5620c7ade88fc7a21498a6a5e5c385e1f68bed822b72aa63c4a9a48a02c2466ee29e"},
39	{BLAKE2B_MAX, -1, "foo", "c0e40240ca002330e69d3e6b84a46a56a6533fd79d51d97a3bb7cad6c2ff43b354185d6dc1e723fb3db4ae0737e120378424c714bb982d9dc5bbd7a0ab318240ddd18f8d"},
40	{BLAKE2B_MAX, 64, "foo", "c0e40240ca002330e69d3e6b84a46a56a6533fd79d51d97a3bb7cad6c2ff43b354185d6dc1e723fb3db4ae0737e120378424c714bb982d9dc5bbd7a0ab318240ddd18f8d"},
41	{BLAKE2B_MAX - 32, -1, "foo", "a0e40220b8fe9f7f6255a6fa08f668ab632a8d081ad87983c77cd274e48ce450f0b349fd"},
42	{BLAKE2B_MAX - 32, 32, "foo", "a0e40220b8fe9f7f6255a6fa08f668ab632a8d081ad87983c77cd274e48ce450f0b349fd"},
43	{BLAKE2B_MAX - 19, -1, "foo", "ade4022dca82ab956d5885e3f5db10cca94182f01a6ca2c47f9f4228497dcc9f4a0121c725468b852a71ec21fcbeb725df"},
44	{BLAKE2B_MAX - 19, 45, "foo", "ade4022dca82ab956d5885e3f5db10cca94182f01a6ca2c47f9f4228497dcc9f4a0121c725468b852a71ec21fcbeb725df"},
45	{BLAKE2B_MAX - 16, -1, "foo", "b0e40230e629ee880953d32c8877e479e3b4cb0a4c9d5805e2b34c675b5a5863c4ad7d64bb2a9b8257fac9d82d289b3d39eb9cc2"},
46	{BLAKE2B_MAX - 16, 48, "foo", "b0e40230e629ee880953d32c8877e479e3b4cb0a4c9d5805e2b34c675b5a5863c4ad7d64bb2a9b8257fac9d82d289b3d39eb9cc2"},
47	{BLAKE2B_MIN + 19, -1, "foo", "94e40214983ceba2afea8694cc933336b27b907f90c53a88"},
48	{BLAKE2B_MIN + 19, 20, "foo", "94e40214983ceba2afea8694cc933336b27b907f90c53a88"},
49	{BLAKE2B_MIN, -1, "foo", "81e4020152"},
50	{BLAKE2B_MIN, 1, "foo", "81e4020152"},
51	{BLAKE2S_MAX, 32, "foo", "e0e4022008d6cad88075de8f192db097573d0e829411cd91eb6ec65e8fc16c017edfdb74"},
52	{MURMUR3_128, 4, "beep boop", "2204243ddb9e"},
53	{KECCAK_256, 32, "foo", "1b2041b1a0649752af1b28b3dc29a1556eee781e4a4c3a1f7f53f90fa834de098c4d"},
54	{KECCAK_512, -1, "beep boop", "1d40e161c54798f78eba3404ac5e7e12d27555b7b810e7fd0db3f25ffa0c785c438331b0fbb6156215f69edf403c642e5280f4521da9bd767296ec81f05100852e78"},
55	{SHAKE_128, 32, "foo", "1820f84e95cb5fbd2038863ab27d3cdeac295ad2d4ab96ad1f4b070c0bf36078ef08"},
56	{SHAKE_256, 64, "foo", "19401af97f7818a28edfdfce5ec66dbdc7e871813816d7d585fe1f12475ded5b6502b7723b74e2ee36f2651a10a8eaca72aa9148c3c761aaceac8f6d6cc64381ed39"},
57	{MD5, -1, "foo", "d50110acbd18db4cc2f85cedef654fccc4a4d8"},
58}
59
60func TestSum(t *testing.T) {
61
62	for _, tc := range sumTestCases {
63
64		m1, err := FromHexString(tc.hex)
65		if err != nil {
66			t.Error(err)
67			continue
68		}
69
70		m2, err := Sum([]byte(tc.input), tc.code, tc.length)
71		if err != nil {
72			t.Error(tc.code, "sum failed.", err)
73			continue
74		}
75
76		if !bytes.Equal(m1, m2) {
77			t.Error(tc.code, Codes[tc.code], "sum failed.", m1, m2)
78			t.Error(hex.EncodeToString(m2))
79		}
80
81		s1 := m1.HexString()
82		if s1 != tc.hex {
83			t.Error("hex strings not the same")
84		}
85
86		s2 := m1.B58String()
87		m3, err := FromB58String(s2)
88		if err != nil {
89			t.Error("failed to decode b58")
90		} else if !bytes.Equal(m3, m1) {
91			t.Error("b58 failing bytes")
92		} else if s2 != m3.B58String() {
93			t.Error("b58 failing string")
94		}
95	}
96}
97
98func BenchmarkSum(b *testing.B) {
99	tc := sumTestCases[0]
100	for i := 0; i < b.N; i++ {
101		Sum([]byte(tc.input), tc.code, tc.length)
102	}
103}
104
105func BenchmarkBlake2B(b *testing.B) {
106	sizes := []uint64{128, 129, 130, 255, 256, 257, 386, 512}
107	for _, s := range sizes {
108		func(si uint64) {
109			b.Run(fmt.Sprintf("blake2b-%d", s), func(b *testing.B) {
110				arr := []byte("test data for some hashing, this is broken")
111				b.ResetTimer()
112				b.ReportAllocs()
113				for i := 0; i < b.N; i++ {
114					m, err := Sum(arr, BLAKE2B_MIN+si/8-1, -1)
115					if err != nil {
116						b.Fatal(err)
117					}
118					runtime.KeepAlive(m)
119				}
120			})
121		}(s)
122	}
123}
124
125// Test that the identity hash function checks
126// its `length` arguemnt for values that are
127// different to its `data` length.
128func TestSmallerLengthHashID(t *testing.T) {
129
130	data := []byte("Identity hash input data.")
131	dataLength := len(data)
132
133	// Normal case: `length == len(data)`.
134	_, err := sumID(data, dataLength)
135	if err != nil {
136		t.Fatal(err)
137	}
138
139	// Unconstrained length (-1): also allowed.
140	_, err = sumID(data, -1)
141	if err != nil {
142		t.Fatal(err)
143	}
144
145	// Any other variation of those two scenarios should fail.
146	for l := (dataLength - 1); l >= 0; l-- {
147		_, err = sumID(data, l)
148		if err == nil {
149			t.Fatal(fmt.Sprintf("identity hash of length %d smaller than data length %d didn't fail",
150				l, dataLength))
151		}
152	}
153}
154
155// Ensure that invalid codecs can't be registered, and existing hash funcs
156// won't be overwritten.
157func TestRegisterHashFunc(t *testing.T) {
158	tests := []struct {
159		code      uint64
160		shouldErr bool
161	}{
162		{9999, true},
163		{SHA1, true},
164	}
165
166	doesNothing := func(data []byte, length int) ([]byte, error) {
167		return []byte{}, nil
168	}
169
170	for _, tt := range tests {
171		err := RegisterHashFunc(tt.code, doesNothing)
172		if err != nil && !tt.shouldErr {
173			t.Error(err)
174		}
175	}
176}
177
178func TestTooLargeLength(t *testing.T) {
179	_, err := Sum([]byte("test"), SHA2_256, 33)
180	if err != ErrLenTooLarge {
181		t.Fatal("bad error", err)
182	}
183}
184
185func TestBasicSum(t *testing.T) {
186	for code, name := range Codes {
187		defaultLen, ok := DefaultLengths[code]
188		if !ok {
189			defaultLen = 32
190		}
191		_, err := Sum([]byte("test"), code, defaultLen)
192		switch err {
193		case ErrSumNotSupported, nil:
194		default:
195			t.Errorf("unexpected error for %s: %s", name, err)
196		}
197	}
198}
199