Home | History | Annotate | Download | only in unit
      1 //Has to be first for StackAllocator swap overload to be taken
      2 //into account (at least using GCC 4.0.1)
      3 #include "stack_allocator.h"
      4 
      5 #include <vector>
      6 #include <algorithm>
      7 #if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
      8 # include <stdexcept>
      9 #endif
     10 
     11 #include "cppunit/cppunit_proxy.h"
     12 
     13 #if !defined (STLPORT) || defined(_STLP_USE_NAMESPACES)
     14 using namespace std;
     15 #endif
     16 
     17 //
     18 // TestCase class
     19 //
     20 class VectorTest : public CPPUNIT_NS::TestCase
     21 {
     22   CPPUNIT_TEST_SUITE(VectorTest);
     23   CPPUNIT_TEST(vec_test_1);
     24   CPPUNIT_TEST(vec_test_2);
     25   CPPUNIT_TEST(vec_test_3);
     26   CPPUNIT_TEST(vec_test_4);
     27   CPPUNIT_TEST(vec_test_5);
     28   CPPUNIT_TEST(vec_test_6);
     29   CPPUNIT_TEST(vec_test_7);
     30   CPPUNIT_TEST(capacity);
     31   CPPUNIT_TEST(at);
     32   CPPUNIT_TEST(pointer);
     33   CPPUNIT_TEST(auto_ref);
     34   CPPUNIT_TEST(allocator_with_state);
     35   CPPUNIT_TEST(iterators);
     36 #if defined (STLPORT) && defined (_STLP_NO_MEMBER_TEMPLATES)
     37   CPPUNIT_IGNORE;
     38 #endif
     39   CPPUNIT_TEST(optimizations_check);
     40   CPPUNIT_TEST(assign_check);
     41   CPPUNIT_STOP_IGNORE;
     42   CPPUNIT_TEST(ebo);
     43   CPPUNIT_TEST_SUITE_END();
     44 
     45 protected:
     46   void vec_test_1();
     47   void vec_test_2();
     48   void vec_test_3();
     49   void vec_test_4();
     50   void vec_test_5();
     51   void vec_test_6();
     52   void vec_test_7();
     53   void capacity();
     54   void at();
     55   void pointer();
     56   void auto_ref();
     57   void allocator_with_state();
     58   void iterators();
     59   void optimizations_check();
     60   void assign_check();
     61   void ebo();
     62 };
     63 
     64 CPPUNIT_TEST_SUITE_REGISTRATION(VectorTest);
     65 
     66 //
     67 // tests implementation
     68 //
     69 void VectorTest::vec_test_1()
     70 {
     71   vector<int> v1; // Empty vector of integers.
     72 
     73   CPPUNIT_ASSERT( v1.empty() == true );
     74   CPPUNIT_ASSERT( v1.size() == 0 );
     75 
     76   // CPPUNIT_ASSERT( v1.max_size() == INT_MAX / sizeof(int) );
     77   // cout << "max_size = " << v1.max_size() << endl;
     78   v1.push_back(42); // Add an integer to the vector.
     79 
     80   CPPUNIT_ASSERT( v1.size() == 1 );
     81 
     82   CPPUNIT_ASSERT( v1[0] == 42 );
     83 
     84   {
     85     vector<vector<int> > vect(10);
     86     vector<vector<int> >::iterator it(vect.begin()), end(vect.end());
     87     for (; it != end; ++it) {
     88       CPPUNIT_ASSERT( (*it).empty() );
     89       CPPUNIT_ASSERT( (*it).size() == 0 );
     90       CPPUNIT_ASSERT( (*it).capacity() == 0 );
     91       CPPUNIT_ASSERT( (*it).begin() == (*it).end() );
     92     }
     93   }
     94 }
     95 
     96 void VectorTest::vec_test_2()
     97 {
     98   vector<double> v1; // Empty vector of doubles.
     99   v1.push_back(32.1);
    100   v1.push_back(40.5);
    101   vector<double> v2; // Another empty vector of doubles.
    102   v2.push_back(3.56);
    103 
    104   CPPUNIT_ASSERT( v1.size() == 2 );
    105   CPPUNIT_ASSERT( v1[0] == 32.1 );
    106   CPPUNIT_ASSERT( v1[1] == 40.5 );
    107 
    108   CPPUNIT_ASSERT( v2.size() == 1 );
    109   CPPUNIT_ASSERT( v2[0] == 3.56 );
    110   size_t v1Cap = v1.capacity();
    111   size_t v2Cap = v2.capacity();
    112 
    113   v1.swap(v2); // Swap the vector's contents.
    114 
    115   CPPUNIT_ASSERT( v1.size() == 1 );
    116   CPPUNIT_ASSERT( v1.capacity() == v2Cap );
    117   CPPUNIT_ASSERT( v1[0] == 3.56 );
    118 
    119   CPPUNIT_ASSERT( v2.size() == 2 );
    120   CPPUNIT_ASSERT( v2.capacity() == v1Cap );
    121   CPPUNIT_ASSERT( v2[0] == 32.1 );
    122   CPPUNIT_ASSERT( v2[1] == 40.5 );
    123 
    124   v2 = v1; // Assign one vector to another.
    125 
    126   CPPUNIT_ASSERT( v2.size() == 1 );
    127   CPPUNIT_ASSERT( v2[0] == 3.56 );
    128 }
    129 
    130 void VectorTest::vec_test_3()
    131 {
    132   typedef vector<char> vec_type;
    133 
    134   vec_type v1; // Empty vector of characters.
    135   v1.push_back('h');
    136   v1.push_back('i');
    137 
    138   CPPUNIT_ASSERT( v1.size() == 2 );
    139   CPPUNIT_ASSERT( v1[0] == 'h' );
    140   CPPUNIT_ASSERT( v1[1] == 'i' );
    141 
    142   vec_type v2(v1.begin(), v1.end());
    143   v2[1] = 'o'; // Replace second character.
    144 
    145   CPPUNIT_ASSERT( v2.size() == 2 );
    146   CPPUNIT_ASSERT( v2[0] == 'h' );
    147   CPPUNIT_ASSERT( v2[1] == 'o' );
    148 
    149   CPPUNIT_ASSERT( (v1 == v2) == false );
    150 
    151   CPPUNIT_ASSERT( (v1 < v2) == true );
    152 }
    153 
    154 void VectorTest::vec_test_4()
    155 {
    156   vector<int> v(4);
    157 
    158   v[0] = 1;
    159   v[1] = 4;
    160   v[2] = 9;
    161   v[3] = 16;
    162 
    163   CPPUNIT_ASSERT( v.front() == 1 );
    164   CPPUNIT_ASSERT( v.back() == 16 );
    165 
    166   v.push_back(25);
    167 
    168   CPPUNIT_ASSERT( v.back() == 25 );
    169   CPPUNIT_ASSERT( v.size() == 5 );
    170 
    171   v.pop_back();
    172 
    173   CPPUNIT_ASSERT( v.back() == 16 );
    174   CPPUNIT_ASSERT( v.size() == 4 );
    175 }
    176 
    177 void VectorTest::vec_test_5()
    178 {
    179   int array [] = { 1, 4, 9, 16 };
    180 
    181   vector<int> v(array, array + 4);
    182 
    183   CPPUNIT_ASSERT( v.size() == 4 );
    184 
    185   CPPUNIT_ASSERT( v[0] == 1 );
    186   CPPUNIT_ASSERT( v[1] == 4 );
    187   CPPUNIT_ASSERT( v[2] == 9 );
    188   CPPUNIT_ASSERT( v[3] == 16 );
    189 }
    190 
    191 void VectorTest::vec_test_6()
    192 {
    193   int array [] = { 1, 4, 9, 16, 25, 36 };
    194 
    195   vector<int> v(array, array + 6);
    196   vector<int>::iterator vit;
    197 
    198   CPPUNIT_ASSERT( v.size() == 6 );
    199   CPPUNIT_ASSERT( v[0] == 1 );
    200   CPPUNIT_ASSERT( v[1] == 4 );
    201   CPPUNIT_ASSERT( v[2] == 9 );
    202   CPPUNIT_ASSERT( v[3] == 16 );
    203   CPPUNIT_ASSERT( v[4] == 25 );
    204   CPPUNIT_ASSERT( v[5] == 36 );
    205 
    206   vit = v.erase( v.begin() ); // Erase first element.
    207   CPPUNIT_ASSERT( *vit == 4 );
    208 
    209   CPPUNIT_ASSERT( v.size() == 5 );
    210   CPPUNIT_ASSERT( v[0] == 4 );
    211   CPPUNIT_ASSERT( v[1] == 9 );
    212   CPPUNIT_ASSERT( v[2] == 16 );
    213   CPPUNIT_ASSERT( v[3] == 25 );
    214   CPPUNIT_ASSERT( v[4] == 36 );
    215 
    216   vit = v.erase(v.end() - 1); // Erase last element.
    217   CPPUNIT_ASSERT( vit == v.end() );
    218 
    219   CPPUNIT_ASSERT( v.size() == 4 );
    220   CPPUNIT_ASSERT( v[0] == 4 );
    221   CPPUNIT_ASSERT( v[1] == 9 );
    222   CPPUNIT_ASSERT( v[2] == 16 );
    223   CPPUNIT_ASSERT( v[3] == 25 );
    224 
    225 
    226   v.erase(v.begin() + 1, v.end() - 1); // Erase all but first and last.
    227 
    228   CPPUNIT_ASSERT( v.size() == 2 );
    229   CPPUNIT_ASSERT( v[0] == 4 );
    230   CPPUNIT_ASSERT( v[1] == 25 );
    231 
    232 }
    233 
    234 void VectorTest::vec_test_7()
    235 {
    236   int array1 [] = { 1, 4, 25 };
    237   int array2 [] = { 9, 16 };
    238 
    239   vector<int> v(array1, array1 + 3);
    240   vector<int>::iterator vit;
    241   vit = v.insert(v.begin(), 0); // Insert before first element.
    242   CPPUNIT_ASSERT( *vit == 0 );
    243 
    244   vit = v.insert(v.end(), 36);  // Insert after last element.
    245   CPPUNIT_ASSERT( *vit == 36 );
    246 
    247   CPPUNIT_ASSERT( v.size() == 5 );
    248   CPPUNIT_ASSERT( v[0] == 0 );
    249   CPPUNIT_ASSERT( v[1] == 1 );
    250   CPPUNIT_ASSERT( v[2] == 4 );
    251   CPPUNIT_ASSERT( v[3] == 25 );
    252   CPPUNIT_ASSERT( v[4] == 36 );
    253 
    254   // Insert contents of array2 before fourth element.
    255   v.insert(v.begin() + 3, array2, array2 + 2);
    256 
    257   CPPUNIT_ASSERT( v.size() == 7 );
    258 
    259   CPPUNIT_ASSERT( v[0] == 0 );
    260   CPPUNIT_ASSERT( v[1] == 1 );
    261   CPPUNIT_ASSERT( v[2] == 4 );
    262   CPPUNIT_ASSERT( v[3] == 9 );
    263   CPPUNIT_ASSERT( v[4] == 16 );
    264   CPPUNIT_ASSERT( v[5] == 25 );
    265   CPPUNIT_ASSERT( v[6] == 36 );
    266 
    267   v.clear();
    268   CPPUNIT_ASSERT( v.empty() );
    269 
    270   v.insert(v.begin(), 5, 10);
    271   CPPUNIT_ASSERT( v.size() == 5 );
    272   CPPUNIT_ASSERT( v[0] == 10 );
    273   CPPUNIT_ASSERT( v[1] == 10 );
    274   CPPUNIT_ASSERT( v[2] == 10 );
    275   CPPUNIT_ASSERT( v[3] == 10 );
    276   CPPUNIT_ASSERT( v[4] == 10 );
    277 
    278   /*
    279   {
    280     vector<float> vf(2.0f, 3.0f);
    281     CPPUNIT_ASSERT( vf.size() == 2 );
    282     CPPUNIT_ASSERT( vf.front() == 3.0f );
    283     CPPUNIT_ASSERT( vf.back() == 3.0f );
    284   }
    285   */
    286 }
    287 
    288 struct TestStruct
    289 {
    290   unsigned int a[3];
    291 };
    292 
    293 void VectorTest::capacity()
    294 {
    295   {
    296     vector<int> v;
    297 
    298     CPPUNIT_ASSERT( v.capacity() == 0 );
    299     v.push_back(42);
    300     CPPUNIT_ASSERT( v.capacity() >= 1 );
    301     v.reserve(5000);
    302     CPPUNIT_ASSERT( v.capacity() >= 5000 );
    303   }
    304 
    305   {
    306     //Test that used to generate an assertion when using __debug_alloc.
    307     vector<TestStruct> va;
    308     va.reserve(1);
    309     va.reserve(2);
    310   }
    311 }
    312 
    313 void VectorTest::at() {
    314   vector<int> v;
    315   vector<int> const& cv = v;
    316 
    317   v.push_back(10);
    318   CPPUNIT_ASSERT( v.at(0) == 10 );
    319   v.at(0) = 20;
    320   CPPUNIT_ASSERT( cv.at(0) == 20 );
    321 
    322 #if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
    323   try {
    324     v.at(1) = 20;
    325     CPPUNIT_FAIL;
    326   }
    327   catch (out_of_range const&) {
    328   }
    329   catch (...) {
    330     CPPUNIT_FAIL;
    331   }
    332 #endif
    333 }
    334 
    335 void VectorTest::pointer()
    336 {
    337   vector<int *> v1;
    338   vector<int *> v2 = v1;
    339   vector<int *> v3;
    340 
    341   v3.insert( v3.end(), v1.begin(), v1.end() );
    342 }
    343 
    344 void VectorTest::auto_ref()
    345 {
    346   vector<int> ref;
    347   for (int i = 0; i < 5; ++i) {
    348     ref.push_back(i);
    349   }
    350 
    351   vector<vector<int> > v_v_int(1, ref);
    352   v_v_int.push_back(v_v_int[0]);
    353   v_v_int.push_back(ref);
    354   v_v_int.push_back(v_v_int[0]);
    355   v_v_int.push_back(v_v_int[0]);
    356   v_v_int.push_back(ref);
    357 
    358   vector<vector<int> >::iterator vvit(v_v_int.begin()), vvitEnd(v_v_int.end());
    359   for (; vvit != vvitEnd; ++vvit) {
    360     CPPUNIT_ASSERT( *vvit == ref );
    361   }
    362 
    363   /*
    364    * Forbidden by the Standard:
    365   v_v_int.insert(v_v_int.end(), v_v_int.begin(), v_v_int.end());
    366   for (vvit = v_v_int.begin(), vvitEnd = v_v_int.end();
    367        vvit != vvitEnd; ++vvit) {
    368     CPPUNIT_ASSERT( *vvit == ref );
    369   }
    370    */
    371 }
    372 
    373 void VectorTest::allocator_with_state()
    374   {
    375     char buf1[1024];
    376     StackAllocator<int> stack1(buf1, buf1 + sizeof(buf1));
    377 
    378     char buf2[1024];
    379     StackAllocator<int> stack2(buf2, buf2 + sizeof(buf2));
    380 
    381     {
    382       typedef vector<int, StackAllocator<int> > VectorInt;
    383       VectorInt vint1(10, 0, stack1);
    384       VectorInt vint1Cpy(vint1);
    385 
    386       VectorInt vint2(10, 1, stack2);
    387       VectorInt vint2Cpy(vint2);
    388 
    389       vint1.swap(vint2);
    390 
    391       CPPUNIT_ASSERT( vint1.get_allocator().swaped() );
    392       CPPUNIT_ASSERT( vint2.get_allocator().swaped() );
    393 
    394       CPPUNIT_ASSERT( vint1 == vint2Cpy );
    395       CPPUNIT_ASSERT( vint2 == vint1Cpy );
    396       CPPUNIT_ASSERT( vint1.get_allocator() == stack2 );
    397       CPPUNIT_ASSERT( vint2.get_allocator() == stack1 );
    398     }
    399     CPPUNIT_ASSERT( stack1.ok() );
    400     CPPUNIT_ASSERT( stack2.ok() );
    401   }
    402 
    403 struct Point {
    404   int x, y;
    405 };
    406 
    407 struct PointEx : public Point {
    408   PointEx() : builtFromBase(false) {}
    409   PointEx(const Point&) : builtFromBase(true) {}
    410 
    411   bool builtFromBase;
    412 };
    413 
    414 #if defined (STLPORT)
    415 #  if defined (_STLP_USE_NAMESPACES)
    416 namespace std {
    417 #  endif
    418   _STLP_TEMPLATE_NULL
    419   struct __type_traits<PointEx> {
    420     typedef __false_type has_trivial_default_constructor;
    421     typedef __true_type has_trivial_copy_constructor;
    422     typedef __true_type has_trivial_assignment_operator;
    423     typedef __true_type has_trivial_destructor;
    424     typedef __true_type is_POD_type;
    425   };
    426 #  if defined (_STLP_USE_NAMESPACES)
    427 }
    428 #  endif
    429 #endif
    430 
    431 //This test check that vector implementation do not over optimize
    432 //operation as PointEx copy constructor is trivial
    433 void VectorTest::optimizations_check()
    434 {
    435 #if !defined (STLPORT) || !defined (_STLP_NO_MEMBER_TEMPLATES)
    436   vector<Point> v1(1);
    437   CPPUNIT_ASSERT( v1.size() == 1 );
    438 
    439   vector<PointEx> v2(v1.begin(), v1.end());
    440   CPPUNIT_ASSERT( v2.size() == 1 );
    441   CPPUNIT_ASSERT( v2[0].builtFromBase == true );
    442 #endif
    443 }
    444 
    445 void VectorTest::assign_check()
    446 {
    447 #if !defined (STLPORT) || !defined (_STLP_NO_MEMBER_TEMPLATES)
    448   vector<int> v(3,1);
    449   int array[] = { 1, 2, 3, 4, 5 };
    450 
    451   v.assign( array, array + 5 );
    452   CPPUNIT_CHECK( v[4] == 5 );
    453   CPPUNIT_CHECK( v[0] == 1 );
    454   CPPUNIT_CHECK( v[1] == 2 );
    455 #endif
    456 }
    457 
    458 void VectorTest::iterators()
    459 {
    460   vector<int> vint(10, 0);
    461   vector<int> const& crvint = vint;
    462 
    463   CPPUNIT_ASSERT( vint.begin() == vint.begin() );
    464   CPPUNIT_ASSERT( crvint.begin() == vint.begin() );
    465   CPPUNIT_ASSERT( vint.begin() == crvint.begin() );
    466   CPPUNIT_ASSERT( crvint.begin() == crvint.begin() );
    467 
    468   CPPUNIT_ASSERT( vint.begin() != vint.end() );
    469   CPPUNIT_ASSERT( crvint.begin() != vint.end() );
    470   CPPUNIT_ASSERT( vint.begin() != crvint.end() );
    471   CPPUNIT_ASSERT( crvint.begin() != crvint.end() );
    472 
    473   CPPUNIT_ASSERT( vint.rbegin() == vint.rbegin() );
    474   // Not Standard:
    475   //CPPUNIT_ASSERT( vint.rbegin() == crvint.rbegin() );
    476   //CPPUNIT_ASSERT( crvint.rbegin() == vint.rbegin() );
    477   CPPUNIT_ASSERT( crvint.rbegin() == crvint.rbegin() );
    478 
    479   CPPUNIT_ASSERT( vint.rbegin() != vint.rend() );
    480   // Not Standard:
    481   //CPPUNIT_ASSERT( vint.rbegin() != crvint.rend() );
    482   //CPPUNIT_ASSERT( crvint.rbegin() != vint.rend() );
    483   CPPUNIT_ASSERT( crvint.rbegin() != crvint.rend() );
    484 }
    485 
    486 
    487 #if !defined (STLPORT) || \
    488     !defined (_STLP_USE_PTR_SPECIALIZATIONS) || defined (_STLP_CLASS_PARTIAL_SPECIALIZATION)
    489 /* Simple compilation test: Check that nested types like iterator
    490  * can be access even if type used to instanciate container is not
    491  * yet completely defined.
    492  */
    493 class IncompleteClass
    494 {
    495   vector<IncompleteClass> instances;
    496   typedef vector<IncompleteClass>::iterator it;
    497 };
    498 #endif
    499 
    500 #if defined (STLPORT)
    501 #  define NOTHROW _STLP_NOTHROW
    502 #else
    503 #  define NOTHROW throw()
    504 #endif
    505 
    506 /* This allocator implementation purpose is simply to break some
    507  * internal STLport mecanism specific to the STLport own allocator
    508  * implementation. */
    509 template <class _Tp>
    510 struct NotSTLportAllocator : public allocator<_Tp> {
    511 #if !defined (STLPORT) || defined (_STLP_MEMBER_TEMPLATE_CLASSES)
    512   template <class _Tp1> struct rebind {
    513     typedef NotSTLportAllocator<_Tp1> other;
    514   };
    515 #endif
    516   NotSTLportAllocator() NOTHROW {}
    517 #if !defined (STLPORT) || defined (_STLP_MEMBER_TEMPLATES)
    518   template <class _Tp1> NotSTLportAllocator(const NotSTLportAllocator<_Tp1>&) NOTHROW {}
    519 #endif
    520   NotSTLportAllocator(const NotSTLportAllocator<_Tp>&) NOTHROW {}
    521   ~NotSTLportAllocator() NOTHROW {}
    522 };
    523 
    524 /* This test check a potential issue with empty base class
    525  * optimization. Some compilers (VC6) do not implement it
    526  * correctly resulting ina wrong behavior. */
    527 void VectorTest::ebo()
    528 {
    529   // We use heap memory as test failure can corrupt vector internal
    530   // representation making executable crash on vector destructor invocation.
    531   // We prefer a simple memory leak, internal corruption should be reveal
    532   // by size or capacity checks.
    533   typedef vector<int, NotSTLportAllocator<int> > V;
    534   V *pv1 = new V(1, 1);
    535   V *pv2 = new V(10, 2);
    536 
    537   size_t v1Capacity = pv1->capacity();
    538   size_t v2Capacity = pv2->capacity();
    539 
    540   pv1->swap(*pv2);
    541 
    542   CPPUNIT_ASSERT( pv1->size() == 10 );
    543   CPPUNIT_ASSERT( pv1->capacity() == v2Capacity );
    544   CPPUNIT_ASSERT( (*pv1)[5] == 2 );
    545 
    546   CPPUNIT_ASSERT( pv2->size() == 1 );
    547   CPPUNIT_ASSERT( pv2->capacity() == v1Capacity );
    548   CPPUNIT_ASSERT( (*pv2)[0] == 1 );
    549 
    550   delete pv2;
    551   delete pv1;
    552 }
    553 
    554