blob: 973ffa679820537004b8c87c091a020e0ee740b7 [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>
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000010
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000011//-----------------------------------------------------------------------------
12// Configuration. TODO - move these to command-line flags
13
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000014bool g_testAll = false;
15
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000016bool g_testSanity = false;
17bool g_testSpeed = false;
18bool g_testDiff = false;
tanjent@gmail.com623590d2011-03-28 18:19:31 +000019bool g_testDiffDist = false;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000020bool g_testAvalanche = false;
tanjent@gmail.com623590d2011-03-28 18:19:31 +000021bool g_testBIC = false;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000022bool g_testCyclic = false;
tanjent@gmail.com96601f22011-03-31 02:41:29 +000023bool g_testTwoBytes = false;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000024bool g_testSparse = false;
25bool g_testPermutation = false;
26bool g_testWindow = false;
27bool g_testText = false;
28bool g_testZeroes = false;
29bool g_testSeed = false;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000030
tanjent@gmail.comf67ce942011-03-14 09:11:18 +000031//-----------------------------------------------------------------------------
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000032// This is the list of all hashes that SMHasher can test.
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000033
34struct HashInfo
35{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000036 pfHash hash;
37 int hashbits;
38 uint32_t verification;
39 const char * name;
40 const char * desc;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000041};
42
43HashInfo g_hashes[] =
44{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000045 { DoNothingHash, 32, 0x00000000, "donothing32", "Do-Nothing function (only valid for measuring call overhead)" },
46 { DoNothingHash, 64, 0x00000000, "donothing64", "Do-Nothing function (only valid for measuring call overhead)" },
47 { DoNothingHash, 128, 0x00000000, "donothing128", "Do-Nothing function (only valid for measuring call overhead)" },
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000048
tanjent@gmail.com623590d2011-03-28 18:19:31 +000049 { crc32, 32, 0x3719DB20, "crc32", "CRC-32" },
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000050
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000051 { md5_32, 32, 0xC10C356B, "md5_32a", "MD5, first 32 bits of result" },
52 { sha1_32a, 32, 0xF9376EA7, "sha1_32a", "SHA1, first 32 bits of result" },
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000053
tanjent@gmail.com623590d2011-03-28 18:19:31 +000054 { FNV, 32, 0xE3CBBE91, "FNV", "Fowler-Noll-Vo hash, 32-bit" },
55 { lookup3_test, 32, 0x3D83917A, "lookup3", "Bob Jenkins' lookup3" },
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000056 { SuperFastHash, 32, 0x980ACD1D, "superfast", "Paul Hsieh's SuperFastHash" },
tanjent@gmail.com623590d2011-03-28 18:19:31 +000057 { MurmurOAAT_test, 32, 0x5363BD98, "MurmurOAAT", "Murmur one-at-a-time" },
58 { Crap8_test, 32, 0x743E97A1, "Crap8", "Crap8" },
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000059
60 // MurmurHash2
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000061
tanjent@gmail.com623590d2011-03-28 18:19:31 +000062 { MurmurHash2_test, 32, 0x27864C1E, "Murmur2", "MurmurHash2 for x86, 32-bit" },
63 { MurmurHash2A_test, 32, 0x7FBD4396, "Murmur2A", "MurmurHash2A for x86, 32-bit" },
64 { MurmurHash64A_test, 64, 0x1F0D3804, "Murmur2B", "MurmurHash2 for x64, 64-bit" },
65 { MurmurHash64B_test, 64, 0xDD537C05, "Murmur2C", "MurmurHash2 for x86, 64-bit" },
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000066
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000067 // MurmurHash3
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000068
tanjent@gmail.com2ff5e9b2011-04-03 06:30:51 +000069 { MurmurHash3_x86_32, 32, 0x3252D141, "Murmur3A", "MurmurHash3 for x86, 32-bit" },
tanjent@gmail.com0f37bbd2011-04-04 23:05:26 +000070 { MurmurHash3_x86_128, 128, 0xB3ECE62A, "Murmur3C", "MurmurHash3 for x86, 128-bit" },
tanjent@gmail.com833fd8d2011-04-11 20:45:44 +000071 { MurmurHash3_x64_128, 128, 0x6384BA69, "Murmur3F", "MurmurHash3 for x64, 128-bit" },
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000072
73};
74
75HashInfo * findHash ( const char * name )
76{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000077 for(int i = 0; i < sizeof(g_hashes) / sizeof(HashInfo); i++)
78 {
79 if(_stricmp(name,g_hashes[i].name) == 0) return &g_hashes[i];
80 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000081
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000082 return NULL;
83}
84
85//-----------------------------------------------------------------------------
86// Self-test on startup - verify that all installed hashes work correctly.
87
88void SelfTest ( void )
89{
90 bool pass = true;
91
92 for(int i = 0; i < sizeof(g_hashes) / sizeof(HashInfo); i++)
93 {
94 HashInfo * info = & g_hashes[i];
95
96 pass &= VerificationTest(info->hash,info->hashbits,info->verification,false);
97 }
98
99 if(!pass)
100 {
101 printf("Self-test FAILED!\n");
102
103 for(int i = 0; i < sizeof(g_hashes) / sizeof(HashInfo); i++)
104 {
105 HashInfo * info = & g_hashes[i];
tanjent@gmail.com833fd8d2011-04-11 20:45:44 +0000106
107 printf("%16s - ",info->name);
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000108 pass &= VerificationTest(info->hash,info->hashbits,info->verification,true);
109 }
110
111 exit(1);
112 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000113}
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000114
115//----------------------------------------------------------------------------
116
117template < typename hashtype >
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000118void test ( hashfunc<hashtype> hash, HashInfo * info )
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000119{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000120 const int hashbits = sizeof(hashtype) * 8;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000121
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000122 printf("-------------------------------------------------------------------------------\n");
tanjent@gmail.com2ff5e9b2011-04-03 06:30:51 +0000123 printf("--- Testing %s (%s)\n\n",info->name,info->desc);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000124
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000125 //-----------------------------------------------------------------------------
126 // Sanity tests
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000127
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000128 if(g_testSanity || g_testAll)
129 {
130 printf("[[[ Sanity Tests ]]]\n\n");
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000131
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000132 VerificationTest(hash,hashbits,info->verification,true);
133 SanityTest(hash,hashbits);
134 AppendedZeroesTest(hash,hashbits);
135 printf("\n");
136 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000137
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000138 //-----------------------------------------------------------------------------
139 // Speed tests
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000140
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000141 if(g_testSpeed || g_testAll)
142 {
143 printf("[[[ Speed Tests ]]]\n\n");
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000144
aappleby@google.com7f20a312011-03-21 20:55:06 +0000145 BulkSpeedTest(info->hash,info->verification);
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000146 printf("\n");
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000147
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000148 for(int i = 1; i < 32; i++)
149 {
150 double cycles;
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000151
aappleby@google.com7f20a312011-03-21 20:55:06 +0000152 TinySpeedTest(hashfunc<hashtype>(info->hash),sizeof(hashtype),i,info->verification,true,cycles);
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000153 }
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000154
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000155 printf("\n");
156 }
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000157
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000158 //-----------------------------------------------------------------------------
159 // Differential tests
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000160
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000161 if(g_testDiff || g_testAll)
162 {
163 printf("[[[ Differential Tests ]]]\n\n");
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000164
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000165 bool result = true;
166 bool dumpCollisions = false;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000167
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000168 result &= DiffTest< Blob<64>, hashtype >(hash,5,1000,dumpCollisions);
169 result &= DiffTest< Blob<128>, hashtype >(hash,4,1000,dumpCollisions);
170 result &= DiffTest< Blob<256>, hashtype >(hash,3,1000,dumpCollisions);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000171
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000172 if(!result) printf("*********FAIL*********\n");
173 printf("\n");
174 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000175
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000176 //-----------------------------------------------------------------------------
tanjent@gmail.com623590d2011-03-28 18:19:31 +0000177 // Differential-distribution tests
178
179 if(g_testDiffDist /*|| g_testAll*/)
180 {
181 printf("[[[ Differential Distribution Tests ]]]\n\n");
182
183 bool result = true;
184
185 result &= DiffDistTest2<uint64_t,hashtype>(hash);
186
187 printf("\n");
188 }
189
190 //-----------------------------------------------------------------------------
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000191 // Avalanche tests
192
193 if(g_testAvalanche || g_testAll)
194 {
195 printf("[[[ Avalanche Tests ]]]\n\n");
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000196
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000197 bool result = true;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000198
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000199 result &= AvalancheTest< Blob< 32>, hashtype > (hash,300000);
200 result &= AvalancheTest< Blob< 40>, hashtype > (hash,300000);
201 result &= AvalancheTest< Blob< 48>, hashtype > (hash,300000);
202 result &= AvalancheTest< Blob< 56>, hashtype > (hash,300000);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000203
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000204 result &= AvalancheTest< Blob< 64>, hashtype > (hash,300000);
205 result &= AvalancheTest< Blob< 72>, hashtype > (hash,300000);
206 result &= AvalancheTest< Blob< 80>, hashtype > (hash,300000);
207 result &= AvalancheTest< Blob< 88>, hashtype > (hash,300000);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000208
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000209 result &= AvalancheTest< Blob< 96>, hashtype > (hash,300000);
210 result &= AvalancheTest< Blob<104>, hashtype > (hash,300000);
211 result &= AvalancheTest< Blob<112>, hashtype > (hash,300000);
212 result &= AvalancheTest< Blob<120>, hashtype > (hash,300000);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000213
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000214 result &= AvalancheTest< Blob<128>, hashtype > (hash,300000);
215 result &= AvalancheTest< Blob<136>, hashtype > (hash,300000);
216 result &= AvalancheTest< Blob<144>, hashtype > (hash,300000);
217 result &= AvalancheTest< Blob<152>, hashtype > (hash,300000);
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000218
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000219 if(!result) printf("*********FAIL*********\n");
220 printf("\n");
221 }
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000222
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000223 //-----------------------------------------------------------------------------
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000224 // Bit Independence Criteria. Interesting, but doesn't tell us much about
225 // collision or distribution.
tanjent@gmail.com623590d2011-03-28 18:19:31 +0000226
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000227 if(g_testBIC)
tanjent@gmail.com623590d2011-03-28 18:19:31 +0000228 {
229 printf("[[[ Bit Independence Criteria ]]]\n\n");
230
231 bool result = true;
232
233 //result &= BicTest<uint64_t,hashtype>(hash,2000000);
234 BicTest3<Blob<88>,hashtype>(hash,2000000);
235
236 if(!result) printf("*********FAIL*********\n");
237 printf("\n");
238 }
239
240 //-----------------------------------------------------------------------------
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000241 // Keyset 'Cyclic' - keys of the form "abcdabcdabcd..."
tanjent@gmail.com2aa29c32011-03-19 08:53:53 +0000242
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000243 if(g_testCyclic || g_testAll)
244 {
245 printf("[[[ Keyset 'Cyclic' Tests ]]]\n\n");
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000246
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000247 bool result = true;
248 bool drawDiagram = false;
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000249
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000250 result &= CyclicKeyTest<hashtype>(hash,sizeof(hashtype)+0,8,10000000,drawDiagram);
251 result &= CyclicKeyTest<hashtype>(hash,sizeof(hashtype)+1,8,10000000,drawDiagram);
252 result &= CyclicKeyTest<hashtype>(hash,sizeof(hashtype)+2,8,10000000,drawDiagram);
253 result &= CyclicKeyTest<hashtype>(hash,sizeof(hashtype)+3,8,10000000,drawDiagram);
254 result &= CyclicKeyTest<hashtype>(hash,sizeof(hashtype)+4,8,10000000,drawDiagram);
255
256 if(!result) printf("*********FAIL*********\n");
257 printf("\n");
258 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000259
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000260 //-----------------------------------------------------------------------------
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000261 // Keyset 'TwoBytes' - all keys up to N bytes containing two non-zero bytes
tanjent@gmail.com96601f22011-03-31 02:41:29 +0000262
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000263 // This generates some huge keysets, 128-bit tests will take ~1.3 gigs of RAM.
264
265 if(g_testTwoBytes || g_testAll)
tanjent@gmail.com96601f22011-03-31 02:41:29 +0000266 {
267 printf("[[[ Keyset 'TwoBytes' Tests ]]]\n\n");
268
269 bool result = true;
270 bool drawDiagram = false;
271
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000272 for(int i = 4; i <= 20; i += 4)
273 {
274 result &= TwoBytesTest2<hashtype>(hash,i,drawDiagram);
275 }
tanjent@gmail.com96601f22011-03-31 02:41:29 +0000276
277 if(!result) printf("*********FAIL*********\n");
278 printf("\n");
279 }
280
281 //-----------------------------------------------------------------------------
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000282 // Keyset 'Sparse' - keys with all bits 0 except a few
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000283
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000284 if(g_testSparse || g_testAll)
285 {
286 printf("[[[ Keyset 'Sparse' Tests ]]]\n\n");
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000287
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000288 bool result = true;
289 bool drawDiagram = false;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000290
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000291 result &= SparseKeyTest< 32,hashtype>(hash,6,true,true,true,drawDiagram);
292 result &= SparseKeyTest< 40,hashtype>(hash,6,true,true,true,drawDiagram);
293 result &= SparseKeyTest< 48,hashtype>(hash,5,true,true,true,drawDiagram);
294 result &= SparseKeyTest< 56,hashtype>(hash,5,true,true,true,drawDiagram);
295 result &= SparseKeyTest< 64,hashtype>(hash,5,true,true,true,drawDiagram);
296 result &= SparseKeyTest< 96,hashtype>(hash,4,true,true,true,drawDiagram);
297 result &= SparseKeyTest< 256,hashtype>(hash,3,true,true,true,drawDiagram);
298 result &= SparseKeyTest<2048,hashtype>(hash,2,true,true,true,drawDiagram);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000299
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000300 if(!result) printf("*********FAIL*********\n");
301 printf("\n");
302 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000303
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000304 //-----------------------------------------------------------------------------
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000305 // Keyset 'Permutation' - all possible combinations of a set of blocks
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000306
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000307 if(g_testPermutation || g_testAll)
308 {
309 {
310 // This one breaks lookup3, surprisingly
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000311
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000312 printf("[[[ Keyset 'Combination Lowbits' Tests ]]]\n\n");
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000313
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000314 bool result = true;
315 bool drawDiagram = false;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000316
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000317 uint32_t blocks[] =
318 {
319 0x00000000,
320
321 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007,
322 };
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000323
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000324 result &= CombinationKeyTest<hashtype>(hash,8,blocks,sizeof(blocks) / sizeof(uint32_t),true,true,drawDiagram);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000325
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000326 if(!result) printf("*********FAIL*********\n");
327 printf("\n");
328 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000329
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000330 {
331 printf("[[[ Keyset 'Combination Highbits' Tests ]]]\n\n");
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000332
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000333 bool result = true;
334 bool drawDiagram = false;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000335
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000336 uint32_t blocks[] =
337 {
338 0x00000000,
339
340 0x20000000, 0x40000000, 0x60000000, 0x80000000, 0xA0000000, 0xC0000000, 0xE0000000
341 };
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000342
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000343 result &= CombinationKeyTest<hashtype>(hash,8,blocks,sizeof(blocks) / sizeof(uint32_t),true,true,drawDiagram);
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000344
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000345 if(!result) printf("*********FAIL*********\n");
346 printf("\n");
347 }
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000348
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000349 {
350 printf("[[[ Keyset 'Combination 0x8000000' Tests ]]]\n\n");
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000351
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000352 bool result = true;
353 bool drawDiagram = false;
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000354
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000355 uint32_t blocks[] =
356 {
357 0x00000000,
358
359 0x80000000,
360 };
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000361
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000362 result &= CombinationKeyTest<hashtype>(hash,20,blocks,sizeof(blocks) / sizeof(uint32_t),true,true,drawDiagram);
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000363
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000364 if(!result) printf("*********FAIL*********\n");
365 printf("\n");
366 }
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000367
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000368 {
369 printf("[[[ Keyset 'Combination 0x0000001' Tests ]]]\n\n");
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000370
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000371 bool result = true;
372 bool drawDiagram = false;
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000373
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000374 uint32_t blocks[] =
375 {
376 0x00000000,
377
378 0x00000001,
379 };
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000380
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000381 result &= CombinationKeyTest<hashtype>(hash,20,blocks,sizeof(blocks) / sizeof(uint32_t),true,true,drawDiagram);
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000382
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000383 if(!result) printf("*********FAIL*********\n");
384 printf("\n");
385 }
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000386
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000387 {
388 printf("[[[ Keyset 'Combination Hi-Lo' Tests ]]]\n\n");
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000389
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000390 bool result = true;
391 bool drawDiagram = false;
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000392
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000393 uint32_t blocks[] =
394 {
395 0x00000000,
396
397 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007,
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000398
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000399 0x80000000, 0x40000000, 0xC0000000, 0x20000000, 0xA0000000, 0x60000000, 0xE0000000
400 };
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000401
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000402 result &= CombinationKeyTest<hashtype>(hash,6,blocks,sizeof(blocks) / sizeof(uint32_t),true,true,drawDiagram);
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000403
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000404 if(!result) printf("*********FAIL*********\n");
405 printf("\n");
406 }
407 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000408
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000409 //-----------------------------------------------------------------------------
410 // Keyset 'Window'
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000411
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000412 // Skip distribution test for these - they're too easy to distribute well,
413 // and it generates a _lot_ of testing
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000414
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000415 if(g_testWindow || g_testAll)
416 {
417 printf("[[[ Keyset 'Window' Tests ]]]\n\n");
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000418
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000419 bool result = true;
420 bool testCollision = true;
421 bool testDistribution = false;
422 bool drawDiagram = false;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000423
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000424 result &= WindowedKeyTest< Blob<hashbits*2>, hashtype > ( hash, 20, testCollision, testDistribution, drawDiagram );
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000425
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000426 if(!result) printf("*********FAIL*********\n");
427 printf("\n");
428 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000429
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000430 //-----------------------------------------------------------------------------
431 // Keyset 'Text'
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000432
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000433 if(g_testText || g_testAll)
434 {
435 printf("[[[ Keyset 'Text' Tests ]]]\n\n");
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000436
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000437 bool result = true;
438 bool drawDiagram = false;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000439
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000440 const char * alnum = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000441
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000442 result &= TextKeyTest( hash, "Foo", alnum,4, "Bar", drawDiagram );
443 result &= TextKeyTest( hash, "FooBar", alnum,4, "", drawDiagram );
444 result &= TextKeyTest( hash, "", alnum,4, "FooBar", drawDiagram );
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000445
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000446 if(!result) printf("*********FAIL*********\n");
447 printf("\n");
448 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000449
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000450 //-----------------------------------------------------------------------------
451 // Keyset 'Zeroes'
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000452
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000453 if(g_testZeroes || g_testAll)
454 {
455 printf("[[[ Keyset 'Zeroes' Tests ]]]\n\n");
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000456
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000457 bool result = true;
458 bool drawDiagram = false;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000459
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000460 result &= ZeroKeyTest<hashtype>( hash, drawDiagram );
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000461
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000462 if(!result) printf("*********FAIL*********\n");
463 printf("\n");
464 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000465
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000466 //-----------------------------------------------------------------------------
467 // Keyset 'Seed'
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000468
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000469 if(g_testSeed || g_testAll)
470 {
471 printf("[[[ Keyset 'Seed' Tests ]]]\n\n");
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000472
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000473 bool result = true;
474 bool drawDiagram = false;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000475
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000476 result &= SeedTest<hashtype>( hash, 1000000, drawDiagram );
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000477
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000478 if(!result) printf("*********FAIL*********\n");
479 printf("\n");
480 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000481}
482
483//-----------------------------------------------------------------------------
484
aappleby@google.com7f20a312011-03-21 20:55:06 +0000485uint32_t g_inputVCode = 1;
486uint32_t g_outputVCode = 1;
487uint32_t g_resultVCode = 1;
488
489HashInfo * g_hashUnderTest = NULL;
490
491void VerifyHash ( const void * key, int len, uint32_t seed, void * out )
492{
493 g_inputVCode = MurmurOAAT(key,len,g_inputVCode);
494 g_inputVCode = MurmurOAAT(&seed,sizeof(uint32_t),g_inputVCode);
495
496 g_hashUnderTest->hash(key,len,seed,out);
497
498 g_outputVCode = MurmurOAAT(out,g_hashUnderTest->hashbits/8,g_outputVCode);
499}
500
501//-----------------------------------------------------------------------------
502
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000503void testHash ( const char * name )
504{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000505 HashInfo * pInfo = findHash(name);
aappleby@google.com7f20a312011-03-21 20:55:06 +0000506
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000507 if(pInfo == NULL)
508 {
509 printf("Invalid hash '%s' specified\n",name);
510 return;
511 }
512 else
513 {
aappleby@google.com7f20a312011-03-21 20:55:06 +0000514 g_hashUnderTest = pInfo;
515
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000516 if(pInfo->hashbits == 32)
517 {
aappleby@google.com7f20a312011-03-21 20:55:06 +0000518 test<uint32_t>( VerifyHash, pInfo );
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000519 }
520 else if(pInfo->hashbits == 64)
521 {
522 test<uint64_t>( pInfo->hash, pInfo );
523 }
524 else if(pInfo->hashbits == 128)
525 {
526 test<uint128_t>( pInfo->hash, pInfo );
527 }
528 else if(pInfo->hashbits == 256)
529 {
530 test<uint256_t>( pInfo->hash, pInfo );
531 }
532 else
533 {
534 printf("Invalid hash bit width %d for hash '%s'",pInfo->hashbits,pInfo->name);
535 }
536 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000537}
538//-----------------------------------------------------------------------------
539
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000540int main ( int argc, char ** argv )
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000541{
tanjent@gmail.com2ff5e9b2011-04-03 06:30:51 +0000542 const char * hashToTest = "murmur3a";
tanjent@gmail.com623590d2011-03-28 18:19:31 +0000543
aappleby@google.com7f20a312011-03-21 20:55:06 +0000544 if(argc < 2)
545 {
tanjent@gmail.com623590d2011-03-28 18:19:31 +0000546 printf("(No test hash given on command line, testing Murmur3_x86_32.)\n");
547 }
548 else
549 {
550 hashToTest = argv[1];
aappleby@google.com7f20a312011-03-21 20:55:06 +0000551 }
552
tanjent@gmail.com97150532011-04-04 23:29:25 +0000553 // Code runs on the 3rd CPU by default
554
555 SetAffinity((1 << 2));
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000556
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000557 SelfTest();
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000558
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000559 int timeBegin = clock();
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000560
tanjent@gmail.com623590d2011-03-28 18:19:31 +0000561 g_testAll = true;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000562
tanjent@gmail.com623590d2011-03-28 18:19:31 +0000563 //g_testSanity = true;
564 //g_testSpeed = true;
aappleby@google.com7f20a312011-03-21 20:55:06 +0000565 //g_testAvalanche = true;
tanjent@gmail.com623590d2011-03-28 18:19:31 +0000566 //g_testBIC = true;
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000567 //g_testCyclic = true;
tanjent@gmail.com96601f22011-03-31 02:41:29 +0000568 //g_testTwoBytes = true;
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000569 //g_testDiff = true;
tanjent@gmail.com623590d2011-03-28 18:19:31 +0000570 //g_testDiffDist = true;
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000571 //g_testSparse = true;
572 //g_testPermutation = true;
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000573 //g_testWindow = true;
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000574 //g_testZeroes = true;
tanjent@gmail.com31a9e8e2010-11-09 20:29:19 +0000575
tanjent@gmail.com623590d2011-03-28 18:19:31 +0000576 testHash(hashToTest);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000577
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000578 //----------
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000579
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000580 int timeEnd = clock();
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000581
tanjent@gmail.com2aa29c32011-03-19 08:53:53 +0000582 printf("\n");
aappleby@google.com7f20a312011-03-21 20:55:06 +0000583 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 +0000584 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 +0000585 printf("-------------------------------------------------------------------------------\n");
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000586 return 0;
tanjent@gmail.com2aa29c32011-03-19 08:53:53 +0000587}