main.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807
  1. #include "Platform.h"
  2. #include "Hashes.h"
  3. #include "KeysetTest.h"
  4. #include "SpeedTest.h"
  5. #include "AvalancheTest.h"
  6. #include "DifferentialTest.h"
  7. #include "PMurHash.h"
  8. #include <stdio.h>
  9. #include <time.h>
  10. //-----------------------------------------------------------------------------
  11. // Configuration. TODO - move these to command-line flags
  12. bool g_testAll = true;
  13. bool g_testSanity = false;
  14. bool g_testSpeed = false;
  15. bool g_testDiff = false;
  16. bool g_testDiffDist = false;
  17. bool g_testAvalanche = false;
  18. bool g_testBIC = false;
  19. bool g_testCyclic = false;
  20. bool g_testTwoBytes = false;
  21. bool g_testSparse = false;
  22. bool g_testPermutation = false;
  23. bool g_testWindow = false;
  24. bool g_testText = false;
  25. bool g_testZeroes = false;
  26. bool g_testSeed = false;
  27. struct TestOpts {
  28. bool &var;
  29. const char* name;
  30. };
  31. TestOpts g_testopts[] =
  32. {
  33. { g_testAll, "All" },
  34. { g_testSanity, "Sanity" },
  35. { g_testSpeed, "Speed" },
  36. { g_testDiff, "Diff" },
  37. { g_testDiffDist, "DiffDist" },
  38. { g_testAvalanche, "Avalanche" },
  39. { g_testBIC, "BIC" },
  40. { g_testCyclic, "Cyclic" },
  41. { g_testTwoBytes, "TwoBytes" },
  42. { g_testSparse, "Sparse" },
  43. { g_testPermutation, "Permutation" },
  44. { g_testWindow, "Window" },
  45. { g_testText, "Text" },
  46. { g_testZeroes, "Zeroes" },
  47. { g_testSeed, "Seed" }
  48. };
  49. //-----------------------------------------------------------------------------
  50. // This is the list of all hashes that SMHasher can test.
  51. struct HashInfo
  52. {
  53. pfHash hash;
  54. int hashbits;
  55. uint32_t verification;
  56. const char * name;
  57. const char * desc;
  58. };
  59. HashInfo g_hashes[] =
  60. {
  61. //NOTE: Jodyhash, here.
  62. { jodyhash, 32, 0xAB432E23, "Jodyhash", "Jodyhash, 32bit" },
  63. // first the bad hash funcs, failing tests:
  64. { DoNothingHash, 32, 0x00000000, "donothing32", "Do-Nothing function (only valid for measuring call overhead)" },
  65. { DoNothingHash, 64, 0x00000000, "donothing64", "Do-Nothing function (only valid for measuring call overhead)" },
  66. { DoNothingHash, 128, 0x00000000, "donothing128", "Do-Nothing function (only valid for measuring call overhead)" },
  67. { NoopOAATReadHash, 64, 0x00000000, "NOP_OAAT_read64", "Noop function (only valid for measuring call + OAAT reading overhead)" },
  68. { BadHash, 32, 0xAB432E23, "BadHash", "very simple XOR shift" },
  69. { sumhash, 32, 0x0000A9AC, "sumhash", "sum all bytes" },
  70. { sumhash32, 32, 0xF5562C80, "sumhash32", "sum all 32bit words" },
  71. // here start the real hashes
  72. { crc32, 32, 0x3719DB20, "crc32", "CRC-32 soft" },
  73. { md5_32, 32, 0xF7192210, "md5_32a", "MD5, first 32 bits of result" },
  74. { sha1_32a, 32, 0x7FE8C80E, "sha1_32a", "SHA1, first 32 bits of result" },
  75. #if 0
  76. { sha1_64a, 32, 0x00000000, "sha1_64a", "SHA1 64-bit, first 64 bits of result" },
  77. { sha2_32a, 32, 0x00000000, "sha2_32a", "SHA2, first 32 bits of result" },
  78. { sha2_64a, 64, 0x00000000, "sha2_64a", "SHA2, first 64 bits of result" },
  79. { sha3_32a, 32, 0x00000000, "sha3_32a", "SHA3, first 32 bits of result" },
  80. { sha3_64a, 64, 0x00000000, "sha3_64a", "SHA3, first 64 bits of result" },
  81. { BLAKE2_32a, 32, 0x00000000, "blake2_32a", "BLAKE2, first 32 bits of result" },
  82. { BLAKE2_64a, 64, 0x00000000, "blake2_64a", "BLAKE2, first 64 bits of result" },
  83. { bcrypt_64a, 64, 0x00000000, "bcrypt_64a", "bcrypt, first 64 bits of result" },
  84. { scrypt_64a, 64, 0x00000000, "scrypt_64a", "scrypt, first 64 bits of result" },
  85. #endif
  86. #ifdef __SSE2__
  87. { hasshe2_test, 256, 0xF5D39DFE, "hasshe2", "SSE2 hasshe2, 256-bit" },
  88. #endif
  89. #if defined(__SSE4_2__) && defined(__x86_64__)
  90. /* Even 32 uses crc32q, quad only */
  91. { crc32c_hw_test, 32, 0x0C7346F0, "crc32_hw", "SSE4.2 crc32 in HW" },
  92. { crc32c_hw1_test, 32, 0x0C7346F0, "crc32_hw1", "Faster Adler SSE4.2 crc32 in HW" },
  93. { crc64c_hw_test, 64, 0xE7C3FD0E, "crc64_hw", "SSE4.2 crc64 in HW" },
  94. #endif
  95. #if 0 && defined(__x86_64__) && (defined(__linux__) || defined(__APPLE__))
  96. // elf64 or macho64 only
  97. { fhtw_test, 64, 0x0, "fhtw", "fhtw asm" },
  98. #endif
  99. { FNV32a, 32, 0xE3CBBE91, "FNV1a", "Fowler-Noll-Vo hash, 32-bit" },
  100. { FNV32a_YoshimitsuTRIAD,32,0xD8AFFD71, "FNV1a_YT", "FNV1a-YoshimitsuTRIAD 32-bit sanmayce" },
  101. { FNV64a, 64, 0x103455FC, "FNV64", "Fowler-Noll-Vo hash, 64-bit" },
  102. #if 0
  103. { fletcher2, 64, 0x0, "fletcher2", "fletcher2 ZFS"} //TODO
  104. { fletcher4, 64, 0x0, "fletcher4", "fletcher4 ZFS"} //TODO
  105. { Jesteress, 32, 0x0, "Jesteress", "FNV1a-Jesteress 32-bit sanmayce" },
  106. { Meiyan, 32, 0x0, "Meiyan", "FNV1a-Meiyan 32-bit sanmayce" },
  107. #endif
  108. { Bernstein, 32, 0xBDB4B640, "bernstein", "Bernstein, 32-bit" },
  109. { sdbm, 32, 0x582AF769, "sdbm", "sdbm as in perl5" },
  110. { x17_test, 32, 0x8128E14C, "x17", "x17" },
  111. // also called jhash:
  112. { JenkinsOOAT, 32, 0x83E133DA, "JenkinsOOAT", "Bob Jenkins' OOAT as in perl 5.18" },
  113. { JenkinsOOAT_perl, 32, 0xEE05869B, "JenkinsOOAT_perl", "Bob Jenkins' OOAT as in old perl5" },
  114. { MicroOAAT, 32, 0x16F1BA97, "MicroOAAT", "Small non-multiplicative OAAT that passes all collision checks (by funny-falcon)" },
  115. { lookup3_test, 32, 0x3D83917A, "lookup3", "Bob Jenkins' lookup3" },
  116. { SuperFastHash, 32, 0x980ACD1D, "superfast", "Paul Hsieh's SuperFastHash" },
  117. { MurmurOAAT_test, 32, 0x5363BD98, "MurmurOAAT", "Murmur one-at-a-time" },
  118. { Crap8_test, 32, 0x743E97A1, "Crap8", "Crap8" },
  119. { MurmurHash2_test, 32, 0x27864C1E, "Murmur2", "MurmurHash2 for x86, 32-bit" },
  120. { MurmurHash2A_test, 32, 0x7FBD4396, "Murmur2A", "MurmurHash2A for x86, 32-bit" },
  121. #if defined(__x86_64__)
  122. { MurmurHash64A_test, 64, 0x1F0D3804, "Murmur2B", "MurmurHash2 for x64, 64-bit" },
  123. #endif
  124. { MurmurHash64B_test, 64, 0xDD537C05, "Murmur2C", "MurmurHash2 for x86, 64-bit" },
  125. { halfsiphash_test, 32, 0xA7A05F72, "HalfSipHash", "HalfSipHash 2-4, 32bit" },
  126. // and now the quality hash funcs, which mostly work
  127. // GoodOOAT passes whole SMHasher (by funny-falcon)
  128. { GoodOAAT, 32, 0x7B14EEE5, "GoodOAAT", "Small non-multiplicative OAAT" },
  129. { siphash_test, 64, 0xC58D7F9C, "SipHash", "SipHash 2-4 - SSSE3 optimized" },
  130. // as in rust and swift
  131. { siphash13_test, 64, 0x29C010BF, "SipHash13", "SipHash 1-3 - SSSE3 optimized" },
  132. { PMurHash32_test, 32, 0xB0F57EE3, "PMurHash32", "Shane Day's portable-ized MurmurHash3 for x86, 32-bit." },
  133. { MurmurHash3_x86_32, 32, 0xB0F57EE3, "Murmur3A", "MurmurHash3 for x86, 32-bit" },
  134. { MurmurHash3_x86_128, 128, 0xB3ECE62A, "Murmur3C", "MurmurHash3 for x86, 128-bit" },
  135. #if defined(__x86_64__)
  136. { MurmurHash3_x64_128, 128, 0x6384BA69, "Murmur3F", "MurmurHash3 for x64, 128-bit" },
  137. #endif
  138. #if defined(__x86_64__)
  139. { fasthash32_test, 32, 0xE9481AFC, "fasthash32", "fast-hash 32bit" },
  140. { fasthash64_test, 64, 0xA16231A7, "fasthash64", "fast-hash 64bit" },
  141. #endif
  142. { CityHash32_test, 32, 0x5C28AD62, "City32", "Google CityHash32WithSeed (old)" },
  143. { CityHash64_test, 64, 0x25A20825, "City64", "Google CityHash64WithSeed (old)" },
  144. #if defined(__SSE4_2__) && defined(__x86_64__)
  145. { CityHash128_test, 128, 0x6531F54E, "City128", "Google CityHash128WithSeed (old)" },
  146. { CityHashCrc128_test, 128, 0xD4389C97, "CityCrc128", "Google CityHashCrc128WithSeed SSE4.2 (old)" },
  147. #endif
  148. #if defined(__x86_64__)
  149. { FarmHash64_test, 64, 0x35F84A93, "FarmHash64", "Google FarmHash64WithSeed" },
  150. { FarmHash128_test, 128, 0x9E636AAE, "FarmHash128", "Google FarmHash128WithSeed" },
  151. { farmhash64_c_test, 64, 0x35F84A93, "farmhash64_c", "farmhash64_with_seed (C99)" },
  152. { farmhash128_c_test, 128, 0x9E636AAE, "farmhash128_c", "farmhash128_with_seed (C99)" },
  153. #endif
  154. { SpookyHash32_test, 32, 0x3F798BBB, "Spooky32", "Bob Jenkins' SpookyHash, 32-bit result" },
  155. { SpookyHash64_test, 64, 0xA7F955F1, "Spooky64", "Bob Jenkins' SpookyHash, 64-bit result" },
  156. { SpookyHash128_test, 128, 0x8D263080, "Spooky128", "Bob Jenkins' SpookyHash, 128-bit result" },
  157. #if defined(__x86_64__)
  158. { xxHash32_test, 32, 0xBA88B743, "xxHash32", "xxHash, 32-bit for x64" },
  159. { xxHash64_test, 64, 0x024B7CF4, "xxHash64", "xxHash, 64-bit" },
  160. #if 0
  161. { xxhash256_test, 64, 0x024B7CF4, "xxhash256", "xxhash256, 64-bit unportable" },
  162. #endif
  163. #endif
  164. #if defined(__x86_64__)
  165. { metrohash64_1_test, 64, 0xEE88F7D2, "metrohash64_1", "MetroHash64_1 for 64-bit" },
  166. { metrohash64_2_test, 64, 0xE1FC7C6E, "metrohash64_2", "MetroHash64_2 for 64-bit" },
  167. { metrohash128_1_test, 128, 0x20E8A1D7, "metrohash128_1", "MetroHash128_1 for 64-bit" },
  168. { metrohash128_2_test, 128, 0x5437C684, "metrohash128_2", "MetroHash128_2 for 64-bit" },
  169. #if defined(__SSE4_2__) && defined(__x86_64__)
  170. { metrohash64crc_1_test, 64, 0x29C68A50, "metrohash64crc_1", "MetroHash64crc_1 for x64" },
  171. { metrohash64crc_2_test, 64, 0x2C00BD9F, "metrohash64crc_2", "MetroHash64crc_2 for x64" },
  172. { metrohash128crc_1_test, 128, 0x5E75144E, "metrohash128crc_1", "MetroHash128crc_1 for x64" },
  173. { metrohash128crc_2_test, 128, 0x1ACF3E77, "metrohash128crc_2", "MetroHash128crc_2 for x64" },
  174. #endif
  175. #endif
  176. #if defined(__x86_64__)
  177. { cmetrohash64_1_optshort_test, 64, 0xEE88F7D2, "cmetrohash64_1o", "cmetrohash64_1 (shorter key optimized) , 64-bit for x64" },
  178. { cmetrohash64_1_test, 64, 0xEE88F7D2, "cmetrohash64_1", "cmetrohash64_1, 64-bit for x64" },
  179. { cmetrohash64_2_test, 64, 0xE1FC7C6E, "cmetrohash64_2", "cmetrohash64_2, 64-bit for x64" },
  180. #endif
  181. #if defined(__SSE4_2__) && defined(__x86_64__)
  182. { falkhash_test_cxx, 64, 0x2F99B071, "falkhash", "falkhash.asm with aesenc, 64-bit for x64" },
  183. #endif
  184. { t1ha_test, 64, 0xD6836381, "t1ha", "Fast Positive Hash (portable, best for: 64-bit, little-endian)" },
  185. { t1ha_64be_test, 64, 0x93F864DE, "t1ha_64be", "Fast Positive Hash (portable, best for: 64-bit, big-engian)" },
  186. { t1ha_32le_test, 64, 0xE489F366, "t1ha_32le", "Fast Positive Hash (portable, best for: 32-bit, little-endian)" },
  187. { t1ha_32be_test, 64, 0x71F649A9, "t1ha_32be", "Fast Positive Hash (portable, best for: 32-bit, big-endian)" },
  188. #if (defined(__SSE4_2__) && defined(__x86_64__)) || defined(_M_X64)
  189. { t1ha_crc_test, 64, 0xA57ACE7D, "t1ha_crc", "Fast Positive Hash (machine-specific, requires: SSE4.2 CRC32C)" },
  190. #endif
  191. #if defined(__AES__) || defined(_M_X64) || defined(_M_IX86)
  192. { t1ha_aes_test, 64, 0x54BBFF21, "t1ha_aes", "Fast Positive Hash (machine-specific, requires: AES-NI)" },
  193. #endif
  194. { mum_hash_test, 64,
  195. #if defined(__GNUC__) && UINT_MAX != ULONG_MAX
  196. 0x3EEAE2D4,
  197. #else
  198. 0xA973C6C0,
  199. #endif
  200. "MUM", "github.com/vnmakarov/mum-hash" },
  201. };
  202. HashInfo * findHash ( const char * name )
  203. {
  204. for(size_t i = 0; i < sizeof(g_hashes) / sizeof(HashInfo); i++)
  205. {
  206. if(_stricmp(name,g_hashes[i].name) == 0) return &g_hashes[i];
  207. }
  208. return NULL;
  209. }
  210. //-----------------------------------------------------------------------------
  211. // Self-test on startup - verify that all installed hashes work correctly.
  212. void SelfTest ( void )
  213. {
  214. bool pass = true;
  215. for(size_t i = 0; i < sizeof(g_hashes) / sizeof(HashInfo); i++)
  216. {
  217. HashInfo * info = & g_hashes[i];
  218. pass &= VerificationTest(info->hash,info->hashbits,info->verification,false);
  219. }
  220. if(!pass)
  221. {
  222. printf("Self-test FAILED!\n");
  223. for(size_t i = 0; i < sizeof(g_hashes) / sizeof(HashInfo); i++)
  224. {
  225. HashInfo * info = & g_hashes[i];
  226. printf("%16s - ",info->name);
  227. pass &= VerificationTest(info->hash,info->hashbits,info->verification,true);
  228. }
  229. exit(1);
  230. }
  231. }
  232. //----------------------------------------------------------------------------
  233. template < typename hashtype >
  234. void test ( hashfunc<hashtype> hash, HashInfo * info )
  235. {
  236. const int hashbits = sizeof(hashtype) * 8;
  237. printf("-------------------------------------------------------------------------------\n");
  238. printf("--- Testing %s \"%s\"\n\n",info->name,info->desc);
  239. fflush(NULL);
  240. //-----------------------------------------------------------------------------
  241. // Sanity tests
  242. if(g_testSanity || g_testAll)
  243. {
  244. printf("[[[ Sanity Tests ]]]\n\n");
  245. fflush(NULL);
  246. VerificationTest(hash,hashbits,info->verification,true);
  247. SanityTest(hash,hashbits);
  248. AppendedZeroesTest(hash,hashbits);
  249. printf("\n");
  250. fflush(NULL);
  251. }
  252. //-----------------------------------------------------------------------------
  253. // Speed tests
  254. if(g_testSpeed || g_testAll)
  255. {
  256. double sum = 0.0;
  257. printf("[[[ Speed Tests ]]]\n\n");
  258. fflush(NULL);
  259. BulkSpeedTest(info->hash,info->verification);
  260. printf("\n");
  261. fflush(NULL);
  262. for(int i = 1; i < 32; i++)
  263. {
  264. sum += TinySpeedTest(hashfunc<hashtype>(info->hash),sizeof(hashtype),i,info->verification,true);
  265. }
  266. sum = sum / 31.0;
  267. printf("Average %6.3f cycles/hash\n",sum);
  268. printf("\n");
  269. fflush(NULL);
  270. }
  271. //-----------------------------------------------------------------------------
  272. // Differential tests
  273. if(g_testDiff || g_testAll)
  274. {
  275. printf("[[[ Differential Tests ]]]\n\n");
  276. fflush(NULL);
  277. bool result = true;
  278. bool dumpCollisions = false;
  279. result &= DiffTest< Blob<64>, hashtype >(hash,5,1000,dumpCollisions);
  280. result &= DiffTest< Blob<128>, hashtype >(hash,4,1000,dumpCollisions);
  281. result &= DiffTest< Blob<256>, hashtype >(hash,3,1000,dumpCollisions);
  282. if(!result) printf("*********FAIL*********\n");
  283. printf("\n");
  284. fflush(NULL);
  285. }
  286. //-----------------------------------------------------------------------------
  287. // Differential-distribution tests
  288. if(g_testDiffDist /*|| g_testAll*/)
  289. {
  290. printf("[[[ Differential Distribution Tests ]]]\n\n");
  291. fflush(NULL);
  292. bool result = true;
  293. result &= DiffDistTest2<uint64_t,hashtype>(hash);
  294. printf("\n");
  295. fflush(NULL);
  296. }
  297. //-----------------------------------------------------------------------------
  298. // Avalanche tests
  299. if(g_testAvalanche || g_testAll)
  300. {
  301. printf("[[[ Avalanche Tests ]]]\n\n");
  302. fflush(NULL);
  303. bool result = true;
  304. result &= AvalancheTest< Blob< 32>, hashtype > (hash,300000);
  305. result &= AvalancheTest< Blob< 40>, hashtype > (hash,300000);
  306. result &= AvalancheTest< Blob< 48>, hashtype > (hash,300000);
  307. result &= AvalancheTest< Blob< 56>, hashtype > (hash,300000);
  308. result &= AvalancheTest< Blob< 64>, hashtype > (hash,300000);
  309. result &= AvalancheTest< Blob< 72>, hashtype > (hash,300000);
  310. result &= AvalancheTest< Blob< 80>, hashtype > (hash,300000);
  311. result &= AvalancheTest< Blob< 88>, hashtype > (hash,300000);
  312. result &= AvalancheTest< Blob< 96>, hashtype > (hash,300000);
  313. result &= AvalancheTest< Blob<104>, hashtype > (hash,300000);
  314. result &= AvalancheTest< Blob<112>, hashtype > (hash,300000);
  315. result &= AvalancheTest< Blob<120>, hashtype > (hash,300000);
  316. result &= AvalancheTest< Blob<128>, hashtype > (hash,300000);
  317. result &= AvalancheTest< Blob<136>, hashtype > (hash,300000);
  318. result &= AvalancheTest< Blob<144>, hashtype > (hash,300000);
  319. result &= AvalancheTest< Blob<152>, hashtype > (hash,300000);
  320. if(!result) printf("*********FAIL*********\n");
  321. printf("\n");
  322. fflush(NULL);
  323. }
  324. //-----------------------------------------------------------------------------
  325. // Bit Independence Criteria. Interesting, but doesn't tell us much about
  326. // collision or distribution.
  327. if(g_testBIC)
  328. {
  329. printf("[[[ Bit Independence Criteria ]]]\n\n");
  330. fflush(NULL);
  331. bool result = true;
  332. //result &= BicTest<uint64_t,hashtype>(hash,2000000);
  333. BicTest3<Blob<88>,hashtype>(hash,2000000);
  334. if(!result) printf("*********FAIL*********\n");
  335. printf("\n");
  336. fflush(NULL);
  337. }
  338. //-----------------------------------------------------------------------------
  339. // Keyset 'Cyclic' - keys of the form "abcdabcdabcd..."
  340. if(g_testCyclic || g_testAll)
  341. {
  342. printf("[[[ Keyset 'Cyclic' Tests ]]]\n\n");
  343. fflush(NULL);
  344. bool result = true;
  345. bool drawDiagram = false;
  346. #if 0
  347. result &= CyclicKeyTest<hashtype>(hash,sizeof(hashtype)+0,8,100000,drawDiagram);
  348. #else
  349. result &= CyclicKeyTest<hashtype>(hash,sizeof(hashtype)+0,8,10000000,drawDiagram);
  350. result &= CyclicKeyTest<hashtype>(hash,sizeof(hashtype)+1,8,10000000,drawDiagram);
  351. result &= CyclicKeyTest<hashtype>(hash,sizeof(hashtype)+2,8,10000000,drawDiagram);
  352. result &= CyclicKeyTest<hashtype>(hash,sizeof(hashtype)+3,8,10000000,drawDiagram);
  353. result &= CyclicKeyTest<hashtype>(hash,sizeof(hashtype)+4,8,10000000,drawDiagram);
  354. #endif
  355. if(!result) printf("*********FAIL*********\n");
  356. printf("\n");
  357. fflush(NULL);
  358. }
  359. //-----------------------------------------------------------------------------
  360. // Keyset 'TwoBytes' - all keys up to N bytes containing two non-zero bytes
  361. // This generates some huge keysets, 128-bit tests will take ~1.3 gigs of RAM.
  362. if(g_testTwoBytes || g_testAll)
  363. {
  364. printf("[[[ Keyset 'TwoBytes' Tests ]]]\n\n");
  365. fflush(NULL);
  366. bool result = true;
  367. bool drawDiagram = false;
  368. for(int i = 4; i <= 20; i += 4)
  369. {
  370. result &= TwoBytesTest2<hashtype>(hash,i,drawDiagram);
  371. }
  372. if(!result) printf("*********FAIL*********\n");
  373. printf("\n");
  374. fflush(NULL);
  375. }
  376. //-----------------------------------------------------------------------------
  377. // Keyset 'Sparse' - keys with all bits 0 except a few
  378. if(g_testSparse || g_testAll)
  379. {
  380. printf("[[[ Keyset 'Sparse' Tests ]]]\n\n");
  381. fflush(NULL);
  382. bool result = true;
  383. bool drawDiagram = false;
  384. result &= SparseKeyTest< 32,hashtype>(hash,6,true,true,true,drawDiagram);
  385. result &= SparseKeyTest< 40,hashtype>(hash,6,true,true,true,drawDiagram);
  386. result &= SparseKeyTest< 48,hashtype>(hash,5,true,true,true,drawDiagram);
  387. result &= SparseKeyTest< 56,hashtype>(hash,5,true,true,true,drawDiagram);
  388. result &= SparseKeyTest< 64,hashtype>(hash,5,true,true,true,drawDiagram);
  389. result &= SparseKeyTest< 96,hashtype>(hash,4,true,true,true,drawDiagram);
  390. result &= SparseKeyTest< 256,hashtype>(hash,3,true,true,true,drawDiagram);
  391. result &= SparseKeyTest<2048,hashtype>(hash,2,true,true,true,drawDiagram);
  392. if(!result) printf("*********FAIL*********\n");
  393. printf("\n");
  394. fflush(NULL);
  395. }
  396. //-----------------------------------------------------------------------------
  397. // Keyset 'Permutation' - all possible combinations of a set of blocks
  398. if(g_testPermutation || g_testAll)
  399. {
  400. {
  401. // This one breaks lookup3, surprisingly
  402. printf("[[[ Keyset 'Combination Lowbits' Tests ]]]\n\n");
  403. fflush(NULL);
  404. bool result = true;
  405. bool drawDiagram = false;
  406. uint32_t blocks[] =
  407. {
  408. 0x00000000,
  409. 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007,
  410. };
  411. result &= CombinationKeyTest<hashtype>(hash,8,blocks,sizeof(blocks) / sizeof(uint32_t),true,true,drawDiagram);
  412. if(!result) printf("*********FAIL*********\n");
  413. printf("\n");
  414. fflush(NULL);
  415. }
  416. {
  417. printf("[[[ Keyset 'Combination Highbits' Tests ]]]\n\n");
  418. fflush(NULL);
  419. bool result = true;
  420. bool drawDiagram = false;
  421. uint32_t blocks[] =
  422. {
  423. 0x00000000,
  424. 0x20000000, 0x40000000, 0x60000000, 0x80000000, 0xA0000000, 0xC0000000, 0xE0000000
  425. };
  426. result &= CombinationKeyTest<hashtype>(hash,8,blocks,sizeof(blocks) / sizeof(uint32_t),true,true,drawDiagram);
  427. if(!result) printf("*********FAIL*********\n");
  428. printf("\n");
  429. fflush(NULL);
  430. }
  431. {
  432. printf("[[[ Keyset 'Combination 0x8000000' Tests ]]]\n\n");
  433. fflush(NULL);
  434. bool result = true;
  435. bool drawDiagram = false;
  436. uint32_t blocks[] =
  437. {
  438. 0x00000000,
  439. 0x80000000,
  440. };
  441. result &= CombinationKeyTest<hashtype>(hash,20,blocks,sizeof(blocks) / sizeof(uint32_t),true,true,drawDiagram);
  442. if(!result) printf("*********FAIL*********\n");
  443. printf("\n");
  444. fflush(NULL);
  445. }
  446. {
  447. printf("[[[ Keyset 'Combination 0x0000001' Tests ]]]\n\n");
  448. bool result = true;
  449. bool drawDiagram = false;
  450. uint32_t blocks[] =
  451. {
  452. 0x00000000,
  453. 0x00000001,
  454. };
  455. result &= CombinationKeyTest<hashtype>(hash,20,blocks,sizeof(blocks) / sizeof(uint32_t),true,true,drawDiagram);
  456. if(!result) printf("*********FAIL*********\n");
  457. printf("\n");
  458. fflush(NULL);
  459. }
  460. {
  461. printf("[[[ Keyset 'Combination Hi-Lo' Tests ]]]\n\n");
  462. bool result = true;
  463. bool drawDiagram = false;
  464. uint32_t blocks[] =
  465. {
  466. 0x00000000,
  467. 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007,
  468. 0x80000000, 0x40000000, 0xC0000000, 0x20000000, 0xA0000000, 0x60000000, 0xE0000000
  469. };
  470. result &= CombinationKeyTest<hashtype>(hash,6,blocks,sizeof(blocks) / sizeof(uint32_t),true,true,drawDiagram);
  471. if(!result) printf("*********FAIL*********\n");
  472. printf("\n");
  473. fflush(NULL);
  474. }
  475. }
  476. //-----------------------------------------------------------------------------
  477. // Keyset 'Window'
  478. // Skip distribution test for these - they're too easy to distribute well,
  479. // and it generates a _lot_ of testing
  480. if(g_testWindow || g_testAll)
  481. {
  482. printf("[[[ Keyset 'Window' Tests ]]]\n\n");
  483. bool result = true;
  484. bool testCollision = true;
  485. bool testDistribution = false;
  486. bool drawDiagram = false;
  487. result &= WindowedKeyTest< Blob<hashbits*2>, hashtype > ( hash, 20, testCollision, testDistribution, drawDiagram );
  488. if(!result) printf("*********FAIL*********\n");
  489. printf("\n");
  490. fflush(NULL);
  491. }
  492. //-----------------------------------------------------------------------------
  493. // Keyset 'Text'
  494. if(g_testText || g_testAll)
  495. {
  496. printf("[[[ Keyset 'Text' Tests ]]]\n\n");
  497. bool result = true;
  498. bool drawDiagram = false;
  499. const char * alnum = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  500. result &= TextKeyTest( hash, "Foo", alnum,4, "Bar", drawDiagram );
  501. result &= TextKeyTest( hash, "FooBar", alnum,4, "", drawDiagram );
  502. result &= TextKeyTest( hash, "", alnum,4, "FooBar", drawDiagram );
  503. if(!result) printf("*********FAIL*********\n");
  504. printf("\n");
  505. fflush(NULL);
  506. }
  507. //-----------------------------------------------------------------------------
  508. // Keyset 'Zeroes'
  509. if(g_testZeroes || g_testAll)
  510. {
  511. printf("[[[ Keyset 'Zeroes' Tests ]]]\n\n");
  512. bool result = true;
  513. bool drawDiagram = false;
  514. result &= ZeroKeyTest<hashtype>( hash, drawDiagram );
  515. if(!result) printf("*********FAIL*********\n");
  516. printf("\n");
  517. fflush(NULL);
  518. }
  519. //-----------------------------------------------------------------------------
  520. // Keyset 'Seed'
  521. if(g_testSeed || g_testAll)
  522. {
  523. printf("[[[ Keyset 'Seed' Tests ]]]\n\n");
  524. bool result = true;
  525. bool drawDiagram = false;
  526. result &= SeedTest<hashtype>( hash, 1000000, drawDiagram );
  527. if(!result) printf("*********FAIL*********\n");
  528. printf("\n");
  529. fflush(NULL);
  530. }
  531. }
  532. //-----------------------------------------------------------------------------
  533. uint32_t g_inputVCode = 1;
  534. uint32_t g_outputVCode = 1;
  535. uint32_t g_resultVCode = 1;
  536. HashInfo * g_hashUnderTest = NULL;
  537. void VerifyHash ( const void * key, int len, uint32_t seed, void * out )
  538. {
  539. g_inputVCode = MurmurOAAT(key,len,g_inputVCode);
  540. g_inputVCode = MurmurOAAT(&seed,sizeof(uint32_t),g_inputVCode);
  541. g_hashUnderTest->hash(key,len,seed,out);
  542. g_outputVCode = MurmurOAAT(out,g_hashUnderTest->hashbits/8,g_outputVCode);
  543. }
  544. //-----------------------------------------------------------------------------
  545. void testHash ( const char * name )
  546. {
  547. HashInfo * pInfo = findHash(name);
  548. if(pInfo == NULL)
  549. {
  550. printf("Invalid hash '%s' specified\n",name);
  551. return;
  552. }
  553. else
  554. {
  555. g_hashUnderTest = pInfo;
  556. if(pInfo->hashbits == 32)
  557. {
  558. test<uint32_t>( VerifyHash, pInfo );
  559. }
  560. else if(pInfo->hashbits == 64)
  561. {
  562. test<uint64_t>( pInfo->hash, pInfo );
  563. }
  564. else if(pInfo->hashbits == 128)
  565. {
  566. test<uint128_t>( pInfo->hash, pInfo );
  567. }
  568. else if(pInfo->hashbits == 256)
  569. {
  570. test<uint256_t>( pInfo->hash, pInfo );
  571. }
  572. else
  573. {
  574. printf("Invalid hash bit width %d for hash '%s'",pInfo->hashbits,pInfo->name);
  575. }
  576. }
  577. }
  578. //-----------------------------------------------------------------------------
  579. #ifdef _MSC_VER
  580. static char* strndup(char const *s, size_t n)
  581. {
  582. size_t len = strnlen(s, n);
  583. char *p = (char*) malloc(len + 1);
  584. if (p == NULL)
  585. return NULL;
  586. p[len] = '\0';
  587. return (char*) memcpy(p, s, len);
  588. }
  589. #endif
  590. int main ( int argc, char ** argv )
  591. {
  592. #if (defined(__x86_64__) && __SSE4_2__) || defined(_M_X64) || defined(_X86_64_)
  593. const char * defaulthash = "metrohash64crc_1"; /* "murmur3a"; */
  594. #else
  595. const char * defaulthash = "t1ha_32le";
  596. #endif
  597. const char * hashToTest = defaulthash;
  598. if(argc < 2) {
  599. printf("No test hash given on command line, testing %s.\n", hashToTest);
  600. printf("Usage: SMHasher --list or --test=Speed,... hash\n");
  601. }
  602. else {
  603. hashToTest = argv[1];
  604. if (strncmp(hashToTest,"--", 2) == 0) {
  605. if (strcmp(hashToTest,"--list") == 0) {
  606. for(size_t i = 0; i < sizeof(g_hashes) / sizeof(HashInfo); i++) {
  607. printf("%-16s\t(%s)\n", g_hashes[i].name, g_hashes[i].desc);
  608. }
  609. exit(0);
  610. }
  611. /* default: --test=All. comma seperated list of options */
  612. if (strncmp(hashToTest,"--test=", 6) == 0) {
  613. char *opt = (char *)&hashToTest[7];
  614. char *rest = opt;
  615. char *p;
  616. bool found = false;
  617. g_testAll = false;
  618. do {
  619. if ((p = strchr(rest, ','))) {
  620. opt = strndup(rest, p-rest);
  621. rest = p+1;
  622. } else {
  623. opt = rest;
  624. }
  625. for(size_t i = 0; i < sizeof(g_testopts) / sizeof(TestOpts); i++) {
  626. if (strcmp(opt, g_testopts[i].name) == 0) {
  627. g_testopts[i].var = true; found = true; break;
  628. }
  629. }
  630. if (!found) {
  631. printf("Invalid option: --test=%s\n", opt);
  632. printf("Valid tests: --test=%s", g_testopts[0].name);
  633. for(size_t i = 1; i < sizeof(g_testopts) / sizeof(TestOpts); i++) {
  634. printf(",%s", g_testopts[i].name);
  635. }
  636. printf("\n");
  637. exit(0);
  638. }
  639. } while (p);
  640. }
  641. if (argc > 2)
  642. hashToTest = argv[2];
  643. else
  644. hashToTest = defaulthash;
  645. }
  646. }
  647. // Code runs on the 3rd CPU by default
  648. //SetAffinity((1 << 2));
  649. SelfTest();
  650. int timeBegin = clock();
  651. testHash(hashToTest);
  652. int timeEnd = clock();
  653. printf("\n");
  654. fflush(NULL);
  655. printf("Input vcode 0x%08x, Output vcode 0x%08x, Result vcode 0x%08x\n",g_inputVCode,g_outputVCode,g_resultVCode);
  656. printf("Verification value is 0x%08x - Testing took %f seconds\n",g_verify,double(timeEnd-timeBegin)/double(CLOCKS_PER_SEC));
  657. printf("-------------------------------------------------------------------------------\n");
  658. fflush(NULL);
  659. return 0;
  660. }