blob: eca08485973c2578d864e1e97da9d7cce0645985 [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
aappleby@google.coma27c2812011-04-13 23:23:14 +000043HashInfo g_hashes[] =
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000044{
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" },
aappleby@google.coma27c2812011-04-13 23:23:14 +000059
tanjent@gmail.com510b8522011-04-12 15:36:18 +000060 { CityHash64_test, 64, 0x45754A6F, "City64", "Google CityHash128WithSeed" },
61 { CityHash128_test, 128, 0x94B0EF46, "City128", "Google CityHash128WithSeed" },
62
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000063 // MurmurHash2
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000064
tanjent@gmail.com623590d2011-03-28 18:19:31 +000065 { MurmurHash2_test, 32, 0x27864C1E, "Murmur2", "MurmurHash2 for x86, 32-bit" },
66 { MurmurHash2A_test, 32, 0x7FBD4396, "Murmur2A", "MurmurHash2A for x86, 32-bit" },
67 { MurmurHash64A_test, 64, 0x1F0D3804, "Murmur2B", "MurmurHash2 for x64, 64-bit" },
68 { MurmurHash64B_test, 64, 0xDD537C05, "Murmur2C", "MurmurHash2 for x86, 64-bit" },
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000069
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000070 // MurmurHash3
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000071
tanjent@gmail.com2ff5e9b2011-04-03 06:30:51 +000072 { MurmurHash3_x86_32, 32, 0x3252D141, "Murmur3A", "MurmurHash3 for x86, 32-bit" },
tanjent@gmail.com0f37bbd2011-04-04 23:05:26 +000073 { MurmurHash3_x86_128, 128, 0xB3ECE62A, "Murmur3C", "MurmurHash3 for x86, 128-bit" },
tanjent@gmail.com833fd8d2011-04-11 20:45:44 +000074 { MurmurHash3_x64_128, 128, 0x6384BA69, "Murmur3F", "MurmurHash3 for x64, 128-bit" },
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000075
76};
77
aappleby@google.coma27c2812011-04-13 23:23:14 +000078HashInfo * findHash ( const char * name )
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000079{
aappleby@google.coma27c2812011-04-13 23:23:14 +000080 for(size_t i = 0; i < sizeof(g_hashes) / sizeof(HashInfo); i++)
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000081 {
82 if(_stricmp(name,g_hashes[i].name) == 0) return &g_hashes[i];
83 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000084
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000085 return NULL;
86}
87
88//-----------------------------------------------------------------------------
89// Self-test on startup - verify that all installed hashes work correctly.
90
91void SelfTest ( void )
92{
93 bool pass = true;
94
aappleby@google.coma27c2812011-04-13 23:23:14 +000095 for(size_t i = 0; i < sizeof(g_hashes) / sizeof(HashInfo); i++)
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000096 {
97 HashInfo * info = & g_hashes[i];
98
99 pass &= VerificationTest(info->hash,info->hashbits,info->verification,false);
100 }
101
102 if(!pass)
103 {
104 printf("Self-test FAILED!\n");
105
aappleby@google.coma27c2812011-04-13 23:23:14 +0000106 for(size_t i = 0; i < sizeof(g_hashes) / sizeof(HashInfo); i++)
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000107 {
108 HashInfo * info = & g_hashes[i];
aappleby@google.coma27c2812011-04-13 23:23:14 +0000109
tanjent@gmail.com833fd8d2011-04-11 20:45:44 +0000110 printf("%16s - ",info->name);
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000111 pass &= VerificationTest(info->hash,info->hashbits,info->verification,true);
112 }
113
114 exit(1);
115 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000116}
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000117
118//----------------------------------------------------------------------------
119
120template < typename hashtype >
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000121void test ( hashfunc<hashtype> hash, HashInfo * info )
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000122{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000123 const int hashbits = sizeof(hashtype) * 8;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000124
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000125 printf("-------------------------------------------------------------------------------\n");
tanjent@gmail.com2ff5e9b2011-04-03 06:30:51 +0000126 printf("--- Testing %s (%s)\n\n",info->name,info->desc);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000127
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000128 //-----------------------------------------------------------------------------
129 // Sanity tests
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000130
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000131 if(g_testSanity || g_testAll)
132 {
133 printf("[[[ Sanity Tests ]]]\n\n");
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000134
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000135 VerificationTest(hash,hashbits,info->verification,true);
136 SanityTest(hash,hashbits);
137 AppendedZeroesTest(hash,hashbits);
138 printf("\n");
139 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000140
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000141 //-----------------------------------------------------------------------------
142 // Speed tests
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000143
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000144 if(g_testSpeed || g_testAll)
145 {
146 printf("[[[ Speed Tests ]]]\n\n");
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000147
aappleby@google.com7f20a312011-03-21 20:55:06 +0000148 BulkSpeedTest(info->hash,info->verification);
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000149 printf("\n");
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000150
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000151 for(int i = 1; i < 32; i++)
152 {
153 double cycles;
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000154
aappleby@google.com7f20a312011-03-21 20:55:06 +0000155 TinySpeedTest(hashfunc<hashtype>(info->hash),sizeof(hashtype),i,info->verification,true,cycles);
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000156 }
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000157
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000158 printf("\n");
159 }
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000160
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000161 //-----------------------------------------------------------------------------
162 // Differential tests
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000163
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000164 if(g_testDiff || g_testAll)
165 {
166 printf("[[[ Differential Tests ]]]\n\n");
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000167
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000168 bool result = true;
169 bool dumpCollisions = false;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000170
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000171 result &= DiffTest< Blob<64>, hashtype >(hash,5,1000,dumpCollisions);
172 result &= DiffTest< Blob<128>, hashtype >(hash,4,1000,dumpCollisions);
173 result &= DiffTest< Blob<256>, hashtype >(hash,3,1000,dumpCollisions);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000174
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000175 if(!result) printf("*********FAIL*********\n");
176 printf("\n");
177 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000178
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000179 //-----------------------------------------------------------------------------
tanjent@gmail.com623590d2011-03-28 18:19:31 +0000180 // Differential-distribution tests
181
182 if(g_testDiffDist /*|| g_testAll*/)
183 {
184 printf("[[[ Differential Distribution Tests ]]]\n\n");
185
186 bool result = true;
187
188 result &= DiffDistTest2<uint64_t,hashtype>(hash);
189
190 printf("\n");
191 }
192
193 //-----------------------------------------------------------------------------
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000194 // Avalanche tests
aappleby@google.coma27c2812011-04-13 23:23:14 +0000195
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000196 if(g_testAvalanche || g_testAll)
197 {
198 printf("[[[ Avalanche Tests ]]]\n\n");
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000199
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000200 bool result = true;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000201
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000202 result &= AvalancheTest< Blob< 32>, hashtype > (hash,300000);
203 result &= AvalancheTest< Blob< 40>, hashtype > (hash,300000);
204 result &= AvalancheTest< Blob< 48>, hashtype > (hash,300000);
205 result &= AvalancheTest< Blob< 56>, hashtype > (hash,300000);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000206
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000207 result &= AvalancheTest< Blob< 64>, hashtype > (hash,300000);
208 result &= AvalancheTest< Blob< 72>, hashtype > (hash,300000);
209 result &= AvalancheTest< Blob< 80>, hashtype > (hash,300000);
210 result &= AvalancheTest< Blob< 88>, hashtype > (hash,300000);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000211
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000212 result &= AvalancheTest< Blob< 96>, hashtype > (hash,300000);
213 result &= AvalancheTest< Blob<104>, hashtype > (hash,300000);
214 result &= AvalancheTest< Blob<112>, hashtype > (hash,300000);
215 result &= AvalancheTest< Blob<120>, hashtype > (hash,300000);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000216
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000217 result &= AvalancheTest< Blob<128>, hashtype > (hash,300000);
218 result &= AvalancheTest< Blob<136>, hashtype > (hash,300000);
219 result &= AvalancheTest< Blob<144>, hashtype > (hash,300000);
220 result &= AvalancheTest< Blob<152>, hashtype > (hash,300000);
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000221
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000222 if(!result) printf("*********FAIL*********\n");
223 printf("\n");
224 }
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000225
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000226 //-----------------------------------------------------------------------------
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000227 // Bit Independence Criteria. Interesting, but doesn't tell us much about
228 // collision or distribution.
tanjent@gmail.com623590d2011-03-28 18:19:31 +0000229
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000230 if(g_testBIC)
tanjent@gmail.com623590d2011-03-28 18:19:31 +0000231 {
232 printf("[[[ Bit Independence Criteria ]]]\n\n");
233
234 bool result = true;
235
236 //result &= BicTest<uint64_t,hashtype>(hash,2000000);
237 BicTest3<Blob<88>,hashtype>(hash,2000000);
238
239 if(!result) printf("*********FAIL*********\n");
240 printf("\n");
241 }
242
243 //-----------------------------------------------------------------------------
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000244 // Keyset 'Cyclic' - keys of the form "abcdabcdabcd..."
tanjent@gmail.com2aa29c32011-03-19 08:53:53 +0000245
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000246 if(g_testCyclic || g_testAll)
247 {
248 printf("[[[ Keyset 'Cyclic' Tests ]]]\n\n");
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000249
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000250 bool result = true;
251 bool drawDiagram = false;
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000252
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000253 result &= CyclicKeyTest<hashtype>(hash,sizeof(hashtype)+0,8,10000000,drawDiagram);
254 result &= CyclicKeyTest<hashtype>(hash,sizeof(hashtype)+1,8,10000000,drawDiagram);
255 result &= CyclicKeyTest<hashtype>(hash,sizeof(hashtype)+2,8,10000000,drawDiagram);
256 result &= CyclicKeyTest<hashtype>(hash,sizeof(hashtype)+3,8,10000000,drawDiagram);
257 result &= CyclicKeyTest<hashtype>(hash,sizeof(hashtype)+4,8,10000000,drawDiagram);
aappleby@google.coma27c2812011-04-13 23:23:14 +0000258
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000259 if(!result) printf("*********FAIL*********\n");
260 printf("\n");
261 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000262
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000263 //-----------------------------------------------------------------------------
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000264 // Keyset 'TwoBytes' - all keys up to N bytes containing two non-zero bytes
tanjent@gmail.com96601f22011-03-31 02:41:29 +0000265
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000266 // This generates some huge keysets, 128-bit tests will take ~1.3 gigs of RAM.
267
268 if(g_testTwoBytes || g_testAll)
tanjent@gmail.com96601f22011-03-31 02:41:29 +0000269 {
270 printf("[[[ Keyset 'TwoBytes' Tests ]]]\n\n");
271
272 bool result = true;
273 bool drawDiagram = false;
274
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000275 for(int i = 4; i <= 20; i += 4)
276 {
277 result &= TwoBytesTest2<hashtype>(hash,i,drawDiagram);
278 }
tanjent@gmail.com96601f22011-03-31 02:41:29 +0000279
280 if(!result) printf("*********FAIL*********\n");
281 printf("\n");
282 }
283
284 //-----------------------------------------------------------------------------
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000285 // Keyset 'Sparse' - keys with all bits 0 except a few
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000286
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000287 if(g_testSparse || g_testAll)
288 {
289 printf("[[[ Keyset 'Sparse' Tests ]]]\n\n");
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000290
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000291 bool result = true;
292 bool drawDiagram = false;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000293
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000294 result &= SparseKeyTest< 32,hashtype>(hash,6,true,true,true,drawDiagram);
295 result &= SparseKeyTest< 40,hashtype>(hash,6,true,true,true,drawDiagram);
296 result &= SparseKeyTest< 48,hashtype>(hash,5,true,true,true,drawDiagram);
297 result &= SparseKeyTest< 56,hashtype>(hash,5,true,true,true,drawDiagram);
298 result &= SparseKeyTest< 64,hashtype>(hash,5,true,true,true,drawDiagram);
aappleby@google.coma27c2812011-04-13 23:23:14 +0000299 result &= SparseKeyTest< 96,hashtype>(hash,4,true,true,true,drawDiagram);
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000300 result &= SparseKeyTest< 256,hashtype>(hash,3,true,true,true,drawDiagram);
301 result &= SparseKeyTest<2048,hashtype>(hash,2,true,true,true,drawDiagram);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000302
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000303 if(!result) printf("*********FAIL*********\n");
304 printf("\n");
305 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000306
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000307 //-----------------------------------------------------------------------------
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000308 // Keyset 'Permutation' - all possible combinations of a set of blocks
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000309
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000310 if(g_testPermutation || g_testAll)
311 {
312 {
313 // This one breaks lookup3, surprisingly
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000314
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000315 printf("[[[ Keyset 'Combination Lowbits' Tests ]]]\n\n");
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000316
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000317 bool result = true;
318 bool drawDiagram = false;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000319
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000320 uint32_t blocks[] =
321 {
aappleby@google.coma27c2812011-04-13 23:23:14 +0000322 0x00000000,
323
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000324 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007,
325 };
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000326
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000327 result &= CombinationKeyTest<hashtype>(hash,8,blocks,sizeof(blocks) / sizeof(uint32_t),true,true,drawDiagram);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000328
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000329 if(!result) printf("*********FAIL*********\n");
330 printf("\n");
331 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000332
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000333 {
334 printf("[[[ Keyset 'Combination Highbits' Tests ]]]\n\n");
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000335
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000336 bool result = true;
337 bool drawDiagram = false;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000338
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000339 uint32_t blocks[] =
340 {
aappleby@google.coma27c2812011-04-13 23:23:14 +0000341 0x00000000,
342
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000343 0x20000000, 0x40000000, 0x60000000, 0x80000000, 0xA0000000, 0xC0000000, 0xE0000000
344 };
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000345
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000346 result &= CombinationKeyTest<hashtype>(hash,8,blocks,sizeof(blocks) / sizeof(uint32_t),true,true,drawDiagram);
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000347
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000348 if(!result) printf("*********FAIL*********\n");
349 printf("\n");
350 }
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000351
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000352 {
353 printf("[[[ Keyset 'Combination 0x8000000' Tests ]]]\n\n");
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000354
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000355 bool result = true;
356 bool drawDiagram = false;
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000357
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000358 uint32_t blocks[] =
359 {
aappleby@google.coma27c2812011-04-13 23:23:14 +0000360 0x00000000,
361
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000362 0x80000000,
363 };
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000364
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000365 result &= CombinationKeyTest<hashtype>(hash,20,blocks,sizeof(blocks) / sizeof(uint32_t),true,true,drawDiagram);
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000366
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000367 if(!result) printf("*********FAIL*********\n");
368 printf("\n");
369 }
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000370
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000371 {
372 printf("[[[ Keyset 'Combination 0x0000001' Tests ]]]\n\n");
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000373
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000374 bool result = true;
375 bool drawDiagram = false;
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000376
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000377 uint32_t blocks[] =
378 {
aappleby@google.coma27c2812011-04-13 23:23:14 +0000379 0x00000000,
380
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000381 0x00000001,
382 };
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000383
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000384 result &= CombinationKeyTest<hashtype>(hash,20,blocks,sizeof(blocks) / sizeof(uint32_t),true,true,drawDiagram);
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000385
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000386 if(!result) printf("*********FAIL*********\n");
387 printf("\n");
388 }
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000389
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000390 {
391 printf("[[[ Keyset 'Combination Hi-Lo' Tests ]]]\n\n");
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000392
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000393 bool result = true;
394 bool drawDiagram = false;
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000395
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000396 uint32_t blocks[] =
397 {
aappleby@google.coma27c2812011-04-13 23:23:14 +0000398 0x00000000,
399
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000400 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007,
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000401
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000402 0x80000000, 0x40000000, 0xC0000000, 0x20000000, 0xA0000000, 0x60000000, 0xE0000000
403 };
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000404
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000405 result &= CombinationKeyTest<hashtype>(hash,6,blocks,sizeof(blocks) / sizeof(uint32_t),true,true,drawDiagram);
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000406
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000407 if(!result) printf("*********FAIL*********\n");
408 printf("\n");
409 }
410 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000411
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000412 //-----------------------------------------------------------------------------
413 // Keyset 'Window'
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000414
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000415 // Skip distribution test for these - they're too easy to distribute well,
416 // and it generates a _lot_ of testing
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000417
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000418 if(g_testWindow || g_testAll)
419 {
420 printf("[[[ Keyset 'Window' Tests ]]]\n\n");
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000421
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000422 bool result = true;
423 bool testCollision = true;
424 bool testDistribution = false;
425 bool drawDiagram = false;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000426
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000427 result &= WindowedKeyTest< Blob<hashbits*2>, hashtype > ( hash, 20, testCollision, testDistribution, drawDiagram );
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000428
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000429 if(!result) printf("*********FAIL*********\n");
430 printf("\n");
431 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000432
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000433 //-----------------------------------------------------------------------------
434 // Keyset 'Text'
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000435
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000436 if(g_testText || g_testAll)
437 {
438 printf("[[[ Keyset 'Text' Tests ]]]\n\n");
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000439
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000440 bool result = true;
441 bool drawDiagram = false;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000442
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000443 const char * alnum = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000444
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000445 result &= TextKeyTest( hash, "Foo", alnum,4, "Bar", drawDiagram );
446 result &= TextKeyTest( hash, "FooBar", alnum,4, "", drawDiagram );
447 result &= TextKeyTest( hash, "", alnum,4, "FooBar", drawDiagram );
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000448
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000449 if(!result) printf("*********FAIL*********\n");
450 printf("\n");
451 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000452
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000453 //-----------------------------------------------------------------------------
454 // Keyset 'Zeroes'
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000455
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000456 if(g_testZeroes || g_testAll)
457 {
458 printf("[[[ Keyset 'Zeroes' Tests ]]]\n\n");
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000459
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000460 bool result = true;
461 bool drawDiagram = false;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000462
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000463 result &= ZeroKeyTest<hashtype>( hash, drawDiagram );
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000464
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000465 if(!result) printf("*********FAIL*********\n");
466 printf("\n");
467 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000468
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000469 //-----------------------------------------------------------------------------
470 // Keyset 'Seed'
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000471
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000472 if(g_testSeed || g_testAll)
473 {
474 printf("[[[ Keyset 'Seed' Tests ]]]\n\n");
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000475
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000476 bool result = true;
477 bool drawDiagram = false;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000478
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000479 result &= SeedTest<hashtype>( hash, 1000000, drawDiagram );
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000480
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000481 if(!result) printf("*********FAIL*********\n");
482 printf("\n");
483 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000484}
485
486//-----------------------------------------------------------------------------
487
aappleby@google.com7f20a312011-03-21 20:55:06 +0000488uint32_t g_inputVCode = 1;
489uint32_t g_outputVCode = 1;
490uint32_t g_resultVCode = 1;
491
492HashInfo * g_hashUnderTest = NULL;
493
494void VerifyHash ( const void * key, int len, uint32_t seed, void * out )
495{
496 g_inputVCode = MurmurOAAT(key,len,g_inputVCode);
497 g_inputVCode = MurmurOAAT(&seed,sizeof(uint32_t),g_inputVCode);
aappleby@google.coma27c2812011-04-13 23:23:14 +0000498
aappleby@google.com7f20a312011-03-21 20:55:06 +0000499 g_hashUnderTest->hash(key,len,seed,out);
aappleby@google.coma27c2812011-04-13 23:23:14 +0000500
aappleby@google.com7f20a312011-03-21 20:55:06 +0000501 g_outputVCode = MurmurOAAT(out,g_hashUnderTest->hashbits/8,g_outputVCode);
502}
503
504//-----------------------------------------------------------------------------
505
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000506void testHash ( const char * name )
507{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000508 HashInfo * pInfo = findHash(name);
aappleby@google.coma27c2812011-04-13 23:23:14 +0000509
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000510 if(pInfo == NULL)
511 {
512 printf("Invalid hash '%s' specified\n",name);
513 return;
514 }
515 else
516 {
aappleby@google.com7f20a312011-03-21 20:55:06 +0000517 g_hashUnderTest = pInfo;
518
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000519 if(pInfo->hashbits == 32)
520 {
aappleby@google.com7f20a312011-03-21 20:55:06 +0000521 test<uint32_t>( VerifyHash, pInfo );
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000522 }
523 else if(pInfo->hashbits == 64)
524 {
525 test<uint64_t>( pInfo->hash, pInfo );
526 }
527 else if(pInfo->hashbits == 128)
528 {
529 test<uint128_t>( pInfo->hash, pInfo );
530 }
531 else if(pInfo->hashbits == 256)
532 {
533 test<uint256_t>( pInfo->hash, pInfo );
534 }
535 else
536 {
537 printf("Invalid hash bit width %d for hash '%s'",pInfo->hashbits,pInfo->name);
538 }
539 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000540}
541//-----------------------------------------------------------------------------
542
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000543int main ( int argc, char ** argv )
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000544{
tanjent@gmail.com2ff5e9b2011-04-03 06:30:51 +0000545 const char * hashToTest = "murmur3a";
tanjent@gmail.com623590d2011-03-28 18:19:31 +0000546
aappleby@google.com7f20a312011-03-21 20:55:06 +0000547 if(argc < 2)
548 {
tanjent@gmail.com623590d2011-03-28 18:19:31 +0000549 printf("(No test hash given on command line, testing Murmur3_x86_32.)\n");
550 }
551 else
552 {
553 hashToTest = argv[1];
aappleby@google.com7f20a312011-03-21 20:55:06 +0000554 }
aappleby@google.coma27c2812011-04-13 23:23:14 +0000555
tanjent@gmail.com97150532011-04-04 23:29:25 +0000556 // Code runs on the 3rd CPU by default
557
558 SetAffinity((1 << 2));
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000559
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000560 SelfTest();
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000561
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000562 int timeBegin = clock();
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000563
tanjent@gmail.com623590d2011-03-28 18:19:31 +0000564 g_testAll = true;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000565
tanjent@gmail.com623590d2011-03-28 18:19:31 +0000566 //g_testSanity = true;
567 //g_testSpeed = true;
aappleby@google.com7f20a312011-03-21 20:55:06 +0000568 //g_testAvalanche = true;
tanjent@gmail.com623590d2011-03-28 18:19:31 +0000569 //g_testBIC = true;
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000570 //g_testCyclic = true;
tanjent@gmail.com96601f22011-03-31 02:41:29 +0000571 //g_testTwoBytes = true;
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000572 //g_testDiff = true;
tanjent@gmail.com623590d2011-03-28 18:19:31 +0000573 //g_testDiffDist = true;
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000574 //g_testSparse = true;
575 //g_testPermutation = true;
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000576 //g_testWindow = true;
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000577 //g_testZeroes = true;
tanjent@gmail.com31a9e8e2010-11-09 20:29:19 +0000578
tanjent@gmail.com623590d2011-03-28 18:19:31 +0000579 testHash(hashToTest);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000580
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000581 //----------
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000582
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000583 int timeEnd = clock();
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000584
tanjent@gmail.com2aa29c32011-03-19 08:53:53 +0000585 printf("\n");
aappleby@google.com7f20a312011-03-21 20:55:06 +0000586 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 +0000587 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 +0000588 printf("-------------------------------------------------------------------------------\n");
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000589 return 0;
tanjent@gmail.com2aa29c32011-03-19 08:53:53 +0000590}