blob: 6519f8b84b52c6fb75030a0ade7b738fe1e11fa6 [file] [log] [blame]
tanjent@gmail.comad4b3632010-11-05 01:20:58 +00001#include "KeysetTest.h"
2
3#include "Random.h"
4
5//-----------------------------------------------------------------------------
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +00006// This should hopefully be a thorough and uambiguous test of whether a hash
7// is correctly implemented on a given platform
tanjent@gmail.comad4b3632010-11-05 01:20:58 +00008
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +00009bool VerificationTest ( pfHash hash, const int hashbits, uint32_t expected, bool verbose )
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000010{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000011 const int hashbytes = hashbits / 8;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000012
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000013 uint8_t * key = new uint8_t[256];
14 uint8_t * hashes = new uint8_t[hashbytes * 256];
15 uint8_t * final = new uint8_t[hashbytes];
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000016
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000017 memset(key,0,256);
18 memset(hashes,0,hashbytes*256);
19 memset(final,0,hashbytes);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000020
tanjent@gmail.com623590d2011-03-28 18:19:31 +000021 // Hash keys of the form {0}, {0,1}, {0,1,2}... up to N=255,using 256-N as
22 // the seed
23
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000024 for(int i = 0; i < 256; i++)
25 {
26 key[i] = (uint8_t)i;
tanjent@gmail.com623590d2011-03-28 18:19:31 +000027
28 hash(key,i,256-i,&hashes[i*hashbytes]);
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000029 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000030
tanjent@gmail.com623590d2011-03-28 18:19:31 +000031 // Then hash the result array
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000032
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000033 hash(hashes,hashbytes*256,0,final);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000034
tanjent@gmail.com623590d2011-03-28 18:19:31 +000035 // The first four bytes of that hash, interpreted as a little-endian integer, is our
36 // verification value
37
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000038 uint32_t verification = (final[0] << 0) | (final[1] << 8) | (final[2] << 16) | (final[3] << 24);
39
40 delete [] key;
41 delete [] hashes;
42 delete [] final;
43
44 //----------
45
46 if(expected != verification)
47 {
48 if(verbose) printf("Verification value 0x%08X : Failed! (Expected 0x%08x)\n",verification,expected);
49 return false;
50 }
51 else
52 {
53 if(verbose) printf("Verification value 0x%08X : Passed!\n",verification);
54 return true;
55 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000056}
57
58//----------------------------------------------------------------------------
tanjent@gmail.combabb5532011-02-28 06:03:12 +000059// Basic sanity checks -
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000060
tanjent@gmail.combabb5532011-02-28 06:03:12 +000061// A hash function should not be reading outside the bounds of the key.
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000062
tanjent@gmail.combabb5532011-02-28 06:03:12 +000063// Flipping a bit of a key should, with overwhelmingly high probability,
64// result in a different hash.
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000065
tanjent@gmail.combabb5532011-02-28 06:03:12 +000066// Hashing the same key twice should always produce the same result.
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000067
tanjent@gmail.combabb5532011-02-28 06:03:12 +000068// The memory alignment of the key should not affect the hash result.
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000069
tanjent@gmail.combabb5532011-02-28 06:03:12 +000070bool SanityTest ( pfHash hash, const int hashbits )
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000071{
72 printf("Running sanity check 1");
aappleby@google.com7f20a312011-03-21 20:55:06 +000073
74 Rand r(883741);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000075
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000076 bool result = true;
tanjent@gmail.com9d17d0b2010-11-17 04:07:51 +000077
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000078 const int hashbytes = hashbits/8;
79 const int reps = 10;
80 const int keymax = 128;
81 const int pad = 16;
82 const int buflen = keymax + pad*3;
83
84 uint8_t * buffer1 = new uint8_t[buflen];
85 uint8_t * buffer2 = new uint8_t[buflen];
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000086
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000087 uint8_t * hash1 = new uint8_t[hashbytes];
88 uint8_t * hash2 = new uint8_t[hashbytes];
tanjent@gmail.combabb5532011-02-28 06:03:12 +000089
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000090 //----------
91
92 for(int irep = 0; irep < reps; irep++)
93 {
94 if(irep % (reps/10) == 0) printf(".");
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000095
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000096 for(int len = 4; len <= keymax; len++)
97 {
98 for(int offset = pad; offset < pad*2; offset++)
99 {
100 uint8_t * key1 = &buffer1[pad];
101 uint8_t * key2 = &buffer2[pad+offset];
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000102
aappleby@google.com7f20a312011-03-21 20:55:06 +0000103 r.rand_p(buffer1,buflen);
104 r.rand_p(buffer2,buflen);
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000105
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000106 memcpy(key2,key1,len);
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000107
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000108 hash(key1,len,0,hash1);
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000109
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000110 for(int bit = 0; bit < (len * 8); bit++)
111 {
112 // Flip a bit, hash the key -> we should get a different result.
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000113
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000114 flipbit(key2,len,bit);
115 hash(key2,len,0,hash2);
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000116
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000117 if(memcmp(hash1,hash2,hashbytes) == 0)
118 {
119 result = false;
120 }
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000121
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000122 // Flip it back, hash again -> we should get the original result.
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000123
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000124 flipbit(key2,len,bit);
125 hash(key2,len,0,hash2);
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000126
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000127 if(memcmp(hash1,hash2,hashbytes) != 0)
128 {
129 result = false;
130 }
131 }
132 }
133 }
134 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000135
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000136 if(result == false)
137 {
138 printf("*********FAIL*********\n");
139 }
140 else
141 {
142 printf("PASS\n");
143 }
tanjent@gmail.com9d17d0b2010-11-17 04:07:51 +0000144
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000145 delete [] hash1;
146 delete [] hash2;
tanjent@gmail.combabb5532011-02-28 06:03:12 +0000147
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000148 return result;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000149}
150
151//----------------------------------------------------------------------------
152// Appending zero bytes to a key should always cause it to produce a different
153// hash value
154
155void AppendedZeroesTest ( pfHash hash, const int hashbits )
156{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000157 printf("Running sanity check 2");
aappleby@google.com7f20a312011-03-21 20:55:06 +0000158
159 Rand r(173994);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000160
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000161 const int hashbytes = hashbits/8;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000162
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000163 for(int rep = 0; rep < 100; rep++)
164 {
165 if(rep % 10 == 0) printf(".");
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000166
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000167 unsigned char key[256];
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000168
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000169 memset(key,0,sizeof(key));
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000170
aappleby@google.com7f20a312011-03-21 20:55:06 +0000171 r.rand_p(key,32);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000172
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000173 uint32_t h1[16];
174 uint32_t h2[16];
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000175
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000176 memset(h1,0,hashbytes);
177 memset(h2,0,hashbytes);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000178
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000179 for(int i = 0; i < 32; i++)
180 {
181 hash(key,32+i,0,h1);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000182
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000183 if(memcmp(h1,h2,hashbytes) == 0)
184 {
185 printf("\n*********FAIL*********\n");
186 return;
187 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000188
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000189 memcpy(h2,h1,hashbytes);
190 }
191 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000192
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000193 printf("PASS\n");
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000194}
195
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000196//-----------------------------------------------------------------------------