• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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