| //Has to be first for StackAllocator swap overload to be taken |
| //into account (at least using GCC 4.0.1) |
| #include "stack_allocator.h" |
| |
| #include <list> |
| #include <algorithm> |
| #include <functional> |
| |
| #include "cppunit/cppunit_proxy.h" |
| |
| #if !defined (STLPORT) || defined(_STLP_USE_NAMESPACES) |
| using namespace std; |
| #endif |
| |
| // |
| // TestCase class |
| // |
| class ListTest : public CPPUNIT_NS::TestCase |
| { |
| CPPUNIT_TEST_SUITE(ListTest); |
| CPPUNIT_TEST(list1); |
| CPPUNIT_TEST(list2); |
| CPPUNIT_TEST(list3); |
| CPPUNIT_TEST(list4); |
| CPPUNIT_TEST(erase); |
| CPPUNIT_TEST(resize); |
| CPPUNIT_TEST(push_back); |
| CPPUNIT_TEST(push_front); |
| CPPUNIT_TEST(allocator_with_state); |
| CPPUNIT_TEST(swap); |
| CPPUNIT_TEST(adl); |
| //CPPUNIT_TEST(const_list); |
| CPPUNIT_TEST_SUITE_END(); |
| |
| protected: |
| void list1(); |
| void list2(); |
| void list3(); |
| void list4(); |
| void erase(); |
| void resize(); |
| void push_back(); |
| void push_front(); |
| void allocator_with_state(); |
| void swap(); |
| void adl(); |
| //void const_list(); |
| }; |
| |
| CPPUNIT_TEST_SUITE_REGISTRATION(ListTest); |
| |
| // |
| // tests implementation |
| // |
| void ListTest::list1() |
| { |
| int array1 [] = { 9, 16, 36 }; |
| int array2 [] = { 1, 4 }; |
| |
| list<int> l1(array1, array1 + 3); |
| list<int> l2(array2, array2 + 2); |
| list<int>::iterator i1 = l1.begin(); |
| list<int>::iterator i2 = l2.begin(); |
| list<int>::const_iterator ci(i1); |
| list<int>::const_iterator ci1(ci); |
| l1.splice(i1, l2); |
| i1 = l1.begin(); |
| CPPUNIT_ASSERT( *i1++ == 1 ); |
| CPPUNIT_ASSERT( *i1++ == 4 ); |
| CPPUNIT_ASSERT( *i1++ == 9 ); |
| CPPUNIT_ASSERT( *i1++ == 16 ); |
| CPPUNIT_ASSERT( *i1++ == 36 ); |
| |
| #if defined (STLPORT) && \ |
| (!defined (_STLP_DEBUG) || (_STLP_DEBUG_LEVEL != _STLP_STANDARD_DBG_LEVEL)) |
| CPPUNIT_ASSERT( i2 == l1.begin() ); |
| #endif |
| |
| //Default construct check (_STLP_DEF_CONST_PLCT_NEW_BUG) |
| list<int> l(2); |
| i1 = l.begin(); |
| CPPUNIT_ASSERT( *(i1++) == 0 ); |
| CPPUNIT_ASSERT( *i1 == 0 ); |
| #if 0 |
| //A small compilation time check to be activated from time to time, |
| //compilation should fail. |
| { |
| list<char>::iterator l_char_ite; |
| list<int>::iterator l_int_ite; |
| CPPUNIT_ASSERT( l_char_ite != l_int_ite ); |
| } |
| #endif |
| } |
| |
| void ListTest::list2() |
| { |
| int array1 [] = { 1, 16 }; |
| int array2 [] = { 4, 9 }; |
| |
| list<int> l1(array1, array1 + 2); |
| list<int> l2(array2, array2 + 2); |
| list<int>::iterator i = l1.begin(); |
| i++; |
| l1.splice(i, l2, l2.begin(), l2.end()); |
| i = l1.begin(); |
| CPPUNIT_ASSERT(*i++==1); |
| CPPUNIT_ASSERT(*i++==4); |
| CPPUNIT_ASSERT(*i++==9); |
| CPPUNIT_ASSERT(*i++==16); |
| } |
| |
| void ListTest::list3() |
| { |
| char array [] = { 'x', 'l', 'x', 't', 's', 's' }; |
| |
| list<char> str(array, array + 6); |
| list<char>::iterator i; |
| |
| str.reverse(); |
| i = str.begin(); |
| CPPUNIT_ASSERT(*i++=='s'); |
| CPPUNIT_ASSERT(*i++=='s'); |
| CPPUNIT_ASSERT(*i++=='t'); |
| CPPUNIT_ASSERT(*i++=='x'); |
| CPPUNIT_ASSERT(*i++=='l'); |
| CPPUNIT_ASSERT(*i++=='x'); |
| |
| str.remove('x'); |
| i = str.begin(); |
| CPPUNIT_ASSERT(*i++=='s'); |
| CPPUNIT_ASSERT(*i++=='s'); |
| CPPUNIT_ASSERT(*i++=='t'); |
| CPPUNIT_ASSERT(*i++=='l'); |
| |
| str.unique(); |
| i = str.begin(); |
| CPPUNIT_ASSERT(*i++=='s'); |
| CPPUNIT_ASSERT(*i++=='t'); |
| CPPUNIT_ASSERT(*i++=='l'); |
| |
| str.sort(); |
| i = str.begin(); |
| CPPUNIT_ASSERT(*i++=='l'); |
| CPPUNIT_ASSERT(*i++=='s'); |
| CPPUNIT_ASSERT(*i++=='t'); |
| } |
| |
| void ListTest::list4() |
| { |
| int array1 [] = { 1, 3, 6, 7 }; |
| int array2 [] = { 2, 4 }; |
| |
| list<int> l1(array1, array1 + 4); |
| list<int> l2(array2, array2 + 2); |
| l1.merge(l2); |
| list<int>::iterator i = l1.begin(); |
| CPPUNIT_ASSERT(*i++==1); |
| CPPUNIT_ASSERT(*i++==2); |
| CPPUNIT_ASSERT(*i++==3); |
| CPPUNIT_ASSERT(*i++==4); |
| CPPUNIT_ASSERT(*i++==6); |
| CPPUNIT_ASSERT(*i++==7); |
| |
| //We use distance to avoid a simple call to an internal counter |
| CPPUNIT_ASSERT(distance(l1.begin(), l1.end()) == 6); |
| CPPUNIT_ASSERT(distance(l2.begin(), l2.end()) == 0); |
| |
| l1.swap(l2); |
| |
| CPPUNIT_ASSERT(distance(l1.begin(), l1.end()) == 0); |
| CPPUNIT_ASSERT(distance(l2.begin(), l2.end()) == 6); |
| } |
| |
| void ListTest::erase() |
| { |
| list<int> l; |
| l.push_back( 1 ); |
| l.erase(l.begin()); |
| CPPUNIT_ASSERT( l.empty() ); |
| |
| int array[] = { 0, 1, 2, 3 }; |
| l.assign(array, array + 4); |
| list<int>::iterator lit; |
| lit = l.erase(l.begin()); |
| CPPUNIT_ASSERT( *lit == 1 ); |
| |
| lit = l.erase(l.begin(), --l.end()); |
| CPPUNIT_ASSERT( *lit == 3 ); |
| |
| l.clear(); |
| CPPUNIT_ASSERT( l.empty() ); |
| } |
| |
| |
| void ListTest::resize() |
| { |
| { |
| list<int> l; |
| l.resize(5, 1); |
| |
| size_t i; |
| list<int>::iterator lit(l.begin()); |
| for (i = 0; i < 5; ++i) { |
| CPPUNIT_ASSERT( lit != l.end() ); |
| CPPUNIT_ASSERT( *(lit++) == 1 ); |
| } |
| CPPUNIT_ASSERT( lit == l.end() ); |
| |
| l.resize(3); |
| lit = l.begin(); |
| for (i = 0; i < 3; ++i) { |
| CPPUNIT_ASSERT( lit != l.end() ); |
| CPPUNIT_ASSERT( *(lit++) == 1 ); |
| } |
| CPPUNIT_ASSERT( lit == l.end() ); |
| } |
| |
| { |
| list<int> l; |
| l.resize(5); |
| |
| size_t i; |
| list<int>::iterator lit(l.begin()); |
| for (i = 0; i < 5; ++i) { |
| CPPUNIT_ASSERT( lit != l.end() ); |
| CPPUNIT_ASSERT( *(lit++) == 0 ); |
| } |
| CPPUNIT_ASSERT( lit == l.end() ); |
| } |
| } |
| |
| void ListTest::push_back() |
| { |
| list<int> l; |
| l.push_back( 1 ); |
| l.push_back( 2 ); |
| l.push_back( 3 ); |
| |
| list<int>::reverse_iterator r = l.rbegin(); |
| |
| CPPUNIT_ASSERT( *r == 3 ); |
| l.push_back( 4 ); |
| /* |
| * Following lines are commented, because ones show standard contradiction |
| * (24.4.1 and 23.2.2.3); but present behaviour is valid, 24.4.1, paragraphs 1 and 2, |
| * 24.4.1.3.3 and 23.1 paragraph 9 (Table 66). The 24.4.1 is more common rule, |
| * so it has preference under 23.2.2.3, by my opinion. |
| * |
| * - ptr |
| */ |
| // CPPUNIT_ASSERT( *r == 3 ); |
| // ++r; |
| // CPPUNIT_ASSERT( *r == 2 ); |
| } |
| |
| void ListTest::push_front() |
| { |
| list<int> l; |
| l.push_back( 1 ); |
| l.push_back( 2 ); |
| l.push_back( 3 ); |
| |
| list<int>::iterator i = l.begin(); |
| |
| CPPUNIT_ASSERT( *i == 1 ); |
| l.push_front( 0 ); |
| CPPUNIT_ASSERT( *i == 1 ); |
| ++i; |
| CPPUNIT_ASSERT( *i == 2 ); |
| } |
| |
| void ListTest::allocator_with_state() |
| { |
| char buf1[1024]; |
| StackAllocator<int> stack1(buf1, buf1 + sizeof(buf1)); |
| |
| char buf2[1024]; |
| StackAllocator<int> stack2(buf2, buf2 + sizeof(buf2)); |
| |
| typedef list<int, StackAllocator<int> > ListInt; |
| { |
| //Swap with both list non empty |
| ListInt lint1(10, 0, stack1); |
| ListInt lint1Cpy(lint1); |
| |
| ListInt lint2(10, 1, stack2); |
| ListInt lint2Cpy(lint2); |
| |
| lint1.swap(lint2); |
| |
| CPPUNIT_ASSERT( lint1.get_allocator().swaped() ); |
| CPPUNIT_ASSERT( lint2.get_allocator().swaped() ); |
| |
| CPPUNIT_ASSERT( lint1 == lint2Cpy ); |
| CPPUNIT_ASSERT( lint2 == lint1Cpy ); |
| CPPUNIT_ASSERT( lint1.get_allocator() == stack2 ); |
| CPPUNIT_ASSERT( lint2.get_allocator() == stack1 ); |
| } |
| CPPUNIT_CHECK( stack1.ok() ); |
| CPPUNIT_CHECK( stack2.ok() ); |
| stack1.reset(); stack2.reset(); |
| |
| { |
| //Swap with empty calle list |
| ListInt lint1(10, 0, stack1); |
| ListInt lint1Cpy(lint1); |
| |
| ListInt lint2(stack2); |
| ListInt lint2Cpy(lint2); |
| |
| lint1.swap(lint2); |
| |
| CPPUNIT_ASSERT( lint1.get_allocator().swaped() ); |
| CPPUNIT_ASSERT( lint2.get_allocator().swaped() ); |
| |
| CPPUNIT_ASSERT( lint1 == lint2Cpy ); |
| CPPUNIT_ASSERT( lint2 == lint1Cpy ); |
| CPPUNIT_ASSERT( lint1.get_allocator() == stack2 ); |
| CPPUNIT_ASSERT( lint2.get_allocator() == stack1 ); |
| } |
| CPPUNIT_CHECK( stack1.ok() ); |
| CPPUNIT_CHECK( stack2.ok() ); |
| stack1.reset(); stack2.reset(); |
| |
| { |
| //Swap with empty caller list |
| ListInt lint1(stack1); |
| ListInt lint1Cpy(lint1); |
| |
| ListInt lint2(10, 0, stack2); |
| ListInt lint2Cpy(lint2); |
| |
| lint1.swap(lint2); |
| |
| CPPUNIT_ASSERT( lint1.get_allocator().swaped() ); |
| CPPUNIT_ASSERT( lint2.get_allocator().swaped() ); |
| |
| CPPUNIT_ASSERT( lint1 == lint2Cpy ); |
| CPPUNIT_ASSERT( lint2 == lint1Cpy ); |
| CPPUNIT_ASSERT( lint1.get_allocator() == stack2 ); |
| CPPUNIT_ASSERT( lint2.get_allocator() == stack1 ); |
| } |
| CPPUNIT_CHECK( stack1.ok() ); |
| CPPUNIT_CHECK( stack2.ok() ); |
| stack1.reset(); stack2.reset(); |
| |
| { |
| ListInt lint1(10, 0, stack1); |
| ListInt lint2(10, 1, stack2); |
| |
| lint1.splice(lint1.begin(), lint2); |
| CPPUNIT_ASSERT( lint1.size() == 20 ); |
| CPPUNIT_ASSERT( lint2.empty() ); |
| } |
| CPPUNIT_CHECK( stack1.ok() ); |
| CPPUNIT_CHECK( stack2.ok() ); |
| stack1.reset(); stack2.reset(); |
| |
| { |
| ListInt lint1(10, 0, stack1); |
| ListInt lint2(10, 1, stack2); |
| |
| lint1.splice(lint1.begin(), lint2, lint2.begin()); |
| CPPUNIT_ASSERT( lint1.size() == 11 ); |
| CPPUNIT_ASSERT( lint2.size() == 9 ); |
| } |
| CPPUNIT_CHECK( stack1.ok() ); |
| CPPUNIT_CHECK( stack2.ok() ); |
| stack1.reset(); stack2.reset(); |
| |
| { |
| ListInt lint1(10, 0, stack1); |
| ListInt lint2(10, 1, stack2); |
| |
| ListInt::iterator lit(lint2.begin()); |
| advance(lit, 5); |
| lint1.splice(lint1.begin(), lint2, lint2.begin(), lit); |
| CPPUNIT_ASSERT( lint1.size() == 15 ); |
| CPPUNIT_ASSERT( lint2.size() == 5 ); |
| } |
| CPPUNIT_CHECK( stack1.ok() ); |
| CPPUNIT_CHECK( stack2.ok() ); |
| stack1.reset(); stack2.reset(); |
| |
| { |
| ListInt lint1(10, 0, stack1); |
| ListInt lint2(10, 1, stack2); |
| |
| ListInt lintref(stack2); |
| lintref.insert(lintref.begin(), 10, 1); |
| lintref.insert(lintref.begin(), 10, 0); |
| |
| lint1.merge(lint2); |
| CPPUNIT_ASSERT( lint1.size() == 20 ); |
| CPPUNIT_ASSERT( lint1 == lintref ); |
| CPPUNIT_ASSERT( lint2.empty() ); |
| } |
| CPPUNIT_CHECK( stack1.ok() ); |
| CPPUNIT_CHECK( stack2.ok() ); |
| |
| #if defined (STLPORT) && !defined (_STLP_NO_MEMBER_TEMPLATES) && \ |
| (!defined (_MSC_VER) || (_MSC_VER >= 1300)) |
| { |
| //This is a compile time test. |
| //We check that sort implementation is correct when list is instanciated |
| //with an allocator that do not have a default constructor. |
| ListInt lint1(10, 0, stack1); |
| lint1.sort(); |
| lint1.sort(greater<int>()); |
| } |
| #endif |
| } |
| |
| /* |
| void ListTest::const_list() |
| { |
| list<const int> cint_list; |
| cint_list.push_back(1); |
| cint_list.push_front(2); |
| } |
| */ |
| void ListTest::swap() |
| { |
| list<int> lst1; |
| list<int> lst2; |
| |
| lst1.push_back(1); |
| lst2.push_back(2); |
| |
| lst1.swap( lst2 ); |
| |
| CPPUNIT_CHECK( lst1.front() == 2 ); |
| CPPUNIT_CHECK( lst2.front() == 1 ); |
| CPPUNIT_CHECK( lst1.size() == 1 ); |
| CPPUNIT_CHECK( lst2.size() == 1 ); |
| |
| lst1.pop_front(); |
| lst2.pop_front(); |
| |
| CPPUNIT_CHECK( lst1.empty() ); |
| CPPUNIT_CHECK( lst2.empty() ); |
| } |
| |
| namespace foo { |
| class bar {}; |
| |
| template <class _It> |
| size_t distance(_It, _It); |
| } |
| |
| void ListTest::adl() |
| { |
| list<foo::bar> lbar; |
| CPPUNIT_ASSERT( lbar.size() == 0); |
| } |
| |
| #if !defined (STLPORT) || \ |
| !defined (_STLP_USE_PTR_SPECIALIZATIONS) || defined (_STLP_CLASS_PARTIAL_SPECIALIZATION) |
| /* Simple compilation test: Check that nested types like iterator |
| * can be access even if type used to instanciate container is not |
| * yet completely defined. |
| */ |
| class IncompleteClass |
| { |
| list<IncompleteClass> instances; |
| typedef list<IncompleteClass>::iterator it; |
| }; |
| #endif |