///////////////////////////////////////////////////////////////////////////// // Copyright (c) Electronic Arts Inc. All rights reserved. ///////////////////////////////////////////////////////////////////////////// #include "EASTLTest.h" #include #include #include #ifdef _MSC_VER #pragma warning(push, 0) #endif #include #include #if defined(_MSC_VER) #pragma warning(pop) #endif using namespace eastl; namespace TestSDListLocal { struct IntNode : public intrusive_sdlist_node { IntNode() {} IntNode(int x) : mX(x) {} operator int() const { return mX; } int mX; }; typedef intrusive_sdlist IntrusiveSDList; template eastl::string IntListToString8(const T& cont) { eastl::string s("<"); char buf[64]; for(typename T::const_iterator it(cont.begin()), itEnd(cont.end()); it != itEnd; ++it) { const int& v = *it; sprintf(buf, " %d", v); s += buf; } s += " >"; return s; } template bool VerifyContainer(const T& cont, const char *testname, ...) { //if (!cont.validate()) { // EASTLTest_Printf("intrusive_list[%s] container damaged!\n", testname); // return false; //} typename T::const_iterator it(cont.begin()), itEnd(cont.end()); va_list val; int index = 0; va_start(val, testname); while(it != itEnd) { int next = va_arg(val, int); if (next == -1 || next != *it) { const int value = *it; const char* const pString = IntListToString8(cont).c_str(); EASTLTest_Printf("intrusive_list[%s] Mismatch at index %d: expected %d, found %d; contents: %s\n", testname, index, next, value, pString); va_end(val); return false; } ++it; ++index; } if (va_arg(val, int) != -1) { do { ++index; } while(va_arg(val, int) != -1); const int countainerSize = (int)cont.size(); const char* const pString = IntListToString8(cont).c_str(); EASTLTest_Printf("intrusive_list[%s] Too many elements: expected %d, found %d; contents: %s\n", testname, index, countainerSize, pString); va_end(val); return false; } va_end(val); // We silence this by default for a quieter test run. // EASTLTest_Printf("intrusive_list[%s] pass\n", testname); return true; } class ListInit { public: ListInit(intrusive_sdlist& container, IntNode* pNodeArray) : mpContainer(&container), mpNodeArray(pNodeArray) { mpContainer->clear(); } ListInit& operator+=(int x) { mpNodeArray->mX = x; mpContainer->push_back(*mpNodeArray++); return *this; } ListInit& operator,(int x) { mpNodeArray->mX = x; mpContainer->push_back(*mpNodeArray++); return *this; } protected: intrusive_sdlist* mpContainer; IntNode* mpNodeArray; }; } // namespace // Template instantations. // These tell the compiler to compile all the functions for the given class. template class eastl::intrusive_sdlist; int TestIntrusiveSDList() { using namespace TestSDListLocal; int nErrorCount = 0; IntNode nodes[20]; IntrusiveSDList l; // Enforce that the intrusive_list copy ctor is visible. If it is not, then // the class is not a POD type as it is supposed to. delete new IntrusiveSDList(l); // Enforce that offsetof() can be used with an intrusive_list in a struct; // it requires a POD type. Some compilers will flag warnings or even errors // when this is violated. struct Test { IntrusiveSDList m; }; #ifndef __GNUC__ // GCC warns on this, though strictly specaking it is allowed to. (void)offsetof(Test, m); #endif VERIFY(VerifyContainer(l, "ctor()", -1)); // push_back ListInit(l, nodes) += 0, 1, 2, 3, 4, 5, 6, 7, 8, 9; VERIFY(VerifyContainer(l, "push_back()", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1)); // iterator++ { IntrusiveSDList::iterator it1(l.begin()); IntrusiveSDList::iterator it2(l.begin()); ++it1; ++it2; if (it1 != it2++ || ++it1 != it2) { VERIFY(!"[iterator::increment] fail\n"); } } // clear()/empty() VERIFY(!l.empty()); l.clear(); VERIFY(VerifyContainer(l, "clear()", -1)); VERIFY(l.empty()); l.erase(l.begin(), l.end()); // Erase an already empty container. VERIFY(l.empty()); IntrusiveSDList l2; // splice //ListInit(l, nodes) += 0, 1, 2, 3, 4, 5, 6, 7, 8, 9; // //l.splice(++l.begin(), l, --l.end()); //VERIFY(VerifyContainer(l, "splice(single)", 0, 9, 1, 2, 3, 4, 5, 6, 7, 8, -1)); // //ListInit(l2, nodes+10) += 10, 11, 12, 13, 14, 15, 16, 17, 18, 19; // //l.splice(++++l.begin(), l2); //VERIFY(VerifyContainer(l2, "splice(whole)", -1)); //VERIFY(VerifyContainer(l, "splice(whole)", 0, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 1, 2, 3, 4, 5, 6, 7, 8, -1)); //l.splice(l.begin(), l, ++++l.begin(), ----l.end()); //VERIFY(VerifyContainer(l, "splice(range)", 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 1, 2, 3, 4, 5, 6, 0, 9, 7, 8, -1)); //l.clear(); //l.swap(l2); //VERIFY(VerifyContainer(l, "swap(empty)", -1)); //VERIFY(VerifyContainer(l2, "swap(empty)", -1)); //l2.push_back(nodes[0]); //l.splice(l.begin(), l2); //VERIFY(VerifyContainer(l, "splice(single)", 0, -1)); //VERIFY(VerifyContainer(l2, "splice(single)", -1)); // splice(single) -- evil case (splice at or right after current position) //ListInit(l, nodes) += 0, 1, 2, 3, 4; //l.splice(++++l.begin(), *++++l.begin()); //VERIFY(VerifyContainer(l, "splice(single)", 0, 1, 2, 3, 4, -1)); //l.splice(++++++l.begin(), *++++l.begin()); //VERIFY(VerifyContainer(l, "splice(single)", 0, 1, 2, 3, 4, -1)); // splice(range) -- evil case (splice right after current position) //ListInit(l, nodes) += 0, 1, 2, 3, 4; //l.splice(++++l.begin(), l, ++l.begin(), ++++l.begin()); //VERIFY(VerifyContainer(l, "splice(range)", 0, 1, 2, 3, 4, -1)); // push_front() l.clear(); l2.clear(); for(int i=4; i>=0; --i) { l.push_front(nodes[i]); l2.push_front(nodes[i+5]); } VERIFY(VerifyContainer(l, "push_front()", 0, 1, 2, 3, 4, -1)); VERIFY(VerifyContainer(l2, "push_front()", 5, 6, 7, 8, 9, -1)); // swap() l.swap(l2); VERIFY(VerifyContainer(l, "swap()", 5, 6, 7, 8, 9, -1)); VERIFY(VerifyContainer(l2, "swap()", 0, 1, 2, 3, 4, -1)); // erase() ListInit(l2, nodes) += 0, 1, 2, 3, 4; ListInit(l, nodes+5) += 5, 6, 7, 8, 9; l.erase(++++l.begin()); VERIFY(VerifyContainer(l, "erase(single)", 5, 6, 8, 9, -1)); l.erase(l.begin(), l.end()); VERIFY(VerifyContainer(l, "erase(all)", -1)); ListInit(l, nodes) += 0, 1, 2; VERIFY(l2.size() == 3); l2.pop_front(); VERIFY(VerifyContainer(l2, "pop_front()", 1, 2, -1)); l2.pop_back(); VERIFY(VerifyContainer(l2, "pop_back()", 1, -1)); // remove IntNode i1(1), i2(2), i3(3); l.clear(); l.push_front(i1); IntrusiveSDList::remove(i1); VERIFY(VerifyContainer(l, "remove()", -1)); l.push_front(i1); l.push_front(i2); IntrusiveSDList::remove(i1); VERIFY(VerifyContainer(l, "remove()", 2, -1)); l.push_front(i1); IntrusiveSDList::remove(i2); VERIFY(VerifyContainer(l, "remove()", 1, -1)); l.push_back(i2); l.push_back(i3); IntrusiveSDList::remove(i2); VERIFY(VerifyContainer(l, "remove()", 1, 3, -1)); // const_iterator / begin const intrusive_sdlist cilist; intrusive_sdlist::const_iterator cit; for(cit = cilist.begin(); cit != cilist.end(); ++cit) VERIFY(cit == cilist.end()); // This is guaranteed to be false. return nErrorCount; }