xsum_sanity_check.c 27 KB

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