| //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 <deque> |
| #include <algorithm> |
| #if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS) |
| # include <stdexcept> |
| #endif |
| |
| #include "cppunit/cppunit_proxy.h" |
| |
| #if !defined (STLPORT) || defined(_STLP_USE_NAMESPACES) |
| using namespace std; |
| #endif |
| |
| // |
| // TestCase class |
| // |
| class DequeTest : public CPPUNIT_NS::TestCase |
| { |
| CPPUNIT_TEST_SUITE(DequeTest); |
| CPPUNIT_TEST(deque1); |
| CPPUNIT_TEST(at); |
| CPPUNIT_TEST(insert); |
| CPPUNIT_TEST(erase); |
| CPPUNIT_TEST(auto_ref); |
| CPPUNIT_TEST(allocator_with_state); |
| #if defined (STLPORT) && defined (_STLP_NO_MEMBER_TEMPLATES) |
| CPPUNIT_IGNORE; |
| #endif |
| CPPUNIT_TEST(optimizations_check); |
| CPPUNIT_TEST_SUITE_END(); |
| |
| protected: |
| void deque1(); |
| void insert(); |
| void erase(); |
| void at(); |
| void auto_ref(); |
| void allocator_with_state(); |
| void optimizations_check(); |
| }; |
| |
| CPPUNIT_TEST_SUITE_REGISTRATION(DequeTest); |
| |
| // |
| // tests implementation |
| // |
| void DequeTest::deque1() |
| { |
| deque<int> d; |
| d.push_back(4); |
| d.push_back(9); |
| d.push_back(16); |
| d.push_front(1); |
| |
| CPPUNIT_ASSERT( d[0] == 1 ); |
| CPPUNIT_ASSERT( d[1] == 4 ); |
| CPPUNIT_ASSERT( d[2] == 9 ); |
| CPPUNIT_ASSERT( d[3] == 16 ); |
| |
| d.pop_front(); |
| d[2] = 25; |
| |
| CPPUNIT_ASSERT( d[0] == 4 ); |
| CPPUNIT_ASSERT( d[1] == 9 ); |
| CPPUNIT_ASSERT( d[2] == 25 ); |
| |
| //Some compile time tests: |
| deque<int>::iterator dit = d.begin(); |
| deque<int>::const_iterator cdit(d.begin()); |
| CPPUNIT_ASSERT( (dit - cdit) == 0 ); |
| CPPUNIT_ASSERT( (cdit - dit) == 0 ); |
| CPPUNIT_ASSERT( (dit - dit) == 0 ); |
| CPPUNIT_ASSERT( (cdit - cdit) == 0 ); |
| CPPUNIT_ASSERT(!((dit < cdit) || (dit > cdit) || (dit != cdit) || !(dit <= cdit) || !(dit >= cdit))); |
| } |
| |
| void DequeTest::insert() |
| { |
| deque<int> d; |
| d.push_back(0); |
| d.push_back(1); |
| d.push_back(2); |
| CPPUNIT_ASSERT( d.size() == 3 ); |
| |
| deque<int>::iterator dit; |
| |
| //Insertion before begin: |
| dit = d.insert(d.begin(), 3); |
| CPPUNIT_ASSERT( dit != d.end() ); |
| CPPUNIT_CHECK( *dit == 3 ); |
| CPPUNIT_ASSERT( d.size() == 4 ); |
| CPPUNIT_ASSERT( d[0] == 3 ); |
| |
| //Insertion after begin: |
| dit = d.insert(d.begin() + 1, 4); |
| CPPUNIT_ASSERT( dit != d.end() ); |
| CPPUNIT_CHECK( *dit == 4 ); |
| CPPUNIT_ASSERT( d.size() == 5 ); |
| CPPUNIT_ASSERT( d[1] == 4 ); |
| |
| //Insertion at end: |
| dit = d.insert(d.end(), 5); |
| CPPUNIT_ASSERT( dit != d.end() ); |
| CPPUNIT_CHECK( *dit == 5 ); |
| CPPUNIT_ASSERT( d.size() == 6 ); |
| CPPUNIT_ASSERT( d[5] == 5 ); |
| |
| //Insertion before last element: |
| dit = d.insert(d.end() - 1, 6); |
| CPPUNIT_ASSERT( dit != d.end() ); |
| CPPUNIT_CHECK( *dit == 6 ); |
| CPPUNIT_ASSERT( d.size() == 7 ); |
| CPPUNIT_ASSERT( d[5] == 6 ); |
| |
| //Insertion of several elements before begin |
| d.insert(d.begin(), 2, 7); |
| CPPUNIT_ASSERT( d.size() == 9 ); |
| CPPUNIT_ASSERT( d[0] == 7 ); |
| CPPUNIT_ASSERT( d[1] == 7 ); |
| |
| //Insertion of several elements after begin |
| //There is more elements to insert than elements before insertion position |
| d.insert(d.begin() + 1, 2, 8); |
| CPPUNIT_ASSERT( d.size() == 11 ); |
| CPPUNIT_ASSERT( d[1] == 8 ); |
| CPPUNIT_ASSERT( d[2] == 8 ); |
| |
| //There is less elements to insert than elements before insertion position |
| d.insert(d.begin() + 3, 2, 9); |
| CPPUNIT_ASSERT( d.size() == 13 ); |
| CPPUNIT_ASSERT( d[3] == 9 ); |
| CPPUNIT_ASSERT( d[4] == 9 ); |
| |
| //Insertion of several elements at end: |
| d.insert(d.end(), 2, 10); |
| CPPUNIT_ASSERT( d.size() == 15 ); |
| CPPUNIT_ASSERT( d[14] == 10 ); |
| CPPUNIT_ASSERT( d[13] == 10 ); |
| |
| //Insertion of several elements before last: |
| //There is more elements to insert than elements after insertion position |
| d.insert(d.end() - 1, 2, 11); |
| CPPUNIT_ASSERT( d.size() == 17 ); |
| CPPUNIT_ASSERT( d[15] == 11 ); |
| CPPUNIT_ASSERT( d[14] == 11 ); |
| |
| //There is less elements to insert than elements after insertion position |
| d.insert(d.end() - 3, 2, 12); |
| CPPUNIT_ASSERT( d.size() == 19 ); |
| CPPUNIT_ASSERT( d[15] == 12 ); |
| CPPUNIT_ASSERT( d[14] == 12 ); |
| } |
| |
| void DequeTest::at() { |
| deque<int> d; |
| deque<int> const& cd = d; |
| |
| d.push_back(10); |
| CPPUNIT_ASSERT( d.at(0) == 10 ); |
| d.at(0) = 20; |
| CPPUNIT_ASSERT( cd.at(0) == 20 ); |
| |
| #if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS) |
| for (;;) { |
| try { |
| d.at(1) = 20; |
| CPPUNIT_ASSERT(false); |
| } |
| catch (out_of_range const&) { |
| return; |
| } |
| catch (...) { |
| CPPUNIT_ASSERT(false); |
| } |
| } |
| #endif |
| } |
| |
| void DequeTest::auto_ref() |
| { |
| int i; |
| deque<int> ref; |
| for (i = 0; i < 5; ++i) { |
| ref.push_back(i); |
| } |
| |
| deque<deque<int> > d_d_int(1, ref); |
| d_d_int.push_back(d_d_int[0]); |
| d_d_int.push_back(ref); |
| d_d_int.push_back(d_d_int[0]); |
| d_d_int.push_back(d_d_int[0]); |
| d_d_int.push_back(ref); |
| |
| for (i = 0; i < 5; ++i) { |
| CPPUNIT_ASSERT( d_d_int[i] == ref ); |
| } |
| } |
| |
| void DequeTest::allocator_with_state() |
| { |
| char buf1[1024]; |
| StackAllocator<int> stack1(buf1, buf1 + sizeof(buf1)); |
| |
| char buf2[1024]; |
| StackAllocator<int> stack2(buf2, buf2 + sizeof(buf2)); |
| |
| { |
| typedef deque<int, StackAllocator<int> > DequeInt; |
| DequeInt dint1(10, 0, stack1); |
| DequeInt dint1Cpy(dint1); |
| |
| DequeInt dint2(10, 1, stack2); |
| DequeInt dint2Cpy(dint2); |
| |
| dint1.swap(dint2); |
| |
| CPPUNIT_ASSERT( dint1.get_allocator().swaped() ); |
| CPPUNIT_ASSERT( dint2.get_allocator().swaped() ); |
| |
| CPPUNIT_ASSERT( dint1 == dint2Cpy ); |
| CPPUNIT_ASSERT( dint2 == dint1Cpy ); |
| CPPUNIT_ASSERT( dint1.get_allocator() == stack2 ); |
| CPPUNIT_ASSERT( dint2.get_allocator() == stack1 ); |
| } |
| CPPUNIT_ASSERT( stack1.ok() ); |
| CPPUNIT_ASSERT( stack2.ok() ); |
| } |
| |
| struct Point { |
| int x, y; |
| }; |
| |
| struct PointEx : public Point { |
| PointEx() : builtFromBase(false) {} |
| PointEx(const Point&) : builtFromBase(true) {} |
| |
| bool builtFromBase; |
| }; |
| |
| #if defined (STLPORT) |
| # if defined (_STLP_USE_NAMESPACES) |
| namespace std { |
| # endif |
| _STLP_TEMPLATE_NULL |
| struct __type_traits<PointEx> { |
| typedef __false_type has_trivial_default_constructor; |
| typedef __true_type has_trivial_copy_constructor; |
| typedef __true_type has_trivial_assignment_operator; |
| typedef __true_type has_trivial_destructor; |
| typedef __true_type is_POD_type; |
| }; |
| # if defined (_STLP_USE_NAMESPACES) |
| } |
| # endif |
| #endif |
| |
| //This test check that deque implementation do not over optimize |
| //operation as PointEx copy constructor is trivial |
| void DequeTest::optimizations_check() |
| { |
| #if !defined (STLPORT) || !defined (_STLP_NO_MEMBER_TEMPLATES) |
| deque<Point> d1(1); |
| CPPUNIT_ASSERT( d1.size() == 1 ); |
| |
| deque<PointEx> d2(d1.begin(), d1.end()); |
| CPPUNIT_ASSERT( d2.size() == 1 ); |
| CPPUNIT_ASSERT( d2[0].builtFromBase == true ); |
| |
| d2.insert(d2.end(), d1.begin(), d1.end()); |
| CPPUNIT_ASSERT( d2.size() == 2 ); |
| CPPUNIT_ASSERT( d2[1].builtFromBase == true ); |
| #endif |
| } |
| |
| void DequeTest::erase() |
| { |
| deque<int> dint; |
| dint.push_back(3); |
| dint.push_front(2); |
| dint.push_back(4); |
| dint.push_front(1); |
| dint.push_back(5); |
| dint.push_front(0); |
| dint.push_back(6); |
| |
| deque<int>::iterator it(dint.begin() + 1); |
| CPPUNIT_ASSERT( *it == 1 ); |
| |
| dint.erase(dint.begin()); |
| CPPUNIT_ASSERT( *it == 1 ); |
| |
| it = dint.end() - 2; |
| CPPUNIT_ASSERT( *it == 5 ); |
| |
| dint.erase(dint.end() - 1); |
| CPPUNIT_ASSERT( *it == 5 ); |
| |
| dint.push_back(6); |
| dint.push_front(0); |
| |
| it = dint.begin() + 2; |
| CPPUNIT_ASSERT( *it == 2 ); |
| |
| dint.erase(dint.begin(), dint.begin() + 2); |
| CPPUNIT_ASSERT( *it == 2 ); |
| |
| it = dint.end() - 3; |
| CPPUNIT_ASSERT( *it == 4 ); |
| |
| dint.erase(dint.end() - 2, dint.end()); |
| CPPUNIT_ASSERT( *it == 4 ); |
| } |
| |
| #if (!defined (STLPORT) || \ |
| (!defined (_STLP_USE_PTR_SPECIALIZATIONS) || defined (_STLP_CLASS_PARTIAL_SPECIALIZATION))) && \ |
| (!defined (_MSC_VER) || (_MSC_VER > 1400)) && \ |
| (!defined(__GNUC__) || (__GNUC__ < 4) || (__GNUC_MINOR__ < 3)) |
| /* 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 |
| { |
| deque<IncompleteClass> instances; |
| typedef deque<IncompleteClass>::size_type size; |
| }; |
| #endif |