diff --git a/src/tests/kernel/core/util/OrderedMapTest.h b/src/tests/kernel/core/util/OrderedMapTest.h new file mode 100644 index 0000000000..dbdbba631f --- /dev/null +++ b/src/tests/kernel/core/util/OrderedMapTest.h @@ -0,0 +1,1166 @@ +// OrderedMapTest.h +#ifndef _ordered_map_test_h_ +#define _ordered_map_test_h_ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "common.h" + +// That's how it should be, but we need to work around compiler bugs +// (in this case an unimplemented feature). +/* +#define _ORDERED_MAP_TEST_TEMPLATE_LIST \ + template class CompareStrategy> \ + class TestStrategy> +*/ +#define _ORDERED_MAP_TEST_TEMPLATE_LIST \ + template class TestStrategy> +#define _ORDERED_MAP_TEST_CLASS_NAME OrderedMapTest + +//template class CompareStrategy> class TestStrategy> +template class TestStrategy> +class OrderedMapTest : public BTestCase { +public: + OrderedMapTest(std::string name = ""); + + static CppUnit::Test* Suite(); + + void ConstructorTest(); + void InsertTest(); + void PutTest(); + void GetTest(); + void RemoveTest(); + void EraseTest(); + void MakeEmptyTest(); + void IndexAccessTest(); + void FindTest(); + void FindCloseTest(); + void IteratorTest(); + +private: + template + void TestList(List &list, typename List::ValueType *values, int valueCount); +}; + +// SimpleValueStrategy +template +class SimpleValueStrategy { +public: + typedef _Value Value; + + SimpleValueStrategy(int32 differentValues = 100000) + : fDifferentValues(differentValues) + { + srand(0); + } + + Value Generate(); + +private: + int32 fDifferentValues; +}; + +template<> +int +SimpleValueStrategy::Generate() +{ + return rand() % fDifferentValues; +} + +template<> +string +SimpleValueStrategy::Generate() +{ + char buffer[10]; + sprintf(buffer, "%ld", rand() % fDifferentValues); + return string(buffer); +} + +// PairEntryStrategy +template +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; +}; + +// ImplicitKeyStrategy +template +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 + class Strategy : public KernelUtilsOrder::Ascending {}; +}; + +// Non-template wrapper for the Descending compare strategy. +// Work-around for our compiler not eating nested template template +// parameters. +struct Descending { + template + class Strategy : public KernelUtilsOrder::Descending {}; +}; + +// CompareWrapper +template +class CompareWrapper { +public: + inline bool operator()(const Value &a, const Value &b) const + { + return (fCompare(a, b) < 0); + } + +private: + Compare fCompare; +}; + + +// TestIterator +template +class TestIterator { +private: + typedef TestIterator + 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) + { + CHK(fMyIterator == other.fMyIterator); + } + + inline Iterator &operator++() + { + MyIterator &myResult = ++fMyIterator; + ReferenceIterator &refResult = ++fReferenceIterator; + if (refResult == fMap->fReferenceMap.end()) + CHK(myResult == fMap->fMyMap.End()); + else { + CHK(myResult->Key() == refResult->first); + CHK(myResult->Value() == refResult->second); + } + return *this; + } + + inline Iterator operator++(int) + { + MyIterator oldMyResult = fMyIterator; + MyIterator myResult = fMyIterator++; + ReferenceIterator refResult = fReferenceIterator++; + CHK(oldMyResult == myResult); + if (refResult == fMap->fReferenceMap.end()) + CHK(myResult == fMap->fMyMap.End()); + else { + CHK(myResult->Key() == refResult->first); + CHK(myResult->Value() == refResult->second); + } + return Iterator(fMap, myResult, refResult); + } + + inline Iterator &operator--() + { + MyIterator &myResult = --fMyIterator; + ReferenceIterator &refResult = --fReferenceIterator; + CHK(myResult->Key() == refResult->first); + CHK(myResult->Value() == refResult->second); + return *this; + } + + inline Iterator operator--(int) + { + MyIterator oldMyResult = fMyIterator; + MyIterator myResult = fMyIterator--; + ReferenceIterator refResult = fReferenceIterator--; + CHK(oldMyResult == myResult); + CHK(myResult->Key() == refResult->first); + CHK(myResult->Value() == refResult->second); + return Iterator(fMap, myResult, refResult); + } + + inline Iterator &operator=(const Iterator &other) + { + fMap = other.fMap; + fMyIterator = other.fMyIterator; + fReferenceIterator = other.fReferenceIterator; + CHK(fMyIterator == other.fMyIterator); + return *this; + } + + inline bool operator==(const Iterator &other) const + { + bool result = (fMyIterator == other.fMyIterator); + CHK((fReferenceIterator == other.fReferenceIterator) == result); + return result; + } + + inline bool operator!=(const Iterator &other) const + { + bool result = (fMyIterator != other.fMyIterator); + CHK((fReferenceIterator != other.fReferenceIterator) == result); + return result; + } + + inline Entry operator*() const + { + Entry entry = *fMyIterator; + CHK(entry.Key() == fReferenceIterator->first); + CHK(entry.Value() == fReferenceIterator->second); + return entry; + } + + inline Entry operator->() const + { + Entry entry = fMyIterator.operator->(); + CHK(entry.Key() == fReferenceIterator->first); + CHK(entry.Value() == fReferenceIterator->second); + return entry; + } + + inline operator bool() const + { + bool result = fMyIterator; + CHK((fMyIterator == fMap->fMyMap.Null()) != result); + return result; + } + +public: + TestMap *fMap; + MyIterator fMyIterator; + ReferenceIterator fReferenceIterator; +}; + +// TestMap +template +class TestMap { +public: + typedef TestMap 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 Iterator; + typedef TestIterator ConstIterator; + + TestMap() + : fMyMap(), + fReferenceMap(), + fChecking(true) + { + } + + void Insert(const Key &key, const Value &value) + { + CHK(fMyMap.Insert(key, value) == B_OK); + fReferenceMap[key] = value; + Check(); + } + + void Put(const Key &key, const Value &value) + { + CHK(fMyMap.Put(key, value) == B_OK); + fReferenceMap[key] = value; + Check(); + } + + Value &Get(const Key &key) + { + Value &value = fMyMap.Get(key); + CHK(value == fReferenceMap[key]); + return value; + } + + const Value &Get(const Key &key) const + { + const Value &value = fMyMap.Get(key); + CHK(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(); + CHK(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) { + CHK(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()) + CHK(myIt == fMyMap.End()); + else { + CHK(myIt->Key() == refIt->first); + CHK(myIt->Value() == refIt->second); + } + return Iterator(this, myIt, refIt); + } + + inline int32 Count() const + { + int32 count = fReferenceMap.size(); + CHK(fMyMap.Count() == count); + return count; + } + + inline bool IsEmpty() const + { + bool result = fReferenceMap.empty(); + CHK(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()) + CHK(myIt = fMyMap.End()); + else { + CHK(myIt->Key() == refIt->first); + CHK(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()) + CHK(myIt = fMyMap.End()); + else { + CHK(myIt->Key() == refIt->first); + CHK(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) + CHK(fCompare(fMyMap.Begin()->Key(), key) > 0); + else + CHK(fCompare((--MyIterator(myIt))->Key(), key) < 0); + } + return End(); + } + if (less) { + CHK(fCompare(myIt->Key(), key) <= 0); + MyIterator nextMyIt(myIt); + ++nextMyIt; + if (nextMyIt != fMyMap.End()) + CHK(fCompare(nextMyIt->Key(), key) > 0); + } else { + CHK(fCompare(myIt->Key(), key) >= 0); + if (myIt != fMyMap.Begin()) { + MyIterator prevMyIt(myIt); + --prevMyIt; + CHK(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) + CHK(fCompare(fMyMap.Begin()->Key(), key) > 0); + else + CHK(fCompare((--MyConstIterator(myIt))->Key(), key) < 0); + } + return End(); + } + if (less) { + CHK(fCompare(myIt->Key(), key) <= 0); + MyConstIterator nextMyIt(myIt); + ++nextMyIt; + if (nextMyIt != fMyMap.End()) + CHK(fCompare(nextMyIt->Key(), key) > 0); + } else { + CHK(fCompare(myIt->Key(), key) >= 0); + if (myIt != fMyMap.Begin()) { + MyConstIterator prevMyIt(myIt); + --prevMyIt; + CHK(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(); + CHK(fMyMap.Count() == count); + CHK(fMyMap.IsEmpty() == fReferenceMap.empty()); + MyConstIterator myIt = fMyMap.Begin(); + ReferenceConstIterator refIt = fReferenceMap.begin(); + for (int32 i = 0; i < count; i++, ++myIt, ++refIt) { + CHK(myIt->Key() == refIt->first); + CHK(myIt->Value() == refIt->second); + CHK((*myIt).Key() == refIt->first); + CHK((*myIt).Value() == refIt->second); + } + CHK(myIt == fMyMap.End()); + } + } + +//private: +public: + MyMap fMyMap; + ReferenceMap fReferenceMap; + bool fChecking; + Compare fCompare; +}; + + +// TestStrategy +template