blob: 4106641a56e712e01ce0326ffb4da2e07a1298aa [file] [log] [blame]
Shih-wei Liao5460a1f2012-03-16 22:41:16 -07001//===- 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
15using namespace std;
16using namespace mcld;
17using namespace mcldtest;
18
19
20// Constructor can do set-up work for all test here.
21HashTableTest::HashTableTest()
22{
23}
24
25// Destructor can do clean-up work that doesn't throw exceptions here.
26HashTableTest::~HashTableTest()
27{
28}
29
30// SetUp() will be called immediately before each test.
31void HashTableTest::SetUp()
32{
33}
34
35// TearDown() will be called immediately after each test.
36void HashTableTest::TearDown()
37{
38}
39
40//==========================================================================//
41// Testcases
42//
43struct IntCompare
44{
45 bool operator()(int X, int Y) const
46 { return (X==Y); }
47};
48
49struct PtrCompare
50{
51 bool operator()(const int* X, const int* Y) const
52 { return (X==Y); }
53};
54
55struct PtrHash
56{
57 size_t operator()(const int* pKey) const
58 {
59 return (unsigned((uintptr_t)pKey) >> 4) ^
60 (unsigned((uintptr_t)pKey) >> 9);
61 }
62};
63
64struct IntHash
65{
66 size_t operator()(int pKey) const
67 { return pKey; }
68};
69
70struct IntMod3Hash
71{
72 size_t operator()(int pKey) const
73 { return pKey % 3; }
74};
75
76TEST_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
97TEST_F( HashTableTest, constructor ) {
98 typedef HashEntry<int, int, IntCompare> HashEntryType;
99 HashTable<HashEntryType, IntHash, EntryFactory<HashEntryType> > hashTable(16);
100 EXPECT_EQ(17, hashTable.numOfBuckets());
101 EXPECT_TRUE(hashTable.empty());
102 EXPECT_EQ(0, hashTable.numOfEntries());
103}
104
105TEST_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
122TEST_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 (unsigned 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_EQ(key, entry->key());
135 entry->setValue(key+10);
136 }
137
138 EXPECT_FALSE(hashTable->empty());
139 EXPECT_EQ(100, hashTable->numOfEntries());
140 EXPECT_EQ(197, hashTable->numOfBuckets());
141 delete hashTable;
142}
143
144TEST_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
169TEST_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 int count;
183 HashTableTy::iterator iter;
184 for (unsigned int key=0; key<100; ++key) {
185 iter = hashTable->find(key);
186 EXPECT_TRUE(iter == hashTable->end());
187 }
188
189 EXPECT_TRUE(hashTable->empty());
190 delete hashTable;
191}
192
193TEST_F( HashTableTest, tombstone ) {
194 typedef HashEntry<int, int, IntCompare> HashEntryType;
195 typedef HashTable<HashEntryType, IntMod3Hash, EntryFactory<HashEntryType> > HashTableTy;
196 HashTableTy *hashTable = new HashTableTy();
197
198 bool exist;
199 HashTableTy::entry_type* entry = 0;
200 for (unsigned int key=0; key<100; ++key) {
201 entry = hashTable->insert(key, exist);
202 }
203 EXPECT_FALSE(hashTable->empty());
204
205 int count;
206 HashTableTy::iterator iter;
207 for (unsigned int key=0; key<20; ++key) {
208 count = hashTable->erase(key);
209 EXPECT_EQ(1, count);
210 iter = hashTable->find(key);
211 EXPECT_TRUE(iter == hashTable->end());
212 }
213 EXPECT_EQ(80, hashTable->numOfEntries());
214
215 for (unsigned int key=20; key<100; ++key) {
216 iter = hashTable->find(key);
217 EXPECT_TRUE(iter != hashTable->end());
218 }
219
220 for (unsigned int key=0; key<20; ++key) {
221 entry = hashTable->insert(key, exist);
222 }
223 EXPECT_EQ(100, hashTable->numOfEntries());
224 EXPECT_EQ(197, hashTable->numOfBuckets());
225
226 delete hashTable;
227}
228
229TEST_F( HashTableTest, rehash_test ) {
230 typedef HashEntry<int, int, IntCompare> HashEntryType;
231 typedef HashTable<HashEntryType, IntHash, EntryFactory<HashEntryType> > HashTableTy;
232 HashTableTy *hashTable = new HashTableTy(0);
233
234 bool exist;
235 HashTableTy::entry_type* entry = 0;
236 for (unsigned int key=0; key<400000; ++key) {
237 entry = hashTable->insert(key, exist);
238 entry->setValue(key+10);
239 }
240
241 HashTableTy::iterator iter;
242 for (unsigned int key=0; key<400000; ++key) {
243 iter = hashTable->find(key);
244 EXPECT_EQ((key+10), iter.getEntry()->value());
245 }
246
247 delete hashTable;
248}
249
250TEST_F( HashTableTest, bucket_iterator ) {
251 typedef HashEntry<int, int, IntCompare> HashEntryType;
252 typedef HashTable<HashEntryType, IntHash, EntryFactory<HashEntryType> > HashTableTy;
253 HashTableTy *hashTable = new HashTableTy(0);
254
255 bool exist;
256 HashTableTy::entry_type* entry = 0;
257 for (unsigned int key=0; key<400000; ++key) {
258 entry = hashTable->insert(key, exist);
259 entry->setValue(key+10);
260 }
261
262 HashTableTy::iterator iter, iEnd = hashTable->end();
263 unsigned int counter = 0;
264 for (iter = hashTable->begin(); iter != iEnd; ++iter) {
265 EXPECT_EQ(iter.getEntry()->key()+10, iter.getEntry()->value());
266 ++counter;
267 }
268 EXPECT_EQ(400000, counter);
269 delete hashTable;
270}
271
272
273TEST_F( HashTableTest, chain_iterator_single ) {
274 typedef HashEntry<int, int, IntCompare> HashEntryType;
275 typedef HashTable<HashEntryType, IntHash, EntryFactory<HashEntryType> > HashTableTy;
276 HashTableTy *hashTable = new HashTableTy();
277
278 bool exist;
279 HashTableTy::entry_type* entry = 0;
280 for (unsigned int key=0; key<16; ++key) {
281 entry = hashTable->insert(key*37, exist);
282 entry->setValue(key+10);
283 }
284 for (unsigned int key=0; key<16; ++key) {
285 unsigned int counter = 0;
286 HashTableTy::chain_iterator iter, iEnd = hashTable->end(key*37);
287 for (iter = hashTable->begin(key*37); iter != iEnd; ++iter) {
288 EXPECT_EQ(key+10, iter.getEntry()->value());
289 ++counter;
290 }
291 EXPECT_EQ(1, counter);
292 }
293 delete hashTable;
294}
295
296struct FixHash
297{
298 size_t operator()(int pKey) const {
299 return 10;
300 }
301};
302
303
304TEST_F( HashTableTest, chain_iterator_list ) {
305 typedef HashEntry<int, int, IntCompare> HashEntryType;
306 typedef HashTable<HashEntryType, FixHash, EntryFactory<HashEntryType> > HashTableTy;
307 HashTableTy *hashTable = new HashTableTy();
308
309 bool exist;
310 HashTableTy::entry_type* entry = 0;
311 for (unsigned int key=0; key<16; ++key) {
312 entry = hashTable->insert(key, exist);
313 ASSERT_FALSE(exist);
314 entry->setValue(key);
315 }
316 ASSERT_EQ(16, hashTable->numOfEntries());
317 ASSERT_EQ(37, hashTable->numOfBuckets());
318
319 unsigned int key = 0;
320 unsigned int count = 0;
321 HashTableTy::chain_iterator iter, iEnd = hashTable->end(key);
322 for (iter = hashTable->begin(key); iter != iEnd; ++iter) {
323 count++;
324 }
325 ASSERT_EQ(16, count);
326 delete hashTable;
327}