blob: 695ccb8a31c2f5ff54af0764eedd9eb970b8c92d [file] [log] [blame]
//===- 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;
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;
for (unsigned int key = 0; key < 100; ++key)
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;
for (unsigned int key = 0; key < 100; ++key) {
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;
for (unsigned int key = 0; key < 100; ++key) {
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) {
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;
}