// OrderedMapTest.h #ifndef _ordered_map_test_h_ #define _ordered_map_test_h_ #include #include #include using std::map; #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