1 //===- HashTableTest.cpp --------------------------------------------------===//
2 //
3 // The MCLinker Project
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "HashTableTest.h"
11 #include "mcld/ADT/HashEntry.h"
12 #include "mcld/ADT/HashTable.h"
13 #include <cstdlib>
14
15 using namespace std;
16 using namespace mcld;
17 using namespace mcldtest;
18
19
20 // Constructor can do set-up work for all test here.
HashTableTest()21 HashTableTest::HashTableTest()
22 {
23 }
24
25 // Destructor can do clean-up work that doesn't throw exceptions here.
~HashTableTest()26 HashTableTest::~HashTableTest()
27 {
28 }
29
30 // SetUp() will be called immediately before each test.
SetUp()31 void HashTableTest::SetUp()
32 {
33 }
34
35 // TearDown() will be called immediately after each test.
TearDown()36 void HashTableTest::TearDown()
37 {
38 }
39
40 //==========================================================================//
41 // Testcases
42 //
43 struct IntCompare
44 {
operator ()IntCompare45 bool operator()(int X, int Y) const
46 { return (X==Y); }
47 };
48
49 struct PtrCompare
50 {
operator ()PtrCompare51 bool operator()(const int* X, const int* Y) const
52 { return (X==Y); }
53 };
54
55 struct PtrHash
56 {
operator ()PtrHash57 size_t operator()(const int* pKey) const
58 {
59 return (unsigned((uintptr_t)pKey) >> 4) ^
60 (unsigned((uintptr_t)pKey) >> 9);
61 }
62 };
63
64 struct IntHash
65 {
operator ()IntHash66 size_t operator()(int pKey) const
67 { return pKey; }
68 };
69
70 struct IntMod3Hash
71 {
operator ()IntMod3Hash72 size_t operator()(int pKey) const
73 { return pKey % 3; }
74 };
75
TEST_F(HashTableTest,ptr_entry)76 TEST_F( HashTableTest, ptr_entry ) {
77 int A = 1;
78 int* pA = &A;
79
80 typedef HashEntry<int*, int, PtrCompare> HashEntryType;
81 typedef HashTable<HashEntryType, PtrHash, EntryFactory<HashEntryType> > HashTableTy;
82 HashTableTy *hashTable = new HashTableTy(0);
83
84 bool exist;
85 HashTableTy::entry_type* entry = 0;
86
87 entry = hashTable->insert(pA, exist);
88
89 EXPECT_FALSE(hashTable->empty());
90
91 HashTableTy::iterator iter;
92 iter = hashTable->find(NULL);
93 EXPECT_TRUE(iter==hashTable->end());
94 delete hashTable;
95 }
96
TEST_F(HashTableTest,constructor)97 TEST_F( HashTableTest, constructor ) {
98 typedef HashEntry<int, int, IntCompare> HashEntryType;
99 HashTable<HashEntryType, IntHash, EntryFactory<HashEntryType> > hashTable(16);
100 EXPECT_TRUE(17 == hashTable.numOfBuckets());
101 EXPECT_TRUE(hashTable.empty());
102 EXPECT_TRUE(0 == hashTable.numOfEntries());
103 }
104
TEST_F(HashTableTest,allocattion)105 TEST_F( HashTableTest, allocattion ) {
106 typedef HashEntry<int, int, IntCompare> HashEntryType;
107 typedef HashTable<HashEntryType, IntHash, EntryFactory<HashEntryType> > HashTableTy;
108 HashTableTy *hashTable = new HashTableTy(22);
109
110 bool exist;
111 int key = 100;
112 HashTableTy::entry_type* val = hashTable->insert(key, exist);
113 val->setValue(999);
114 EXPECT_FALSE(hashTable->empty());
115 EXPECT_FALSE(exist);
116 EXPECT_FALSE(NULL == val);
117 HashTableTy::iterator entry = hashTable->find(key);
118 EXPECT_EQ(999, entry.getEntry()->value());
119 delete hashTable;
120 }
121
TEST_F(HashTableTest,alloc100)122 TEST_F( HashTableTest, alloc100 ) {
123 typedef HashEntry<int, int, IntCompare> HashEntryType;
124 typedef HashTable<HashEntryType, IntHash, EntryFactory<HashEntryType> > HashTableTy;
125 HashTableTy *hashTable = new HashTableTy(22);
126
127 bool exist;
128 HashTableTy::entry_type* entry = 0;
129 for (int key=0; key<100; ++key) {
130 entry = hashTable->insert(key, exist);
131 EXPECT_FALSE(hashTable->empty());
132 EXPECT_FALSE(exist);
133 EXPECT_FALSE(NULL == entry);
134 EXPECT_TRUE(key == entry->key());
135 entry->setValue(key+10);
136 }
137
138 EXPECT_FALSE(hashTable->empty());
139 EXPECT_TRUE(100 == hashTable->numOfEntries());
140 EXPECT_TRUE(197 == hashTable->numOfBuckets());
141 delete hashTable;
142 }
143
TEST_F(HashTableTest,erase100)144 TEST_F( HashTableTest, erase100 ) {
145 typedef HashEntry<int, int, IntCompare> HashEntryType;
146 typedef HashTable<HashEntryType, IntHash, EntryFactory<HashEntryType> > HashTableTy;
147 HashTableTy *hashTable = new HashTableTy(0);
148
149 bool exist;
150 HashTableTy::entry_type* entry = 0;
151 for (unsigned int key=0; key<100; ++key)
152 entry = hashTable->insert(key, exist);
153
154 EXPECT_FALSE(hashTable->empty());
155
156 int count;
157 HashTableTy::iterator iter;
158 for (unsigned int key=0; key<100; ++key) {
159 count = hashTable->erase(key);
160 EXPECT_EQ(1, count);
161 iter = hashTable->find(key);
162 EXPECT_TRUE(iter == hashTable->end());
163 }
164
165 EXPECT_TRUE(hashTable->empty());
166 delete hashTable;
167 }
168
TEST_F(HashTableTest,clear)169 TEST_F( HashTableTest, clear) {
170 typedef HashEntry<int, int, IntCompare> HashEntryType;
171 typedef HashTable<HashEntryType, IntHash, EntryFactory<HashEntryType> > HashTableTy;
172 HashTableTy *hashTable = new HashTableTy(22);
173
174 bool exist;
175 HashTableTy::entry_type* entry = 0;
176 for (unsigned int key=0; key<100; ++key) {
177 entry = hashTable->insert(key, exist);
178 }
179
180 hashTable->clear();
181
182 HashTableTy::iterator iter;
183 for (unsigned int key=0; key<100; ++key) {
184 iter = hashTable->find(key);
185 EXPECT_TRUE(iter == hashTable->end());
186 }
187
188 EXPECT_TRUE(hashTable->empty());
189 delete hashTable;
190 }
191
TEST_F(HashTableTest,tombstone)192 TEST_F( HashTableTest, tombstone ) {
193 typedef HashEntry<int, int, IntCompare> HashEntryType;
194 typedef HashTable<HashEntryType, IntMod3Hash, EntryFactory<HashEntryType> > HashTableTy;
195 HashTableTy *hashTable = new HashTableTy();
196
197 bool exist;
198 HashTableTy::entry_type* entry = 0;
199 for (unsigned int key=0; key<100; ++key) {
200 entry = hashTable->insert(key, exist);
201 }
202 EXPECT_FALSE(hashTable->empty());
203
204 int count;
205 HashTableTy::iterator iter;
206 for (unsigned int key=0; key<20; ++key) {
207 count = hashTable->erase(key);
208 EXPECT_EQ(1, count);
209 iter = hashTable->find(key);
210 EXPECT_TRUE(iter == hashTable->end());
211 }
212 EXPECT_TRUE(80 == hashTable->numOfEntries());
213
214 for (unsigned int key=20; key<100; ++key) {
215 iter = hashTable->find(key);
216 EXPECT_TRUE(iter != hashTable->end());
217 }
218
219 for (unsigned int key=0; key<20; ++key) {
220 entry = hashTable->insert(key, exist);
221 }
222 EXPECT_TRUE(100 == hashTable->numOfEntries());
223 EXPECT_TRUE(197 == hashTable->numOfBuckets());
224
225 delete hashTable;
226 }
227
TEST_F(HashTableTest,rehash_test)228 TEST_F( HashTableTest, rehash_test ) {
229 typedef HashEntry<int, int, IntCompare> HashEntryType;
230 typedef HashTable<HashEntryType, IntHash, EntryFactory<HashEntryType> > HashTableTy;
231 HashTableTy *hashTable = new HashTableTy(0);
232
233 bool exist;
234 HashTableTy::entry_type* entry = 0;
235 for (unsigned int key=0; key<400000; ++key) {
236 entry = hashTable->insert(key, exist);
237 entry->setValue(key+10);
238 }
239
240 HashTableTy::iterator iter;
241 for (int key=0; key<400000; ++key) {
242 iter = hashTable->find(key);
243 EXPECT_EQ((key+10), iter.getEntry()->value());
244 }
245
246 delete hashTable;
247 }
248
TEST_F(HashTableTest,bucket_iterator)249 TEST_F( HashTableTest, bucket_iterator ) {
250 typedef HashEntry<int, int, IntCompare> HashEntryType;
251 typedef HashTable<HashEntryType, IntHash, EntryFactory<HashEntryType> > HashTableTy;
252 HashTableTy *hashTable = new HashTableTy(0);
253
254 bool exist;
255 HashTableTy::entry_type* entry = 0;
256 for (unsigned int key=0; key<400000; ++key) {
257 entry = hashTable->insert(key, exist);
258 entry->setValue(key+10);
259 }
260
261 HashTableTy::iterator iter, iEnd = hashTable->end();
262 int counter = 0;
263 for (iter = hashTable->begin(); iter != iEnd; ++iter) {
264 EXPECT_EQ(iter.getEntry()->key()+10, iter.getEntry()->value());
265 ++counter;
266 }
267 EXPECT_EQ(400000, counter);
268 delete hashTable;
269 }
270
271
TEST_F(HashTableTest,chain_iterator_single)272 TEST_F( HashTableTest, chain_iterator_single ) {
273 typedef HashEntry<int, int, IntCompare> HashEntryType;
274 typedef HashTable<HashEntryType, IntHash, EntryFactory<HashEntryType> > HashTableTy;
275 HashTableTy *hashTable = new HashTableTy();
276
277 bool exist;
278 HashTableTy::entry_type* entry = 0;
279 for (int key=0; key<16; ++key) {
280 entry = hashTable->insert(key*37, exist);
281 entry->setValue(key+10);
282 }
283 for (int key=0; key<16; ++key) {
284 int counter = 0;
285 HashTableTy::chain_iterator iter, iEnd = hashTable->end(key*37);
286 for (iter = hashTable->begin(key*37); iter != iEnd; ++iter) {
287 EXPECT_EQ(key+10, iter.getEntry()->value());
288 ++counter;
289 }
290 EXPECT_EQ(1, counter);
291 }
292 delete hashTable;
293 }
294
295 struct FixHash
296 {
operator ()FixHash297 size_t operator()(int pKey) const {
298 return 10;
299 }
300 };
301
302
TEST_F(HashTableTest,chain_iterator_list)303 TEST_F( HashTableTest, chain_iterator_list ) {
304 typedef HashEntry<int, int, IntCompare> HashEntryType;
305 typedef HashTable<HashEntryType, FixHash, EntryFactory<HashEntryType> > HashTableTy;
306 HashTableTy *hashTable = new HashTableTy();
307
308 bool exist;
309 HashTableTy::entry_type* entry = 0;
310 for (unsigned int key=0; key<16; ++key) {
311 entry = hashTable->insert(key, exist);
312 ASSERT_FALSE(exist);
313 entry->setValue(key);
314 }
315 ASSERT_TRUE(16 == hashTable->numOfEntries());
316 ASSERT_TRUE(37 == hashTable->numOfBuckets());
317
318 unsigned int key = 0;
319 int count = 0;
320 HashTableTy::chain_iterator iter, iEnd = hashTable->end(key);
321 for (iter = hashTable->begin(key); iter != iEnd; ++iter) {
322 count++;
323 }
324 ASSERT_EQ(16, count);
325 delete hashTable;
326 }
327