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. 21 HashTableTest::HashTableTest() 22 { 23 } 24 25 // Destructor can do clean-up work that doesn't throw exceptions here. 26 HashTableTest::~HashTableTest() 27 { 28 } 29 30 // SetUp() will be called immediately before each test. 31 void HashTableTest::SetUp() 32 { 33 } 34 35 // TearDown() will be called immediately after each test. 36 void HashTableTest::TearDown() 37 { 38 } 39 40 //==========================================================================// 41 // Testcases 42 // 43 struct IntCompare 44 { 45 bool operator()(int X, int Y) const 46 { return (X==Y); } 47 }; 48 49 struct PtrCompare 50 { 51 bool operator()(const int* X, const int* Y) const 52 { return (X==Y); } 53 }; 54 55 struct 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 64 struct IntHash 65 { 66 size_t operator()(int pKey) const 67 { return pKey; } 68 }; 69 70 struct IntMod3Hash 71 { 72 size_t operator()(int pKey) const 73 { return pKey % 3; } 74 }; 75 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 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 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 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 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 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 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 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 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 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 { 297 size_t operator()(int pKey) const { 298 return 10; 299 } 300 }; 301 302 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