1 /*
2 * xxhsum - Command line interface for xxhash algorithms
3 * Copyright (C) 2013-2020 Yann Collet
4 *
5 * GPL v2 License
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * You can contact the author at:
22 * - xxHash homepage: https://www.xxhash.com
23 * - xxHash source repository: https://github.com/Cyan4973/xxHash
24 */
25
26 #include "xsum_config.h"
27 #include "xsum_sanity_check.h"
28 #include "xsum_output.h"
29 #include <stdlib.h>
30 #include <assert.h>
31 #include <string.h>
32 #ifndef XXH_STATIC_LINKING_ONLY
33 # define XXH_STATIC_LINKING_ONLY
34 #endif
35 #include "../xxhash.h"
36
37 /* use #define to make them constant, required for initialization */
38 #define PRIME32 2654435761U
39 #define PRIME64 11400714785074694797ULL
40
41 /*
42 * Fills a test buffer with pseudorandom data.
43 *
44 * This is used in the sanity check - its values must not be changed.
45 */
XSUM_fillTestBuffer(XSUM_U8 * buffer,size_t len)46 XSUM_API void XSUM_fillTestBuffer(XSUM_U8* buffer, size_t len)
47 {
48 XSUM_U64 byteGen = PRIME32;
49 size_t i;
50
51 assert(buffer != NULL);
52
53 for (i=0; i<len; i++) {
54 buffer[i] = (XSUM_U8)(byteGen>>56);
55 byteGen *= PRIME64;
56 }
57 }
58
59
60
61 /* ************************************************
62 * Self-test:
63 * ensure results consistency accross platforms
64 *********************************************** */
65 #if XSUM_NO_TESTS
XSUM_sanityCheck(void)66 XSUM_API void XSUM_sanityCheck(void)
67 {
68 XSUM_log("This version of xxhsum is not verified.\n");
69 }
70 #else
71
72 /*
73 * Test data vectors
74 */
75 typedef struct {
76 XSUM_U32 len;
77 XSUM_U32 seed;
78 XSUM_U32 Nresult;
79 } XSUM_testdata32_t;
80
81 typedef struct {
82 XSUM_U32 len;
83 XSUM_U64 seed;
84 XSUM_U64 Nresult;
85 } XSUM_testdata64_t;
86
87 typedef struct {
88 XSUM_U32 len;
89 XSUM_U64 seed;
90 XXH128_hash_t Nresult;
91 } XSUM_testdata128_t;
92
93 #define SECRET_SAMPLE_NBBYTES 4
94 typedef struct {
95 XSUM_U32 len;
96 XSUM_U8 byte[SECRET_SAMPLE_NBBYTES];
97 } XSUM_testdata_sample_t;
98
99 /* XXH32 */
100 static const XSUM_testdata32_t XSUM_XXH32_testdata[] = {
101 { 0, 0, 0x02CC5D05U },
102 { 0, PRIME32, 0x36B78AE7U },
103 { 1, 0, 0xCF65B03EU },
104 { 1, PRIME32, 0xB4545AA4U },
105 { 14, 0, 0x1208E7E2U },
106 { 14, PRIME32, 0x6AF1D1FEU },
107 { 222, 0, 0x5BD11DBDU },
108 { 222, PRIME32, 0x58803C5FU }
109 };
110
111 /* XXH64 */
112 static const XSUM_testdata64_t XSUM_XXH64_testdata[] = {
113 { 0, 0, 0xEF46DB3751D8E999ULL },
114 { 0, PRIME32, 0xAC75FDA2929B17EFULL },
115 { 1, 0, 0xE934A84ADB052768ULL },
116 { 1, PRIME32, 0x5014607643A9B4C3ULL },
117 { 4, 0, 0x9136A0DCA57457EEULL },
118 { 14, 0, 0x8282DCC4994E35C8ULL },
119 { 14, PRIME32, 0xC3BD6BF63DEB6DF0ULL },
120 { 222, 0, 0xB641AE8CB691C174ULL },
121 { 222, PRIME32, 0x20CB8AB7AE10C14AULL }
122 };
123 /*
124 * XXH3:
125 * Due to being a more complex hash function with specializations for certain
126 * lengths, a more extensive test is used for XXH3.
127 */
128
129 /* XXH3_64bits, seeded */
130 static const XSUM_testdata64_t XSUM_XXH3_testdata[] = {
131 { 0, 0, 0x2D06800538D394C2ULL }, /* empty string */
132 { 0, PRIME64, 0xA8A6B918B2F0364AULL }, /* empty string */
133 { 1, 0, 0xC44BDFF4074EECDBULL }, /* 1 - 3 */
134 { 1, PRIME64, 0x032BE332DD766EF8ULL }, /* 1 - 3 */
135 { 6, 0, 0x27B56A84CD2D7325ULL }, /* 4 - 8 */
136 { 6, PRIME64, 0x84589C116AB59AB9ULL }, /* 4 - 8 */
137 { 12, 0, 0xA713DAF0DFBB77E7ULL }, /* 9 - 16 */
138 { 12, PRIME64, 0xE7303E1B2336DE0EULL }, /* 9 - 16 */
139 { 24, 0, 0xA3FE70BF9D3510EBULL }, /* 17 - 32 */
140 { 24, PRIME64, 0x850E80FC35BDD690ULL }, /* 17 - 32 */
141 { 48, 0, 0x397DA259ECBA1F11ULL }, /* 33 - 64 */
142 { 48, PRIME64, 0xADC2CBAA44ACC616ULL }, /* 33 - 64 */
143 { 80, 0, 0xBCDEFBBB2C47C90AULL }, /* 65 - 96 */
144 { 80, PRIME64, 0xC6DD0CB699532E73ULL }, /* 65 - 96 */
145 { 195, 0, 0xCD94217EE362EC3AULL }, /* 129-240 */
146 { 195, PRIME64, 0xBA68003D370CB3D9ULL }, /* 129-240 */
147
148 { 403, 0, 0xCDEB804D65C6DEA4ULL }, /* one block, last stripe is overlapping */
149 { 403, PRIME64, 0x6259F6ECFD6443FDULL }, /* one block, last stripe is overlapping */
150 { 512, 0, 0x617E49599013CB6BULL }, /* one block, finishing at stripe boundary */
151 { 512, PRIME64, 0x3CE457DE14C27708ULL }, /* one block, finishing at stripe boundary */
152 { 2048, 0, 0xDD59E2C3A5F038E0ULL }, /* 2 blocks, finishing at block boundary */
153 { 2048, PRIME64, 0x66F81670669ABABCULL }, /* 2 blocks, finishing at block boundary */
154 { 2240, 0, 0x6E73A90539CF2948ULL }, /* 3 blocks, finishing at stripe boundary */
155 { 2240, PRIME64, 0x757BA8487D1B5247ULL }, /* 3 blocks, finishing at stripe boundary */
156 { 2367, 0, 0xCB37AEB9E5D361EDULL }, /* 3 blocks, last stripe is overlapping */
157 { 2367, PRIME64, 0xD2DB3415B942B42AULL } /* 3 blocks, last stripe is overlapping */
158 };
159 /* XXH3_64bits, custom secret */
160 static const XSUM_testdata64_t XSUM_XXH3_withSecret_testdata[] = {
161 { 0, 0, 0x3559D64878C5C66CULL }, /* empty string */
162 { 1, 0, 0x8A52451418B2DA4DULL }, /* 1 - 3 */
163 { 6, 0, 0x82C90AB0519369ADULL }, /* 4 - 8 */
164 { 12, 0, 0x14631E773B78EC57ULL }, /* 9 - 16 */
165 { 24, 0, 0xCDD5542E4A9D9FE8ULL }, /* 17 - 32 */
166 { 48, 0, 0x33ABD54D094B2534ULL }, /* 33 - 64 */
167 { 80, 0, 0xE687BA1684965297ULL }, /* 65 - 96 */
168 { 195, 0, 0xA057273F5EECFB20ULL }, /* 129-240 */
169
170 { 403, 0, 0x14546019124D43B8ULL }, /* one block, last stripe is overlapping */
171 { 512, 0, 0x7564693DD526E28DULL }, /* one block, finishing at stripe boundary */
172 { 2048, 0, 0xD32E975821D6519FULL }, /* >= 2 blodcks, at least one scrambling */
173 { 2367, 0, 0x293FA8E5173BB5E7ULL }, /* >= 2 blocks, at least one scrambling, last stripe unaligned */
174
175 { 64*10*3, 0, 0x751D2EC54BC6038BULL } /* exactly 3 full blocks, not a multiple of 256 */
176 };
177 /* XXH3_128bits, seeded */
178 static const XSUM_testdata128_t XSUM_XXH128_testdata[] = {
179 { 0, 0, { 0x6001C324468D497FULL, 0x99AA06D3014798D8ULL } }, /* empty string */
180 { 0, PRIME32, { 0x5444F7869C671AB0ULL, 0x92220AE55E14AB50ULL } }, /* empty string */
181 { 1, 0, { 0xC44BDFF4074EECDBULL, 0xA6CD5E9392000F6AULL } }, /* 1 - 3 */
182 { 1, PRIME32, { 0xB53D5557E7F76F8DULL, 0x89B99554BA22467CULL } }, /* 1 - 3 */
183 { 6, 0, { 0x3E7039BDDA43CFC6ULL, 0x082AFE0B8162D12AULL } }, /* 4 - 8 */
184 { 6, PRIME32, { 0x269D8F70BE98856EULL, 0x5A865B5389ABD2B1ULL } }, /* 4 - 8 */
185 { 12, 0, { 0x061A192713F69AD9ULL, 0x6E3EFD8FC7802B18ULL } }, /* 9 - 16 */
186 { 12, PRIME32, { 0x9BE9F9A67F3C7DFBULL, 0xD7E09D518A3405D3ULL } }, /* 9 - 16 */
187 { 24, 0, { 0x1E7044D28B1B901DULL, 0x0CE966E4678D3761ULL } }, /* 17 - 32 */
188 { 24, PRIME32, { 0xD7304C54EBAD40A9ULL, 0x3162026714A6A243ULL } }, /* 17 - 32 */
189 { 48, 0, { 0xF942219AED80F67BULL, 0xA002AC4E5478227EULL } }, /* 33 - 64 */
190 { 48, PRIME32, { 0x7BA3C3E453A1934EULL, 0x163ADDE36C072295ULL } }, /* 33 - 64 */
191 { 81, 0, { 0x5E8BAFB9F95FB803ULL, 0x4952F58181AB0042ULL } }, /* 65 - 96 */
192 { 81, PRIME32, { 0x703FBB3D7A5F755CULL, 0x2724EC7ADC750FB6ULL } }, /* 65 - 96 */
193 { 222, 0, { 0xF1AEBD597CEC6B3AULL, 0x337E09641B948717ULL } }, /* 129-240 */
194 { 222, PRIME32, { 0xAE995BB8AF917A8DULL, 0x91820016621E97F1ULL } }, /* 129-240 */
195
196 { 403, 0, { 0xCDEB804D65C6DEA4ULL, 0x1B6DE21E332DD73DULL } }, /* one block, last stripe is overlapping */
197 { 403, PRIME64, { 0x6259F6ECFD6443FDULL, 0xBED311971E0BE8F2ULL } }, /* one block, last stripe is overlapping */
198 { 512, 0, { 0x617E49599013CB6BULL, 0x18D2D110DCC9BCA1ULL } }, /* one block, finishing at stripe boundary */
199 { 512, PRIME64, { 0x3CE457DE14C27708ULL, 0x925D06B8EC5B8040ULL } }, /* one block, finishing at stripe boundary */
200 { 2048, 0, { 0xDD59E2C3A5F038E0ULL, 0xF736557FD47073A5ULL } }, /* 2 blocks, finishing at block boundary */
201 { 2048, PRIME32, { 0x230D43F30206260BULL, 0x7FB03F7E7186C3EAULL } }, /* 2 blocks, finishing at block boundary */
202 { 2240, 0, { 0x6E73A90539CF2948ULL, 0xCCB134FBFA7CE49DULL } }, /* 3 blocks, finishing at stripe boundary */
203 { 2240, PRIME32, { 0xED385111126FBA6FULL, 0x50A1FE17B338995FULL } }, /* 3 blocks, finishing at stripe boundary */
204 { 2367, 0, { 0xCB37AEB9E5D361EDULL, 0xE89C0F6FF369B427ULL } }, /* 3 blocks, last stripe is overlapping */
205 { 2367, PRIME32, { 0x6F5360AE69C2F406ULL, 0xD23AAE4B76C31ECBULL } } /* 3 blocks, last stripe is overlapping */
206 };
207
208 /* XXH128, custom secret */
209 static const XSUM_testdata128_t XSUM_XXH128_withSecret_testdata[] = {
210 { 0, 0, { 0x005923CCEECBE8AEULL, 0x5F70F4EA232F1D38ULL } }, /* empty string */
211 { 1, 0, { 0x8A52451418B2DA4DULL, 0x3A66AF5A9819198EULL } }, /* 1 - 3 */
212 { 6, 0, { 0x0B61C8ACA7D4778FULL, 0x376BD91B6432F36DULL } }, /* 4 - 8 */
213 { 12, 0, { 0xAF82F6EBA263D7D8ULL, 0x90A3C2D839F57D0FULL } } /* 9 - 16 */
214 };
215
216 static const XSUM_testdata_sample_t XSUM_XXH3_generateSecret_testdata[] = {
217 { 0, { 0xB8, 0x26, 0x83, 0x7E } },
218 { 1, { 0xA6, 0x16, 0x06, 0x7B } },
219 { XXH3_SECRET_SIZE_MIN - 1, { 0xDA, 0x2A, 0x12, 0x11 } },
220 { XXH3_SECRET_DEFAULT_SIZE + 500, { 0x7E, 0x48, 0x0C, 0xA7 } }
221 };
222
XSUM_checkResult32(XXH32_hash_t r1,XXH32_hash_t r2)223 static void XSUM_checkResult32(XXH32_hash_t r1, XXH32_hash_t r2)
224 {
225 static int nbTests = 1;
226 if (r1!=r2) {
227 XSUM_log("\rError: 32-bit hash test %i: Internal sanity check failed!\n", nbTests);
228 XSUM_log("\rGot 0x%08X, expected 0x%08X.\n", (unsigned)r1, (unsigned)r2);
229 XSUM_log("\rNote: If you modified the hash functions, make sure to either update the values\n"
230 "or temporarily recompile with XSUM_NO_TESTS=1.\n");
231 exit(1);
232 }
233 nbTests++;
234 }
235
XSUM_checkResult64(XXH64_hash_t r1,XXH64_hash_t r2)236 static void XSUM_checkResult64(XXH64_hash_t r1, XXH64_hash_t r2)
237 {
238 static int nbTests = 1;
239 if (r1!=r2) {
240 XSUM_log("\rError: 64-bit hash test %i: Internal sanity check failed!\n", nbTests);
241 XSUM_log("\rGot 0x%08X%08XULL, expected 0x%08X%08XULL.\n",
242 (unsigned)(r1>>32), (unsigned)r1, (unsigned)(r2>>32), (unsigned)r2);
243 XSUM_log("\rNote: If you modified the hash functions, make sure to either update the values\n"
244 "or temporarily recompile with XSUM_NO_TESTS=1.\n");
245 exit(1);
246 }
247 nbTests++;
248 }
249
XSUM_checkResult128(XXH128_hash_t r1,XXH128_hash_t r2)250 static void XSUM_checkResult128(XXH128_hash_t r1, XXH128_hash_t r2)
251 {
252 static int nbTests = 1;
253 if ((r1.low64 != r2.low64) || (r1.high64 != r2.high64)) {
254 XSUM_log("\rError: 128-bit hash test %i: Internal sanity check failed.\n", nbTests);
255 XSUM_log("\rGot { 0x%08X%08XULL, 0x%08X%08XULL }, expected { 0x%08X%08XULL, 0x%08X%08XULL } \n",
256 (unsigned)(r1.low64>>32), (unsigned)r1.low64, (unsigned)(r1.high64>>32), (unsigned)r1.high64,
257 (unsigned)(r2.low64>>32), (unsigned)r2.low64, (unsigned)(r2.high64>>32), (unsigned)r2.high64 );
258 XSUM_log("\rNote: If you modified the hash functions, make sure to either update the values\n"
259 "or temporarily recompile with XSUM_NO_TESTS=1.\n");
260 exit(1);
261 }
262 nbTests++;
263 }
264
265
XSUM_testXXH32(const void * data,const XSUM_testdata32_t * testData)266 static void XSUM_testXXH32(const void* data, const XSUM_testdata32_t* testData)
267 {
268 XXH32_state_t *state = XXH32_createState();
269 size_t pos;
270
271 size_t len = testData->len;
272 XSUM_U32 seed = testData->seed;
273 XSUM_U32 Nresult = testData->Nresult;
274
275 if (len == 0) {
276 data = NULL;
277 } else {
278 assert(data != NULL);
279 }
280
281 assert(state != NULL);
282
283 XSUM_checkResult32(XXH32(data, len, seed), Nresult);
284
285 (void)XXH32_reset(state, seed);
286 (void)XXH32_update(state, data, len);
287 XSUM_checkResult32(XXH32_digest(state), Nresult);
288
289 (void)XXH32_reset(state, seed);
290 for (pos=0; pos<len; pos++)
291 (void)XXH32_update(state, ((const char*)data)+pos, 1);
292 XSUM_checkResult32(XXH32_digest(state), Nresult);
293 XXH32_freeState(state);
294 }
295
XSUM_testXXH64(const void * data,const XSUM_testdata64_t * testData)296 static void XSUM_testXXH64(const void* data, const XSUM_testdata64_t* testData)
297 {
298 XXH64_state_t *state = XXH64_createState();
299 size_t pos;
300
301 size_t len = (size_t)testData->len;
302 XSUM_U64 seed = testData->seed;
303 XSUM_U64 Nresult = testData->Nresult;
304
305 if (len == 0) {
306 data = NULL;
307 } else {
308 assert(data != NULL);
309 }
310
311 assert(state != NULL);
312
313 XSUM_checkResult64(XXH64(data, len, seed), Nresult);
314
315 (void)XXH64_reset(state, seed);
316 (void)XXH64_update(state, data, len);
317 XSUM_checkResult64(XXH64_digest(state), Nresult);
318
319 (void)XXH64_reset(state, seed);
320 for (pos=0; pos<len; pos++)
321 (void)XXH64_update(state, ((const char*)data)+pos, 1);
322 XSUM_checkResult64(XXH64_digest(state), Nresult);
323 XXH64_freeState(state);
324 }
325
326 /*
327 * Used to get "random" (but actually 100% reproducible) lengths for
328 * XSUM_XXH3_randomUpdate.
329 */
XSUM_rand(void)330 static XSUM_U32 XSUM_rand(void)
331 {
332 static XSUM_U64 seed = PRIME32;
333 seed *= PRIME64;
334 return (XSUM_U32)(seed >> 40);
335 }
336
337 /*
338 * Technically, XXH3_64bits_update is identical to XXH3_128bits_update as of
339 * v0.8.0, but we treat them as separate.
340 */
341 typedef XXH_errorcode (*XSUM_XXH3_update_t)(XXH3_state_t* state, const void* input, size_t length);
342
343 /*
344 * Runs the passed XXH3_update variant on random lengths. This is to test the
345 * more complex logic of the update function, catching bugs like this one:
346 * https://github.com/Cyan4973/xxHash/issues/378
347 */
XSUM_XXH3_randomUpdate(XXH3_state_t * state,const void * data,size_t len,XSUM_XXH3_update_t update_fn)348 static void XSUM_XXH3_randomUpdate(XXH3_state_t* state, const void* data,
349 size_t len, XSUM_XXH3_update_t update_fn)
350 {
351 size_t p = 0;
352 while (p < len) {
353 size_t const modulo = len > 2 ? len : 2;
354 size_t l = (size_t)(XSUM_rand()) % modulo;
355 if (p + l > len) l = len - p;
356 (void)update_fn(state, (const char*)data+p, l);
357 p += l;
358 }
359 }
360
XSUM_testXXH3(const void * data,const XSUM_testdata64_t * testData)361 static void XSUM_testXXH3(const void* data, const XSUM_testdata64_t* testData)
362 {
363 size_t len = testData->len;
364 XSUM_U64 seed = testData->seed;
365 XSUM_U64 Nresult = testData->Nresult;
366 if (len == 0) {
367 data = NULL;
368 } else {
369 assert(data != NULL);
370 }
371 { XSUM_U64 const Dresult = XXH3_64bits_withSeed(data, len, seed);
372 XSUM_checkResult64(Dresult, Nresult);
373 }
374
375 /* check that the no-seed variant produces same result as seed==0 */
376 if (seed == 0) {
377 XSUM_U64 const Dresult = XXH3_64bits(data, len);
378 XSUM_checkResult64(Dresult, Nresult);
379 }
380
381 /* streaming API test */
382 { XXH3_state_t* const state = XXH3_createState();
383 assert(state != NULL);
384 /* single ingestion */
385 (void)XXH3_64bits_reset_withSeed(state, seed);
386 (void)XXH3_64bits_update(state, data, len);
387 XSUM_checkResult64(XXH3_64bits_digest(state), Nresult);
388
389 /* random ingestion */
390 (void)XXH3_64bits_reset_withSeed(state, seed);
391 XSUM_XXH3_randomUpdate(state, data, len, &XXH3_64bits_update);
392 XSUM_checkResult64(XXH3_64bits_digest(state), Nresult);
393
394 /* byte by byte ingestion */
395 { size_t pos;
396 (void)XXH3_64bits_reset_withSeed(state, seed);
397 for (pos=0; pos<len; pos++)
398 (void)XXH3_64bits_update(state, ((const char*)data)+pos, 1);
399 XSUM_checkResult64(XXH3_64bits_digest(state), Nresult);
400 }
401 XXH3_freeState(state);
402 }
403 }
404
XSUM_testXXH3_withSecret(const void * data,const void * secret,size_t secretSize,const XSUM_testdata64_t * testData)405 static void XSUM_testXXH3_withSecret(const void* data, const void* secret,
406 size_t secretSize, const XSUM_testdata64_t* testData)
407 {
408 size_t len = (size_t)testData->len;
409 XSUM_U64 Nresult = testData->Nresult;
410
411 if (len == 0) {
412 data = NULL;
413 } else {
414 assert(data != NULL);
415 }
416 { XSUM_U64 const Dresult = XXH3_64bits_withSecret(data, len, secret, secretSize);
417 XSUM_checkResult64(Dresult, Nresult);
418 }
419
420 /* streaming API test */
421 { XXH3_state_t *state = XXH3_createState();
422 assert(state != NULL);
423 (void)XXH3_64bits_reset_withSecret(state, secret, secretSize);
424 (void)XXH3_64bits_update(state, data, len);
425 XSUM_checkResult64(XXH3_64bits_digest(state), Nresult);
426
427 /* random ingestion */
428 (void)XXH3_64bits_reset_withSecret(state, secret, secretSize);
429 XSUM_XXH3_randomUpdate(state, data, len, &XXH3_64bits_update);
430 XSUM_checkResult64(XXH3_64bits_digest(state), Nresult);
431
432 /* byte by byte ingestion */
433 { size_t pos;
434 (void)XXH3_64bits_reset_withSecret(state, secret, secretSize);
435 for (pos=0; pos<len; pos++)
436 (void)XXH3_64bits_update(state, ((const char*)data)+pos, 1);
437 XSUM_checkResult64(XXH3_64bits_digest(state), Nresult);
438 }
439 XXH3_freeState(state);
440 }
441 }
442
XSUM_testXXH128(const void * data,const XSUM_testdata128_t * testData)443 static void XSUM_testXXH128(const void* data, const XSUM_testdata128_t* testData)
444 {
445 size_t len = (size_t)testData->len;
446 XSUM_U64 seed = testData->seed;
447 XXH128_hash_t const Nresult = testData->Nresult;
448 if (len == 0) {
449 data = NULL;
450 } else {
451 assert(data != NULL);
452 }
453
454 { XXH128_hash_t const Dresult = XXH3_128bits_withSeed(data, len, seed);
455 XSUM_checkResult128(Dresult, Nresult);
456 }
457
458 /* check that XXH128() is identical to XXH3_128bits_withSeed() */
459 { XXH128_hash_t const Dresult2 = XXH128(data, len, seed);
460 XSUM_checkResult128(Dresult2, Nresult);
461 }
462
463 /* check that the no-seed variant produces same result as seed==0 */
464 if (seed == 0) {
465 XXH128_hash_t const Dresult = XXH3_128bits(data, len);
466 XSUM_checkResult128(Dresult, Nresult);
467 }
468
469 /* streaming API test */
470 { XXH3_state_t *state = XXH3_createState();
471 assert(state != NULL);
472
473 /* single ingestion */
474 (void)XXH3_128bits_reset_withSeed(state, seed);
475 (void)XXH3_128bits_update(state, data, len);
476 XSUM_checkResult128(XXH3_128bits_digest(state), Nresult);
477
478 /* random ingestion */
479 (void)XXH3_128bits_reset_withSeed(state, seed);
480 XSUM_XXH3_randomUpdate(state, data, len, &XXH3_128bits_update);
481 XSUM_checkResult128(XXH3_128bits_digest(state), Nresult);
482
483 /* byte by byte ingestion */
484 { size_t pos;
485 (void)XXH3_128bits_reset_withSeed(state, seed);
486 for (pos=0; pos<len; pos++)
487 (void)XXH3_128bits_update(state, ((const char*)data)+pos, 1);
488 XSUM_checkResult128(XXH3_128bits_digest(state), Nresult);
489 }
490 XXH3_freeState(state);
491 }
492 }
493
XSUM_testXXH128_withSecret(const void * data,const void * secret,size_t secretSize,const XSUM_testdata128_t * testData)494 static void XSUM_testXXH128_withSecret(const void* data, const void* secret, size_t secretSize, const XSUM_testdata128_t* testData)
495 {
496 size_t len = testData->len;
497 XXH128_hash_t Nresult = testData->Nresult;
498 if (len == 0) {
499 data = NULL;
500 } else if (len>0) {
501 assert(data != NULL);
502 }
503 { XXH128_hash_t const Dresult = XXH3_128bits_withSecret(data, len, secret, secretSize);
504 XSUM_checkResult128(Dresult, Nresult);
505 }
506
507 /* streaming API test */
508 { XXH3_state_t* const state = XXH3_createState();
509 assert(state != NULL);
510 (void)XXH3_128bits_reset_withSecret(state, secret, secretSize);
511 (void)XXH3_128bits_update(state, data, len);
512 XSUM_checkResult128(XXH3_128bits_digest(state), Nresult);
513
514 /* random ingestion */
515 (void)XXH3_128bits_reset_withSecret(state, secret, secretSize);
516 XSUM_XXH3_randomUpdate(state, data, len, &XXH3_128bits_update);
517 XSUM_checkResult128(XXH3_128bits_digest(state), Nresult);
518
519 /* byte by byte ingestion */
520 { size_t pos;
521 (void)XXH3_128bits_reset_withSecret(state, secret, secretSize);
522 for (pos=0; pos<len; pos++)
523 (void)XXH3_128bits_update(state, ((const char*)data)+pos, 1);
524 XSUM_checkResult128(XXH3_128bits_digest(state), Nresult);
525 }
526 XXH3_freeState(state);
527 }
528 }
529
XSUM_testSecretGenerator(const void * customSeed,const XSUM_testdata_sample_t * testData)530 static void XSUM_testSecretGenerator(const void* customSeed, const XSUM_testdata_sample_t* testData)
531 {
532 static int nbTests = 1;
533 const int sampleIndex[SECRET_SAMPLE_NBBYTES] = { 0, 62, 131, 191};
534 XSUM_U8 secretBuffer[XXH3_SECRET_DEFAULT_SIZE] = {0};
535 XSUM_U8 samples[SECRET_SAMPLE_NBBYTES];
536 int i;
537
538 XXH3_generateSecret(secretBuffer, customSeed, testData->len);
539 for (i=0; i<SECRET_SAMPLE_NBBYTES; i++) {
540 samples[i] = secretBuffer[sampleIndex[i]];
541 }
542 if (memcmp(samples, testData->byte, sizeof(testData->byte))) {
543 XSUM_log("\rError: Secret generation test %i: Internal sanity check failed. \n", nbTests);
544 XSUM_log("\rGot { 0x%02X, 0x%02X, 0x%02X, 0x%02X }, expected { 0x%02X, 0x%02X, 0x%02X, 0x%02X } \n",
545 samples[0], samples[1], samples[2], samples[3],
546 testData->byte[0], testData->byte[1], testData->byte[2], testData->byte[3] );
547 exit(1);
548 }
549 nbTests++;
550 }
551
552 /*!
553 * XSUM_sanityCheck():
554 * Runs a sanity check before the benchmark.
555 *
556 * Exits on an incorrect output.
557 */
XSUM_sanityCheck(void)558 XSUM_API void XSUM_sanityCheck(void)
559 {
560 size_t i;
561 #define SANITY_BUFFER_SIZE 2367
562 XSUM_U8 sanityBuffer[SANITY_BUFFER_SIZE];
563 const void* const secret = sanityBuffer + 7;
564 const size_t secretSize = XXH3_SECRET_SIZE_MIN + 11;
565 assert(sizeof(sanityBuffer) >= 7 + secretSize);
566
567 XSUM_fillTestBuffer(sanityBuffer, sizeof(sanityBuffer));
568
569 /* XXH32 */
570 for (i = 0; i < (sizeof(XSUM_XXH32_testdata)/sizeof(XSUM_XXH32_testdata[0])); i++) {
571 XSUM_testXXH32(sanityBuffer, &XSUM_XXH32_testdata[i]);
572 }
573 /* XXH64 */
574 for (i = 0; i < (sizeof(XSUM_XXH64_testdata)/sizeof(XSUM_XXH64_testdata[0])); i++) {
575 XSUM_testXXH64(sanityBuffer, &XSUM_XXH64_testdata[i]);
576 }
577 /* XXH3_64bits, seeded */
578 for (i = 0; i < (sizeof(XSUM_XXH3_testdata)/sizeof(XSUM_XXH3_testdata[0])); i++) {
579 XSUM_testXXH3(sanityBuffer, &XSUM_XXH3_testdata[i]);
580 }
581 /* XXH3_64bits, custom secret */
582 for (i = 0; i < (sizeof(XSUM_XXH3_withSecret_testdata)/sizeof(XSUM_XXH3_withSecret_testdata[0])); i++) {
583 XSUM_testXXH3_withSecret(sanityBuffer, secret, secretSize, &XSUM_XXH3_withSecret_testdata[i]);
584 }
585 /* XXH128 */
586 for (i = 0; i < (sizeof(XSUM_XXH128_testdata)/sizeof(XSUM_XXH128_testdata[0])); i++) {
587 XSUM_testXXH128(sanityBuffer, &XSUM_XXH128_testdata[i]);
588 }
589 /* XXH128 with custom Secret */
590 for (i = 0; i < (sizeof(XSUM_XXH128_withSecret_testdata)/sizeof(XSUM_XXH128_withSecret_testdata[0])); i++) {
591 XSUM_testXXH128_withSecret(sanityBuffer, secret, secretSize, &XSUM_XXH128_withSecret_testdata[i]);
592 }
593 /* secret generator */
594 for (i = 0; i < (sizeof(XSUM_XXH3_generateSecret_testdata)/sizeof(XSUM_XXH3_generateSecret_testdata[0])); i++) {
595 XSUM_testSecretGenerator(sanityBuffer, &XSUM_XXH3_generateSecret_testdata[i]);
596 }
597
598 XSUM_logVerbose(3, "\r%70s\r", ""); /* Clean display line */
599 XSUM_logVerbose(3, "Sanity check -- all tests ok\n");
600 }
601
602 #endif /* !XSUM_NO_TESTS */
603