aboutsummaryrefslogtreecommitdiff
path: root/EASTL/test/source/TestIntrusiveList.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'EASTL/test/source/TestIntrusiveList.cpp')
-rw-r--r--EASTL/test/source/TestIntrusiveList.cpp403
1 files changed, 403 insertions, 0 deletions
diff --git a/EASTL/test/source/TestIntrusiveList.cpp b/EASTL/test/source/TestIntrusiveList.cpp
new file mode 100644
index 0000000..60b2378
--- /dev/null
+++ b/EASTL/test/source/TestIntrusiveList.cpp
@@ -0,0 +1,403 @@
+/////////////////////////////////////////////////////////////////////////////
+// Copyright (c) Electronic Arts Inc. All rights reserved.
+/////////////////////////////////////////////////////////////////////////////
+
+
+#include "EASTLTest.h"
+#include <EASTL/intrusive_list.h>
+#include <EABase/eabase.h>
+
+EA_DISABLE_ALL_VC_WARNINGS()
+#include <stdio.h>
+#include <stdarg.h>
+#include <stddef.h>
+
+#ifndef EA_COMPILER_NO_STANDARD_CPP_LIBRARY
+ #include <string>
+#endif
+EA_RESTORE_ALL_VC_WARNINGS()
+
+using namespace eastl;
+
+
+namespace
+{
+
+ /// IntNode
+ ///
+ /// Test intrusive_list node.
+ ///
+ struct IntNode : public eastl::intrusive_list_node
+ {
+ int mX;
+
+ IntNode(int x = 0)
+ : mX(x) { }
+
+ operator int() const
+ { return mX; }
+ };
+
+
+ /// ListInit
+ ///
+ /// Utility class for setting up a list.
+ ///
+ class ListInit
+ {
+ public:
+ ListInit(intrusive_list<IntNode>& 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_list<IntNode>* mpContainer;
+ IntNode* mpNodeArray;
+ };
+
+} // namespace
+
+
+
+
+// Template instantations.
+// These tell the compiler to compile all the functions for the given class.
+template class eastl::intrusive_list<IntNode>;
+
+
+
+int TestIntrusiveList()
+{
+ int nErrorCount = 0;
+ int i;
+
+ {
+ // Verify that intrusive_list_node is a POD, at least when EASTL_VALIDATE_INTRUSIVE_LIST is disabled.
+ #if !EASTL_VALIDATE_INTRUSIVE_LIST
+ // is_pod doesn't currently detect structs as PODs, even though it should.
+ // This is due to limitations in C++.
+ // VERIFY(eastl::is_pod<eastl::intrusive_list_node>::value);
+
+ const size_t offset = offsetof(intrusive_list_node, mpPrev);
+ VERIFY(offset == sizeof(intrusive_list_node*));
+ #endif
+ }
+
+ {
+ IntNode nodes[20];
+
+ intrusive_list<IntNode> ilist;
+
+ // 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 be.
+ delete new intrusive_list<IntNode>(ilist);
+
+ #ifndef __GNUC__ // GCC warns on this, though strictly specaking it is allowed to.
+ // 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 {
+ intrusive_list<IntNode> m;
+ };
+ (void)offsetof(Test, m);
+ #endif
+
+ // begin / end
+ VERIFY(VerifySequence(ilist.begin(), ilist.end(), int(), "ctor()", -1));
+
+
+ // push_back
+ ListInit(ilist, nodes) += 0, 1, 2, 3, 4, 5, 6, 7, 8, 9;
+ VERIFY(VerifySequence(ilist.begin(), ilist.end(), int(), "push_back()", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1));
+
+
+ // iterator / begin
+ intrusive_list<IntNode>::iterator it = ilist.begin();
+ VERIFY(it->mX == 0);
+ ++it;
+ VERIFY(it->mX == 1);
+ ++it;
+ VERIFY(it->mX == 2);
+ ++it;
+ VERIFY(it->mX == 3);
+
+
+ // const_iterator / begin
+ const intrusive_list<IntNode> cilist;
+ intrusive_list<IntNode>::const_iterator cit;
+ for(cit = cilist.begin(); cit != cilist.end(); ++cit)
+ VERIFY(cit == cilist.end()); // This is guaranteed to be false.
+
+
+ // reverse_iterator / rbegin
+ intrusive_list<IntNode>::reverse_iterator itr = ilist.rbegin();
+ VERIFY(itr->mX == 9);
+ ++itr;
+ VERIFY(itr->mX == 8);
+ ++itr;
+ VERIFY(itr->mX == 7);
+ ++itr;
+ VERIFY(itr->mX == 6);
+
+
+ // iterator++/--
+ {
+ intrusive_list<IntNode>::iterator it1(ilist.begin());
+ intrusive_list<IntNode>::iterator it2(ilist.begin());
+
+ ++it1;
+ ++it2;
+ if ((it1 != it2++) || (++it1 != it2))
+ VERIFY(!"[iterator::increment] fail\n");
+
+ if ((it1 != it2--) || (--it1 != it2))
+ VERIFY(!"[iterator::decrement] fail\n");
+ }
+
+
+ // clear / empty
+ VERIFY(!ilist.empty());
+
+ ilist.clear();
+ VERIFY(VerifySequence(ilist.begin(), ilist.end(), int(), "clear()", -1));
+ VERIFY(ilist.empty());
+
+
+ // splice
+ ListInit(ilist, nodes) += 0, 1, 2, 3, 4, 5, 6, 7, 8, 9;
+
+ ilist.splice(++ilist.begin(), ilist, --ilist.end());
+ VERIFY(VerifySequence(ilist.begin(), ilist.end(), int(), "splice(single)", 0, 9, 1, 2, 3, 4, 5, 6, 7, 8, -1));
+
+ intrusive_list<IntNode> ilist2;
+ ListInit(ilist2, nodes+10) += 10, 11, 12, 13, 14, 15, 16, 17, 18, 19;
+
+ ilist.splice(++++ilist.begin(), ilist2);
+ VERIFY(VerifySequence(ilist2.begin(), ilist2.end(), int(), "splice(whole)", -1));
+ VERIFY(VerifySequence(ilist.begin(), ilist.end(), int(), "splice(whole)", 0, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 1, 2, 3, 4, 5, 6, 7, 8, -1));
+
+ ilist.splice(ilist.begin(), ilist, ++++ilist.begin(), ----ilist.end());
+ VERIFY(VerifySequence(ilist.begin(), ilist.end(), int(), "splice(range)", 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 1, 2, 3, 4, 5, 6, 0, 9, 7, 8, -1));
+
+ ilist.clear();
+ ilist.swap(ilist2);
+ VERIFY(VerifySequence(ilist.begin(), ilist.end(), int(), "swap(empty)", -1));
+ VERIFY(VerifySequence(ilist2.begin(), ilist2.end(), int(), "swap(empty)", -1));
+
+ ilist2.push_back(nodes[0]);
+ ilist.splice(ilist.begin(), ilist2);
+ VERIFY(VerifySequence(ilist.begin(), ilist.end(), int(), "splice(single)", 0, -1));
+ VERIFY(VerifySequence(ilist2.begin(), ilist2.end(), int(), "splice(single)", -1));
+
+
+ // splice(single) -- evil case (splice at or right after current position)
+ ListInit(ilist, nodes) += 0, 1, 2, 3, 4;
+ ilist.splice(++++ilist.begin(), *++++ilist.begin());
+ VERIFY(VerifySequence(ilist.begin(), ilist.end(), int(), "splice(single)", 0, 1, 2, 3, 4, -1));
+ ilist.splice(++++++ilist.begin(), *++++ilist.begin());
+ VERIFY(VerifySequence(ilist.begin(), ilist.end(), int(), "splice(single)", 0, 1, 2, 3, 4, -1));
+
+
+ // splice(range) -- evil case (splice right after current position)
+ ListInit(ilist, nodes) += 0, 1, 2, 3, 4;
+ ilist.splice(++++ilist.begin(), ilist, ++ilist.begin(), ++++ilist.begin());
+ VERIFY(VerifySequence(ilist.begin(), ilist.end(), int(), "splice(range)", 0, 1, 2, 3, 4, -1));
+
+
+ // push_front / push_back
+ ilist.clear();
+ ilist2.clear();
+ for(i = 4; i >= 0; --i)
+ ilist.push_front(nodes[i]);
+ for(i = 5; i < 10; ++i)
+ ilist2.push_back(nodes[i]);
+
+ VERIFY(VerifySequence(ilist.begin(), ilist.end(), int(), "push_front()", 0, 1, 2, 3, 4, -1));
+ VERIFY(VerifySequence(ilist2.begin(), ilist2.end(), int(), "push_back()", 5, 6, 7, 8, 9, -1));
+
+ for(i = 4; i >= 0; --i)
+ {
+ ilist.pop_front();
+ ilist2.pop_back();
+ }
+
+ VERIFY(ilist.empty() && ilist2.empty());
+ VERIFY(VerifySequence(ilist.begin(), ilist.end(), int(), "pop_front()", -1));
+ VERIFY(VerifySequence(ilist2.begin(), ilist2.end(), int(), "pop_back()", -1));
+
+
+ // contains / locate
+ for(i = 0; i < 5; ++i)
+ ilist.push_back(nodes[i]);
+
+ VERIFY( ilist.contains(nodes[2]));
+ VERIFY(!ilist.contains(nodes[7]));
+
+ it = ilist.locate(nodes[3]);
+ VERIFY(it->mX == 3);
+
+ it = ilist.locate(nodes[8]);
+ VERIFY(it == ilist.end());
+
+
+ // reverse
+ ilist.reverse();
+ VERIFY(VerifySequence(ilist.begin(), ilist.end(), int(), "push_front()", 4, 3, 2, 1, 0, -1));
+
+
+ // validate / validate_iterator
+ VERIFY(ilist.validate());
+ it = ilist.locate(nodes[3]);
+ VERIFY((ilist.validate_iterator(it) & (isf_valid | isf_can_dereference)) != 0);
+ VERIFY( ilist.validate_iterator(intrusive_list<IntNode>::iterator(NULL)) == isf_none);
+
+
+ // swap()
+ ilist.swap(ilist2);
+ VERIFY(VerifySequence(ilist.begin(), ilist.end(), int(), "swap()", -1));
+ VERIFY(VerifySequence(ilist2.begin(), ilist2.end(), int(), "swap()", 4, 3, 2, 1, 0, -1));
+
+
+ // erase()
+ ListInit(ilist2, nodes) += 0, 1, 2, 3, 4;
+ ListInit(ilist, nodes+5) += 5, 6, 7, 8, 9;
+ ilist.erase(++++ilist.begin());
+ VERIFY(VerifySequence(ilist.begin(), ilist.end(), int(), "erase(single)", 5, 6, 8, 9, -1));
+
+ ilist.erase(ilist.begin(), ilist.end());
+ VERIFY(VerifySequence(ilist.begin(), ilist.end(), int(), "erase(all)", -1));
+
+ ilist2.erase(++ilist2.begin(), ----ilist2.end());
+ VERIFY(VerifySequence(ilist2.begin(), ilist2.end(), int(), "erase(range)", 0, 3, 4, -1));
+
+
+ // size
+ VERIFY(ilist2.size() == 3);
+
+
+ // pop_front / pop_back
+ ilist2.pop_front();
+ VERIFY(VerifySequence(ilist2.begin(), ilist2.end(), int(), "pop_front()", 3, 4, -1));
+
+ ilist2.pop_back();
+ VERIFY(VerifySequence(ilist2.begin(), ilist2.end(), int(), "pop_back()", 3, -1));
+ }
+
+
+ {
+ // Test copy construction and assignment.
+ // The following *should* not compile.
+
+ intrusive_list<IntNode> ilist1;
+ intrusive_list<IntNode> ilist2(ilist1);
+ ilist1 = ilist2;
+ }
+
+
+ {
+ // void sort()
+ // void sort(Compare compare)
+
+ const int kSize = 10;
+ IntNode nodes[kSize];
+
+ intrusive_list<IntNode> listEmpty;
+ listEmpty.sort();
+ VERIFY(VerifySequence(listEmpty.begin(), listEmpty.end(), int(), "list::sort", -1));
+
+ intrusive_list<IntNode> list1;
+ ListInit(list1, nodes) += 1;
+ list1.sort();
+ VERIFY(VerifySequence(list1.begin(), list1.end(), int(), "list::sort", 1, -1));
+ list1.clear();
+
+ intrusive_list<IntNode> list4;
+ ListInit(list4, nodes) += 1, 9, 2, 3;
+ list4.sort();
+ VERIFY(VerifySequence(list4.begin(), list4.end(), int(), "list::sort", 1, 2, 3, 9, -1));
+ list4.clear();
+
+ intrusive_list<IntNode> listA;
+ ListInit(listA, nodes) += 1, 9, 2, 3, 5, 7, 4, 6, 8, 0;
+ listA.sort();
+ VERIFY(VerifySequence(listA.begin(), listA.end(), int(), "list::sort", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1));
+ listA.clear();
+
+ intrusive_list<IntNode> listB;
+ ListInit(listB, nodes) += 1, 9, 2, 3, 5, 7, 4, 6, 8, 0;
+ listB.sort(eastl::less<int>());
+ VERIFY(VerifySequence(listB.begin(), listB.end(), int(), "list::sort", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1));
+ listB.clear();
+ }
+
+
+ {
+ // void merge(this_type& x);
+ // void merge(this_type& x, Compare compare);
+
+ const int kSize = 8;
+ IntNode nodesA[kSize];
+ IntNode nodesB[kSize];
+
+ intrusive_list<IntNode> listA;
+ ListInit(listA, nodesA) += 1, 2, 3, 4, 4, 5, 9, 9;
+
+ intrusive_list<IntNode> listB;
+ ListInit(listB, nodesB) += 1, 2, 3, 4, 4, 5, 9, 9;
+
+ listA.merge(listB);
+ VERIFY(VerifySequence(listA.begin(), listA.end(), int(), "list::merge", 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 9, 9, 9, 9, -1));
+ VERIFY(VerifySequence(listB.begin(), listB.end(), int(), "list::merge", -1));
+ }
+
+
+ {
+ // void unique();
+ // void unique(BinaryPredicate);
+
+ const int kSize = 8;
+ IntNode nodesA[kSize];
+ IntNode nodesB[kSize];
+
+ intrusive_list<IntNode> listA;
+ ListInit(listA, nodesA) += 1, 2, 3, 4, 4, 5, 9, 9;
+ listA.unique();
+ VERIFY(VerifySequence(listA.begin(), listA.end(), int(), "list::unique", 1, 2, 3, 4, 5, 9, -1));
+
+ intrusive_list<IntNode> listB;
+ ListInit(listB, nodesB) += 1, 2, 3, 4, 4, 5, 9, 9;
+ listB.unique(eastl::equal_to<int>());
+ VERIFY(VerifySequence(listA.begin(), listA.end(), int(), "list::unique", 1, 2, 3, 4, 5, 9, -1));
+ }
+
+
+ return nErrorCount;
+}
+
+
+
+
+
+
+
+
+
+
+
+