| //===- HashTableTest.cpp --------------------------------------------------===// |
| // |
| // The MCLinker Project |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "HashTableTest.h" |
| #include "mcld/ADT/HashEntry.h" |
| #include "mcld/ADT/HashTable.h" |
| #include <cstdlib> |
| |
| using namespace std; |
| using namespace mcld; |
| using namespace mcldtest; |
| |
| |
| // Constructor can do set-up work for all test here. |
| HashTableTest::HashTableTest() |
| { |
| } |
| |
| // Destructor can do clean-up work that doesn't throw exceptions here. |
| HashTableTest::~HashTableTest() |
| { |
| } |
| |
| // SetUp() will be called immediately before each test. |
| void HashTableTest::SetUp() |
| { |
| } |
| |
| // TearDown() will be called immediately after each test. |
| void HashTableTest::TearDown() |
| { |
| } |
| |
| //==========================================================================// |
| // Testcases |
| // |
| struct IntCompare |
| { |
| bool operator()(int X, int Y) const |
| { return (X==Y); } |
| }; |
| |
| struct PtrCompare |
| { |
| bool operator()(const int* X, const int* Y) const |
| { return (X==Y); } |
| }; |
| |
| struct PtrHash |
| { |
| size_t operator()(const int* pKey) const |
| { |
| return (unsigned((uintptr_t)pKey) >> 4) ^ |
| (unsigned((uintptr_t)pKey) >> 9); |
| } |
| }; |
| |
| struct IntHash |
| { |
| size_t operator()(int pKey) const |
| { return pKey; } |
| }; |
| |
| struct IntMod3Hash |
| { |
| size_t operator()(int pKey) const |
| { return pKey % 3; } |
| }; |
| |
| TEST_F( HashTableTest, ptr_entry ) { |
| int A = 1; |
| int* pA = &A; |
| |
| typedef HashEntry<int*, int, PtrCompare> HashEntryType; |
| typedef HashTable<HashEntryType, PtrHash, EntryFactory<HashEntryType> > HashTableTy; |
| HashTableTy *hashTable = new HashTableTy(0); |
| |
| bool exist; |
| HashTableTy::entry_type* entry = 0; |
| |
| entry = hashTable->insert(pA, exist); |
| |
| EXPECT_FALSE(hashTable->empty()); |
| |
| HashTableTy::iterator iter; |
| iter = hashTable->find(NULL); |
| EXPECT_TRUE(iter==hashTable->end()); |
| delete hashTable; |
| } |
| |
| TEST_F( HashTableTest, constructor ) { |
| typedef HashEntry<int, int, IntCompare> HashEntryType; |
| HashTable<HashEntryType, IntHash, EntryFactory<HashEntryType> > hashTable(16); |
| EXPECT_TRUE(17 == hashTable.numOfBuckets()); |
| EXPECT_TRUE(hashTable.empty()); |
| EXPECT_TRUE(0 == hashTable.numOfEntries()); |
| } |
| |
| TEST_F( HashTableTest, allocattion ) { |
| typedef HashEntry<int, int, IntCompare> HashEntryType; |
| typedef HashTable<HashEntryType, IntHash, EntryFactory<HashEntryType> > HashTableTy; |
| HashTableTy *hashTable = new HashTableTy(22); |
| |
| bool exist; |
| int key = 100; |
| HashTableTy::entry_type* val = hashTable->insert(key, exist); |
| val->setValue(999); |
| EXPECT_FALSE(hashTable->empty()); |
| EXPECT_FALSE(exist); |
| EXPECT_FALSE(NULL == val); |
| HashTableTy::iterator entry = hashTable->find(key); |
| EXPECT_EQ(999, entry.getEntry()->value()); |
| delete hashTable; |
| } |
| |
| TEST_F( HashTableTest, alloc100 ) { |
| typedef HashEntry<int, int, IntCompare> HashEntryType; |
| typedef HashTable<HashEntryType, IntHash, EntryFactory<HashEntryType> > HashTableTy; |
| HashTableTy *hashTable = new HashTableTy(22); |
| |
| bool exist; |
| HashTableTy::entry_type* entry = 0; |
| for (int key=0; key<100; ++key) { |
| entry = hashTable->insert(key, exist); |
| EXPECT_FALSE(hashTable->empty()); |
| EXPECT_FALSE(exist); |
| EXPECT_FALSE(NULL == entry); |
| EXPECT_TRUE(key == entry->key()); |
| entry->setValue(key+10); |
| } |
| |
| EXPECT_FALSE(hashTable->empty()); |
| EXPECT_TRUE(100 == hashTable->numOfEntries()); |
| EXPECT_TRUE(197 == hashTable->numOfBuckets()); |
| delete hashTable; |
| } |
| |
| TEST_F( HashTableTest, erase100 ) { |
| typedef HashEntry<int, int, IntCompare> HashEntryType; |
| typedef HashTable<HashEntryType, IntHash, EntryFactory<HashEntryType> > HashTableTy; |
| HashTableTy *hashTable = new HashTableTy(0); |
| |
| bool exist; |
| HashTableTy::entry_type* entry = 0; |
| for (unsigned int key=0; key<100; ++key) |
| entry = hashTable->insert(key, exist); |
| |
| EXPECT_FALSE(hashTable->empty()); |
| |
| int count; |
| HashTableTy::iterator iter; |
| for (unsigned int key=0; key<100; ++key) { |
| count = hashTable->erase(key); |
| EXPECT_EQ(1, count); |
| iter = hashTable->find(key); |
| EXPECT_TRUE(iter == hashTable->end()); |
| } |
| |
| EXPECT_TRUE(hashTable->empty()); |
| delete hashTable; |
| } |
| |
| TEST_F( HashTableTest, clear) { |
| typedef HashEntry<int, int, IntCompare> HashEntryType; |
| typedef HashTable<HashEntryType, IntHash, EntryFactory<HashEntryType> > HashTableTy; |
| HashTableTy *hashTable = new HashTableTy(22); |
| |
| bool exist; |
| HashTableTy::entry_type* entry = 0; |
| for (unsigned int key=0; key<100; ++key) { |
| entry = hashTable->insert(key, exist); |
| } |
| |
| hashTable->clear(); |
| |
| HashTableTy::iterator iter; |
| for (unsigned int key=0; key<100; ++key) { |
| iter = hashTable->find(key); |
| EXPECT_TRUE(iter == hashTable->end()); |
| } |
| |
| EXPECT_TRUE(hashTable->empty()); |
| delete hashTable; |
| } |
| |
| TEST_F( HashTableTest, tombstone ) { |
| typedef HashEntry<int, int, IntCompare> HashEntryType; |
| typedef HashTable<HashEntryType, IntMod3Hash, EntryFactory<HashEntryType> > HashTableTy; |
| HashTableTy *hashTable = new HashTableTy(); |
| |
| bool exist; |
| HashTableTy::entry_type* entry = 0; |
| for (unsigned int key=0; key<100; ++key) { |
| entry = hashTable->insert(key, exist); |
| } |
| EXPECT_FALSE(hashTable->empty()); |
| |
| int count; |
| HashTableTy::iterator iter; |
| for (unsigned int key=0; key<20; ++key) { |
| count = hashTable->erase(key); |
| EXPECT_EQ(1, count); |
| iter = hashTable->find(key); |
| EXPECT_TRUE(iter == hashTable->end()); |
| } |
| EXPECT_TRUE(80 == hashTable->numOfEntries()); |
| |
| for (unsigned int key=20; key<100; ++key) { |
| iter = hashTable->find(key); |
| EXPECT_TRUE(iter != hashTable->end()); |
| } |
| |
| for (unsigned int key=0; key<20; ++key) { |
| entry = hashTable->insert(key, exist); |
| } |
| EXPECT_TRUE(100 == hashTable->numOfEntries()); |
| EXPECT_TRUE(197 == hashTable->numOfBuckets()); |
| |
| delete hashTable; |
| } |
| |
| TEST_F( HashTableTest, rehash_test ) { |
| typedef HashEntry<int, int, IntCompare> HashEntryType; |
| typedef HashTable<HashEntryType, IntHash, EntryFactory<HashEntryType> > HashTableTy; |
| HashTableTy *hashTable = new HashTableTy(0); |
| |
| bool exist; |
| HashTableTy::entry_type* entry = 0; |
| for (unsigned int key=0; key<400000; ++key) { |
| entry = hashTable->insert(key, exist); |
| entry->setValue(key+10); |
| } |
| |
| HashTableTy::iterator iter; |
| for (int key=0; key<400000; ++key) { |
| iter = hashTable->find(key); |
| EXPECT_EQ((key+10), iter.getEntry()->value()); |
| } |
| |
| delete hashTable; |
| } |
| |
| TEST_F( HashTableTest, bucket_iterator ) { |
| typedef HashEntry<int, int, IntCompare> HashEntryType; |
| typedef HashTable<HashEntryType, IntHash, EntryFactory<HashEntryType> > HashTableTy; |
| HashTableTy *hashTable = new HashTableTy(0); |
| |
| bool exist; |
| HashTableTy::entry_type* entry = 0; |
| for (unsigned int key=0; key<400000; ++key) { |
| entry = hashTable->insert(key, exist); |
| entry->setValue(key+10); |
| } |
| |
| HashTableTy::iterator iter, iEnd = hashTable->end(); |
| int counter = 0; |
| for (iter = hashTable->begin(); iter != iEnd; ++iter) { |
| EXPECT_EQ(iter.getEntry()->key()+10, iter.getEntry()->value()); |
| ++counter; |
| } |
| EXPECT_EQ(400000, counter); |
| delete hashTable; |
| } |
| |
| |
| TEST_F( HashTableTest, chain_iterator_single ) { |
| typedef HashEntry<int, int, IntCompare> HashEntryType; |
| typedef HashTable<HashEntryType, IntHash, EntryFactory<HashEntryType> > HashTableTy; |
| HashTableTy *hashTable = new HashTableTy(); |
| |
| bool exist; |
| HashTableTy::entry_type* entry = 0; |
| for (int key=0; key<16; ++key) { |
| entry = hashTable->insert(key*37, exist); |
| entry->setValue(key+10); |
| } |
| for (int key=0; key<16; ++key) { |
| int counter = 0; |
| HashTableTy::chain_iterator iter, iEnd = hashTable->end(key*37); |
| for (iter = hashTable->begin(key*37); iter != iEnd; ++iter) { |
| EXPECT_EQ(key+10, iter.getEntry()->value()); |
| ++counter; |
| } |
| EXPECT_EQ(1, counter); |
| } |
| delete hashTable; |
| } |
| |
| struct FixHash |
| { |
| size_t operator()(int pKey) const { |
| return 10; |
| } |
| }; |
| |
| |
| TEST_F( HashTableTest, chain_iterator_list ) { |
| typedef HashEntry<int, int, IntCompare> HashEntryType; |
| typedef HashTable<HashEntryType, FixHash, EntryFactory<HashEntryType> > HashTableTy; |
| HashTableTy *hashTable = new HashTableTy(); |
| |
| bool exist; |
| HashTableTy::entry_type* entry = 0; |
| for (unsigned int key=0; key<16; ++key) { |
| entry = hashTable->insert(key, exist); |
| ASSERT_FALSE(exist); |
| entry->setValue(key); |
| } |
| ASSERT_TRUE(16 == hashTable->numOfEntries()); |
| ASSERT_TRUE(37 == hashTable->numOfBuckets()); |
| |
| unsigned int key = 0; |
| int count = 0; |
| HashTableTy::chain_iterator iter, iEnd = hashTable->end(key); |
| for (iter = hashTable->begin(key); iter != iEnd; ++iter) { |
| count++; |
| } |
| ASSERT_EQ(16, count); |
| delete hashTable; |
| } |