blob: 03f3e427ac233cd67d52a8aefe53d92a1b720bf8 [file] [log] [blame]
tanjent@gmail.comf67ce942011-03-14 09:11:18 +00001#include "Platform.h"
tanjent@gmail.com2aa29c32011-03-19 08:53:53 +00002#include "Hashes.h"
tanjent@gmail.comad4b3632010-11-05 01:20:58 +00003#include "KeysetTest.h"
4#include "SpeedTest.h"
5#include "AvalancheTest.h"
6#include "DifferentialTest.h"
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +00007
tanjent@gmail.comf67ce942011-03-14 09:11:18 +00008#include <stdio.h>
tanjent@gmail.comad4b3632010-11-05 01:20:58 +00009#include <time.h>
aappleby@google.coma27c2812011-04-13 23:23:14 +000010#include <unistd.h>
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000011
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000012//-----------------------------------------------------------------------------
13// Configuration. TODO - move these to command-line flags
14
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000015bool g_testAll = false;
16
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000017bool g_testSanity = false;
18bool g_testSpeed = false;
19bool g_testDiff = false;
tanjent@gmail.com623590d2011-03-28 18:19:31 +000020bool g_testDiffDist = false;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000021bool g_testAvalanche = false;
tanjent@gmail.com623590d2011-03-28 18:19:31 +000022bool g_testBIC = false;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000023bool g_testCyclic = false;
tanjent@gmail.com96601f22011-03-31 02:41:29 +000024bool g_testTwoBytes = false;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000025bool g_testSparse = false;
26bool g_testPermutation = false;
27bool g_testWindow = false;
28bool g_testText = false;
29bool g_testZeroes = false;
30bool g_testSeed = false;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000031
tanjent@gmail.comf67ce942011-03-14 09:11:18 +000032//-----------------------------------------------------------------------------
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000033// This is the list of all hashes that SMHasher can test.
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000034
35struct HashInfo
36{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000037 pfHash hash;
38 int hashbits;
39 uint32_t verification;
40 const char * name;
41 const char * desc;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000042};
43
aappleby@google.coma27c2812011-04-13 23:23:14 +000044HashInfo g_hashes[] =
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000045{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000046 { DoNothingHash, 32, 0x00000000, "donothing32", "Do-Nothing function (only valid for measuring call overhead)" },
47 { DoNothingHash, 64, 0x00000000, "donothing64", "Do-Nothing function (only valid for measuring call overhead)" },
48 { DoNothingHash, 128, 0x00000000, "donothing128", "Do-Nothing function (only valid for measuring call overhead)" },
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000049
tanjent@gmail.com623590d2011-03-28 18:19:31 +000050 { crc32, 32, 0x3719DB20, "crc32", "CRC-32" },
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000051
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000052 { md5_32, 32, 0xC10C356B, "md5_32a", "MD5, first 32 bits of result" },
53 { sha1_32a, 32, 0xF9376EA7, "sha1_32a", "SHA1, first 32 bits of result" },
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000054
tanjent@gmail.com623590d2011-03-28 18:19:31 +000055 { FNV, 32, 0xE3CBBE91, "FNV", "Fowler-Noll-Vo hash, 32-bit" },
56 { lookup3_test, 32, 0x3D83917A, "lookup3", "Bob Jenkins' lookup3" },
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000057 { SuperFastHash, 32, 0x980ACD1D, "superfast", "Paul Hsieh's SuperFastHash" },
tanjent@gmail.com623590d2011-03-28 18:19:31 +000058 { MurmurOAAT_test, 32, 0x5363BD98, "MurmurOAAT", "Murmur one-at-a-time" },
59 { Crap8_test, 32, 0x743E97A1, "Crap8", "Crap8" },
aappleby@google.coma27c2812011-04-13 23:23:14 +000060
tanjent@gmail.com510b8522011-04-12 15:36:18 +000061 { CityHash64_test, 64, 0x45754A6F, "City64", "Google CityHash128WithSeed" },
62 { CityHash128_test, 128, 0x94B0EF46, "City128", "Google CityHash128WithSeed" },
63
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000064 // MurmurHash2
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000065
tanjent@gmail.com623590d2011-03-28 18:19:31 +000066 { MurmurHash2_test, 32, 0x27864C1E, "Murmur2", "MurmurHash2 for x86, 32-bit" },
67 { MurmurHash2A_test, 32, 0x7FBD4396, "Murmur2A", "MurmurHash2A for x86, 32-bit" },
68 { MurmurHash64A_test, 64, 0x1F0D3804, "Murmur2B", "MurmurHash2 for x64, 64-bit" },
69 { MurmurHash64B_test, 64, 0xDD537C05, "Murmur2C", "MurmurHash2 for x86, 64-bit" },
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000070
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000071 // MurmurHash3
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000072
tanjent@gmail.com2ff5e9b2011-04-03 06:30:51 +000073 { MurmurHash3_x86_32, 32, 0x3252D141, "Murmur3A", "MurmurHash3 for x86, 32-bit" },
tanjent@gmail.com0f37bbd2011-04-04 23:05:26 +000074 { MurmurHash3_x86_128, 128, 0xB3ECE62A, "Murmur3C", "MurmurHash3 for x86, 128-bit" },
tanjent@gmail.com833fd8d2011-04-11 20:45:44 +000075 { MurmurHash3_x64_128, 128, 0x6384BA69, "Murmur3F", "MurmurHash3 for x64, 128-bit" },
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000076
77};
78
aappleby@google.coma27c2812011-04-13 23:23:14 +000079HashInfo * findHash ( const char * name )
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000080{
aappleby@google.coma27c2812011-04-13 23:23:14 +000081 for(size_t i = 0; i < sizeof(g_hashes) / sizeof(HashInfo); i++)
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000082 {
83 if(_stricmp(name,g_hashes[i].name) == 0) return &g_hashes[i];
84 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000085
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000086 return NULL;
87}
88
89//-----------------------------------------------------------------------------
90// Self-test on startup - verify that all installed hashes work correctly.
91
92void SelfTest ( void )
93{
94 bool pass = true;
95
aappleby@google.coma27c2812011-04-13 23:23:14 +000096 for(size_t i = 0; i < sizeof(g_hashes) / sizeof(HashInfo); i++)
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000097 {
98 HashInfo * info = & g_hashes[i];
99
100 pass &= VerificationTest(info->hash,info->hashbits,info->verification,false);
101 }
102
103 if(!pass)
104 {
105 printf("Self-test FAILED!\n");
106
aappleby@google.coma27c2812011-04-13 23:23:14 +0000107 for(size_t i = 0; i < sizeof(g_hashes) / sizeof(HashInfo); i++)
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000108 {
109 HashInfo * info = & g_hashes[i];
aappleby@google.coma27c2812011-04-13 23:23:14 +0000110
tanjent@gmail.com833fd8d2011-04-11 20:45:44 +0000111 printf("%16s - ",info->name);
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000112 pass &= VerificationTest(info->hash,info->hashbits,info->verification,true);
113 }
114
115 exit(1);
116 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000117}
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000118
119//----------------------------------------------------------------------------
120
121template < typename hashtype >
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000122void test ( hashfunc<hashtype> hash, HashInfo * info )
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000123{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000124 const int hashbits = sizeof(hashtype) * 8;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000125
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000126 printf("-------------------------------------------------------------------------------\n");
tanjent@gmail.com2ff5e9b2011-04-03 06:30:51 +0000127 printf("--- Testing %s (%s)\n\n",info->name,info->desc);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000128
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000129 //-----------------------------------------------------------------------------
130 // Sanity tests
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000131
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000132 if(g_testSanity || g_testAll)
133 {
134 printf("[[[ Sanity Tests ]]]\n\n");
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000135
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000136 VerificationTest(hash,hashbits,info->verification,true);
137 SanityTest(hash,hashbits);
138 AppendedZeroesTest(hash,hashbits);
139 printf("\n");
140 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000141
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000142 //-----------------------------------------------------------------------------
143 // Speed tests
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000144
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000145 if(g_testSpeed || g_testAll)
146 {
147 printf("[[[ Speed Tests ]]]\n\n");
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000148
aappleby@google.com7f20a312011-03-21 20:55:06 +0000149 BulkSpeedTest(info->hash,info->verification);
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000150 printf("\n");
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000151
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000152 for(int i = 1; i < 32; i++)
153 {
154 double cycles;
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000155
aappleby@google.com7f20a312011-03-21 20:55:06 +0000156 TinySpeedTest(hashfunc<hashtype>(info->hash),sizeof(hashtype),i,info->verification,true,cycles);
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000157 }
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000158
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000159 printf("\n");
160 }
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000161
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000162 //-----------------------------------------------------------------------------
163 // Differential tests
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000164
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000165 if(g_testDiff || g_testAll)
166 {
167 printf("[[[ Differential Tests ]]]\n\n");
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000168
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000169 bool result = true;
170 bool dumpCollisions = false;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000171
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000172 result &= DiffTest< Blob<64>, hashtype >(hash,5,1000,dumpCollisions);
173 result &= DiffTest< Blob<128>, hashtype >(hash,4,1000,dumpCollisions);
174 result &= DiffTest< Blob<256>, hashtype >(hash,3,1000,dumpCollisions);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000175
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000176 if(!result) printf("*********FAIL*********\n");
177 printf("\n");
178 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000179
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000180 //-----------------------------------------------------------------------------
tanjent@gmail.com623590d2011-03-28 18:19:31 +0000181 // Differential-distribution tests
182
183 if(g_testDiffDist /*|| g_testAll*/)
184 {
185 printf("[[[ Differential Distribution Tests ]]]\n\n");
186
187 bool result = true;
188
189 result &= DiffDistTest2<uint64_t,hashtype>(hash);
190
191 printf("\n");
192 }
193
194 //-----------------------------------------------------------------------------
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000195 // Avalanche tests
aappleby@google.coma27c2812011-04-13 23:23:14 +0000196
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000197 if(g_testAvalanche || g_testAll)
198 {
199 printf("[[[ Avalanche Tests ]]]\n\n");
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000200
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000201 bool result = true;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000202
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000203 result &= AvalancheTest< Blob< 32>, hashtype > (hash,300000);
204 result &= AvalancheTest< Blob< 40>, hashtype > (hash,300000);
205 result &= AvalancheTest< Blob< 48>, hashtype > (hash,300000);
206 result &= AvalancheTest< Blob< 56>, hashtype > (hash,300000);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000207
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000208 result &= AvalancheTest< Blob< 64>, hashtype > (hash,300000);
209 result &= AvalancheTest< Blob< 72>, hashtype > (hash,300000);
210 result &= AvalancheTest< Blob< 80>, hashtype > (hash,300000);
211 result &= AvalancheTest< Blob< 88>, hashtype > (hash,300000);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000212
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000213 result &= AvalancheTest< Blob< 96>, hashtype > (hash,300000);
214 result &= AvalancheTest< Blob<104>, hashtype > (hash,300000);
215 result &= AvalancheTest< Blob<112>, hashtype > (hash,300000);
216 result &= AvalancheTest< Blob<120>, hashtype > (hash,300000);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000217
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000218 result &= AvalancheTest< Blob<128>, hashtype > (hash,300000);
219 result &= AvalancheTest< Blob<136>, hashtype > (hash,300000);
220 result &= AvalancheTest< Blob<144>, hashtype > (hash,300000);
221 result &= AvalancheTest< Blob<152>, hashtype > (hash,300000);
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000222
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000223 if(!result) printf("*********FAIL*********\n");
224 printf("\n");
225 }
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000226
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000227 //-----------------------------------------------------------------------------
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000228 // Bit Independence Criteria. Interesting, but doesn't tell us much about
229 // collision or distribution.
tanjent@gmail.com623590d2011-03-28 18:19:31 +0000230
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000231 if(g_testBIC)
tanjent@gmail.com623590d2011-03-28 18:19:31 +0000232 {
233 printf("[[[ Bit Independence Criteria ]]]\n\n");
234
235 bool result = true;
236
237 //result &= BicTest<uint64_t,hashtype>(hash,2000000);
238 BicTest3<Blob<88>,hashtype>(hash,2000000);
239
240 if(!result) printf("*********FAIL*********\n");
241 printf("\n");
242 }
243
244 //-----------------------------------------------------------------------------
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000245 // Keyset 'Cyclic' - keys of the form "abcdabcdabcd..."
tanjent@gmail.com2aa29c32011-03-19 08:53:53 +0000246
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000247 if(g_testCyclic || g_testAll)
248 {
249 printf("[[[ Keyset 'Cyclic' Tests ]]]\n\n");
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000250
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000251 bool result = true;
252 bool drawDiagram = false;
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000253
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000254 result &= CyclicKeyTest<hashtype>(hash,sizeof(hashtype)+0,8,10000000,drawDiagram);
255 result &= CyclicKeyTest<hashtype>(hash,sizeof(hashtype)+1,8,10000000,drawDiagram);
256 result &= CyclicKeyTest<hashtype>(hash,sizeof(hashtype)+2,8,10000000,drawDiagram);
257 result &= CyclicKeyTest<hashtype>(hash,sizeof(hashtype)+3,8,10000000,drawDiagram);
258 result &= CyclicKeyTest<hashtype>(hash,sizeof(hashtype)+4,8,10000000,drawDiagram);
aappleby@google.coma27c2812011-04-13 23:23:14 +0000259
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000260 if(!result) printf("*********FAIL*********\n");
261 printf("\n");
262 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000263
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000264 //-----------------------------------------------------------------------------
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000265 // Keyset 'TwoBytes' - all keys up to N bytes containing two non-zero bytes
tanjent@gmail.com96601f22011-03-31 02:41:29 +0000266
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000267 // This generates some huge keysets, 128-bit tests will take ~1.3 gigs of RAM.
268
269 if(g_testTwoBytes || g_testAll)
tanjent@gmail.com96601f22011-03-31 02:41:29 +0000270 {
271 printf("[[[ Keyset 'TwoBytes' Tests ]]]\n\n");
272
273 bool result = true;
274 bool drawDiagram = false;
275
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000276 for(int i = 4; i <= 20; i += 4)
277 {
278 result &= TwoBytesTest2<hashtype>(hash,i,drawDiagram);
279 }
tanjent@gmail.com96601f22011-03-31 02:41:29 +0000280
281 if(!result) printf("*********FAIL*********\n");
282 printf("\n");
283 }
284
285 //-----------------------------------------------------------------------------
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000286 // Keyset 'Sparse' - keys with all bits 0 except a few
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000287
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000288 if(g_testSparse || g_testAll)
289 {
290 printf("[[[ Keyset 'Sparse' Tests ]]]\n\n");
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000291
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000292 bool result = true;
293 bool drawDiagram = false;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000294
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000295 result &= SparseKeyTest< 32,hashtype>(hash,6,true,true,true,drawDiagram);
296 result &= SparseKeyTest< 40,hashtype>(hash,6,true,true,true,drawDiagram);
297 result &= SparseKeyTest< 48,hashtype>(hash,5,true,true,true,drawDiagram);
298 result &= SparseKeyTest< 56,hashtype>(hash,5,true,true,true,drawDiagram);
299 result &= SparseKeyTest< 64,hashtype>(hash,5,true,true,true,drawDiagram);
aappleby@google.coma27c2812011-04-13 23:23:14 +0000300 result &= SparseKeyTest< 96,hashtype>(hash,4,true,true,true,drawDiagram);
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000301 result &= SparseKeyTest< 256,hashtype>(hash,3,true,true,true,drawDiagram);
302 result &= SparseKeyTest<2048,hashtype>(hash,2,true,true,true,drawDiagram);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000303
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000304 if(!result) printf("*********FAIL*********\n");
305 printf("\n");
306 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000307
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000308 //-----------------------------------------------------------------------------
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000309 // Keyset 'Permutation' - all possible combinations of a set of blocks
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000310
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000311 if(g_testPermutation || g_testAll)
312 {
313 {
314 // This one breaks lookup3, surprisingly
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000315
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000316 printf("[[[ Keyset 'Combination Lowbits' Tests ]]]\n\n");
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000317
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000318 bool result = true;
319 bool drawDiagram = false;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000320
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000321 uint32_t blocks[] =
322 {
aappleby@google.coma27c2812011-04-13 23:23:14 +0000323 0x00000000,
324
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000325 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007,
326 };
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000327
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000328 result &= CombinationKeyTest<hashtype>(hash,8,blocks,sizeof(blocks) / sizeof(uint32_t),true,true,drawDiagram);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000329
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000330 if(!result) printf("*********FAIL*********\n");
331 printf("\n");
332 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000333
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000334 {
335 printf("[[[ Keyset 'Combination Highbits' Tests ]]]\n\n");
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000336
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000337 bool result = true;
338 bool drawDiagram = false;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000339
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000340 uint32_t blocks[] =
341 {
aappleby@google.coma27c2812011-04-13 23:23:14 +0000342 0x00000000,
343
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000344 0x20000000, 0x40000000, 0x60000000, 0x80000000, 0xA0000000, 0xC0000000, 0xE0000000
345 };
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000346
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000347 result &= CombinationKeyTest<hashtype>(hash,8,blocks,sizeof(blocks) / sizeof(uint32_t),true,true,drawDiagram);
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000348
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000349 if(!result) printf("*********FAIL*********\n");
350 printf("\n");
351 }
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000352
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000353 {
354 printf("[[[ Keyset 'Combination 0x8000000' Tests ]]]\n\n");
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000355
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000356 bool result = true;
357 bool drawDiagram = false;
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000358
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000359 uint32_t blocks[] =
360 {
aappleby@google.coma27c2812011-04-13 23:23:14 +0000361 0x00000000,
362
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000363 0x80000000,
364 };
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000365
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000366 result &= CombinationKeyTest<hashtype>(hash,20,blocks,sizeof(blocks) / sizeof(uint32_t),true,true,drawDiagram);
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000367
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000368 if(!result) printf("*********FAIL*********\n");
369 printf("\n");
370 }
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000371
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000372 {
373 printf("[[[ Keyset 'Combination 0x0000001' Tests ]]]\n\n");
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000374
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000375 bool result = true;
376 bool drawDiagram = false;
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000377
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000378 uint32_t blocks[] =
379 {
aappleby@google.coma27c2812011-04-13 23:23:14 +0000380 0x00000000,
381
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000382 0x00000001,
383 };
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000384
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000385 result &= CombinationKeyTest<hashtype>(hash,20,blocks,sizeof(blocks) / sizeof(uint32_t),true,true,drawDiagram);
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000386
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000387 if(!result) printf("*********FAIL*********\n");
388 printf("\n");
389 }
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000390
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000391 {
392 printf("[[[ Keyset 'Combination Hi-Lo' Tests ]]]\n\n");
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000393
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000394 bool result = true;
395 bool drawDiagram = false;
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000396
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000397 uint32_t blocks[] =
398 {
aappleby@google.coma27c2812011-04-13 23:23:14 +0000399 0x00000000,
400
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000401 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007,
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000402
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000403 0x80000000, 0x40000000, 0xC0000000, 0x20000000, 0xA0000000, 0x60000000, 0xE0000000
404 };
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000405
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000406 result &= CombinationKeyTest<hashtype>(hash,6,blocks,sizeof(blocks) / sizeof(uint32_t),true,true,drawDiagram);
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000407
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000408 if(!result) printf("*********FAIL*********\n");
409 printf("\n");
410 }
411 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000412
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000413 //-----------------------------------------------------------------------------
414 // Keyset 'Window'
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000415
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000416 // Skip distribution test for these - they're too easy to distribute well,
417 // and it generates a _lot_ of testing
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000418
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000419 if(g_testWindow || g_testAll)
420 {
421 printf("[[[ Keyset 'Window' Tests ]]]\n\n");
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000422
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000423 bool result = true;
424 bool testCollision = true;
425 bool testDistribution = false;
426 bool drawDiagram = false;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000427
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000428 result &= WindowedKeyTest< Blob<hashbits*2>, hashtype > ( hash, 20, testCollision, testDistribution, drawDiagram );
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000429
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000430 if(!result) printf("*********FAIL*********\n");
431 printf("\n");
432 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000433
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000434 //-----------------------------------------------------------------------------
435 // Keyset 'Text'
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000436
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000437 if(g_testText || g_testAll)
438 {
439 printf("[[[ Keyset 'Text' Tests ]]]\n\n");
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000440
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000441 bool result = true;
442 bool drawDiagram = false;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000443
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000444 const char * alnum = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000445
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000446 result &= TextKeyTest( hash, "Foo", alnum,4, "Bar", drawDiagram );
447 result &= TextKeyTest( hash, "FooBar", alnum,4, "", drawDiagram );
448 result &= TextKeyTest( hash, "", alnum,4, "FooBar", drawDiagram );
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000449
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000450 if(!result) printf("*********FAIL*********\n");
451 printf("\n");
452 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000453
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000454 //-----------------------------------------------------------------------------
455 // Keyset 'Zeroes'
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000456
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000457 if(g_testZeroes || g_testAll)
458 {
459 printf("[[[ Keyset 'Zeroes' Tests ]]]\n\n");
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000460
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000461 bool result = true;
462 bool drawDiagram = false;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000463
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000464 result &= ZeroKeyTest<hashtype>( hash, drawDiagram );
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000465
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000466 if(!result) printf("*********FAIL*********\n");
467 printf("\n");
468 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000469
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000470 //-----------------------------------------------------------------------------
471 // Keyset 'Seed'
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000472
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000473 if(g_testSeed || g_testAll)
474 {
475 printf("[[[ Keyset 'Seed' Tests ]]]\n\n");
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000476
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000477 bool result = true;
478 bool drawDiagram = false;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000479
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000480 result &= SeedTest<hashtype>( hash, 1000000, drawDiagram );
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000481
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000482 if(!result) printf("*********FAIL*********\n");
483 printf("\n");
484 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000485}
486
487//-----------------------------------------------------------------------------
488
aappleby@google.com7f20a312011-03-21 20:55:06 +0000489uint32_t g_inputVCode = 1;
490uint32_t g_outputVCode = 1;
491uint32_t g_resultVCode = 1;
492
493HashInfo * g_hashUnderTest = NULL;
494
495void VerifyHash ( const void * key, int len, uint32_t seed, void * out )
496{
497 g_inputVCode = MurmurOAAT(key,len,g_inputVCode);
498 g_inputVCode = MurmurOAAT(&seed,sizeof(uint32_t),g_inputVCode);
aappleby@google.coma27c2812011-04-13 23:23:14 +0000499
aappleby@google.com7f20a312011-03-21 20:55:06 +0000500 g_hashUnderTest->hash(key,len,seed,out);
aappleby@google.coma27c2812011-04-13 23:23:14 +0000501
aappleby@google.com7f20a312011-03-21 20:55:06 +0000502 g_outputVCode = MurmurOAAT(out,g_hashUnderTest->hashbits/8,g_outputVCode);
503}
504
505//-----------------------------------------------------------------------------
506
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000507void testHash ( const char * name )
508{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000509 HashInfo * pInfo = findHash(name);
aappleby@google.coma27c2812011-04-13 23:23:14 +0000510
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000511 if(pInfo == NULL)
512 {
513 printf("Invalid hash '%s' specified\n",name);
514 return;
515 }
516 else
517 {
aappleby@google.com7f20a312011-03-21 20:55:06 +0000518 g_hashUnderTest = pInfo;
519
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000520 if(pInfo->hashbits == 32)
521 {
aappleby@google.com7f20a312011-03-21 20:55:06 +0000522 test<uint32_t>( VerifyHash, pInfo );
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000523 }
524 else if(pInfo->hashbits == 64)
525 {
526 test<uint64_t>( pInfo->hash, pInfo );
527 }
528 else if(pInfo->hashbits == 128)
529 {
530 test<uint128_t>( pInfo->hash, pInfo );
531 }
532 else if(pInfo->hashbits == 256)
533 {
534 test<uint256_t>( pInfo->hash, pInfo );
535 }
536 else
537 {
538 printf("Invalid hash bit width %d for hash '%s'",pInfo->hashbits,pInfo->name);
539 }
540 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000541}
542//-----------------------------------------------------------------------------
543
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000544int main ( int argc, char ** argv )
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000545{
tanjent@gmail.com2ff5e9b2011-04-03 06:30:51 +0000546 const char * hashToTest = "murmur3a";
tanjent@gmail.com623590d2011-03-28 18:19:31 +0000547
aappleby@google.com7f20a312011-03-21 20:55:06 +0000548 if(argc < 2)
549 {
tanjent@gmail.com623590d2011-03-28 18:19:31 +0000550 printf("(No test hash given on command line, testing Murmur3_x86_32.)\n");
551 }
552 else
553 {
554 hashToTest = argv[1];
aappleby@google.com7f20a312011-03-21 20:55:06 +0000555 }
aappleby@google.coma27c2812011-04-13 23:23:14 +0000556
tanjent@gmail.com97150532011-04-04 23:29:25 +0000557 // Code runs on the 3rd CPU by default
558
559 SetAffinity((1 << 2));
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000560
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000561 SelfTest();
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000562
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000563 int timeBegin = clock();
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000564
tanjent@gmail.com623590d2011-03-28 18:19:31 +0000565 g_testAll = true;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000566
tanjent@gmail.com623590d2011-03-28 18:19:31 +0000567 //g_testSanity = true;
568 //g_testSpeed = true;
aappleby@google.com7f20a312011-03-21 20:55:06 +0000569 //g_testAvalanche = true;
tanjent@gmail.com623590d2011-03-28 18:19:31 +0000570 //g_testBIC = true;
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000571 //g_testCyclic = true;
tanjent@gmail.com96601f22011-03-31 02:41:29 +0000572 //g_testTwoBytes = true;
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000573 //g_testDiff = true;
tanjent@gmail.com623590d2011-03-28 18:19:31 +0000574 //g_testDiffDist = true;
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000575 //g_testSparse = true;
576 //g_testPermutation = true;
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000577 //g_testWindow = true;
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000578 //g_testZeroes = true;
tanjent@gmail.com31a9e8e2010-11-09 20:29:19 +0000579
tanjent@gmail.com623590d2011-03-28 18:19:31 +0000580 testHash(hashToTest);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000581
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000582 //----------
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000583
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000584 int timeEnd = clock();
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000585
tanjent@gmail.com2aa29c32011-03-19 08:53:53 +0000586 printf("\n");
aappleby@google.com7f20a312011-03-21 20:55:06 +0000587 printf("Input vcode 0x%08x, Output vcode 0x%08x, Result vcode 0x%08x\n",g_inputVCode,g_outputVCode,g_resultVCode);
tanjent@gmail.com3ee45612011-03-21 19:33:01 +0000588 printf("Verification value is 0x%08x - Testing took %f seconds\n",g_verify,double(timeEnd-timeBegin)/double(CLOCKS_PER_SEC));
tanjent@gmail.com2aa29c32011-03-19 08:53:53 +0000589 printf("-------------------------------------------------------------------------------\n");
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000590 return 0;
tanjent@gmail.com2aa29c32011-03-19 08:53:53 +0000591}