TestHash.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Copyright (c) Electronic Arts Inc. All rights reserved.
  3. ///////////////////////////////////////////////////////////////////////////////
  4. #include <EABase/eabase.h>
  5. #include <EAStdC/EAHashString.h>
  6. #include <EAStdC/EAHashCRC.h>
  7. #include <EAStdC/EABitTricks.h>
  8. #include <EAStdCTest/EAStdCTest.h>
  9. #include <EATest/EATest.h>
  10. #if defined(_MSC_VER)
  11. #pragma warning(disable: 6211) // Leaking memory due to an exception. Consider using a local catch block to clean up memory.
  12. #endif
  13. static int TestHashString()
  14. {
  15. using namespace EA::StdC;
  16. int nErrorCount(0);
  17. // GCC 2.x fails due to compiler bugs.
  18. #if (!defined(__GNUC__) || (__GNUC__ >= 3))
  19. { // Test CTStringHash
  20. char stringArray[] = "01234567890123456789012345678901234567890";
  21. uint32_t nCTHashArray[33];
  22. nCTHashArray[0] = CTStringHash<0>::value;
  23. nCTHashArray[1] = CTStringHash<'0'>::value;
  24. nCTHashArray[2] = CTStringHash<'0', '1'>::value;
  25. nCTHashArray[3] = CTStringHash<'0', '1', '2'>::value;
  26. nCTHashArray[4] = CTStringHash<'0', '1', '2', '3'>::value;
  27. nCTHashArray[5] = CTStringHash<'0', '1', '2', '3', '4'>::value;
  28. nCTHashArray[6] = CTStringHash<'0', '1', '2', '3', '4', '5'>::value;
  29. nCTHashArray[7] = CTStringHash<'0', '1', '2', '3', '4', '5', '6'>::value;
  30. nCTHashArray[8] = CTStringHash<'0', '1', '2', '3', '4', '5', '6', '7'>::value;
  31. nCTHashArray[9] = CTStringHash<'0', '1', '2', '3', '4', '5', '6', '7', '8'>::value;
  32. nCTHashArray[10] = CTStringHash<'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'>::value;
  33. nCTHashArray[11] = CTStringHash<'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'>::value;
  34. nCTHashArray[12] = CTStringHash<'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1'>::value;
  35. nCTHashArray[13] = CTStringHash<'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2'>::value;
  36. nCTHashArray[14] = CTStringHash<'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3'>::value;
  37. nCTHashArray[15] = CTStringHash<'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4'>::value;
  38. nCTHashArray[16] = CTStringHash<'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5'>::value;
  39. nCTHashArray[17] = CTStringHash<'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6'>::value;
  40. nCTHashArray[18] = CTStringHash<'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7'>::value;
  41. nCTHashArray[19] = CTStringHash<'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8'>::value;
  42. nCTHashArray[20] = CTStringHash<'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'>::value;
  43. nCTHashArray[21] = CTStringHash<'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'>::value;
  44. nCTHashArray[22] = CTStringHash<'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1'>::value;
  45. nCTHashArray[23] = CTStringHash<'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2'>::value;
  46. nCTHashArray[24] = CTStringHash<'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3'>::value;
  47. nCTHashArray[25] = CTStringHash<'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4'>::value;
  48. nCTHashArray[26] = CTStringHash<'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5'>::value;
  49. nCTHashArray[27] = CTStringHash<'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6'>::value;
  50. nCTHashArray[28] = CTStringHash<'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7'>::value;
  51. nCTHashArray[29] = CTStringHash<'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8'>::value;
  52. nCTHashArray[30] = CTStringHash<'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'>::value;
  53. nCTHashArray[31] = CTStringHash<'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'>::value;
  54. nCTHashArray[32] = CTStringHash<'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1'>::value;
  55. for(int i = 31; i >= 0; i--)
  56. {
  57. stringArray[i] = 0;
  58. const uint32_t nHashFNV1 = FNV1_String8(stringArray);
  59. EATEST_VERIFY(nHashFNV1 == nCTHashArray[i]);
  60. }
  61. }
  62. #endif
  63. return nErrorCount;
  64. }
  65. int TestHash()
  66. {
  67. using namespace EA::StdC;
  68. int nErrorCount(0);
  69. EA::UnitTest::Report("TestHash\n");
  70. const int kDataLength(16384); // We intentionally choose a power of 2.
  71. EATEST_VERIFY((kDataLength % 8) == 0); // Code below depends on this.
  72. uint8_t* pDataA = new uint8_t[kDataLength];
  73. uint8_t* pDataB = new uint8_t[kDataLength];
  74. char8_t* pData8A = new char8_t[kDataLength];
  75. char8_t* pData8B = new char8_t[kDataLength];
  76. char16_t* pData16A = new char16_t[kDataLength];
  77. char16_t* pData16B = new char16_t[kDataLength];
  78. char32_t* pData32A = new char32_t[kDataLength];
  79. char32_t* pData32B = new char32_t[kDataLength];
  80. // Initialize data
  81. for(int i(0); i < kDataLength; i++)
  82. {
  83. const int c = ((i == 0) ? 1 : i);
  84. pDataA[i] = (uint8_t) c;
  85. pDataB[i] = (uint8_t) c;
  86. pData8A[i] = (char8_t) c;
  87. pData8B[i] = (char8_t) c;
  88. pData16A[i] = (char16_t)c;
  89. pData16B[i] = (char16_t)c;
  90. pData32A[i] = (char32_t)c;
  91. pData32B[i] = (char32_t)c;
  92. }
  93. pDataA[kDataLength - 1] = 0;
  94. pDataB[kDataLength - 1] = 0;
  95. pData8A[kDataLength - 1] = 0;
  96. pData8B[kDataLength - 1] = 0;
  97. pData16A[kDataLength - 1] = 0;
  98. pData16B[kDataLength - 1] = 0;
  99. pData32A[kDataLength - 1] = 0;
  100. pData32B[kDataLength - 1] = 0;
  101. { // Test DJB2 string hash
  102. uint32_t nInitialValue(0x12345678);
  103. uint32_t nHashValue(0);
  104. nHashValue = DJB2(pDataA, kDataLength, nInitialValue);
  105. EATEST_VERIFY(nHashValue != 0);
  106. nHashValue = DJB2_String8(pData8A, nInitialValue);
  107. EATEST_VERIFY(nHashValue != 0);
  108. nHashValue = DJB2_String16(pData16A, nInitialValue);
  109. EATEST_VERIFY(nHashValue != 0);
  110. }
  111. { // Test FNV1 string hash
  112. uint32_t nInitialValue(0x12345678);
  113. uint32_t nHashValue(0);
  114. // To do: Come up with better test validation.
  115. nHashValue = FNV1(pDataA, kDataLength, nInitialValue);
  116. EATEST_VERIFY(nHashValue == 0x67f6dbec);
  117. nHashValue = FNV1_String8(pData8A, nInitialValue);
  118. EATEST_VERIFY(nHashValue == 0x70533413);
  119. nHashValue = FNV1_String16(pData16A, nInitialValue);
  120. EATEST_VERIFY(nHashValue == 0xa1014ae4);
  121. nHashValue = FNV1_String32(pData32A, nInitialValue);
  122. EATEST_VERIFY(nHashValue == 0xa1014ae4);
  123. }
  124. { // Test FNV64 string hash
  125. uint64_t nInitialValue(0x12345678);
  126. uint64_t nHashValue(0);
  127. // To do: Come up with better test validation.
  128. nHashValue = FNV64(pDataA, kDataLength, nInitialValue);
  129. EATEST_VERIFY(nHashValue == UINT64_C(0xbe387e6512cbab0c));
  130. nHashValue = FNV64_String8(pData8A, nInitialValue);
  131. EATEST_VERIFY(nHashValue == UINT64_C(0x78b14197ac736ef3));
  132. nHashValue = FNV64_String16(pData16A, nInitialValue);
  133. EATEST_VERIFY(nHashValue == UINT64_C(0xf07159d175cf1dc4));
  134. nHashValue = FNV64_String32(pData32A, nInitialValue);
  135. EATEST_VERIFY(nHashValue == UINT64_C(0xf07159d175cf1dc4));
  136. }
  137. nErrorCount += TestHashString();
  138. { // Test CRC16 binary hash
  139. uint16_t nHashValue1;
  140. uint16_t nHashValue2(kCRC16InitialValue);
  141. // Test one-shot CRC.
  142. nHashValue1 = CRC16(pDataA, kDataLength);
  143. // Test iterative CRC.
  144. for(int i = 0; i < 8; i++)
  145. nHashValue2 = CRC16(pDataA + (i * (kDataLength / 8)), kDataLength / 8, nHashValue2, i == 7);
  146. EATEST_VERIFY(nHashValue1 == nHashValue2);
  147. }
  148. { // Test CRC24 binary hash
  149. uint32_t nHashValue1;
  150. uint32_t nHashValue2(kCRC24InitialValue);
  151. // Test one-shot CRC.
  152. nHashValue1 = CRC24(pDataA, kDataLength);
  153. // Test iterative CRC.
  154. for(int i = 0; i < 8; i++)
  155. nHashValue2 = CRC24(pDataA + (i * (kDataLength / 8)), kDataLength / 8, nHashValue2, i == 7);
  156. EATEST_VERIFY(EA::StdC::GetHighestBitPowerOf2(nHashValue1) <= 24);
  157. EATEST_VERIFY(EA::StdC::GetHighestBitPowerOf2(nHashValue2) <= 24);
  158. EATEST_VERIFY(nHashValue1 == nHashValue2);
  159. }
  160. { // Test CRC32 binary hash
  161. uint32_t nHashValue1;
  162. uint32_t nHashValue2(kCRC32InitialValue);
  163. // Test one-shot CRC.
  164. nHashValue1 = CRC32(pDataA, kDataLength);
  165. // Test iterative CRC.
  166. for(int i = 0; i < 8; i++)
  167. nHashValue2 = CRC32(pDataA + (i * (kDataLength / 8)), kDataLength / 8, nHashValue2, i == 7);
  168. EATEST_VERIFY(nHashValue1 == nHashValue2);
  169. }
  170. { // Test CRC32 big-endian binary hash
  171. uint32_t nHashValue1;
  172. uint32_t nHashValue2(kCRC32InitialValue);
  173. // Test one-shot CRC.
  174. nHashValue1 = CRC32Reverse(pDataA, kDataLength);
  175. // Test iterative CRC.
  176. for(int i = 0; i < 8; i++)
  177. nHashValue2 = CRC32Reverse(pDataA + (i * (kDataLength / 8)), kDataLength / 8, nHashValue2, i == 7);
  178. EATEST_VERIFY(nHashValue1 == nHashValue2);
  179. }
  180. { // Test CRC64 binary hash
  181. uint64_t nHashValue1;
  182. uint64_t nHashValue2(kCRC64InitialValue);
  183. // Test one-shot CRC.
  184. nHashValue1 = CRC64(pDataA, kDataLength);
  185. // Test iterative CRC.
  186. for(int i = 0; i < 8; i++)
  187. nHashValue2 = CRC64(pDataA + (i * (kDataLength / 8)), kDataLength / 8, nHashValue2, i == 7);
  188. EATEST_VERIFY(nHashValue1 == nHashValue2);
  189. }
  190. {
  191. const char a[ 1] = { 'a' };
  192. const char b[ 2] = { 'b', 'c' };
  193. const char c[ 3] = { 'c', 'd', 'e' };
  194. const char d[ 4] = { 'd', 'e', 'f', 'g' };
  195. const char e[ 5] = { 'd', 'e', 'f', 'g', 'h' };
  196. const char h[ 8] = { 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k' };
  197. const char j[10] = { 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm' };
  198. // To do: Establish correct test result values for these.
  199. EATEST_VERIFY(CRC16(a, sizeof(a), 0xfbea, false) == 0x67bb);
  200. EATEST_VERIFY(CRC16(b, sizeof(b), 0xfbea, false) == 0xaa67);
  201. EATEST_VERIFY(CRC16(c, sizeof(c), 0xfbea, false) == 0x3178);
  202. EATEST_VERIFY(CRC16(d, sizeof(d), 0xfbea, false) == 0x8c20);
  203. EATEST_VERIFY(CRC24(a, sizeof(a)) != 0x00000000);
  204. EATEST_VERIFY(CRC24(b, sizeof(b)) != 0x00000000);
  205. EATEST_VERIFY(CRC24(c, sizeof(c)) != 0x00000000);
  206. EATEST_VERIFY(CRC24(d, sizeof(d)) != 0x00000000);
  207. EATEST_VERIFY(CRC32(a, sizeof(a)) != 0x00000000);
  208. EATEST_VERIFY(CRC32(b, sizeof(b)) != 0x00000000);
  209. EATEST_VERIFY(CRC32(c, sizeof(c)) != 0x00000000);
  210. EATEST_VERIFY(CRC32(d, sizeof(d)) != 0x00000000);
  211. EATEST_VERIFY(CRC32Reverse(a, sizeof(a)) != 0x00000000);
  212. EATEST_VERIFY(CRC32Reverse(b, sizeof(b)) != 0x00000000);
  213. EATEST_VERIFY(CRC32Reverse(c, sizeof(c)) != 0x00000000);
  214. EATEST_VERIFY(CRC32Reverse(d, sizeof(d)) != 0x00000000);
  215. EATEST_VERIFY(CRC32Reverse(e, sizeof(e)) != 0x00000000);
  216. EATEST_VERIFY(CRC32Reverse(h, sizeof(h)) != 0x00000000);
  217. EATEST_VERIFY(CRC32Reverse(j, sizeof(j)) != 0x00000000);
  218. EATEST_VERIFY(CRC64(a, sizeof(a)) != 0x00000000);
  219. EATEST_VERIFY(CRC64(b, sizeof(b)) != 0x00000000);
  220. EATEST_VERIFY(CRC64(c, sizeof(c)) != 0x00000000);
  221. EATEST_VERIFY(CRC64(d, sizeof(d)) != 0x00000000);
  222. }
  223. delete[] pDataA;
  224. delete[] pDataB;
  225. delete[] pData8A;
  226. delete[] pData8B;
  227. delete[] pData16A;
  228. delete[] pData16B;
  229. delete[] pData32A;
  230. delete[] pData32B;
  231. return nErrorCount;
  232. }