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