#include #include #include using std::set; #include #include #include #include #include #include "common.h" #include "VectorSetTest.h" using VectorSetOrder::Ascending; using VectorSetOrder::Descending; VectorSetTest::VectorSetTest(std::string name) : BTestCase(name) { } CppUnit::Test* VectorSetTest::Suite() { CppUnit::TestSuite *suite = new CppUnit::TestSuite("VectorSet"); ADD_TEST4(VectorSet, suite, VectorSetTest, ConstructorTest); ADD_TEST4(VectorSet, suite, VectorSetTest, InsertTest); ADD_TEST4(VectorSet, suite, VectorSetTest, RemoveTest); ADD_TEST4(VectorSet, suite, VectorSetTest, EraseTest); ADD_TEST4(VectorSet, suite, VectorSetTest, MakeEmptyTest); ADD_TEST4(VectorSet, suite, VectorSetTest, FindTest); ADD_TEST4(VectorSet, suite, VectorSetTest, FindCloseTest); ADD_TEST4(VectorSet, suite, VectorSetTest, IteratorTest); return suite; } //! ConstructorTest void VectorSetTest::ConstructorTest() { NextSubTest(); VectorSet v1(100); CHK(v1.Count() == 0); CHK(v1.IsEmpty()); NextSubTest(); VectorSet v2(100); CHK(v2.Count() == 0); CHK(v2.IsEmpty()); NextSubTest(); VectorSet v3(0); CHK(v3.Count() == 0); CHK(v3.IsEmpty()); NextSubTest(); VectorSet v4(0); CHK(v4.Count() == 0); CHK(v4.IsEmpty()); } // TestIterator template class TestIterator { private: typedef TestIterator Iterator; public: inline TestIterator(TestSet *s, MyIterator myIt, ReferenceIterator refIt) : fSet(s), fMyIterator(myIt), fReferenceIterator(refIt) { } inline TestIterator(const Iterator &other) : fSet(other.fSet), fMyIterator(other.fMyIterator), fReferenceIterator(other.fReferenceIterator) { CHK(fMyIterator == other.fMyIterator); } inline Iterator &operator++() { MyIterator &myResult = ++fMyIterator; ReferenceIterator &refResult = ++fReferenceIterator; if (refResult == fSet->fReferenceSet.end()) CHK(myResult == fSet->fMySet.End()); else CHK(*myResult == *refResult); return *this; } inline Iterator operator++(int) { MyIterator oldMyResult = fMyIterator; MyIterator myResult = fMyIterator++; ReferenceIterator refResult = fReferenceIterator++; CHK(oldMyResult == myResult); if (refResult == fSet->fReferenceSet.end()) CHK(myResult == fSet->fMySet.End()); else CHK(*myResult == *refResult); return Iterator(fSet, myResult, refResult); } inline Iterator &operator--() { MyIterator &myResult = --fMyIterator; ReferenceIterator &refResult = --fReferenceIterator; CHK(*myResult == *refResult); return *this; } inline Iterator operator--(int) { MyIterator oldMyResult = fMyIterator; MyIterator myResult = fMyIterator--; ReferenceIterator refResult = fReferenceIterator--; CHK(oldMyResult == myResult); CHK(*myResult == *refResult); return Iterator(fSet, myResult, refResult); } inline Iterator &operator=(const Iterator &other) { fSet = other.fSet; 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 Value &operator*() const { Value &result = *fMyIterator; CHK(result == *fReferenceIterator); return result; } inline Value *operator->() const { Value *result = fMyIterator.operator->(); CHK(*result == *fReferenceIterator); return result; } inline operator bool() const { bool result = fMyIterator; CHK((fMyIterator == fSet->fMySet.Null()) != result); return result; } public: TestSet *fSet; MyIterator fMyIterator; ReferenceIterator fReferenceIterator; }; // TestSet template class TestSet { public: typedef TestSet Class; typedef typename MySet::Iterator MyIterator; typedef typename ReferenceSet::iterator ReferenceIterator; typedef typename MySet::ConstIterator MyConstIterator; typedef typename ReferenceSet::const_iterator ReferenceConstIterator; typedef TestIterator Iterator; typedef TestIterator ConstIterator; TestSet() : fMySet(), fReferenceSet(), fChecking(true) { } void Insert(const Value &value, bool replace = true) { CHK(fMySet.Insert(value, replace) == B_OK); ReferenceIterator it = fReferenceSet.find(value); if (it != fReferenceSet.end()) fReferenceSet.erase(it); fReferenceSet.insert(value); Check(); } void Remove(const Value &value) { int32 oldCount = Count(); fReferenceSet.erase(value); int32 newCount = fReferenceSet.size(); CHK(fMySet.Remove(value) == oldCount - newCount); Check(); } Iterator Erase(const Iterator &iterator) { bool outOfRange = (iterator.fReferenceIterator == fReferenceSet.end()); MyIterator myIt = fMySet.Erase(iterator.fMyIterator); if (outOfRange) { CHK(myIt == fMySet.Null()); return Iterator(this, myIt, fReferenceSet.end()); } Value nextValue; ReferenceIterator refIt = iterator.fReferenceIterator; ++refIt; bool noNextValue = (refIt == fReferenceSet.end()); if (!noNextValue) nextValue = *refIt; fReferenceSet.erase(iterator.fReferenceIterator); if (noNextValue) refIt = fReferenceSet.end(); else refIt = fReferenceSet.find(nextValue); Check(); if (refIt == fReferenceSet.end()) CHK(myIt == fMySet.End()); else CHK(*myIt == *refIt); return Iterator(this, myIt, refIt); } inline int32 Count() const { int32 count = fReferenceSet.size(); CHK(fMySet.Count() == count); return count; } inline bool IsEmpty() const { bool result = fReferenceSet.empty(); CHK(fMySet.IsEmpty() == result); return result; } void MakeEmpty() { fMySet.MakeEmpty(); fReferenceSet.clear(); Check(); } inline Iterator Begin() { return Iterator(this, fMySet.Begin(), fReferenceSet.begin()); } inline ConstIterator Begin() const { return ConstIterator(this, fMySet.Begin(), fReferenceSet.begin()); } inline Iterator End() { return Iterator(this, fMySet.End(), fReferenceSet.end()); } inline ConstIterator End() const { return ConstIterator(this, fMySet.End(), fReferenceSet.end()); } inline Iterator Null() { return Iterator(this, fMySet.Null(), fReferenceSet.end()); } inline ConstIterator Null() const { return ConstIterator(this, fMySet.Null(), fReferenceSet.end()); } // for testing only inline Iterator IteratorForIndex(int32 index) { if (index < 0 || index > Count()) return End(); MyIterator myIt = fMySet.Begin(); ReferenceIterator refIt = fReferenceSet.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 = fMySet.Begin(); ReferenceConstIterator refIt = fReferenceSet.begin(); for (int32 i = 0; i < index; i++) { ++myIt; ++refIt; } return ConstIterator(this, myIt, refIt); } Iterator Find(const Value &value) { MyIterator myIt = fMySet.Find(value); ReferenceIterator refIt = fReferenceSet.find(value); if (refIt == fReferenceSet.end()) CHK(myIt = fMySet.End()); else CHK(*myIt == *refIt); return Iterator(this, myIt, refIt); } ConstIterator Find(const Value &value) const { MyConstIterator myIt = fMySet.Find(value); ReferenceConstIterator refIt = fReferenceSet.find(value); if (refIt == fReferenceSet.end()) CHK(myIt = fMySet.End()); else CHK(*myIt == *refIt); return ConstIterator(this, myIt, refIt); } Iterator FindClose(const Value &value, bool less) { MyIterator myIt = fMySet.FindClose(value, less); if (myIt == fMySet.End()) { if (fMySet.Count() > 0) { if (less) CHK(fCompare(*fMySet.Begin(), value) > 0); else CHK(fCompare(*--MyIterator(myIt), value) < 0); } return End(); } if (less) { CHK(fCompare(*myIt, value) <= 0); MyIterator nextMyIt(myIt); ++nextMyIt; if (nextMyIt != fMySet.End()) CHK(fCompare(*nextMyIt, value) > 0); } else { CHK(fCompare(*myIt, value) >= 0); if (myIt != fMySet.Begin()) { MyIterator prevMyIt(myIt); --prevMyIt; CHK(fCompare(*prevMyIt, value) < 0); } } return Iterator(this, myIt, fReferenceSet.find(*myIt)); } ConstIterator FindClose(const Value &value, bool less) const { MyConstIterator myIt = fMySet.FindClose(value, less); if (myIt == fMySet.End()) { if (fMySet.Count() > 0) { if (less) CHK(fCompare(*fMySet.Begin(), value) > 0); else CHK(fCompare(*--MyConstIterator(myIt), value) < 0); } return End(); } if (less) { CHK(fCompare(*myIt, value) <= 0); MyConstIterator nextMyIt(myIt); ++nextMyIt; if (nextMyIt != fMySet.End()) CHK(fCompare(*nextMyIt, value) > 0); } else { CHK(fCompare(*myIt, value) >= 0); if (myIt != fMySet.Begin()) { MyConstIterator prevMyIt(myIt); --prevMyIt; CHK(fCompare(*prevMyIt, value) < 0); } } return ConstIterator(this, myIt, fReferenceSet.find(*myIt)); } void SetChecking(bool enable) { fChecking = enable; } void Check() const { if (fChecking) { int32 count = fReferenceSet.size(); CHK(fMySet.Count() == count); CHK(fMySet.IsEmpty() == fReferenceSet.empty()); MyConstIterator myIt = fMySet.Begin(); ReferenceConstIterator refIt = fReferenceSet.begin(); for (int32 i = 0; i < count; i++, ++myIt, ++refIt) CHK(*myIt == *refIt); CHK(myIt == fMySet.End()); } } //private: public: MySet fMySet; ReferenceSet fReferenceSet; bool fChecking; Compare fCompare; }; // IntStrategy class IntStrategy { public: typedef int Value; IntStrategy(int32 differentValues = 100000) : fDifferentValues(differentValues) { srand(0); } Value Generate() { return rand() % fDifferentValues; } private: int32 fDifferentValues; }; // StringStrategy class StringStrategy { public: typedef string Value; StringStrategy(int32 differentValues = 100000) : fDifferentValues(differentValues) { srand(0); } Value Generate() { char buffer[10]; sprintf(buffer, "%ld", rand() % fDifferentValues); return string(buffer); } private: int32 fDifferentValues; }; // CompareWrapper template class CompareWrapper { public: inline bool operator()(const Value &a, const Value &b) const { return (fCompare(a, b) < 0); } private: Compare fCompare; }; // TestStrategy template class _CompareStrategy> class TestStrategy { public: typedef _ValueStrategy ValueStrategy; typedef typename ValueStrategy::Value Value; typedef _CompareStrategy Compare; typedef CompareWrapper BoolCompare; typedef VectorSet MySet; typedef set ReferenceSet; typedef TestSet TestClass; }; typedef TestStrategy AIntTestStrategy; typedef TestStrategy AStringTestStrategy; typedef TestStrategy DIntTestStrategy; typedef TestStrategy DStringTestStrategy; // GenericInsertTest template static void GenericInsertTest(int32 maxNumber) { typedef typename _TestStrategy::ValueStrategy ValueStrategy; typedef typename _TestStrategy::TestClass TestClass; ValueStrategy strategy; TestClass v; for (int32 i = 0; i < maxNumber; i++) v.Insert(strategy.Generate()); } // InsertTest void VectorSetTest::InsertTest() { NextSubTest(); GenericInsertTest(30); NextSubTest(); GenericInsertTest(30); NextSubTest(); GenericInsertTest(200); NextSubTest(); GenericInsertTest(200); NextSubTest(); GenericInsertTest(30); NextSubTest(); GenericInsertTest(30); NextSubTest(); GenericInsertTest(200); NextSubTest(); GenericInsertTest(200); } // GenericFill template static void GenericFill(TestClass &v, ValueStrategy strategy, int32 maxNumber) { v.SetChecking(false); for (int32 i = 0; v.Count() < maxNumber; i++) v.Insert(strategy.Generate()); v.SetChecking(true); v.Check(); } // GenericRemoveTest template static void GenericRemoveTest(int32 maxNumber) { typedef typename _TestStrategy::ValueStrategy ValueStrategy; typedef typename _TestStrategy::Value Value; typedef typename _TestStrategy::TestClass TestClass; ValueStrategy strategy; TestClass v; GenericFill(v, strategy, maxNumber); while (v.Count() > 0) { int32 index = rand() % (v.Count()); Value value = *v.IteratorForIndex(index); v.Remove(value); v.Remove(value); } } // RemoveTest void VectorSetTest::RemoveTest() { NextSubTest(); GenericRemoveTest(30); NextSubTest(); GenericRemoveTest(30); NextSubTest(); GenericRemoveTest(200); NextSubTest(); GenericRemoveTest(200); NextSubTest(); GenericRemoveTest(30); NextSubTest(); GenericRemoveTest(30); NextSubTest(); GenericRemoveTest(200); NextSubTest(); GenericRemoveTest(200); } // GenericEraseTest template static void GenericEraseTest(int32 maxNumber) { typedef typename _TestStrategy::ValueStrategy ValueStrategy; typedef typename _TestStrategy::TestClass TestClass; ValueStrategy strategy; TestClass v; GenericFill(v, strategy, maxNumber); for (int32 i = maxNumber - 1; i >= 0; i--) { int32 index = rand() % (i + 1); v.Erase(v.IteratorForIndex(index)); } } // EraseTest void VectorSetTest::EraseTest() { NextSubTest(); GenericEraseTest(30); NextSubTest(); GenericEraseTest(30); NextSubTest(); GenericEraseTest(200); NextSubTest(); GenericEraseTest(200); NextSubTest(); GenericEraseTest(30); NextSubTest(); GenericEraseTest(30); NextSubTest(); GenericEraseTest(200); NextSubTest(); GenericEraseTest(200); } // GenericMakeEmptyTest template static void GenericMakeEmptyTest(int32 maxNumber) { typedef typename _TestStrategy::ValueStrategy ValueStrategy; typedef typename _TestStrategy::TestClass TestClass; ValueStrategy strategy; TestClass v; v.MakeEmpty(); GenericFill(v, strategy, maxNumber); v.MakeEmpty(); v.MakeEmpty(); } // MakeEmptyTest void VectorSetTest::MakeEmptyTest() { NextSubTest(); GenericMakeEmptyTest(30); NextSubTest(); GenericMakeEmptyTest(30); NextSubTest(); GenericMakeEmptyTest(200); NextSubTest(); GenericMakeEmptyTest(200); NextSubTest(); GenericMakeEmptyTest(30); NextSubTest(); GenericMakeEmptyTest(30); NextSubTest(); GenericMakeEmptyTest(200); NextSubTest(); GenericMakeEmptyTest(200); } // GenericFindTest template static void GenericFindTest(int32 maxNumber) { typedef typename _TestStrategy::ValueStrategy ValueStrategy; typedef typename _TestStrategy::Value Value; typedef typename _TestStrategy::TestClass TestClass; typedef typename TestClass::Iterator Iterator; typedef typename TestClass::ConstIterator ConstIterator; ValueStrategy strategy; TestClass v; GenericFill(v, strategy, maxNumber); const TestClass &cv = v; // find the values in the set for (int32 i = 0; i < maxNumber; i++) { const Value &value = *v.IteratorForIndex(i); Iterator it = v.Find(value); ConstIterator cit = cv.Find(value); CHK(&*it == &*cit); } // try to find some random values for (int32 i = 0; i < maxNumber; i++) { Value value = strategy.Generate(); Iterator it = v.Find(value); ConstIterator cit = cv.Find(value); if (it != v.End()) CHK(&*it == &*cit); } } // FindTest void VectorSetTest::FindTest() { NextSubTest(); GenericFindTest(30); NextSubTest(); GenericFindTest(30); NextSubTest(); GenericFindTest(200); NextSubTest(); GenericFindTest(200); NextSubTest(); GenericFindTest(30); NextSubTest(); GenericFindTest(30); NextSubTest(); GenericFindTest(200); NextSubTest(); GenericFindTest(200); } // GenericFindCloseTest template static void GenericFindCloseTest(int32 maxNumber) { typedef typename _TestStrategy::ValueStrategy ValueStrategy; typedef typename _TestStrategy::Value Value; typedef typename _TestStrategy::TestClass TestClass; typedef typename TestClass::Iterator Iterator; typedef typename TestClass::ConstIterator ConstIterator; ValueStrategy strategy; TestClass v; GenericFill(v, strategy, maxNumber); const TestClass &cv = v; // find the values in the set for (int32 i = 0; i < maxNumber; i++) { const Value &value = *v.IteratorForIndex(i); // less Iterator it = v.FindClose(value, true); ConstIterator cit = cv.FindClose(value, true); CHK(*it == value); CHK(&*it == &*cit); // greater it = v.FindClose(value, false); cit = cv.FindClose(value, false); CHK(*it == value); CHK(&*it == &*cit); } // try to find some random values for (int32 i = 0; i < maxNumber; i++) { Value value = strategy.Generate(); // less Iterator it = v.FindClose(value, true); ConstIterator cit = cv.FindClose(value, true); if (it != v.End()) CHK(&*it == &*cit); // greater it = v.FindClose(value, false); cit = cv.FindClose(value, false); if (it != v.End()) CHK(&*it == &*cit); } } // FindCloseTest void VectorSetTest::FindCloseTest() { NextSubTest(); GenericFindCloseTest(30); NextSubTest(); GenericFindCloseTest(30); NextSubTest(); GenericFindCloseTest(200); NextSubTest(); GenericFindCloseTest(200); NextSubTest(); GenericFindCloseTest(30); NextSubTest(); GenericFindCloseTest(30); NextSubTest(); GenericFindCloseTest(200); NextSubTest(); GenericFindCloseTest(200); } // GenericIteratorTest template static void GenericIteratorTest(int32 maxNumber) { typedef typename _TestStrategy::ValueStrategy ValueStrategy; typedef typename _TestStrategy::TestClass TestClass; typedef typename TestClass::Iterator Iterator; typedef typename TestClass::ConstIterator ConstIterator; ValueStrategy strategy; TestClass v; GenericFill(v, strategy, maxNumber); const TestClass &cv = v; Iterator it = v.Begin(); ConstIterator cit = cv.Begin(); for (; it != v.End(); ++it, ++cit) { CHK(&*it == &*cit); CHK(&*it == it.operator->()); CHK(&*cit == cit.operator->()); CHK(it); CHK(cit); } CHK(cit == cv.End()); while (it != v.Begin()) { --it; --cit; CHK(&*it == &*cit); CHK(&*it == it.operator->()); CHK(&*cit == cit.operator->()); CHK(it); CHK(cit); } CHK(cit == cv.Begin()); CHK(!v.Null()); CHK(!cv.Null()); } // IteratorTest void VectorSetTest::IteratorTest() { NextSubTest(); GenericIteratorTest(30); NextSubTest(); GenericIteratorTest(30); NextSubTest(); GenericIteratorTest(200); NextSubTest(); GenericIteratorTest(200); NextSubTest(); GenericIteratorTest(30); NextSubTest(); GenericIteratorTest(30); NextSubTest(); GenericIteratorTest(200); NextSubTest(); GenericIteratorTest(200); }