Refactor Kernel Util tests
Change-Id: I4f5dbc664a621cdba3d928f2f358a73a07b71aa1 Reviewed-on: https://review.haiku-os.org/c/haiku/+/10671 Tested-by: Commit checker robot <[email protected]> Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
@@ -1,32 +1,23 @@
|
||||
#include <AVLTreeMapTest.h>
|
||||
#include <cppunit/Test.h>
|
||||
#include <cppunit/TestCaller.h>
|
||||
#include <cppunit/TestSuite.h>
|
||||
#include <stdio.h>
|
||||
#include <TestUtils.h>
|
||||
/*
|
||||
* Copyright 2003-2026, Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <TestSuiteAddon.h>
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
|
||||
#include <AVLTreeMap.h>
|
||||
|
||||
AVLTreeMapTest::AVLTreeMapTest(std::string name)
|
||||
: BTestCase(name)
|
||||
{
|
||||
}
|
||||
|
||||
CppUnit::Test*
|
||||
AVLTreeMapTest::Suite()
|
||||
{
|
||||
CppUnit::TestSuite *suite = new CppUnit::TestSuite("AVLTreeMap");
|
||||
class AVLTreeMapTest : public CppUnit::TestFixture {
|
||||
CPPUNIT_TEST_SUITE(AVLTreeMapTest);
|
||||
CPPUNIT_TEST(Test1);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
suite->addTest(new CppUnit::TestCaller<AVLTreeMapTest>(
|
||||
"SinglyLinkedList::User Strategy Test (default next parameter)",
|
||||
&AVLTreeMapTest::Test1));
|
||||
public:
|
||||
void Test1() {}
|
||||
};
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
||||
//! Test1
|
||||
void
|
||||
AVLTreeMapTest::Test1()
|
||||
{
|
||||
}
|
||||
|
||||
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(AVLTreeMapTest, getTestSuiteName());
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
#ifndef _avl_tree_map_test_h_
|
||||
#define _avl_tree_map_test_h_
|
||||
|
||||
#include <TestCase.h>
|
||||
|
||||
class AVLTreeMapTest : public BTestCase {
|
||||
public:
|
||||
AVLTreeMapTest(std::string name = "");
|
||||
|
||||
static CppUnit::Test* Suite();
|
||||
|
||||
void Test1();
|
||||
|
||||
private:
|
||||
template <class List>
|
||||
void TestList(List &list, typename List::ValueType *values, int valueCount);
|
||||
};
|
||||
|
||||
#endif // _avl_tree_map_test_h_
|
||||
@@ -1,399 +0,0 @@
|
||||
#include <cppunit/TestAssert.h>
|
||||
#include <cppunit/TestCaller.h>
|
||||
#include <cppunit/TestSuite.h>
|
||||
#include <TestShell.h>
|
||||
|
||||
#include <os/support/ObjectList.h>
|
||||
#include <shared/AutoDeleter.h>
|
||||
#include <util/OpenHashTable.h>
|
||||
|
||||
#include "BOpenHashTableTest.h"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
class Entry {
|
||||
public:
|
||||
Entry(uint32_t value)
|
||||
:
|
||||
fValue(value),
|
||||
fNext(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
const uint32_t Value() const
|
||||
{
|
||||
return fValue;
|
||||
}
|
||||
|
||||
Entry* Next() const
|
||||
{
|
||||
return fNext;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t fValue;
|
||||
Entry *fNext;
|
||||
|
||||
friend class EntryDefinition;
|
||||
};
|
||||
|
||||
|
||||
class EntryDefinition {
|
||||
public:
|
||||
typedef uint32_t KeyType;
|
||||
typedef Entry ValueType;
|
||||
|
||||
size_t HashKey(const KeyType& key) const
|
||||
{
|
||||
return key;
|
||||
}
|
||||
|
||||
size_t Hash(Entry* entry) const
|
||||
{
|
||||
return entry->fValue;
|
||||
}
|
||||
|
||||
bool Compare(const KeyType& key, Entry* entry) const
|
||||
{
|
||||
return key == entry->fValue;
|
||||
}
|
||||
|
||||
Entry*& GetLink(Entry* entry) const
|
||||
{
|
||||
return entry->fNext;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
CppUnit::Test* BOpenHashTableTest::Suite()
|
||||
{
|
||||
CppUnit::TestSuite* suite = new CppUnit::TestSuite("BOpenHashTable");
|
||||
|
||||
suite->addTest(new CppUnit::TestCaller<BOpenHashTableTest>(
|
||||
"BOpenHashTable::Insert test",
|
||||
&BOpenHashTableTest::InsertTest));
|
||||
suite->addTest(new CppUnit::TestCaller<BOpenHashTableTest>(
|
||||
"BOpenHashTable::Insert unchecked test",
|
||||
&BOpenHashTableTest::InsertUncheckedTest));
|
||||
suite->addTest(new CppUnit::TestCaller<BOpenHashTableTest>(
|
||||
"BOpenHashTable::Insert unchecked uninitialized test",
|
||||
&BOpenHashTableTest::InsertUncheckedUninitializedTest));
|
||||
suite->addTest(new CppUnit::TestCaller<BOpenHashTableTest>(
|
||||
"BOpenHashTable::Iterate and count test",
|
||||
&BOpenHashTableTest::IterateAndCountTest));
|
||||
suite->addTest(new CppUnit::TestCaller<BOpenHashTableTest>(
|
||||
"BOpenHashTable::Lookup test",
|
||||
&BOpenHashTableTest::LookupTest));
|
||||
suite->addTest(new CppUnit::TestCaller<BOpenHashTableTest>(
|
||||
"BOpenHashTable::Resize test",
|
||||
&BOpenHashTableTest::ResizeTest));
|
||||
suite->addTest(new CppUnit::TestCaller<BOpenHashTableTest>(
|
||||
"BOpenHashTable::Remove test",
|
||||
&BOpenHashTableTest::RemoveTest));
|
||||
suite->addTest(new CppUnit::TestCaller<BOpenHashTableTest>(
|
||||
"BOpenHashTable::Remove unchecked test",
|
||||
&BOpenHashTableTest::RemoveUncheckedTest));
|
||||
suite->addTest(new CppUnit::TestCaller<BOpenHashTableTest>(
|
||||
"BOpenHashTable::Remove when not present test",
|
||||
&BOpenHashTableTest::RemoveWhenNotPresentTest));
|
||||
suite->addTest(new CppUnit::TestCaller<BOpenHashTableTest>(
|
||||
"BOpenHashTable::Duplicate insert test",
|
||||
&BOpenHashTableTest::DuplicateInsertTest));
|
||||
suite->addTest(new CppUnit::TestCaller<BOpenHashTableTest>(
|
||||
"BOpenHashTable::Disable auto expand",
|
||||
&BOpenHashTableTest::DisableAutoExpandTest));
|
||||
suite->addTest(new CppUnit::TestCaller<BOpenHashTableTest>(
|
||||
"BOpenHashTable::Init with zero size",
|
||||
&BOpenHashTableTest::InitWithZeroSizeTest));
|
||||
suite->addTest(new CppUnit::TestCaller<BOpenHashTableTest>(
|
||||
"BOpenHashTable::Clear test",
|
||||
&BOpenHashTableTest::ClearTest));
|
||||
suite->addTest(new CppUnit::TestCaller<BOpenHashTableTest>(
|
||||
"BOpenHashTable::Clear and return test",
|
||||
&BOpenHashTableTest::ClearAndReturnTest));
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
||||
|
||||
BOpenHashTableTest::BOpenHashTableTest(std::string name)
|
||||
: BTestCase(name)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void BOpenHashTableTest::InsertTest()
|
||||
{
|
||||
Entry entry(123);
|
||||
|
||||
BOpenHashTable<EntryDefinition> table;
|
||||
CPPUNIT_ASSERT_EQUAL(table.Init(), B_OK);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(table.Insert(&entry), B_OK);
|
||||
}
|
||||
|
||||
|
||||
void BOpenHashTableTest::InsertUncheckedTest()
|
||||
{
|
||||
Entry entry(123);
|
||||
|
||||
BOpenHashTable<EntryDefinition> table;
|
||||
CPPUNIT_ASSERT_EQUAL(table.Init(), B_OK);
|
||||
|
||||
table.InsertUnchecked(&entry);
|
||||
}
|
||||
|
||||
|
||||
void BOpenHashTableTest::InsertUncheckedUninitializedTest()
|
||||
{
|
||||
Entry entry(123);
|
||||
|
||||
BOpenHashTable<EntryDefinition> table;
|
||||
CPPUNIT_ASSERT_EQUAL(table.Init(), B_OK);
|
||||
|
||||
table.InsertUnchecked(&entry);
|
||||
}
|
||||
|
||||
|
||||
void BOpenHashTableTest::IterateAndCountTest() {
|
||||
const size_t kEntryCount = 20;
|
||||
|
||||
BObjectList<Entry, true> entries(20);
|
||||
|
||||
BOpenHashTable<EntryDefinition> table;
|
||||
CPPUNIT_ASSERT_EQUAL(table.Init(kEntryCount * 2), B_OK);
|
||||
|
||||
for (uint32_t i = 0; i < kEntryCount; ++i) {
|
||||
Entry* entry = new Entry(i);
|
||||
entries.AddItem(entry);
|
||||
CPPUNIT_ASSERT_EQUAL(table.Insert(entry), B_OK);
|
||||
}
|
||||
|
||||
// Verify that the table contains the expected values.
|
||||
uint64_t map = 0;
|
||||
BOpenHashTable<EntryDefinition>::Iterator iterator = table.GetIterator();
|
||||
while (iterator.HasNext()) {
|
||||
Entry* entry = iterator.Next();
|
||||
CPPUNIT_ASSERT_EQUAL(0, map & (1 << entry->Value()));
|
||||
map |= (1 << entry->Value());
|
||||
}
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(map, (1 << kEntryCount) - 1);
|
||||
CPPUNIT_ASSERT_EQUAL(kEntryCount, table.CountElements());
|
||||
}
|
||||
|
||||
|
||||
void BOpenHashTableTest::ResizeTest()
|
||||
{
|
||||
// This is the same as IterateAndCountTest, except that the table will
|
||||
// be resized mid insertion.
|
||||
const size_t kEntryCount = 20;
|
||||
BObjectList<Entry, true> entries(20);
|
||||
BOpenHashTable<EntryDefinition> table;
|
||||
|
||||
// Start off with capacity for 8 elements. This will mean that the table
|
||||
// will be resized in the loop below since we are inserting 20 elements.
|
||||
CPPUNIT_ASSERT_EQUAL(table.Init(8), B_OK);
|
||||
|
||||
for (uint32_t i = 0; i < kEntryCount; ++i) {
|
||||
Entry* entry = new Entry(i);
|
||||
entries.AddItem(entry);
|
||||
CPPUNIT_ASSERT_EQUAL(table.Insert(entry), B_OK);
|
||||
}
|
||||
|
||||
// Verify that after resize the expected elements are present within
|
||||
// the table.
|
||||
uint64_t map = 0;
|
||||
BOpenHashTable<EntryDefinition>::Iterator iterator = table.GetIterator();
|
||||
while (iterator.HasNext()) {
|
||||
Entry* entry = iterator.Next();
|
||||
CPPUNIT_ASSERT_EQUAL(0, map & (1 << entry->Value()));
|
||||
map |= (1 << entry->Value());
|
||||
}
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(map, (1 << kEntryCount) - 1);
|
||||
CPPUNIT_ASSERT_EQUAL(kEntryCount, table.CountElements());
|
||||
}
|
||||
|
||||
|
||||
void BOpenHashTableTest::LookupTest() {
|
||||
Entry entry(123);
|
||||
|
||||
BOpenHashTable<EntryDefinition> table;
|
||||
CPPUNIT_ASSERT_EQUAL(table.Init(0), B_OK);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(table.Insert(&entry), B_OK);
|
||||
CPPUNIT_ASSERT_EQUAL(table.Lookup(123), &entry);
|
||||
}
|
||||
|
||||
|
||||
void BOpenHashTableTest::RemoveTest() {
|
||||
Entry entry(123);
|
||||
|
||||
BOpenHashTable<EntryDefinition> table;
|
||||
CPPUNIT_ASSERT_EQUAL(table.Init(0), B_OK);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(table.Insert(&entry), B_OK);
|
||||
CPPUNIT_ASSERT_EQUAL(table.Lookup(123), &entry);
|
||||
|
||||
table.Remove(&entry);
|
||||
CPPUNIT_ASSERT_EQUAL(table.Lookup(123), NULL);
|
||||
}
|
||||
|
||||
|
||||
void BOpenHashTableTest::RemoveUncheckedTest()
|
||||
{
|
||||
Entry entry(123);
|
||||
|
||||
BOpenHashTable<EntryDefinition> table;
|
||||
CPPUNIT_ASSERT_EQUAL(table.Init(0), B_OK);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(table.Insert(&entry), B_OK);
|
||||
CPPUNIT_ASSERT_EQUAL(table.Lookup(123), &entry);
|
||||
|
||||
table.RemoveUnchecked(&entry);
|
||||
CPPUNIT_ASSERT_EQUAL(table.Lookup(123), NULL);
|
||||
}
|
||||
|
||||
|
||||
void BOpenHashTableTest::RemoveWhenNotPresentTest()
|
||||
{
|
||||
Entry entry1(123);
|
||||
Entry entry2(456);
|
||||
Entry entry3(789);
|
||||
|
||||
BOpenHashTable<EntryDefinition> table;
|
||||
CPPUNIT_ASSERT_EQUAL(table.Init(), B_OK);
|
||||
|
||||
// Only add the first two entries.
|
||||
table.Insert(&entry1);
|
||||
table.Insert(&entry2);
|
||||
|
||||
// entry3 is not in the table, but we'll remove it anyway.
|
||||
table.Remove(&entry3);
|
||||
table.RemoveUnchecked(&entry3);
|
||||
|
||||
// The original two entries should still be there.
|
||||
CPPUNIT_ASSERT_EQUAL(table.CountElements(), 2);
|
||||
CPPUNIT_ASSERT_EQUAL(table.Lookup(123), &entry1);
|
||||
CPPUNIT_ASSERT_EQUAL(table.Lookup(456), &entry2);
|
||||
CPPUNIT_ASSERT_EQUAL(table.Lookup(789), NULL);
|
||||
}
|
||||
|
||||
|
||||
void BOpenHashTableTest::DuplicateInsertTest()
|
||||
{
|
||||
Entry entry(123);
|
||||
|
||||
BOpenHashTable<EntryDefinition, true, true> table;
|
||||
CPPUNIT_ASSERT_EQUAL(table.Init(0), B_OK);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(table.Insert(&entry), B_OK);
|
||||
CPPUNIT_ASSERT_EQUAL(table.Lookup(123), &entry);
|
||||
|
||||
CPPUNIT_ASSERT_DEBUGGER(table.Insert(&entry));
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(table.Lookup(123), &entry);
|
||||
|
||||
// The item can basically never be removed now since there is a cycle,
|
||||
// but we'll break into the debugger on remove when that happens as well.
|
||||
CPPUNIT_ASSERT_DEBUGGER(table.Remove(&entry));
|
||||
CPPUNIT_ASSERT_EQUAL(table.Lookup(123), &entry);
|
||||
|
||||
CPPUNIT_ASSERT_DEBUGGER(table.Remove(&entry));
|
||||
CPPUNIT_ASSERT_EQUAL(table.Lookup(123), &entry);
|
||||
}
|
||||
|
||||
|
||||
void BOpenHashTableTest::DisableAutoExpandTest()
|
||||
{
|
||||
// Insert multiple items into a table with a fixed size of 1. This
|
||||
// essentially turns this BOpenHashTable into a linked list, since resize
|
||||
// will never occur.
|
||||
Entry entry1(123);
|
||||
Entry entry2(456);
|
||||
|
||||
BOpenHashTable<EntryDefinition, false> table;
|
||||
CPPUNIT_ASSERT_EQUAL(table.Init(1), B_OK);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(table.Insert(&entry1), B_OK);
|
||||
CPPUNIT_ASSERT_EQUAL(table.Insert(&entry2), B_OK);
|
||||
CPPUNIT_ASSERT_EQUAL(table.CountElements(), 2);
|
||||
}
|
||||
|
||||
|
||||
void BOpenHashTableTest::InitWithZeroSizeTest()
|
||||
{
|
||||
Entry entry(123);
|
||||
|
||||
BOpenHashTable<EntryDefinition> table;
|
||||
CPPUNIT_ASSERT_EQUAL(table.Init(0), B_OK);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(table.Insert(&entry), B_OK);
|
||||
CPPUNIT_ASSERT_EQUAL(table.Lookup(123), &entry);
|
||||
}
|
||||
|
||||
|
||||
void BOpenHashTableTest::ClearTest()
|
||||
{
|
||||
const size_t kEntryCount = 3;
|
||||
|
||||
BObjectList<Entry, true> entries(20);
|
||||
|
||||
BOpenHashTable<EntryDefinition> table;
|
||||
CPPUNIT_ASSERT_EQUAL(table.Init(), B_OK);
|
||||
|
||||
for (uint32_t i = 0; i < kEntryCount; ++i) {
|
||||
Entry* entry = new Entry(i);
|
||||
entries.AddItem(entry);
|
||||
CPPUNIT_ASSERT_EQUAL(table.Insert(entry), B_OK);
|
||||
}
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(table.CountElements(), kEntryCount);
|
||||
CPPUNIT_ASSERT(table.Lookup(2) != NULL);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(table.Clear(false), NULL);
|
||||
CPPUNIT_ASSERT_EQUAL(table.CountElements(), 0);
|
||||
CPPUNIT_ASSERT_EQUAL(table.Lookup(2), NULL);
|
||||
CPPUNIT_ASSERT_EQUAL(table.GetIterator().HasNext(), false);
|
||||
}
|
||||
|
||||
|
||||
void BOpenHashTableTest::ClearAndReturnTest()
|
||||
{
|
||||
// Same as ClearTest(), except that Clear(true) is called, which tells
|
||||
// the BOpenHashTable<T> to return a linked list of entries before clearing
|
||||
// the table.
|
||||
const size_t kEntryCount = 3;
|
||||
BOpenHashTable<EntryDefinition> table;
|
||||
CPPUNIT_ASSERT_EQUAL(table.Init(), B_OK);
|
||||
|
||||
for (uint32_t i = 0; i < kEntryCount; ++i) {
|
||||
Entry* entry = new Entry(i);
|
||||
CPPUNIT_ASSERT_EQUAL(table.Insert(entry), B_OK);
|
||||
}
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(table.CountElements(), kEntryCount);
|
||||
CPPUNIT_ASSERT(table.Lookup(2) != NULL);
|
||||
|
||||
Entry* head = table.Clear(true);
|
||||
CPPUNIT_ASSERT(head != NULL);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(table.CountElements(), 0);
|
||||
CPPUNIT_ASSERT_EQUAL(table.Lookup(2), NULL);
|
||||
CPPUNIT_ASSERT_EQUAL(table.GetIterator().HasNext(), false);
|
||||
|
||||
size_t items_returned = 0;
|
||||
while (head != NULL) {
|
||||
Entry* next = head->Next();
|
||||
delete head;
|
||||
head = next;
|
||||
|
||||
++items_returned;
|
||||
}
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(items_returned, kEntryCount);
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
#ifndef BOPENHASHTABLE_TEST_H
|
||||
#define BOPENHASHTABLE_TEST_H
|
||||
|
||||
#include <TestCase.h>
|
||||
|
||||
class BOpenHashTableTest : public BTestCase {
|
||||
public:
|
||||
BOpenHashTableTest(std::string name = "");
|
||||
|
||||
void InsertTest();
|
||||
void InsertUncheckedTest();
|
||||
void InsertUncheckedUninitializedTest();
|
||||
void IterateAndCountTest();
|
||||
void ResizeTest();
|
||||
void LookupTest();
|
||||
void RemoveTest();
|
||||
void RemoveUncheckedTest();
|
||||
void RemoveWhenNotPresentTest();
|
||||
void DuplicateInsertTest();
|
||||
void DisableAutoExpandTest();
|
||||
void InitWithZeroSizeTest();
|
||||
void ClearTest();
|
||||
void ClearAndReturnTest();
|
||||
|
||||
static CppUnit::Test* Suite();
|
||||
};
|
||||
|
||||
#endif // BOPENHASHTABLE_TEST_H
|
||||
@@ -1,95 +1,94 @@
|
||||
#include <cppunit/Test.h>
|
||||
#include <cppunit/TestCaller.h>
|
||||
#include <cppunit/TestSuite.h>
|
||||
#include <stdio.h>
|
||||
#include <TestUtils.h>
|
||||
/*
|
||||
* Copyright 2022-2026, Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <cppunit/TestFixture.h>
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
|
||||
#include <TestSuiteAddon.h>
|
||||
|
||||
#include "BitmapTest.h"
|
||||
#include "Bitmap.h"
|
||||
|
||||
BitmapTest::BitmapTest(std::string name)
|
||||
: BTestCase(name)
|
||||
{
|
||||
}
|
||||
|
||||
CppUnit::Test*
|
||||
BitmapTest::Suite()
|
||||
{
|
||||
CppUnit::TestSuite *suite = new CppUnit::TestSuite("Bitmap");
|
||||
class BitmapTest : public CppUnit::TestFixture {
|
||||
CPPUNIT_TEST_SUITE(BitmapTest);
|
||||
CPPUNIT_TEST(Shift_CorrectBitSet);
|
||||
CPPUNIT_TEST(Multielement_Shift_CorrectBitSet);
|
||||
CPPUNIT_TEST(Resize_CorrectBitSet);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
suite->addTest(new CppUnit::TestCaller<BitmapTest>("Bitmap::Resize test",
|
||||
&BitmapTest::ResizeTest));
|
||||
suite->addTest(new CppUnit::TestCaller<BitmapTest>("Bitmap::Shift test",
|
||||
&BitmapTest::ShiftTest));
|
||||
public:
|
||||
void Shift_CorrectBitSet()
|
||||
{
|
||||
BKernel::Bitmap bitmap(20);
|
||||
bitmap.Set(6);
|
||||
|
||||
return suite;
|
||||
}
|
||||
CPPUNIT_ASSERT(bitmap.Get(6));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(5));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(7));
|
||||
|
||||
void
|
||||
BitmapTest::ResizeTest()
|
||||
{
|
||||
BKernel::Bitmap bitmap(10);
|
||||
bitmap.Set(6);
|
||||
bitmap.Shift(10);
|
||||
|
||||
CPPUNIT_ASSERT(bitmap.Get(6));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(5));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(7));
|
||||
CPPUNIT_ASSERT(bitmap.Get(16));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(15));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(17));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(6));
|
||||
|
||||
bitmap.Resize(20);
|
||||
bitmap.Shift(-9);
|
||||
|
||||
CPPUNIT_ASSERT(bitmap.Get(6));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(7));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(19));
|
||||
CPPUNIT_ASSERT(bitmap.Get(7));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(6));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(8));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(16));
|
||||
}
|
||||
|
||||
bitmap.Resize(200);
|
||||
bitmap.Set(199);
|
||||
void Multielement_Shift_CorrectBitSet() {
|
||||
BKernel::Bitmap bitmap(200);
|
||||
bitmap.Set(7);
|
||||
|
||||
CPPUNIT_ASSERT(bitmap.Get(6));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(7));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(19));
|
||||
CPPUNIT_ASSERT(bitmap.Get(199));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(198));
|
||||
}
|
||||
CPPUNIT_ASSERT(bitmap.Get(7));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(6));
|
||||
|
||||
void
|
||||
BitmapTest::ShiftTest()
|
||||
{
|
||||
BKernel::Bitmap bitmap(20);
|
||||
bitmap.Set(6);
|
||||
bitmap.Shift(100);
|
||||
|
||||
CPPUNIT_ASSERT(bitmap.Get(6));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(5));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(7));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(7));
|
||||
CPPUNIT_ASSERT(bitmap.Get(107));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(106));
|
||||
|
||||
bitmap.Shift(10);
|
||||
bitmap.Shift(-100);
|
||||
|
||||
CPPUNIT_ASSERT(bitmap.Get(16));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(15));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(17));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(6));
|
||||
CPPUNIT_ASSERT(bitmap.Get(7));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(107));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(6));
|
||||
}
|
||||
|
||||
bitmap.Shift(-9);
|
||||
void Resize_CorrectBitSet()
|
||||
{
|
||||
BKernel::Bitmap bitmap(10);
|
||||
bitmap.Set(6);
|
||||
|
||||
CPPUNIT_ASSERT(bitmap.Get(7));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(6));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(8));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(16));
|
||||
CPPUNIT_ASSERT(bitmap.Get(6));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(5));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(7));
|
||||
|
||||
// Now test cross-element shifting.
|
||||
bitmap.Resize(200);
|
||||
bitmap.Resize(20);
|
||||
|
||||
CPPUNIT_ASSERT(bitmap.Get(7));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(6));
|
||||
CPPUNIT_ASSERT(bitmap.Get(6));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(7));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(19));
|
||||
|
||||
bitmap.Shift(100);
|
||||
bitmap.Resize(200);
|
||||
bitmap.Set(199);
|
||||
|
||||
CPPUNIT_ASSERT(!bitmap.Get(7));
|
||||
CPPUNIT_ASSERT(bitmap.Get(107));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(106));
|
||||
CPPUNIT_ASSERT(bitmap.Get(6));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(7));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(19));
|
||||
CPPUNIT_ASSERT(bitmap.Get(199));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(198));
|
||||
}
|
||||
};
|
||||
|
||||
bitmap.Shift(-100);
|
||||
|
||||
CPPUNIT_ASSERT(bitmap.Get(7));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(107));
|
||||
CPPUNIT_ASSERT(!bitmap.Get(6));
|
||||
}
|
||||
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(BitmapTest, getTestSuiteName());
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
#ifndef _bitmap_test_h_
|
||||
#define _bitmap_test_h_
|
||||
|
||||
#include <TestCase.h>
|
||||
|
||||
class BitmapTest : public BTestCase {
|
||||
public:
|
||||
BitmapTest(std::string name = "");
|
||||
|
||||
static CppUnit::Test* Suite();
|
||||
|
||||
void ResizeTest();
|
||||
void ShiftTest();
|
||||
};
|
||||
|
||||
#endif // _bitmap_test_h_
|
||||
@@ -1,192 +1,144 @@
|
||||
/*
|
||||
** Copyright 2003-2004, Axel Dörfler, [email protected]. All rights reserved.
|
||||
** Distributed under the terms of the MIT License.
|
||||
*/
|
||||
/*
|
||||
* Copyright 2003-2004, Axel Dörfler, [email protected]. All rights reserved.
|
||||
* Copyright 2026, Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "DoublyLinkedListTest.h"
|
||||
|
||||
#include <cppunit/TestCaller.h>
|
||||
#include <cppunit/TestSuite.h>
|
||||
#include <TestSuiteAddon.h>
|
||||
#include <TestUtils.h>
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
|
||||
#include <util/DoublyLinkedList.h>
|
||||
|
||||
|
||||
// Class used for testing without offset
|
||||
class ItemWithout {
|
||||
public:
|
||||
DoublyLinkedListLink<ItemWithout> fLink;
|
||||
int32 value;
|
||||
public:
|
||||
DoublyLinkedListLink<ItemWithout> fLink;
|
||||
int32 value;
|
||||
};
|
||||
|
||||
|
||||
// Class used for testing with offset
|
||||
class ItemWith {
|
||||
public:
|
||||
int32 value;
|
||||
DoublyLinkedListLink<ItemWith> fLink;
|
||||
public:
|
||||
int32 value;
|
||||
DoublyLinkedListLink<ItemWith> fLink;
|
||||
};
|
||||
|
||||
|
||||
// Class used for testing without offset
|
||||
class ItemVirtualWithout {
|
||||
public:
|
||||
virtual int32 Value();
|
||||
public:
|
||||
DoublyLinkedListLink<ItemVirtualWithout> fLink;
|
||||
int32 value;
|
||||
|
||||
DoublyLinkedListLink<ItemVirtualWithout> fLink;
|
||||
int32 value;
|
||||
int32 Value() { return value; }
|
||||
};
|
||||
|
||||
|
||||
// Class used for testing with offset
|
||||
class ItemVirtualWith {
|
||||
public:
|
||||
virtual int32 Value();
|
||||
public:
|
||||
int32 value;
|
||||
DoublyLinkedListLink<ItemVirtualWith> fLink;
|
||||
|
||||
int32 value;
|
||||
DoublyLinkedListLink<ItemVirtualWith> fLink;
|
||||
int32 Value() { return value; }
|
||||
};
|
||||
|
||||
|
||||
int32
|
||||
ItemVirtualWithout::Value()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
template<typename Item>
|
||||
class DoublyLinkedListTest : public CppUnit::TestFixture {
|
||||
CPPUNIT_TEST_SUITE(DoublyLinkedListTest);
|
||||
CPPUNIT_TEST(IsEmpty_ReturnsFalse);
|
||||
CPPUNIT_TEST(Count_ReturnsItemCount);
|
||||
CPPUNIT_TEST(Iterating_ItemsEqualAddedItems);
|
||||
CPPUNIT_TEST(RemoveHead_ReturnsFirstItem);
|
||||
CPPUNIT_TEST(HeadAndEverySecondItemRemoved_AddingFirstItem_ItemsAndCountAreCorrect);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
typedef DoublyLinkedList<Item, DoublyLinkedListMemberGetLink<Item> > List;
|
||||
List* fList;
|
||||
static const int fValueCount = 10;
|
||||
Item fItems[fValueCount];
|
||||
|
||||
int32
|
||||
ItemVirtualWith::Value()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
DoublyLinkedListTest::DoublyLinkedListTest(std::string name)
|
||||
: BTestCase(name)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
CppUnit::Test*
|
||||
DoublyLinkedListTest::Suite() {
|
||||
CppUnit::TestSuite *suite = new CppUnit::TestSuite("DLL");
|
||||
|
||||
suite->addTest(new CppUnit::TestCaller<DoublyLinkedListTest>("DoublyLinkedList::no offset", &DoublyLinkedListTest::WithoutOffsetTest));
|
||||
suite->addTest(new CppUnit::TestCaller<DoublyLinkedListTest>("DoublyLinkedList::with offset", &DoublyLinkedListTest::WithOffsetTest));
|
||||
suite->addTest(new CppUnit::TestCaller<DoublyLinkedListTest>("DoublyLinkedList::virtual no offset", &DoublyLinkedListTest::VirtualWithoutOffsetTest));
|
||||
suite->addTest(new CppUnit::TestCaller<DoublyLinkedListTest>("DoublyLinkedList::virtual with offset", &DoublyLinkedListTest::VirtualWithOffsetTest));
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
||||
|
||||
//! Tests the given list
|
||||
|
||||
template <typename Item>
|
||||
void
|
||||
DoublyLinkedListTest::TestList()
|
||||
{
|
||||
DoublyLinkedList<Item, DoublyLinkedListMemberGetLink<Item> > list;
|
||||
int valueCount = 10;
|
||||
Item items[valueCount];
|
||||
|
||||
// initialize
|
||||
|
||||
for (int i = 0; i < valueCount; i++) {
|
||||
items[i].value = i;
|
||||
list.Add(&items[i]);
|
||||
public:
|
||||
void setUp()
|
||||
{
|
||||
fList = new List;
|
||||
for (int i = 0; i < fValueCount; i++) {
|
||||
fItems[i].value = i;
|
||||
fList->Add(&fItems[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// list must not be empty
|
||||
|
||||
CHK(!list.IsEmpty());
|
||||
|
||||
// count items in list
|
||||
|
||||
int count = 0;
|
||||
typename DoublyLinkedList<Item,
|
||||
DoublyLinkedListMemberGetLink<Item> >::Iterator
|
||||
iterator = list.GetIterator();
|
||||
while (iterator.Next() != NULL)
|
||||
count++;
|
||||
|
||||
CHK(count == valueCount);
|
||||
|
||||
// test for equality
|
||||
|
||||
iterator = list.GetIterator();
|
||||
|
||||
int i = 0;
|
||||
Item *item;
|
||||
while ((item = iterator.Next()) != NULL) {
|
||||
CHK(item->value == i);
|
||||
CHK(item == &items[i]);
|
||||
i++;
|
||||
void tearDown()
|
||||
{
|
||||
delete fList;
|
||||
}
|
||||
|
||||
// remove first
|
||||
|
||||
Item *first = list.RemoveHead();
|
||||
CHK(first->value == 0);
|
||||
CHK(first == &items[0]);
|
||||
|
||||
// remove every second
|
||||
|
||||
iterator = list.GetIterator();
|
||||
i = 0;
|
||||
while ((item = iterator.Next()) != NULL) {
|
||||
CHK(item->value == i + 1);
|
||||
|
||||
if (i % 2)
|
||||
list.Remove(item);
|
||||
i++;
|
||||
void IsEmpty_ReturnsFalse()
|
||||
{
|
||||
CPPUNIT_ASSERT(!fList->IsEmpty());
|
||||
}
|
||||
|
||||
// re-add first
|
||||
|
||||
list.Add(first);
|
||||
|
||||
// count again
|
||||
void Count_ReturnsItemCount()
|
||||
{
|
||||
int count = 0;
|
||||
typename List::Iterator iterator = fList->GetIterator();
|
||||
while (iterator.Next() != NULL)
|
||||
count++;
|
||||
|
||||
count = 0;
|
||||
iterator = list.GetIterator();
|
||||
while (iterator.Next() != NULL)
|
||||
count++;
|
||||
CPPUNIT_ASSERT(count == fValueCount);
|
||||
}
|
||||
|
||||
CHK(count == (valueCount / 2) + 1);
|
||||
}
|
||||
void Iterating_ItemsEqualAddedItems()
|
||||
{
|
||||
int i = 0;
|
||||
typename List::Iterator iterator = fList->GetIterator();
|
||||
Item* item;
|
||||
while ((item = iterator.Next()) != NULL) {
|
||||
CPPUNIT_ASSERT(item->value == i);
|
||||
CPPUNIT_ASSERT(item == &fItems[i]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveHead_ReturnsFirstItem()
|
||||
{
|
||||
Item* first = fList->RemoveHead();
|
||||
CPPUNIT_ASSERT(first->value == 0);
|
||||
CPPUNIT_ASSERT(first == &fItems[0]);
|
||||
}
|
||||
|
||||
void HeadAndEverySecondItemRemoved_AddingFirstItem_ItemsAndCountAreCorrect()
|
||||
{
|
||||
fList->RemoveHead();
|
||||
typename List::Iterator iterator = fList->GetIterator();
|
||||
int i = 0;
|
||||
Item* item;
|
||||
while ((item = iterator.Next()) != NULL) {
|
||||
CPPUNIT_ASSERT(item->value == i + 1);
|
||||
|
||||
if (i % 2)
|
||||
fList->Remove(item);
|
||||
i++;
|
||||
}
|
||||
|
||||
fList->Add(&fItems[0]);
|
||||
|
||||
int count = 0;
|
||||
iterator = fList->GetIterator();
|
||||
while (iterator.Next() != NULL)
|
||||
count++;
|
||||
|
||||
CPPUNIT_ASSERT(count == (fValueCount / 2) + 1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! Test using no offset, no virtual
|
||||
|
||||
void
|
||||
DoublyLinkedListTest::WithoutOffsetTest() {
|
||||
TestList<ItemWithout>();
|
||||
}
|
||||
|
||||
|
||||
//! Test using offset, no virtual
|
||||
|
||||
void
|
||||
DoublyLinkedListTest::WithOffsetTest() {
|
||||
TestList<ItemWith>();
|
||||
}
|
||||
|
||||
|
||||
//! Test using no offset, virtual
|
||||
|
||||
void
|
||||
DoublyLinkedListTest::VirtualWithoutOffsetTest() {
|
||||
TestList<ItemVirtualWithout>();
|
||||
}
|
||||
|
||||
|
||||
//! Test using offset, virtual
|
||||
|
||||
void
|
||||
DoublyLinkedListTest::VirtualWithOffsetTest() {
|
||||
TestList<ItemVirtualWith>();
|
||||
}
|
||||
|
||||
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(DoublyLinkedListTest<ItemWith>, getTestSuiteName());
|
||||
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(DoublyLinkedListTest<ItemWithout>, getTestSuiteName());
|
||||
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(DoublyLinkedListTest<ItemVirtualWith>, getTestSuiteName());
|
||||
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(DoublyLinkedListTest<ItemVirtualWithout>, getTestSuiteName());
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
#ifndef _DOUBLY_LINKED_LIST_TEST_H_
|
||||
#define _DOUBLY_LINKED_LIST_TEST_H_
|
||||
|
||||
#include <TestCase.h>
|
||||
|
||||
class DoublyLinkedListTest : public BTestCase {
|
||||
public:
|
||||
DoublyLinkedListTest(std::string name = "");
|
||||
|
||||
static CppUnit::Test *Suite();
|
||||
|
||||
void WithoutOffsetTest();
|
||||
void WithOffsetTest();
|
||||
void VirtualWithoutOffsetTest();
|
||||
void VirtualWithOffsetTest();
|
||||
|
||||
private:
|
||||
template <typename Item> void TestList();
|
||||
};
|
||||
|
||||
#endif /* _DOUBLY_LINKED_LIST_TEST_H_ */
|
||||
@@ -12,7 +12,7 @@ SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src system kernel util ] ;
|
||||
UnitTestLib libkernelutilstest.so
|
||||
: KernelUtilsTestAddon.cpp
|
||||
# AVLTreeMapTest.cpp
|
||||
BOpenHashTableTest.cpp
|
||||
OpenHashTableTest.cpp
|
||||
BitmapTest.cpp
|
||||
SinglyLinkedListTest.cpp
|
||||
DoublyLinkedListTest.cpp
|
||||
|
||||
@@ -1,25 +1,13 @@
|
||||
/*
|
||||
* Copyright 2003-2026, Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <TestSuite.h>
|
||||
#include <TestSuiteAddon.h>
|
||||
|
||||
//#include "AVLTreeMapTest.h"
|
||||
#include "BOpenHashTableTest.h"
|
||||
#include "BitmapTest.h"
|
||||
#include "DoublyLinkedListTest.h"
|
||||
#include "SinglyLinkedListTest.h"
|
||||
#include "VectorMapTest.h"
|
||||
#include "VectorSetTest.h"
|
||||
#include "VectorTest.h"
|
||||
|
||||
|
||||
BTestSuite* getTestSuite() {
|
||||
BTestSuite *suite = new BTestSuite("KernelUtils");
|
||||
// suite->addTest("AVLTreeMap", AVLTreeMapTest::Suite());
|
||||
suite->addTest("BOpenHashTable", BOpenHashTableTest::Suite());
|
||||
suite->addTest("Bitmap", BitmapTest::Suite());
|
||||
suite->addTest("SinglyLinkedList", SinglyLinkedListTest::Suite());
|
||||
suite->addTest("DoublyLinkedList", DoublyLinkedListTest::Suite());
|
||||
suite->addTest("VectorMap", VectorMapTest::Suite());
|
||||
suite->addTest("VectorSet", VectorSetTest::Suite());
|
||||
suite->addTest("Vector", VectorTest::Suite());
|
||||
return suite;
|
||||
const char* getTestSuiteName() {
|
||||
return "KernelUtils";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,326 @@
|
||||
/*
|
||||
* Copyright 2020-2026, Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <TestShell.h>
|
||||
#include <TestSuiteAddon.h>
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
|
||||
#include <os/support/ObjectList.h>
|
||||
#include <shared/AutoDeleter.h>
|
||||
#include <util/OpenHashTable.h>
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
class Entry {
|
||||
public:
|
||||
Entry(uint32_t value)
|
||||
:
|
||||
fValue(value),
|
||||
fNext(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
const uint32_t Value() const { return fValue; }
|
||||
|
||||
Entry* Next() const { return fNext; }
|
||||
|
||||
private:
|
||||
uint32_t fValue;
|
||||
Entry* fNext;
|
||||
|
||||
friend class EntryDefinition;
|
||||
};
|
||||
|
||||
|
||||
class EntryDefinition {
|
||||
public:
|
||||
typedef uint32_t KeyType;
|
||||
typedef Entry ValueType;
|
||||
|
||||
size_t HashKey(const KeyType& key) const { return key; }
|
||||
|
||||
size_t Hash(Entry* entry) const { return entry->fValue; }
|
||||
|
||||
bool Compare(const KeyType& key, Entry* entry) const { return key == entry->fValue; }
|
||||
|
||||
Entry*& GetLink(Entry* entry) const { return entry->fNext; }
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
class OpenHashTableTest : public CppUnit::TestFixture {
|
||||
CPPUNIT_TEST_SUITE(OpenHashTableTest);
|
||||
CPPUNIT_TEST(Init_ZeroSize_ReturnsOk);
|
||||
CPPUNIT_TEST(Clear_EmptiesTable);
|
||||
CPPUNIT_TEST(Clear_ReturnElementsSet_ClearsAndReturnsEntries);
|
||||
CPPUNIT_TEST(Insert_AutoExpandDisabled_InsertsEntriesWithoutResize);
|
||||
CPPUNIT_TEST(Insert_DuplicateEntry_ReturnsError);
|
||||
CPPUNIT_TEST(Insert_InsertsEntry_ReturnsOk);
|
||||
CPPUNIT_TEST(InsertUnchecked_InsertsEntry_ReturnsOk);
|
||||
CPPUNIT_TEST(IterateAndCount_IteratesEntries_ReturnsCorrectCount);
|
||||
CPPUNIT_TEST(Lookup_ExistingKey_ReturnsEntry);
|
||||
CPPUNIT_TEST(Remove_ExistingEntry_ReturnsOk);
|
||||
CPPUNIT_TEST(Remove_NotPresent_ReturnsNull);
|
||||
CPPUNIT_TEST(RemoveUnchecked_RemovesEntry_ReturnsOk);
|
||||
CPPUNIT_TEST(Resize_InsertsManyEntries_ResizesSuccessfully);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
public:
|
||||
void Init_ZeroSize_ReturnsOk()
|
||||
{
|
||||
Entry entry(123);
|
||||
|
||||
BOpenHashTable<EntryDefinition> table;
|
||||
CPPUNIT_ASSERT_EQUAL(table.Init(0), B_OK);
|
||||
}
|
||||
|
||||
void Clear_EmptiesTable()
|
||||
{
|
||||
const size_t kEntryCount = 3;
|
||||
|
||||
BObjectList<Entry, true> entries(20);
|
||||
|
||||
BOpenHashTable<EntryDefinition> table;
|
||||
CPPUNIT_ASSERT_EQUAL(table.Init(), B_OK);
|
||||
|
||||
for (uint32_t i = 0; i < kEntryCount; ++i) {
|
||||
Entry* entry = new Entry(i);
|
||||
entries.AddItem(entry);
|
||||
CPPUNIT_ASSERT_EQUAL(table.Insert(entry), B_OK);
|
||||
}
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(table.CountElements(), kEntryCount);
|
||||
CPPUNIT_ASSERT(table.Lookup(2) != NULL);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(table.Clear(false), NULL);
|
||||
CPPUNIT_ASSERT_EQUAL(table.CountElements(), 0);
|
||||
CPPUNIT_ASSERT_EQUAL(table.Lookup(2), NULL);
|
||||
CPPUNIT_ASSERT_EQUAL(table.GetIterator().HasNext(), false);
|
||||
}
|
||||
|
||||
void Clear_ReturnElementsSet_ClearsAndReturnsEntries()
|
||||
{
|
||||
// Same as ClearTest(), except that Clear(true) is called, which tells
|
||||
// the BOpenHashTable<T> to return a linked list of entries before clearing
|
||||
// the table.
|
||||
const size_t kEntryCount = 3;
|
||||
BOpenHashTable<EntryDefinition> table;
|
||||
CPPUNIT_ASSERT_EQUAL(table.Init(), B_OK);
|
||||
|
||||
for (uint32_t i = 0; i < kEntryCount; ++i) {
|
||||
Entry* entry = new Entry(i);
|
||||
CPPUNIT_ASSERT_EQUAL(table.Insert(entry), B_OK);
|
||||
}
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(table.CountElements(), kEntryCount);
|
||||
CPPUNIT_ASSERT(table.Lookup(2) != NULL);
|
||||
|
||||
Entry* head = table.Clear(true);
|
||||
CPPUNIT_ASSERT(head != NULL);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(table.CountElements(), 0);
|
||||
CPPUNIT_ASSERT_EQUAL(table.Lookup(2), NULL);
|
||||
CPPUNIT_ASSERT_EQUAL(table.GetIterator().HasNext(), false);
|
||||
|
||||
size_t items_returned = 0;
|
||||
while (head != NULL) {
|
||||
Entry* next = head->Next();
|
||||
delete head;
|
||||
head = next;
|
||||
|
||||
++items_returned;
|
||||
}
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(items_returned, kEntryCount);
|
||||
}
|
||||
|
||||
void Insert_AutoExpandDisabled_InsertsEntriesWithoutResize()
|
||||
{
|
||||
// Insert multiple items into a table with a fixed size of 1. This
|
||||
// essentially turns this BOpenHashTable into a linked list, since resize
|
||||
// will never occur.
|
||||
Entry entry1(123);
|
||||
Entry entry2(456);
|
||||
|
||||
BOpenHashTable<EntryDefinition, false> table;
|
||||
CPPUNIT_ASSERT_EQUAL(table.Init(1), B_OK);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(table.Insert(&entry1), B_OK);
|
||||
CPPUNIT_ASSERT_EQUAL(table.Insert(&entry2), B_OK);
|
||||
CPPUNIT_ASSERT_EQUAL(table.CountElements(), 2);
|
||||
}
|
||||
|
||||
void Insert_DuplicateEntry_ReturnsError()
|
||||
{
|
||||
Entry entry(123);
|
||||
|
||||
BOpenHashTable<EntryDefinition, true, true> table;
|
||||
CPPUNIT_ASSERT_EQUAL(table.Init(0), B_OK);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(table.Insert(&entry), B_OK);
|
||||
CPPUNIT_ASSERT_EQUAL(table.Lookup(123), &entry);
|
||||
|
||||
CPPUNIT_ASSERT_DEBUGGER(table.Insert(&entry));
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(table.Lookup(123), &entry);
|
||||
|
||||
// The item can basically never be removed now since there is a cycle,
|
||||
// but we'll break into the debugger on remove when that happens as well.
|
||||
CPPUNIT_ASSERT_DEBUGGER(table.Remove(&entry));
|
||||
CPPUNIT_ASSERT_EQUAL(table.Lookup(123), &entry);
|
||||
|
||||
CPPUNIT_ASSERT_DEBUGGER(table.Remove(&entry));
|
||||
CPPUNIT_ASSERT_EQUAL(table.Lookup(123), &entry);
|
||||
}
|
||||
|
||||
void Insert_InsertsEntry_ReturnsOk()
|
||||
{
|
||||
Entry entry(123);
|
||||
|
||||
BOpenHashTable<EntryDefinition> table;
|
||||
CPPUNIT_ASSERT_EQUAL(table.Init(), B_OK);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(table.Insert(&entry), B_OK);
|
||||
}
|
||||
|
||||
void InsertUnchecked_InsertsEntry_ReturnsOk()
|
||||
{
|
||||
Entry entry(123);
|
||||
|
||||
BOpenHashTable<EntryDefinition> table;
|
||||
CPPUNIT_ASSERT_EQUAL(table.Init(), B_OK);
|
||||
|
||||
table.InsertUnchecked(&entry);
|
||||
}
|
||||
|
||||
void IterateAndCount_IteratesEntries_ReturnsCorrectCount()
|
||||
{
|
||||
const size_t kEntryCount = 20;
|
||||
|
||||
BObjectList<Entry, true> entries(20);
|
||||
|
||||
BOpenHashTable<EntryDefinition> table;
|
||||
CPPUNIT_ASSERT_EQUAL(table.Init(kEntryCount * 2), B_OK);
|
||||
|
||||
for (uint32_t i = 0; i < kEntryCount; ++i) {
|
||||
Entry* entry = new Entry(i);
|
||||
entries.AddItem(entry);
|
||||
CPPUNIT_ASSERT_EQUAL(table.Insert(entry), B_OK);
|
||||
}
|
||||
|
||||
// Verify that the table contains the expected values.
|
||||
uint64_t map = 0;
|
||||
BOpenHashTable<EntryDefinition>::Iterator iterator = table.GetIterator();
|
||||
while (iterator.HasNext()) {
|
||||
Entry* entry = iterator.Next();
|
||||
CPPUNIT_ASSERT_EQUAL(0, map & (1 << entry->Value()));
|
||||
map |= (1 << entry->Value());
|
||||
}
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(map, (1 << kEntryCount) - 1);
|
||||
CPPUNIT_ASSERT_EQUAL(kEntryCount, table.CountElements());
|
||||
}
|
||||
|
||||
void Lookup_ExistingKey_ReturnsEntry()
|
||||
{
|
||||
Entry entry(123);
|
||||
|
||||
BOpenHashTable<EntryDefinition> table;
|
||||
CPPUNIT_ASSERT_EQUAL(table.Init(0), B_OK);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(table.Insert(&entry), B_OK);
|
||||
CPPUNIT_ASSERT_EQUAL(table.Lookup(123), &entry);
|
||||
}
|
||||
|
||||
void Remove_ExistingEntry_ReturnsOk()
|
||||
{
|
||||
Entry entry(123);
|
||||
|
||||
BOpenHashTable<EntryDefinition> table;
|
||||
CPPUNIT_ASSERT_EQUAL(table.Init(0), B_OK);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(table.Insert(&entry), B_OK);
|
||||
CPPUNIT_ASSERT_EQUAL(table.Lookup(123), &entry);
|
||||
|
||||
table.Remove(&entry);
|
||||
CPPUNIT_ASSERT_EQUAL(table.Lookup(123), NULL);
|
||||
}
|
||||
|
||||
void Remove_NotPresent_ReturnsNull()
|
||||
{
|
||||
Entry entry1(123);
|
||||
Entry entry2(456);
|
||||
Entry entry3(789);
|
||||
|
||||
BOpenHashTable<EntryDefinition> table;
|
||||
CPPUNIT_ASSERT_EQUAL(table.Init(), B_OK);
|
||||
|
||||
// Only add the first two entries.
|
||||
table.Insert(&entry1);
|
||||
table.Insert(&entry2);
|
||||
|
||||
// entry3 is not in the table, but we'll remove it anyway.
|
||||
table.Remove(&entry3);
|
||||
table.RemoveUnchecked(&entry3);
|
||||
|
||||
// The original two entries should still be there.
|
||||
CPPUNIT_ASSERT_EQUAL(table.CountElements(), 2);
|
||||
CPPUNIT_ASSERT_EQUAL(table.Lookup(123), &entry1);
|
||||
CPPUNIT_ASSERT_EQUAL(table.Lookup(456), &entry2);
|
||||
CPPUNIT_ASSERT_EQUAL(table.Lookup(789), NULL);
|
||||
}
|
||||
|
||||
void RemoveUnchecked_RemovesEntry_ReturnsOk()
|
||||
{
|
||||
Entry entry(123);
|
||||
|
||||
BOpenHashTable<EntryDefinition> table;
|
||||
CPPUNIT_ASSERT_EQUAL(table.Init(0), B_OK);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(table.Insert(&entry), B_OK);
|
||||
CPPUNIT_ASSERT_EQUAL(table.Lookup(123), &entry);
|
||||
|
||||
table.RemoveUnchecked(&entry);
|
||||
CPPUNIT_ASSERT_EQUAL(table.Lookup(123), NULL);
|
||||
}
|
||||
|
||||
void Resize_InsertsManyEntries_ResizesSuccessfully()
|
||||
{
|
||||
// This is the same as IterateAndCountTest, except that the table will
|
||||
// be resized mid insertion.
|
||||
const size_t kEntryCount = 20;
|
||||
BObjectList<Entry, true> entries(20);
|
||||
BOpenHashTable<EntryDefinition> table;
|
||||
|
||||
// Start off with capacity for 8 elements. This will mean that the table
|
||||
// will be resized in the loop below since we are inserting 20 elements.
|
||||
CPPUNIT_ASSERT_EQUAL(table.Init(8), B_OK);
|
||||
|
||||
for (uint32_t i = 0; i < kEntryCount; ++i) {
|
||||
Entry* entry = new Entry(i);
|
||||
entries.AddItem(entry);
|
||||
CPPUNIT_ASSERT_EQUAL(table.Insert(entry), B_OK);
|
||||
}
|
||||
|
||||
// Verify that after resize the expected elements are present within
|
||||
// the table.
|
||||
uint64_t map = 0;
|
||||
BOpenHashTable<EntryDefinition>::Iterator iterator = table.GetIterator();
|
||||
while (iterator.HasNext()) {
|
||||
Entry* entry = iterator.Next();
|
||||
CPPUNIT_ASSERT_EQUAL(0, map & (1 << entry->Value()));
|
||||
map |= (1 << entry->Value());
|
||||
}
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(map, (1 << kEntryCount) - 1);
|
||||
CPPUNIT_ASSERT_EQUAL(kEntryCount, table.CountElements());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(OpenHashTableTest, getTestSuiteName());
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,107 +1,110 @@
|
||||
#include <cppunit/Test.h>
|
||||
#include <cppunit/TestCaller.h>
|
||||
#include <cppunit/TestSuite.h>
|
||||
#include <stdio.h>
|
||||
#include <TestUtils.h>
|
||||
/*
|
||||
* Copyright 2003-2026, Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <TestSuiteAddon.h>
|
||||
#include <cppunit/TestFixture.h>
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
|
||||
#include "SinglyLinkedListTest.h"
|
||||
#include "SinglyLinkedList.h"
|
||||
|
||||
SinglyLinkedListTest::SinglyLinkedListTest(std::string name)
|
||||
: BTestCase(name)
|
||||
{
|
||||
}
|
||||
|
||||
CppUnit::Test*
|
||||
SinglyLinkedListTest::Suite() {
|
||||
CppUnit::TestSuite *suite = new CppUnit::TestSuite("SLL");
|
||||
|
||||
suite->addTest(new CppUnit::TestCaller<SinglyLinkedListTest>("SinglyLinkedList::User Strategy Test (default next parameter)", &SinglyLinkedListTest::UserDefaultTest));
|
||||
suite->addTest(new CppUnit::TestCaller<SinglyLinkedListTest>("SinglyLinkedList::User Strategy Test (custom next parameter)", &SinglyLinkedListTest::UserCustomTest));
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
||||
// Class used for testing default User strategy
|
||||
class Link {
|
||||
public:
|
||||
SinglyLinkedListLink<Link> next;
|
||||
long data;
|
||||
|
||||
SinglyLinkedListLink<Link>* GetSinglyLinkedListLink() {
|
||||
return &next;
|
||||
}
|
||||
|
||||
bool operator==(const Link &ref) {
|
||||
return data == ref.data;
|
||||
}
|
||||
SinglyLinkedListLink<Link>* GetSinglyLinkedListLink() { return &next; }
|
||||
|
||||
bool operator==(const Link& ref) { return data == ref.data; }
|
||||
};
|
||||
|
||||
|
||||
// Class used for testing custom User strategy
|
||||
class MyLink {
|
||||
public:
|
||||
SinglyLinkedListLink<MyLink> mynext;
|
||||
SinglyLinkedListLink<MyLink> next;
|
||||
long data;
|
||||
|
||||
bool operator==(const MyLink &ref) {
|
||||
return data == ref.data;
|
||||
bool operator==(const MyLink& ref) { return data == ref.data; }
|
||||
};
|
||||
|
||||
|
||||
template<typename Link, typename List>
|
||||
class SinglyLinkedListTest : public CppUnit::TestFixture {
|
||||
CPPUNIT_TEST_SUITE(SinglyLinkedListTest);
|
||||
CPPUNIT_TEST(TwoValues_MakeEmpty_ListIsEmpty);
|
||||
CPPUNIT_TEST(EmptyList_AddingValues_CountIncreases);
|
||||
CPPUNIT_TEST(TenValues_AccessingWithIterator_IteratesThroughAllValues);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
List* fList;
|
||||
static const int fValueCount = 10;
|
||||
Link fValues[fValueCount];
|
||||
|
||||
public:
|
||||
void setUp()
|
||||
{
|
||||
fList = new List;
|
||||
for (int i = 0; i < fValueCount; i++) {
|
||||
fValues[i].data = i * 2;
|
||||
if (!(i % 2))
|
||||
fValues[i].next.next = NULL; // Leave some next pointers invalid just for fun
|
||||
}
|
||||
}
|
||||
|
||||
void tearDown()
|
||||
{
|
||||
delete fList;
|
||||
}
|
||||
|
||||
void TwoValues_MakeEmpty_ListIsEmpty()
|
||||
{
|
||||
Link value1, value2;
|
||||
value1.data = 2;
|
||||
value2.data = 5;
|
||||
fList->Add(&value1);
|
||||
fList->Add(&value2);
|
||||
CPPUNIT_ASSERT(fList->Count() == 2);
|
||||
|
||||
fList->MakeEmpty();
|
||||
CPPUNIT_ASSERT(fList->Count() == 0);
|
||||
}
|
||||
|
||||
void EmptyList_AddingValues_CountIncreases() {
|
||||
for (int i = 0; i < fValueCount; i++) {
|
||||
CPPUNIT_ASSERT(fList->Count() == i);
|
||||
fList->Add(&fValues[i]);
|
||||
CPPUNIT_ASSERT(fList->Count() == i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void TenValues_AccessingWithIterator_IteratesThroughAllValues()
|
||||
{
|
||||
for (int i = 0; i < fValueCount; i++) {
|
||||
fList->Add(&fValues[i]);
|
||||
}
|
||||
|
||||
// Prefix increment
|
||||
int preIndex = fValueCount - 1;
|
||||
for (typename List::ConstIterator iterator = fList->GetIterator(); iterator.HasNext();
|
||||
--preIndex) {
|
||||
Link* element = iterator.Next();
|
||||
CPPUNIT_ASSERT(*element == fValues[preIndex]);
|
||||
}
|
||||
CPPUNIT_ASSERT(preIndex == -1);
|
||||
}
|
||||
};
|
||||
|
||||
//! Tests the given list
|
||||
template <class List, class Element>
|
||||
void
|
||||
SinglyLinkedListTest::TestList(List &list, Element *values, int valueCount)
|
||||
{
|
||||
list.MakeEmpty();
|
||||
|
||||
// PushFront
|
||||
for (int i = 0; i < valueCount; i++) {
|
||||
NextSubTest();
|
||||
CHK(list.Count() == i);
|
||||
list.Add(&values[i]);
|
||||
CHK(list.Count() == i+1);
|
||||
}
|
||||
|
||||
// Prefix increment
|
||||
int preIndex = valueCount-1;
|
||||
for (typename List::ConstIterator iterator = list.GetIterator();
|
||||
iterator.HasNext(); --preIndex) {
|
||||
NextSubTest();
|
||||
|
||||
Element* element = iterator.Next();
|
||||
CHK(*element == values[preIndex]);
|
||||
}
|
||||
CHK(preIndex == -1);
|
||||
list.MakeEmpty();
|
||||
}
|
||||
|
||||
typedef SinglyLinkedListTest<Link, SinglyLinkedList<Link> > SinglyLinkedListDefaultTest;
|
||||
typedef SinglyLinkedListTest<MyLink,
|
||||
SinglyLinkedList<MyLink, SinglyLinkedListMemberGetLink<MyLink, &MyLink::next> > >
|
||||
SinglyLinkedListCustomTest;
|
||||
//! Test using the User strategy with the default NextMember.
|
||||
void
|
||||
SinglyLinkedListTest::UserDefaultTest() {
|
||||
SinglyLinkedList<Link> list;
|
||||
const int valueCount = 10;
|
||||
Link values[valueCount];
|
||||
for (int i = 0; i < valueCount; i++) {
|
||||
values[i].data = i;
|
||||
if (i % 2)
|
||||
values[i].next.next = NULL; // Leave some next pointers invalid just for fun
|
||||
}
|
||||
|
||||
TestList(list, values, valueCount);
|
||||
}
|
||||
|
||||
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(SinglyLinkedListDefaultTest, getTestSuiteName());
|
||||
//! Test using the User strategy with a custom NextMember.
|
||||
void
|
||||
SinglyLinkedListTest::UserCustomTest() {
|
||||
SinglyLinkedList<MyLink, SinglyLinkedListMemberGetLink<MyLink, &MyLink::mynext> > list;
|
||||
const int valueCount = 10;
|
||||
MyLink values[valueCount];
|
||||
for (int i = 0; i < valueCount; i++) {
|
||||
values[i].data = i*2;
|
||||
if (!(i % 2))
|
||||
values[i].mynext.next = NULL; // Leave some next pointers invalid just for fun
|
||||
}
|
||||
|
||||
TestList(list, values, valueCount);
|
||||
}
|
||||
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(SinglyLinkedListCustomTest, getTestSuiteName());
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
#ifndef _single_linked_list_test_h_
|
||||
#define _single_linked_list_test_h_
|
||||
|
||||
#include <TestCase.h>
|
||||
|
||||
class SinglyLinkedListTest : public BTestCase {
|
||||
public:
|
||||
SinglyLinkedListTest(std::string name = "");
|
||||
|
||||
static CppUnit::Test* Suite();
|
||||
|
||||
void UserDefaultTest();
|
||||
void UserCustomTest();
|
||||
private:
|
||||
template <class List, class Element>
|
||||
void TestList(List &list, Element *values, int valueCount);
|
||||
};
|
||||
|
||||
#endif // _single_linked_list_test_h_
|
||||
@@ -1,19 +1,825 @@
|
||||
/*
|
||||
* Copyright 2003-2026, Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <TestUtils.h>
|
||||
#include <cppunit/Test.h>
|
||||
#include <cppunit/TestCaller.h>
|
||||
#include <cppunit/TestSuite.h>
|
||||
#include <TestSuiteAddon.h>
|
||||
#include <cppunit/TestFixture.h>
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
|
||||
#include <VectorMap.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "OrderedMapTest.h"
|
||||
#include "VectorMapTest.h"
|
||||
#include <KernelUtilsOrder.h>
|
||||
|
||||
|
||||
template<typename _Value> class SimpleValueStrategy {
|
||||
public:
|
||||
typedef _Value Value;
|
||||
|
||||
SimpleValueStrategy(int32 differentValues = 100000)
|
||||
:
|
||||
fDifferentValues(differentValues)
|
||||
{
|
||||
srand(0);
|
||||
}
|
||||
|
||||
Value Generate();
|
||||
|
||||
private:
|
||||
int32 fDifferentValues;
|
||||
};
|
||||
|
||||
|
||||
template<>
|
||||
int
|
||||
SimpleValueStrategy<int>::Generate()
|
||||
{
|
||||
return rand() % fDifferentValues;
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
string
|
||||
SimpleValueStrategy<string>::Generate()
|
||||
{
|
||||
char buffer[10];
|
||||
sprintf(buffer, "%ld", rand() % fDifferentValues);
|
||||
return string(buffer);
|
||||
}
|
||||
|
||||
|
||||
template<typename _KeyStrategy, typename _ValueStrategy>
|
||||
class PairEntryStrategy {
|
||||
public:
|
||||
typedef _KeyStrategy KeyStrategy;
|
||||
typedef _ValueStrategy ValueStrategy;
|
||||
typedef typename KeyStrategy::Value Key;
|
||||
typedef typename ValueStrategy::Value Value;
|
||||
|
||||
inline Key GenerateKey() { return fKeyStrategy.Generate(); }
|
||||
|
||||
inline Value GenerateValue() { return fValueStrategy.Generate(); }
|
||||
|
||||
inline void Generate(Key& key, Value& value)
|
||||
{
|
||||
key = GenerateKey();
|
||||
value = GenerateValue();
|
||||
}
|
||||
|
||||
private:
|
||||
KeyStrategy fKeyStrategy;
|
||||
ValueStrategy fValueStrategy;
|
||||
};
|
||||
|
||||
|
||||
template<typename _KeyStrategy, typename _ValueStrategy, typename GetKey>
|
||||
class ImplicitKeyStrategy {
|
||||
public:
|
||||
typedef _KeyStrategy KeyStrategy;
|
||||
typedef _ValueStrategy ValueStrategy;
|
||||
typedef typename KeyStrategy::Value Key;
|
||||
typedef typename ValueStrategy::Value Value;
|
||||
|
||||
inline Key GenerateKey() { return fKeyStrategy.Generate(); }
|
||||
inline Value GenerateValue() { return fValueStrategy.Generate(); }
|
||||
inline void Generate(Key& key, Value& value)
|
||||
{
|
||||
value = GenerateValue();
|
||||
key = fGetKey(value);
|
||||
}
|
||||
|
||||
private:
|
||||
KeyStrategy fKeyStrategy;
|
||||
ValueStrategy fValueStrategy;
|
||||
GetKey fGetKey;
|
||||
};
|
||||
|
||||
|
||||
// Non-template wrapper for the Ascending compare strategy.
|
||||
// Work-around for our compiler not eating nested template template
|
||||
// parameters.
|
||||
struct Ascending {
|
||||
template<typename Value>
|
||||
class Strategy : public KernelUtilsOrder::Ascending<Value> {};
|
||||
};
|
||||
|
||||
|
||||
// Non-template wrapper for the Descending compare strategy.
|
||||
// Work-around for our compiler not eating nested template template
|
||||
// parameters.
|
||||
struct Descending {
|
||||
template<typename Value>
|
||||
class Strategy : public KernelUtilsOrder::Descending<Value> {};
|
||||
};
|
||||
|
||||
|
||||
template<typename Value, typename Compare>
|
||||
class CompareWrapper {
|
||||
public:
|
||||
inline bool operator()(const Value& a, const Value& b) const
|
||||
{ return fCompare(a, b) < 0; }
|
||||
|
||||
private:
|
||||
Compare fCompare;
|
||||
};
|
||||
|
||||
|
||||
template<typename Entry, typename TestMap, typename MyIterator, typename ReferenceIterator>
|
||||
class TestIterator {
|
||||
private:
|
||||
typedef TestIterator<Entry, TestMap, MyIterator, ReferenceIterator> Iterator;
|
||||
|
||||
public:
|
||||
inline TestIterator(TestMap* s, MyIterator myIt, ReferenceIterator refIt)
|
||||
:
|
||||
fMap(s),
|
||||
fMyIterator(myIt),
|
||||
fReferenceIterator(refIt)
|
||||
{
|
||||
}
|
||||
|
||||
inline TestIterator(const Iterator& other)
|
||||
:
|
||||
fMap(other.fMap),
|
||||
fMyIterator(other.fMyIterator),
|
||||
fReferenceIterator(other.fReferenceIterator)
|
||||
{
|
||||
CPPUNIT_ASSERT(fMyIterator == other.fMyIterator);
|
||||
}
|
||||
|
||||
inline Iterator& operator++()
|
||||
{
|
||||
MyIterator& myResult = ++fMyIterator;
|
||||
ReferenceIterator& refResult = ++fReferenceIterator;
|
||||
if (refResult == fMap->fReferenceMap.end()) {
|
||||
CPPUNIT_ASSERT(myResult == fMap->fMyMap.End());
|
||||
} else {
|
||||
CPPUNIT_ASSERT(myResult->Key() == refResult->first);
|
||||
CPPUNIT_ASSERT(myResult->Value() == refResult->second);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Iterator operator++(int)
|
||||
{
|
||||
MyIterator oldMyResult = fMyIterator;
|
||||
MyIterator myResult = fMyIterator++;
|
||||
ReferenceIterator refResult = fReferenceIterator++;
|
||||
CPPUNIT_ASSERT(oldMyResult == myResult);
|
||||
if (refResult == fMap->fReferenceMap.end()) {
|
||||
CPPUNIT_ASSERT(myResult == fMap->fMyMap.End());
|
||||
} else {
|
||||
CPPUNIT_ASSERT(myResult->Key() == refResult->first);
|
||||
CPPUNIT_ASSERT(myResult->Value() == refResult->second);
|
||||
}
|
||||
return Iterator(fMap, myResult, refResult);
|
||||
}
|
||||
|
||||
inline Iterator& operator--()
|
||||
{
|
||||
MyIterator& myResult = --fMyIterator;
|
||||
ReferenceIterator& refResult = --fReferenceIterator;
|
||||
CPPUNIT_ASSERT(myResult->Key() == refResult->first);
|
||||
CPPUNIT_ASSERT(myResult->Value() == refResult->second);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Iterator operator--(int)
|
||||
{
|
||||
MyIterator oldMyResult = fMyIterator;
|
||||
MyIterator myResult = fMyIterator--;
|
||||
ReferenceIterator refResult = fReferenceIterator--;
|
||||
CPPUNIT_ASSERT(oldMyResult == myResult);
|
||||
CPPUNIT_ASSERT(myResult->Key() == refResult->first);
|
||||
CPPUNIT_ASSERT(myResult->Value() == refResult->second);
|
||||
return Iterator(fMap, myResult, refResult);
|
||||
}
|
||||
|
||||
inline Iterator& operator=(const Iterator& other)
|
||||
{
|
||||
fMap = other.fMap;
|
||||
fMyIterator = other.fMyIterator;
|
||||
fReferenceIterator = other.fReferenceIterator;
|
||||
CPPUNIT_ASSERT(fMyIterator == other.fMyIterator);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline bool operator==(const Iterator& other) const
|
||||
{
|
||||
bool result = (fMyIterator == other.fMyIterator);
|
||||
CPPUNIT_ASSERT((fReferenceIterator == other.fReferenceIterator) == result);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline bool operator!=(const Iterator& other) const
|
||||
{
|
||||
bool result = (fMyIterator != other.fMyIterator);
|
||||
CPPUNIT_ASSERT((fReferenceIterator != other.fReferenceIterator) == result);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline Entry operator*() const
|
||||
{
|
||||
Entry entry = *fMyIterator;
|
||||
CPPUNIT_ASSERT(entry.Key() == fReferenceIterator->first);
|
||||
CPPUNIT_ASSERT(entry.Value() == fReferenceIterator->second);
|
||||
return entry;
|
||||
}
|
||||
|
||||
inline Entry operator->() const
|
||||
{
|
||||
Entry entry = fMyIterator.operator->();
|
||||
CPPUNIT_ASSERT(entry.Key() == fReferenceIterator->first);
|
||||
CPPUNIT_ASSERT(entry.Value() == fReferenceIterator->second);
|
||||
return entry;
|
||||
}
|
||||
|
||||
inline operator bool() const
|
||||
{
|
||||
bool result = fMyIterator;
|
||||
CPPUNIT_ASSERT((fMyIterator == fMap->fMyMap.Null()) != result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public:
|
||||
TestMap* fMap;
|
||||
MyIterator fMyIterator;
|
||||
ReferenceIterator fReferenceIterator;
|
||||
};
|
||||
|
||||
|
||||
template<typename Key, typename Value, typename MyMap, typename ReferenceMap, typename Compare>
|
||||
class TestMap {
|
||||
public:
|
||||
typedef TestMap<Key, Value, MyMap, ReferenceMap, Compare> Class;
|
||||
|
||||
typedef typename MyMap::Iterator MyIterator;
|
||||
typedef typename ReferenceMap::iterator ReferenceIterator;
|
||||
typedef typename MyMap::ConstIterator MyConstIterator;
|
||||
typedef typename ReferenceMap::const_iterator ReferenceConstIterator;
|
||||
typedef typename MyMap::Entry Entry;
|
||||
typedef typename MyMap::ConstEntry ConstEntry;
|
||||
typedef TestIterator<Entry, Class, MyIterator, ReferenceIterator> Iterator;
|
||||
typedef TestIterator<ConstEntry, const Class, MyConstIterator, ReferenceConstIterator>
|
||||
ConstIterator;
|
||||
|
||||
TestMap()
|
||||
:
|
||||
fMyMap(),
|
||||
fReferenceMap(),
|
||||
fChecking(true)
|
||||
{
|
||||
}
|
||||
|
||||
void Insert(const Key& key, const Value& value)
|
||||
{
|
||||
CPPUNIT_ASSERT(fMyMap.Insert(key, value) == B_OK);
|
||||
fReferenceMap[key] = value;
|
||||
Check();
|
||||
}
|
||||
|
||||
void Put(const Key& key, const Value& value)
|
||||
{
|
||||
CPPUNIT_ASSERT(fMyMap.Put(key, value) == B_OK);
|
||||
fReferenceMap[key] = value;
|
||||
Check();
|
||||
}
|
||||
|
||||
Value& Get(const Key& key)
|
||||
{
|
||||
Value& value = fMyMap.Get(key);
|
||||
CPPUNIT_ASSERT(value == fReferenceMap[key]);
|
||||
return value;
|
||||
}
|
||||
|
||||
const Value& Get(const Key& key) const
|
||||
{
|
||||
const Value& value = fMyMap.Get(key);
|
||||
CPPUNIT_ASSERT(value == fReferenceMap.find(key)->second);
|
||||
return value;
|
||||
}
|
||||
|
||||
void Remove(const Key& key)
|
||||
{
|
||||
int32 oldCount = Count();
|
||||
ReferenceIterator it = fReferenceMap.find(key);
|
||||
if (it != fReferenceMap.end())
|
||||
fReferenceMap.erase(it);
|
||||
int32 newCount = fReferenceMap.size();
|
||||
CPPUNIT_ASSERT(fMyMap.Remove(key) == oldCount - newCount);
|
||||
Check();
|
||||
}
|
||||
|
||||
Iterator Erase(const Iterator& iterator)
|
||||
{
|
||||
bool outOfRange = (iterator.fReferenceIterator == fReferenceMap.end());
|
||||
MyIterator myIt = fMyMap.Erase(iterator.fMyIterator);
|
||||
if (outOfRange) {
|
||||
CPPUNIT_ASSERT(myIt == fMyMap.Null());
|
||||
return Iterator(this, myIt, fReferenceMap.end());
|
||||
}
|
||||
Key nextKey;
|
||||
ReferenceIterator refIt = iterator.fReferenceIterator;
|
||||
++refIt;
|
||||
bool noNextEntry = (refIt == fReferenceMap.end());
|
||||
if (!noNextEntry)
|
||||
nextKey = refIt->first;
|
||||
fReferenceMap.erase(iterator.fReferenceIterator);
|
||||
if (noNextEntry)
|
||||
refIt = fReferenceMap.end();
|
||||
else
|
||||
refIt = fReferenceMap.find(nextKey);
|
||||
Check();
|
||||
if (refIt == fReferenceMap.end()) {
|
||||
CPPUNIT_ASSERT(myIt == fMyMap.End());
|
||||
} else {
|
||||
CPPUNIT_ASSERT(myIt->Key() == refIt->first);
|
||||
CPPUNIT_ASSERT(myIt->Value() == refIt->second);
|
||||
}
|
||||
return Iterator(this, myIt, refIt);
|
||||
}
|
||||
|
||||
inline int32 Count() const
|
||||
{
|
||||
int32 count = fReferenceMap.size();
|
||||
CPPUNIT_ASSERT(fMyMap.Count() == count);
|
||||
return count;
|
||||
}
|
||||
|
||||
inline bool IsEmpty() const
|
||||
{
|
||||
bool result = fReferenceMap.empty();
|
||||
CPPUNIT_ASSERT(fMyMap.IsEmpty() == result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void MakeEmpty()
|
||||
{
|
||||
fMyMap.MakeEmpty();
|
||||
fReferenceMap.clear();
|
||||
Check();
|
||||
}
|
||||
|
||||
inline Iterator Begin() { return Iterator(this, fMyMap.Begin(), fReferenceMap.begin()); }
|
||||
|
||||
inline ConstIterator Begin() const
|
||||
{
|
||||
return ConstIterator(this, fMyMap.Begin(), fReferenceMap.begin());
|
||||
}
|
||||
|
||||
inline Iterator End() { return Iterator(this, fMyMap.End(), fReferenceMap.end()); }
|
||||
|
||||
inline ConstIterator End() const
|
||||
{
|
||||
return ConstIterator(this, fMyMap.End(), fReferenceMap.end());
|
||||
}
|
||||
|
||||
inline Iterator Null() { return Iterator(this, fMyMap.Null(), fReferenceMap.end()); }
|
||||
|
||||
inline ConstIterator Null() const
|
||||
{
|
||||
return ConstIterator(this, fMyMap.Null(), fReferenceMap.end());
|
||||
}
|
||||
|
||||
// for testing only
|
||||
inline Iterator IteratorForIndex(int32 index)
|
||||
{
|
||||
if (index < 0 || index > Count())
|
||||
return End();
|
||||
MyIterator myIt = fMyMap.Begin();
|
||||
ReferenceIterator refIt = fReferenceMap.begin();
|
||||
for (int32 i = 0; i < index; i++) {
|
||||
++myIt;
|
||||
++refIt;
|
||||
}
|
||||
return Iterator(this, myIt, refIt);
|
||||
}
|
||||
|
||||
// for testing only
|
||||
inline ConstIterator IteratorForIndex(int32 index) const
|
||||
{
|
||||
if (index < 0 || index > Count())
|
||||
return End();
|
||||
MyConstIterator myIt = fMyMap.Begin();
|
||||
ReferenceConstIterator refIt = fReferenceMap.begin();
|
||||
for (int32 i = 0; i < index; i++) {
|
||||
++myIt;
|
||||
++refIt;
|
||||
}
|
||||
return ConstIterator(this, myIt, refIt);
|
||||
}
|
||||
|
||||
Iterator Find(const Key& key)
|
||||
{
|
||||
MyIterator myIt = fMyMap.Find(key);
|
||||
ReferenceIterator refIt = fReferenceMap.find(key);
|
||||
if (refIt == fReferenceMap.end()) {
|
||||
CPPUNIT_ASSERT(myIt = fMyMap.End());
|
||||
} else {
|
||||
CPPUNIT_ASSERT(myIt->Key() == refIt->first);
|
||||
CPPUNIT_ASSERT(myIt->Value() == refIt->second);
|
||||
}
|
||||
return Iterator(this, myIt, refIt);
|
||||
}
|
||||
|
||||
ConstIterator Find(const Key& key) const
|
||||
{
|
||||
MyConstIterator myIt = fMyMap.Find(key);
|
||||
ReferenceConstIterator refIt = fReferenceMap.find(key);
|
||||
if (refIt == fReferenceMap.end()) {
|
||||
CPPUNIT_ASSERT(myIt = fMyMap.End());
|
||||
} else {
|
||||
CPPUNIT_ASSERT(myIt->Key() == refIt->first);
|
||||
CPPUNIT_ASSERT(myIt->Value() == refIt->second);
|
||||
}
|
||||
return ConstIterator(this, myIt, refIt);
|
||||
}
|
||||
|
||||
Iterator FindClose(const Key& key, bool less)
|
||||
{
|
||||
MyIterator myIt = fMyMap.FindClose(key, less);
|
||||
if (myIt == fMyMap.End()) {
|
||||
if (fMyMap.Count() > 0) {
|
||||
if (less)
|
||||
CPPUNIT_ASSERT(fCompare(fMyMap.Begin()->Key(), key) > 0);
|
||||
else
|
||||
CPPUNIT_ASSERT(fCompare((--MyIterator(myIt))->Key(), key) < 0);
|
||||
}
|
||||
return End();
|
||||
}
|
||||
if (less) {
|
||||
CPPUNIT_ASSERT(fCompare(myIt->Key(), key) <= 0);
|
||||
MyIterator nextMyIt(myIt);
|
||||
++nextMyIt;
|
||||
if (nextMyIt != fMyMap.End())
|
||||
CPPUNIT_ASSERT(fCompare(nextMyIt->Key(), key) > 0);
|
||||
} else {
|
||||
CPPUNIT_ASSERT(fCompare(myIt->Key(), key) >= 0);
|
||||
if (myIt != fMyMap.Begin()) {
|
||||
MyIterator prevMyIt(myIt);
|
||||
--prevMyIt;
|
||||
CPPUNIT_ASSERT(fCompare(prevMyIt->Key(), key) < 0);
|
||||
}
|
||||
}
|
||||
return Iterator(this, myIt, fReferenceMap.find(myIt->Key()));
|
||||
}
|
||||
|
||||
ConstIterator FindClose(const Key& key, bool less) const
|
||||
{
|
||||
MyConstIterator myIt = fMyMap.FindClose(key, less);
|
||||
if (myIt == fMyMap.End()) {
|
||||
if (fMyMap.Count() > 0) {
|
||||
if (less)
|
||||
CPPUNIT_ASSERT(fCompare(fMyMap.Begin()->Key(), key) > 0);
|
||||
else
|
||||
CPPUNIT_ASSERT(fCompare((--MyConstIterator(myIt))->Key(), key) < 0);
|
||||
}
|
||||
return End();
|
||||
}
|
||||
if (less) {
|
||||
CPPUNIT_ASSERT(fCompare(myIt->Key(), key) <= 0);
|
||||
MyConstIterator nextMyIt(myIt);
|
||||
++nextMyIt;
|
||||
if (nextMyIt != fMyMap.End())
|
||||
CPPUNIT_ASSERT(fCompare(nextMyIt->Key(), key) > 0);
|
||||
} else {
|
||||
CPPUNIT_ASSERT(fCompare(myIt->Key(), key) >= 0);
|
||||
if (myIt != fMyMap.Begin()) {
|
||||
MyConstIterator prevMyIt(myIt);
|
||||
--prevMyIt;
|
||||
CPPUNIT_ASSERT(fCompare(prevMyIt->Key(), key) < 0);
|
||||
}
|
||||
}
|
||||
return ConstIterator(this, myIt, fReferenceMap.find(myIt->Key()));
|
||||
}
|
||||
|
||||
void SetChecking(bool enable) { fChecking = enable; }
|
||||
|
||||
void Check() const
|
||||
{
|
||||
if (fChecking) {
|
||||
int32 count = fReferenceMap.size();
|
||||
CPPUNIT_ASSERT(fMyMap.Count() == count);
|
||||
CPPUNIT_ASSERT(fMyMap.IsEmpty() == fReferenceMap.empty());
|
||||
MyConstIterator myIt = fMyMap.Begin();
|
||||
ReferenceConstIterator refIt = fReferenceMap.begin();
|
||||
for (int32 i = 0; i < count; i++, ++myIt, ++refIt) {
|
||||
CPPUNIT_ASSERT(myIt->Key() == refIt->first);
|
||||
CPPUNIT_ASSERT(myIt->Value() == refIt->second);
|
||||
CPPUNIT_ASSERT((*myIt).Key() == refIt->first);
|
||||
CPPUNIT_ASSERT((*myIt).Value() == refIt->second);
|
||||
}
|
||||
CPPUNIT_ASSERT(myIt == fMyMap.End());
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
MyMap fMyMap;
|
||||
ReferenceMap fReferenceMap;
|
||||
bool fChecking;
|
||||
Compare fCompare;
|
||||
};
|
||||
|
||||
|
||||
template<template<typename> class _MyMap, typename _EntryStrategy,
|
||||
// template<typename> class _CompareStrategy>
|
||||
class CompareStrategyWrapper>
|
||||
class TestStrategy {
|
||||
public:
|
||||
typedef _EntryStrategy EntryStrategy;
|
||||
typedef typename EntryStrategy::KeyStrategy KeyStrategy;
|
||||
typedef typename EntryStrategy::ValueStrategy ValueStrategy;
|
||||
typedef typename KeyStrategy::Value Key;
|
||||
typedef typename ValueStrategy::Value Value;
|
||||
// typedef _CompareStrategy<Key> Compare;
|
||||
typedef typename CompareStrategyWrapper::template Strategy<Key> Compare;
|
||||
typedef CompareWrapper<Key, Compare> BoolCompare;
|
||||
typedef _MyMap<Compare> MyMap;
|
||||
typedef std::map<Key, Value, BoolCompare> ReferenceMap;
|
||||
typedef TestMap<Key, Value, MyMap, ReferenceMap, Compare> TestClass;
|
||||
};
|
||||
|
||||
|
||||
template<class TestStrategy>
|
||||
class VectorMapTest : public CppUnit::TestFixture {
|
||||
CPPUNIT_TEST_SUITE(VectorMapTest);
|
||||
CPPUNIT_TEST(ConstructorTest);
|
||||
CPPUNIT_TEST(Insert30ElementsTest);
|
||||
CPPUNIT_TEST(Insert200ElementsTest);
|
||||
CPPUNIT_TEST(Put30ElementsTest);
|
||||
CPPUNIT_TEST(Put200ElementsTest);
|
||||
CPPUNIT_TEST(Get30ElementsTest);
|
||||
CPPUNIT_TEST(Get200ElementsTest);
|
||||
CPPUNIT_TEST(Remove30ElementsTest);
|
||||
CPPUNIT_TEST(Remove200ElementsTest);
|
||||
CPPUNIT_TEST(Erase30ElementsTest);
|
||||
CPPUNIT_TEST(Erase200ElementsTest);
|
||||
CPPUNIT_TEST(MakeEmpty30ElementsTest);
|
||||
CPPUNIT_TEST(MakeEmpty200ElementsTest);
|
||||
CPPUNIT_TEST(Find30ElementsTest);
|
||||
CPPUNIT_TEST(Find200ElementsTest);
|
||||
CPPUNIT_TEST(FindClose30ElementsTest);
|
||||
CPPUNIT_TEST(FindClose200ElementsTest);
|
||||
CPPUNIT_TEST(Iterator30ElementsTest);
|
||||
CPPUNIT_TEST(Iterator200ElementsTest);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
typedef typename TestStrategy::EntryStrategy EntryStrategy;
|
||||
typedef typename TestStrategy::Key Key;
|
||||
typedef typename TestStrategy::Value Value;
|
||||
typedef typename TestStrategy::TestClass TestClass;
|
||||
typedef typename TestStrategy::MyMap MyMap;
|
||||
typedef typename TestClass::Iterator Iterator;
|
||||
typedef typename TestClass::ConstIterator ConstIterator;
|
||||
|
||||
void InsertTest(int32 maxNumber)
|
||||
{
|
||||
EntryStrategy entryStrategy;
|
||||
TestClass v;
|
||||
for (int32 i = 0; i < maxNumber; i++) {
|
||||
Key key;
|
||||
Value value;
|
||||
entryStrategy.Generate(key, value);
|
||||
v.Insert(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
void PutTest(int32 maxNumber)
|
||||
{
|
||||
EntryStrategy entryStrategy;
|
||||
TestClass v;
|
||||
for (int32 i = 0; i < maxNumber; i++) {
|
||||
Key key;
|
||||
Value value;
|
||||
entryStrategy.Generate(key, value);
|
||||
v.Put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
void GetTest(int32 maxNumber)
|
||||
{
|
||||
EntryStrategy entryStrategy;
|
||||
TestClass v;
|
||||
Fill(v, entryStrategy, maxNumber);
|
||||
const TestClass& cv = v;
|
||||
// find the keys in the map
|
||||
for (int32 i = 0; i < maxNumber; i++) {
|
||||
Iterator it = v.IteratorForIndex(i);
|
||||
Key key = it->Key();
|
||||
const Value& value = it->Value();
|
||||
CPPUNIT_ASSERT(&v.Get(key) == &value);
|
||||
CPPUNIT_ASSERT(&cv.Get(key) == &value);
|
||||
}
|
||||
}
|
||||
|
||||
void Fill(TestClass& v, EntryStrategy strategy, int32 maxNumber)
|
||||
{
|
||||
typedef typename EntryStrategy::Key Key;
|
||||
typedef typename EntryStrategy::Value Value;
|
||||
v.SetChecking(false);
|
||||
for (int32 i = 0; v.Count() < maxNumber; i++) {
|
||||
Key key;
|
||||
Value value;
|
||||
strategy.Generate(key, value);
|
||||
v.Put(key, value);
|
||||
}
|
||||
v.SetChecking(true);
|
||||
v.Check();
|
||||
}
|
||||
|
||||
void RemoveTest(int32 maxNumber)
|
||||
{
|
||||
EntryStrategy entryStrategy;
|
||||
TestClass v;
|
||||
Fill(v, entryStrategy, maxNumber);
|
||||
while (v.Count() > 0) {
|
||||
int32 index = rand() % (v.Count());
|
||||
Key key = v.IteratorForIndex(index)->Key();
|
||||
v.Remove(key);
|
||||
v.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
void EraseTest(int32 maxNumber)
|
||||
{
|
||||
EntryStrategy entryStrategy;
|
||||
TestClass v;
|
||||
Fill(v, entryStrategy, maxNumber);
|
||||
for (int32 i = maxNumber - 1; i >= 0; i--) {
|
||||
int32 index = rand() % (i + 1);
|
||||
v.Erase(v.IteratorForIndex(index));
|
||||
}
|
||||
}
|
||||
|
||||
void MakeEmptyTest(int32 maxNumber)
|
||||
{
|
||||
EntryStrategy entryStrategy;
|
||||
TestClass v;
|
||||
v.MakeEmpty();
|
||||
Fill(v, entryStrategy, maxNumber);
|
||||
v.MakeEmpty();
|
||||
v.MakeEmpty();
|
||||
}
|
||||
|
||||
void FindTest(int32 maxNumber)
|
||||
{
|
||||
EntryStrategy entryStrategy;
|
||||
TestClass v;
|
||||
Fill(v, entryStrategy, maxNumber);
|
||||
const TestClass& cv = v;
|
||||
// find the values in the set
|
||||
for (int32 i = 0; i < maxNumber; i++) {
|
||||
Key key = v.IteratorForIndex(i)->Key();
|
||||
Iterator it = v.Find(key);
|
||||
ConstIterator cit = cv.Find(key);
|
||||
CPPUNIT_ASSERT(it->Key() == key);
|
||||
CPPUNIT_ASSERT(it->Key() == cit->Key());
|
||||
CPPUNIT_ASSERT((*it).Key() == (*it).Key());
|
||||
CPPUNIT_ASSERT(&it->Value() == &cit->Value());
|
||||
CPPUNIT_ASSERT(&(*it).Value() == &(*it).Value());
|
||||
}
|
||||
// try to find some random values
|
||||
for (int32 i = 0; i < maxNumber; i++) {
|
||||
Key key = v.IteratorForIndex(i)->Key();
|
||||
Iterator it = v.Find(key);
|
||||
ConstIterator cit = cv.Find(key);
|
||||
if (it != v.End()) {
|
||||
CPPUNIT_ASSERT(it->Key() == key);
|
||||
CPPUNIT_ASSERT(it->Key() == cit->Key());
|
||||
CPPUNIT_ASSERT((*it).Key() == (*it).Key());
|
||||
CPPUNIT_ASSERT(&it->Value() == &cit->Value());
|
||||
CPPUNIT_ASSERT(&(*it).Value() == &(*it).Value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FindCloseTest(int32 maxNumber)
|
||||
{
|
||||
EntryStrategy entryStrategy;
|
||||
TestClass v;
|
||||
Fill(v, entryStrategy, maxNumber);
|
||||
const TestClass& cv = v;
|
||||
// find the values in the set
|
||||
for (int32 i = 0; i < maxNumber; i++) {
|
||||
Key key = v.IteratorForIndex(i)->Key();
|
||||
// less
|
||||
Iterator it = v.FindClose(key, true);
|
||||
ConstIterator cit = cv.FindClose(key, true);
|
||||
CPPUNIT_ASSERT(it->Key() == key);
|
||||
CPPUNIT_ASSERT(it->Key() == cit->Key());
|
||||
CPPUNIT_ASSERT((*it).Key() == (*it).Key());
|
||||
CPPUNIT_ASSERT(&it->Value() == &cit->Value());
|
||||
CPPUNIT_ASSERT(&(*it).Value() == &(*it).Value());
|
||||
// greater
|
||||
it = v.FindClose(key, false);
|
||||
cit = cv.FindClose(key, false);
|
||||
CPPUNIT_ASSERT(it->Key() == key);
|
||||
CPPUNIT_ASSERT(it->Key() == cit->Key());
|
||||
CPPUNIT_ASSERT((*it).Key() == (*it).Key());
|
||||
CPPUNIT_ASSERT(&it->Value() == &cit->Value());
|
||||
CPPUNIT_ASSERT(&(*it).Value() == &(*it).Value());
|
||||
}
|
||||
// try to find some random values
|
||||
for (int32 i = 0; i < maxNumber; i++) {
|
||||
Key key = entryStrategy.GenerateKey();
|
||||
// less
|
||||
Iterator it = v.FindClose(key, true);
|
||||
ConstIterator cit = cv.FindClose(key, true);
|
||||
if (it != v.End()) {
|
||||
CPPUNIT_ASSERT(it->Key() == cit->Key());
|
||||
CPPUNIT_ASSERT((*it).Key() == (*it).Key());
|
||||
CPPUNIT_ASSERT(&it->Value() == &cit->Value());
|
||||
CPPUNIT_ASSERT(&(*it).Value() == &(*it).Value());
|
||||
}
|
||||
// greater
|
||||
it = v.FindClose(key, false);
|
||||
cit = cv.FindClose(key, false);
|
||||
if (it != v.End()) {
|
||||
CPPUNIT_ASSERT(it->Key() == cit->Key());
|
||||
CPPUNIT_ASSERT((*it).Key() == (*it).Key());
|
||||
CPPUNIT_ASSERT(&it->Value() == &cit->Value());
|
||||
CPPUNIT_ASSERT(&(*it).Value() == &(*it).Value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IteratorTest(int32 maxNumber)
|
||||
{
|
||||
EntryStrategy entryStrategy;
|
||||
TestClass v;
|
||||
Fill(v, entryStrategy, maxNumber);
|
||||
const TestClass& cv = v;
|
||||
Iterator it = v.Begin();
|
||||
ConstIterator cit = cv.Begin();
|
||||
for (; it != v.End(); ++it, ++cit) {
|
||||
CPPUNIT_ASSERT(it->Key() == cit->Key());
|
||||
CPPUNIT_ASSERT(&it->Value() == &cit->Value());
|
||||
CPPUNIT_ASSERT(it->Key() == (*it).Key());
|
||||
CPPUNIT_ASSERT(cit->Key() == (*cit).Key());
|
||||
CPPUNIT_ASSERT(&it->Value() == &(*it).Value());
|
||||
CPPUNIT_ASSERT(&cit->Value() == &(*cit).Value());
|
||||
CPPUNIT_ASSERT(it->Key() == it.operator->().Key());
|
||||
CPPUNIT_ASSERT(&it->Value() == &it.operator->().Value());
|
||||
CPPUNIT_ASSERT(cit->Key() == cit.operator->().Key());
|
||||
CPPUNIT_ASSERT(&cit->Value() == &cit.operator->().Value());
|
||||
CPPUNIT_ASSERT(it);
|
||||
CPPUNIT_ASSERT(cit);
|
||||
}
|
||||
CPPUNIT_ASSERT(cit == cv.End());
|
||||
while (it != v.Begin()) {
|
||||
--it;
|
||||
--cit;
|
||||
CPPUNIT_ASSERT(it->Key() == cit->Key());
|
||||
CPPUNIT_ASSERT(&it->Value() == &cit->Value());
|
||||
CPPUNIT_ASSERT(it->Key() == (*it).Key());
|
||||
CPPUNIT_ASSERT(cit->Key() == (*cit).Key());
|
||||
CPPUNIT_ASSERT(&it->Value() == &(*it).Value());
|
||||
CPPUNIT_ASSERT(&cit->Value() == &(*cit).Value());
|
||||
CPPUNIT_ASSERT(it->Key() == it.operator->().Key());
|
||||
CPPUNIT_ASSERT(&it->Value() == &it.operator->().Value());
|
||||
CPPUNIT_ASSERT(cit->Key() == cit.operator->().Key());
|
||||
CPPUNIT_ASSERT(&cit->Value() == &cit.operator->().Value());
|
||||
CPPUNIT_ASSERT(it);
|
||||
CPPUNIT_ASSERT(cit);
|
||||
}
|
||||
CPPUNIT_ASSERT(cit == cv.Begin());
|
||||
CPPUNIT_ASSERT(!v.Null());
|
||||
CPPUNIT_ASSERT(!cv.Null());
|
||||
}
|
||||
|
||||
public:
|
||||
void ConstructorTest()
|
||||
{
|
||||
MyMap v1;
|
||||
CPPUNIT_ASSERT(v1.Count() == 0);
|
||||
CPPUNIT_ASSERT(v1.IsEmpty());
|
||||
}
|
||||
|
||||
void Put30ElementsTest() { PutTest(30); }
|
||||
void Put200ElementsTest() { PutTest(200); }
|
||||
void Get30ElementsTest() { GetTest(30); }
|
||||
void Get200ElementsTest() { GetTest(200); }
|
||||
void Insert30ElementsTest() { InsertTest(30); }
|
||||
void Insert200ElementsTest() { InsertTest(200); }
|
||||
void Remove30ElementsTest() { RemoveTest(30); }
|
||||
void Remove200ElementsTest() { RemoveTest(200); }
|
||||
void Erase30ElementsTest() { EraseTest(30); }
|
||||
void Erase200ElementsTest() { EraseTest(200); }
|
||||
void MakeEmpty30ElementsTest() { MakeEmptyTest(30); }
|
||||
void MakeEmpty200ElementsTest() { MakeEmptyTest(200); }
|
||||
void Find30ElementsTest() { FindTest(30); }
|
||||
void Find200ElementsTest() { FindTest(200); }
|
||||
void FindClose30ElementsTest() { FindCloseTest(30); }
|
||||
void FindClose200ElementsTest() { FindCloseTest(200); }
|
||||
void Iterator30ElementsTest() { IteratorTest(30); }
|
||||
void Iterator200ElementsTest() { IteratorTest(200); }
|
||||
};
|
||||
|
||||
|
||||
// That's how it should work, if we had a working compiler.
|
||||
/*
|
||||
@@ -39,7 +845,6 @@ typedef typename PairTestBase<int, int>::Strategy IntIntTestStrategy;
|
||||
*/
|
||||
|
||||
// ugly work-around:
|
||||
|
||||
template<typename Key, typename Value>
|
||||
struct PairTestBase {
|
||||
typedef SimpleValueStrategy<Key> KeyStrategy;
|
||||
@@ -48,38 +853,28 @@ struct PairTestBase {
|
||||
|
||||
template<typename CompareStrategy>
|
||||
struct MyMap
|
||||
: public VectorMap<Key, Value, VectorMapEntryStrategy::Pair<Key, Value,
|
||||
CompareStrategy> > {
|
||||
: public VectorMap<Key, Value, VectorMapEntryStrategy::Pair<Key, Value, CompareStrategy> > {
|
||||
};
|
||||
};
|
||||
|
||||
#define DECLARE_TEST_STRATEGY(Key, Value, Map, Strategy, ClassName) \
|
||||
template<typename CS> struct Map : PairTestBase<Key, Value>::MyMap<CS> {};\
|
||||
template<typename CS> \
|
||||
struct Strategy \
|
||||
: public TestStrategy<Map, PairTestBase<Key, Value>::EntryStrategy, \
|
||||
CS> { \
|
||||
static const char *kClassName; \
|
||||
}; \
|
||||
template<typename CS> const char *Strategy<CS>::kClassName = ClassName;
|
||||
|
||||
DECLARE_TEST_STRATEGY(int, int, IntIntMap, IntIntTestStrategy,
|
||||
"VectorMap<int, int, Pair>")
|
||||
DECLARE_TEST_STRATEGY(int, string, IntStringMap, IntStringTestStrategy,
|
||||
"VectorMap<int, string, Pair>")
|
||||
DECLARE_TEST_STRATEGY(string, int, StringIntMap, StringIntTestStrategy,
|
||||
"VectorMap<string, int, Pair>")
|
||||
DECLARE_TEST_STRATEGY(string, string, StringStringMap,
|
||||
StringStringTestStrategy,
|
||||
"VectorMap<string, string, Pair>")
|
||||
#define DECLARE_TEST_STRATEGY(Key, Value, Map, Strategy) \
|
||||
template<typename CS> struct Map : PairTestBase<Key, Value>::MyMap<CS> {}; \
|
||||
template<typename CS> \
|
||||
struct Strategy : public TestStrategy<Map, PairTestBase<Key, Value>::EntryStrategy, CS> {};
|
||||
|
||||
|
||||
DECLARE_TEST_STRATEGY(int, int, IntIntMap, IntIntTestStrategy)
|
||||
DECLARE_TEST_STRATEGY(int, string, IntStringMap, IntStringTestStrategy)
|
||||
DECLARE_TEST_STRATEGY(string, int, StringIntMap, StringIntTestStrategy)
|
||||
DECLARE_TEST_STRATEGY(string, string, StringStringMap, StringStringTestStrategy)
|
||||
|
||||
|
||||
// TestStrategy for the ImplicitKey entry strategy
|
||||
|
||||
// string_hash (from the Dragon Book: a slightly modified hashpjw())
|
||||
static inline
|
||||
int
|
||||
string_hash(const char *name)
|
||||
static inline int
|
||||
string_hash(const char* name)
|
||||
{
|
||||
uint32 h = 0;
|
||||
for (; *name; name++) {
|
||||
@@ -90,53 +885,45 @@ string_hash(const char *name)
|
||||
return (int)h;
|
||||
}
|
||||
|
||||
|
||||
struct ImplicitKeyTestGetKey {
|
||||
int operator()(string value) const
|
||||
{
|
||||
return string_hash(value.c_str());
|
||||
}
|
||||
int operator()(string value) const { return string_hash(value.c_str()); }
|
||||
};
|
||||
|
||||
|
||||
template<typename CompareStrategy>
|
||||
struct ImplicitKeyTestMap
|
||||
: public VectorMap<int, string,
|
||||
VectorMapEntryStrategy::ImplicitKey<int, string, ImplicitKeyTestGetKey,
|
||||
CompareStrategy> > {
|
||||
};
|
||||
struct ImplicitKeyTestMap : public VectorMap<int, string,
|
||||
VectorMapEntryStrategy::ImplicitKey<int, string,
|
||||
ImplicitKeyTestGetKey, CompareStrategy> > {};
|
||||
|
||||
typedef ImplicitKeyStrategy<SimpleValueStrategy<int>,
|
||||
SimpleValueStrategy<string>,
|
||||
ImplicitKeyTestGetKey>
|
||||
|
||||
typedef ImplicitKeyStrategy<SimpleValueStrategy<int>, SimpleValueStrategy<string>,
|
||||
ImplicitKeyTestGetKey>
|
||||
ImplicitKeyTestEntryStrategy;
|
||||
|
||||
|
||||
template<class CompareStrategy>
|
||||
struct ImplicitKeyTestStrategy : public TestStrategy<
|
||||
ImplicitKeyTestMap, ImplicitKeyTestEntryStrategy, CompareStrategy> {
|
||||
static const char *kClassName;
|
||||
};
|
||||
template<class CompareStrategy>
|
||||
const char *ImplicitKeyTestStrategy<CompareStrategy>::kClassName
|
||||
= "VectorMap<int, string, ImplicitKey>";
|
||||
struct ImplicitKeyTestStrategy
|
||||
: public TestStrategy<ImplicitKeyTestMap, ImplicitKeyTestEntryStrategy, CompareStrategy> {};
|
||||
|
||||
|
||||
// constructor
|
||||
VectorMapTest::VectorMapTest(std::string name)
|
||||
: BTestCase(name)
|
||||
{
|
||||
}
|
||||
|
||||
// Suite
|
||||
CppUnit::Test*
|
||||
VectorMapTest::Suite()
|
||||
{
|
||||
CppUnit::TestSuite *suite = new CppUnit::TestSuite("VectorMap");
|
||||
|
||||
suite->addTest(OrderedMapTest<IntIntTestStrategy>::Suite());
|
||||
suite->addTest(OrderedMapTest<IntStringTestStrategy>::Suite());
|
||||
suite->addTest(OrderedMapTest<StringIntTestStrategy>::Suite());
|
||||
suite->addTest(OrderedMapTest<StringStringTestStrategy>::Suite());
|
||||
suite->addTest(OrderedMapTest<ImplicitKeyTestStrategy>::Suite());
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
||||
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(VectorMapTest<IntIntTestStrategy<Ascending> >,
|
||||
getTestSuiteName());
|
||||
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(VectorMapTest<IntIntTestStrategy<Descending> >,
|
||||
getTestSuiteName());
|
||||
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(VectorMapTest<IntStringTestStrategy<Ascending> >,
|
||||
getTestSuiteName());
|
||||
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(VectorMapTest<IntStringTestStrategy<Descending> >,
|
||||
getTestSuiteName());
|
||||
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(VectorMapTest<StringIntTestStrategy<Ascending> >,
|
||||
getTestSuiteName());
|
||||
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(VectorMapTest<StringIntTestStrategy<Descending> >,
|
||||
getTestSuiteName());
|
||||
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(VectorMapTest<StringStringTestStrategy<Ascending> >,
|
||||
getTestSuiteName());
|
||||
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(VectorMapTest<StringStringTestStrategy<Descending> >,
|
||||
getTestSuiteName());
|
||||
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(VectorMapTest<ImplicitKeyTestStrategy<Ascending> >,
|
||||
getTestSuiteName());
|
||||
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(VectorMapTest<ImplicitKeyTestStrategy<Descending> >,
|
||||
getTestSuiteName());
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
#ifndef _vector_map_test_h_
|
||||
#define _vector_map_test_h_
|
||||
|
||||
#include <TestCase.h>
|
||||
|
||||
class VectorMapTest : public BTestCase {
|
||||
public:
|
||||
VectorMapTest(std::string name = "");
|
||||
|
||||
static CppUnit::Test* Suite();
|
||||
};
|
||||
|
||||
#endif // _vector_map_test_h_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,27 +0,0 @@
|
||||
#ifndef _vector_set_test_h_
|
||||
#define _vector_set_test_h_
|
||||
|
||||
#include <TestCase.h>
|
||||
|
||||
class VectorSetTest : public BTestCase {
|
||||
public:
|
||||
VectorSetTest(std::string name = "");
|
||||
|
||||
static CppUnit::Test* Suite();
|
||||
|
||||
void ConstructorTest();
|
||||
void InsertTest();
|
||||
void RemoveTest();
|
||||
void EraseTest();
|
||||
void MakeEmptyTest();
|
||||
void IndexAccessTest();
|
||||
void FindTest();
|
||||
void FindCloseTest();
|
||||
void IteratorTest();
|
||||
|
||||
private:
|
||||
template <class List>
|
||||
void TestList(List &list, typename List::ValueType *values, int valueCount);
|
||||
};
|
||||
|
||||
#endif // _vector_set_test_h_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,29 +0,0 @@
|
||||
#ifndef _vector_test_h_
|
||||
#define _vector_test_h_
|
||||
|
||||
#include <TestCase.h>
|
||||
|
||||
class VectorTest : public BTestCase {
|
||||
public:
|
||||
VectorTest(std::string name = "");
|
||||
|
||||
static CppUnit::Test* Suite();
|
||||
|
||||
void ConstructorTest1();
|
||||
void ConstructorTest2();
|
||||
void PushPopFrontTest();
|
||||
void PushPopBackTest();
|
||||
void InsertTest();
|
||||
void RemoveTest();
|
||||
void EraseTest();
|
||||
void MakeEmptyTest();
|
||||
void IndexAccessTest();
|
||||
void FindTest();
|
||||
void IteratorTest();
|
||||
|
||||
private:
|
||||
template <class List>
|
||||
void TestList(List &list, typename List::ValueType *values, int valueCount);
|
||||
};
|
||||
|
||||
#endif // _vector_test_h_
|
||||
Reference in New Issue
Block a user