blob: 1f4e4793fc9b4f9aade50f32e17920d8afa336a1 [file] [log] [blame]
Talin1a4b19e2012-02-18 21:00:49 +00001//===- llvm/unittest/ADT/HashingTest.cpp ----------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Hashing.h unit tests.
11//
12//===----------------------------------------------------------------------===//
13
14#include "gtest/gtest.h"
15#include "llvm/ADT/Hashing.h"
Chandler Carruth0b66c6f2012-03-01 18:55:25 +000016#include "llvm/Support/DataTypes.h"
17#include <deque>
18#include <list>
19#include <map>
20#include <vector>
21
22namespace llvm {
23
24// Helper for test code to print hash codes.
25void PrintTo(const hash_code &code, std::ostream *os) {
26 *os << static_cast<size_t>(code);
27}
28
29// Fake an object that is recognized as hashable data to test super large
30// objects.
31struct LargeTestInteger { uint64_t arr[8]; };
32
33namespace hashing {
34namespace detail {
35template <> struct is_hashable_data<LargeTestInteger> : true_type {};
36} // namespace detail
37} // namespace hashing
38
39} // namespace llvm
Talin1a4b19e2012-02-18 21:00:49 +000040
41using namespace llvm;
42
43namespace {
44
Chandler Carruth0b66c6f2012-03-01 18:55:25 +000045TEST(HashingTest, HashValueBasicTest) {
46 int x = 42, y = 43, c = 'x';
47 void *p = 0;
48 uint64_t i = 71;
49 const unsigned ci = 71;
50 volatile int vi = 71;
51 const volatile int cvi = 71;
52 uintptr_t addr = reinterpret_cast<uintptr_t>(&y);
53 EXPECT_EQ(hash_value(42), hash_value(x));
54 EXPECT_NE(hash_value(42), hash_value(y));
55 EXPECT_NE(hash_value(42), hash_value(p));
56 EXPECT_NE(hash_code::get_null_code(), hash_value(p));
57 EXPECT_EQ(hash_value(71), hash_value(i));
58 EXPECT_EQ(hash_value(71), hash_value(ci));
59 EXPECT_EQ(hash_value(71), hash_value(vi));
60 EXPECT_EQ(hash_value(71), hash_value(cvi));
61 EXPECT_EQ(hash_value(c), hash_value('x'));
62 EXPECT_EQ(hash_value('4'), hash_value('0' + 4));
63 EXPECT_EQ(hash_value(addr), hash_value(&y));
Talin1a4b19e2012-02-18 21:00:49 +000064}
65
Chandler Carruth0b66c6f2012-03-01 18:55:25 +000066template <typename T, size_t N> T *begin(T (&arr)[N]) { return arr; }
67template <typename T, size_t N> T *end(T (&arr)[N]) { return arr + N; }
68
69// Provide a dummy, hashable type designed for easy verification: its hash is
70// the same as its value.
71struct HashableDummy { size_t value; };
72hash_code hash_value(HashableDummy dummy) { return dummy.value; }
73
74TEST(HashingTest, HashCombineRangeBasicTest) {
75 // Leave this uninitialized in the hope that valgrind will catch bad reads.
76 int dummy;
77 hash_code dummy_hash = hash_combine_range(&dummy, &dummy);
78 EXPECT_NE(hash_code::get_null_code(), dummy_hash);
79 EXPECT_NE(hash_code::get_invalid_code(), dummy_hash);
80
81 const int arr1[] = { 1, 2, 3 };
82 hash_code arr1_hash = hash_combine_range(begin(arr1), end(arr1));
83 EXPECT_NE(hash_code::get_null_code(), arr1_hash);
84 EXPECT_NE(hash_code::get_invalid_code(), arr1_hash);
85 EXPECT_NE(dummy_hash, arr1_hash);
86 EXPECT_EQ(arr1_hash, hash_combine_range(begin(arr1), end(arr1)));
87
88 const std::vector<int> vec(begin(arr1), end(arr1));
89 EXPECT_EQ(arr1_hash, hash_combine_range(vec.begin(), vec.end()));
90
91 const std::list<int> list(begin(arr1), end(arr1));
92 EXPECT_EQ(arr1_hash, hash_combine_range(list.begin(), list.end()));
93
94 const std::deque<int> deque(begin(arr1), end(arr1));
95 EXPECT_EQ(arr1_hash, hash_combine_range(deque.begin(), deque.end()));
96
97 const int arr2[] = { 3, 2, 1 };
98 hash_code arr2_hash = hash_combine_range(begin(arr2), end(arr2));
99 EXPECT_NE(hash_code::get_null_code(), arr2_hash);
100 EXPECT_NE(hash_code::get_invalid_code(), arr2_hash);
101 EXPECT_NE(dummy_hash, arr2_hash);
102 EXPECT_NE(arr1_hash, arr2_hash);
103
104 const int arr3[] = { 1, 1, 2, 3 };
105 hash_code arr3_hash = hash_combine_range(begin(arr3), end(arr3));
106 EXPECT_NE(hash_code::get_null_code(), arr3_hash);
107 EXPECT_NE(hash_code::get_invalid_code(), arr3_hash);
108 EXPECT_NE(dummy_hash, arr3_hash);
109 EXPECT_NE(arr1_hash, arr3_hash);
110
111 const int arr4[] = { 1, 2, 3, 3 };
112 hash_code arr4_hash = hash_combine_range(begin(arr4), end(arr4));
113 EXPECT_NE(hash_code::get_null_code(), arr4_hash);
114 EXPECT_NE(hash_code::get_invalid_code(), arr4_hash);
115 EXPECT_NE(dummy_hash, arr4_hash);
116 EXPECT_NE(arr1_hash, arr4_hash);
117
118 const size_t arr5[] = { 1, 2, 3 };
119 const HashableDummy d_arr5[] = { {1}, {2}, {3} };
120 hash_code arr5_hash = hash_combine_range(begin(arr5), end(arr5));
121 hash_code d_arr5_hash = hash_combine_range(begin(d_arr5), end(d_arr5));
122 EXPECT_EQ(arr5_hash, d_arr5_hash);
Talin1a4b19e2012-02-18 21:00:49 +0000123}
124
Chandler Carruth0b66c6f2012-03-01 18:55:25 +0000125TEST(HashingTest, HashCombineRangeLengthDiff) {
126 // Test that as only the length varies, we compute different hash codes for
127 // sequences.
128 std::map<size_t, size_t> code_to_size;
129 std::vector<char> all_one_c(256, '\xff');
130 for (unsigned Idx = 1, Size = all_one_c.size(); Idx < Size; ++Idx) {
131 hash_code code = hash_combine_range(&all_one_c[0], &all_one_c[0] + Idx);
132 std::map<size_t, size_t>::iterator
133 I = code_to_size.insert(std::make_pair(code, Idx)).first;
134 EXPECT_EQ(Idx, I->second);
135 }
136 code_to_size.clear();
137 std::vector<char> all_zero_c(256, '\0');
138 for (unsigned Idx = 1, Size = all_zero_c.size(); Idx < Size; ++Idx) {
139 hash_code code = hash_combine_range(&all_zero_c[0], &all_zero_c[0] + Idx);
140 std::map<size_t, size_t>::iterator
141 I = code_to_size.insert(std::make_pair(code, Idx)).first;
142 EXPECT_EQ(Idx, I->second);
143 }
144 code_to_size.clear();
145 std::vector<unsigned> all_one_int(512, -1);
146 for (unsigned Idx = 1, Size = all_one_int.size(); Idx < Size; ++Idx) {
147 hash_code code = hash_combine_range(&all_one_int[0], &all_one_int[0] + Idx);
148 std::map<size_t, size_t>::iterator
149 I = code_to_size.insert(std::make_pair(code, Idx)).first;
150 EXPECT_EQ(Idx, I->second);
151 }
152 code_to_size.clear();
153 std::vector<unsigned> all_zero_int(512, 0);
154 for (unsigned Idx = 1, Size = all_zero_int.size(); Idx < Size; ++Idx) {
155 hash_code code = hash_combine_range(&all_zero_int[0], &all_zero_int[0] + Idx);
156 std::map<size_t, size_t>::iterator
157 I = code_to_size.insert(std::make_pair(code, Idx)).first;
158 EXPECT_EQ(Idx, I->second);
159 }
Talin1a4b19e2012-02-18 21:00:49 +0000160}
161
Chandler Carruth0b66c6f2012-03-01 18:55:25 +0000162TEST(HashingTest, HashCombineRangeGoldenTest) {
163 struct { const char *s; uint64_t hash; } golden_data[] = {
164 { "a", 0xaeb6f9d5517c61f8ULL },
165 { "ab", 0x7ab1edb96be496b4ULL },
166 { "abc", 0xe38e60bf19c71a3fULL },
167 { "abcde", 0xd24461a66de97f6eULL },
168 { "abcdefgh", 0x4ef872ec411dec9dULL },
169 { "abcdefghijklm", 0xe8a865539f4eadfeULL },
170 { "abcdefghijklmnopqrstu", 0x261cdf85faaf4e79ULL },
171 { "abcdefghijklmnopqrstuvwxyzabcdef", 0x43ba70e4198e3b2aULL },
172 { "abcdefghijklmnopqrstuvwxyzabcdef"
173 "abcdefghijklmnopqrstuvwxyzghijkl"
174 "abcdefghijklmnopqrstuvwxyzmnopqr"
175 "abcdefghijklmnopqrstuvwxyzstuvwx"
176 "abcdefghijklmnopqrstuvwxyzyzabcd", 0xdcd57fb2afdf72beULL },
177 { "a", 0xaeb6f9d5517c61f8ULL },
178 { "aa", 0xf2b3b69a9736a1ebULL },
179 { "aaa", 0xf752eb6f07b1cafeULL },
180 { "aaaaa", 0x812bd21e1236954cULL },
181 { "aaaaaaaa", 0xff07a2cff08ac587ULL },
182 { "aaaaaaaaaaaaa", 0x84ac949d54d704ecULL },
183 { "aaaaaaaaaaaaaaaaaaaaa", 0xcb2c8fb6be8f5648ULL },
184 { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0xcc40ab7f164091b6ULL },
185 { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
186 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
187 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
188 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
189 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0xc58e174c1e78ffe9ULL },
190 { "z", 0x1ba160d7e8f8785cULL },
191 { "zz", 0x2c5c03172f1285d7ULL },
192 { "zzz", 0x9d2c4f4b507a2ac3ULL },
193 { "zzzzz", 0x0f03b9031735693aULL },
194 { "zzzzzzzz", 0xe674147c8582c08eULL },
195 { "zzzzzzzzzzzzz", 0x3162d9fa6938db83ULL },
196 { "zzzzzzzzzzzzzzzzzzzzz", 0x37b9a549e013620cULL },
197 { "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz", 0x8921470aff885016ULL },
198 { "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
199 "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
200 "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
201 "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
202 "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz", 0xf60fdcd9beb08441ULL },
203 { "a", 0xaeb6f9d5517c61f8ULL },
204 { "ab", 0x7ab1edb96be496b4ULL },
205 { "aba", 0x3edb049950884d0aULL },
206 { "ababa", 0x8f2de9e73a97714bULL },
207 { "abababab", 0xee14a29ddf0ce54cULL },
208 { "ababababababa", 0x38b3ddaada2d52b4ULL },
209 { "ababababababababababa", 0xd3665364219f2b85ULL },
210 { "abababababababababababababababab"
211 "abababababababababababababababab"
212 "abababababababababababababababab"
213 "abababababababababababababababab"
214 "abababababababababababababababab", 0x840192d129f7a22bULL }
215 };
216 for (unsigned i = 0; i < sizeof(golden_data)/sizeof(*golden_data); ++i) {
217 StringRef str = golden_data[i].s;
218 hash_code hash = hash_combine_range(str.begin(), str.end());
219#if 0 // Enable this to generate paste-able text for the above structure.
220 std::string member_str = "\"" + str.str() + "\",";
221 fprintf(stderr, " { %-35s 0x%016lxULL },\n",
222 member_str.c_str(), (size_t)hash);
223#endif
224 EXPECT_EQ(static_cast<size_t>(golden_data[i].hash),
225 static_cast<size_t>(hash));
226 }
Talin1a4b19e2012-02-18 21:00:49 +0000227}
228
Chandler Carruth0b66c6f2012-03-01 18:55:25 +0000229TEST(HashingTest, HashCombineBasicTest) {
230 // Hashing a sequence of homogenous types matches range hashing.
231 const int i1 = 42, i2 = 43, i3 = 123, i4 = 999, i5 = 0, i6 = 79;
232 const int arr1[] = { i1, i2, i3, i4, i5, i6 };
233 EXPECT_EQ(hash_combine_range(arr1, arr1 + 1), hash_combine(i1));
234 EXPECT_EQ(hash_combine_range(arr1, arr1 + 2), hash_combine(i1, i2));
235 EXPECT_EQ(hash_combine_range(arr1, arr1 + 3), hash_combine(i1, i2, i3));
236 EXPECT_EQ(hash_combine_range(arr1, arr1 + 4), hash_combine(i1, i2, i3, i4));
237 EXPECT_EQ(hash_combine_range(arr1, arr1 + 5),
238 hash_combine(i1, i2, i3, i4, i5));
239 EXPECT_EQ(hash_combine_range(arr1, arr1 + 6),
240 hash_combine(i1, i2, i3, i4, i5, i6));
Talin1a4b19e2012-02-18 21:00:49 +0000241
Chandler Carruth0b66c6f2012-03-01 18:55:25 +0000242 // Hashing a sequence of heterogenous types which *happen* to all produce the
243 // same data for hashing produces the same as a range-based hash of the
244 // fundamental values.
245 const size_t s1 = 1024, s2 = 8888, s3 = 9000000;
246 const HashableDummy d1 = { 1024 }, d2 = { 8888 }, d3 = { 9000000 };
247 const size_t arr2[] = { s1, s2, s3 };
248 EXPECT_EQ(hash_combine_range(begin(arr2), end(arr2)),
249 hash_combine(s1, s2, s3));
250 EXPECT_EQ(hash_combine(s1, s2, s3), hash_combine(s1, s2, d3));
251 EXPECT_EQ(hash_combine(s1, s2, s3), hash_combine(s1, d2, s3));
252 EXPECT_EQ(hash_combine(s1, s2, s3), hash_combine(d1, s2, s3));
253 EXPECT_EQ(hash_combine(s1, s2, s3), hash_combine(d1, d2, s3));
254 EXPECT_EQ(hash_combine(s1, s2, s3), hash_combine(d1, d2, d3));
255
256 // Permuting values causes hashes to change.
257 EXPECT_NE(hash_combine(i1, i1, i1), hash_combine(i1, i1, i2));
258 EXPECT_NE(hash_combine(i1, i1, i1), hash_combine(i1, i2, i1));
259 EXPECT_NE(hash_combine(i1, i1, i1), hash_combine(i2, i1, i1));
260 EXPECT_NE(hash_combine(i1, i1, i1), hash_combine(i2, i2, i1));
261 EXPECT_NE(hash_combine(i1, i1, i1), hash_combine(i2, i2, i2));
262 EXPECT_NE(hash_combine(i2, i1, i1), hash_combine(i1, i1, i2));
263 EXPECT_NE(hash_combine(i1, i1, i2), hash_combine(i1, i2, i1));
264 EXPECT_NE(hash_combine(i1, i2, i1), hash_combine(i2, i1, i1));
265
266 // Changing type w/o changing value causes hashes to change.
267 EXPECT_NE(hash_combine(i1, i2, i3), hash_combine((char)i1, i2, i3));
268 EXPECT_NE(hash_combine(i1, i2, i3), hash_combine(i1, (char)i2, i3));
269 EXPECT_NE(hash_combine(i1, i2, i3), hash_combine(i1, i2, (char)i3));
270
271 // This is array of uint64, but it should have the exact same byte pattern as
272 // an array of LargeTestIntegers.
273 const uint64_t bigarr[] = {
274 0xaaaaaaaaababababULL, 0xacacacacbcbcbcbcULL, 0xccddeeffeeddccbbULL,
275 0xdeadbeafdeadbeefULL, 0xfefefefededededeULL, 0xafafafafededededULL,
276 0xffffeeeeddddccccULL, 0xaaaacbcbffffababULL,
277 0xaaaaaaaaababababULL, 0xacacacacbcbcbcbcULL, 0xccddeeffeeddccbbULL,
278 0xdeadbeafdeadbeefULL, 0xfefefefededededeULL, 0xafafafafededededULL,
279 0xffffeeeeddddccccULL, 0xaaaacbcbffffababULL,
280 0xaaaaaaaaababababULL, 0xacacacacbcbcbcbcULL, 0xccddeeffeeddccbbULL,
281 0xdeadbeafdeadbeefULL, 0xfefefefededededeULL, 0xafafafafededededULL,
282 0xffffeeeeddddccccULL, 0xaaaacbcbffffababULL
283 };
284 // Hash a preposterously large integer, both aligned with the buffer and
285 // misaligned.
286 const LargeTestInteger li = { {
287 0xaaaaaaaaababababULL, 0xacacacacbcbcbcbcULL, 0xccddeeffeeddccbbULL,
288 0xdeadbeafdeadbeefULL, 0xfefefefededededeULL, 0xafafafafededededULL,
289 0xffffeeeeddddccccULL, 0xaaaacbcbffffababULL
290 } };
291 // Rotate the storage from 'li'.
292 const LargeTestInteger l2 = { {
293 0xacacacacbcbcbcbcULL, 0xccddeeffeeddccbbULL, 0xdeadbeafdeadbeefULL,
294 0xfefefefededededeULL, 0xafafafafededededULL, 0xffffeeeeddddccccULL,
295 0xaaaacbcbffffababULL, 0xaaaaaaaaababababULL
296 } };
297 const LargeTestInteger l3 = { {
298 0xccddeeffeeddccbbULL, 0xdeadbeafdeadbeefULL, 0xfefefefededededeULL,
299 0xafafafafededededULL, 0xffffeeeeddddccccULL, 0xaaaacbcbffffababULL,
300 0xaaaaaaaaababababULL, 0xacacacacbcbcbcbcULL
301 } };
302 EXPECT_EQ(hash_combine_range(begin(bigarr), end(bigarr)),
303 hash_combine(li, li, li));
304 EXPECT_EQ(hash_combine_range(bigarr, bigarr + 9),
305 hash_combine(bigarr[0], l2));
306 EXPECT_EQ(hash_combine_range(bigarr, bigarr + 10),
307 hash_combine(bigarr[0], bigarr[1], l3));
308 EXPECT_EQ(hash_combine_range(bigarr, bigarr + 17),
309 hash_combine(li, bigarr[0], l2));
310 EXPECT_EQ(hash_combine_range(bigarr, bigarr + 18),
311 hash_combine(li, bigarr[0], bigarr[1], l3));
312 EXPECT_EQ(hash_combine_range(bigarr, bigarr + 18),
313 hash_combine(bigarr[0], l2, bigarr[9], l3));
314 EXPECT_EQ(hash_combine_range(bigarr, bigarr + 20),
315 hash_combine(bigarr[0], l2, bigarr[9], l3, bigarr[18], bigarr[19]));
Talin1a4b19e2012-02-18 21:00:49 +0000316}
317
318}