C++程序  |  311行  |  8.42 KB

//===- 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;
}