Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenvector_test.cpp
Go to the documentation of this file.
00001 //Has to be first for StackAllocator swap overload to be taken 00002 //into account (at least using GCC 4.0.1) 00003 #include "stack_allocator.h" 00004 00005 #include <vector> 00006 #include <algorithm> 00007 #if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS) 00008 # include <stdexcept> 00009 #endif 00010 00011 #include "cppunit/cppunit_proxy.h" 00012 00013 #if !defined (STLPORT) || defined(_STLP_USE_NAMESPACES) 00014 using namespace std; 00015 #endif 00016 00017 // 00018 // TestCase class 00019 // 00020 class VectorTest : public CPPUNIT_NS::TestCase 00021 { 00022 CPPUNIT_TEST_SUITE(VectorTest); 00023 CPPUNIT_TEST(vec_test_1); 00024 CPPUNIT_TEST(vec_test_2); 00025 CPPUNIT_TEST(vec_test_3); 00026 CPPUNIT_TEST(vec_test_4); 00027 CPPUNIT_TEST(vec_test_5); 00028 CPPUNIT_TEST(vec_test_6); 00029 CPPUNIT_TEST(vec_test_7); 00030 CPPUNIT_TEST(capacity); 00031 CPPUNIT_TEST(at); 00032 CPPUNIT_TEST(pointer); 00033 CPPUNIT_TEST(auto_ref); 00034 CPPUNIT_TEST(allocator_with_state); 00035 CPPUNIT_TEST(iterators); 00036 #if defined (STLPORT) && defined (_STLP_NO_MEMBER_TEMPLATES) 00037 CPPUNIT_IGNORE; 00038 #endif 00039 CPPUNIT_TEST(optimizations_check); 00040 CPPUNIT_TEST(assign_check); 00041 CPPUNIT_STOP_IGNORE; 00042 CPPUNIT_TEST(ebo); 00043 CPPUNIT_TEST_SUITE_END(); 00044 00045 protected: 00046 void vec_test_1(); 00047 void vec_test_2(); 00048 void vec_test_3(); 00049 void vec_test_4(); 00050 void vec_test_5(); 00051 void vec_test_6(); 00052 void vec_test_7(); 00053 void capacity(); 00054 void at(); 00055 void pointer(); 00056 void auto_ref(); 00057 void allocator_with_state(); 00058 void iterators(); 00059 void optimizations_check(); 00060 void assign_check(); 00061 void ebo(); 00062 }; 00063 00064 CPPUNIT_TEST_SUITE_REGISTRATION(VectorTest); 00065 00066 // 00067 // tests implementation 00068 // 00069 void VectorTest::vec_test_1() 00070 { 00071 vector<int> v1; // Empty vector of integers. 00072 00073 CPPUNIT_ASSERT( v1.empty() == true ); 00074 CPPUNIT_ASSERT( v1.size() == 0 ); 00075 00076 // CPPUNIT_ASSERT( v1.max_size() == INT_MAX / sizeof(int) ); 00077 // cout << "max_size = " << v1.max_size() << endl; 00078 v1.push_back(42); // Add an integer to the vector. 00079 00080 CPPUNIT_ASSERT( v1.size() == 1 ); 00081 00082 CPPUNIT_ASSERT( v1[0] == 42 ); 00083 00084 { 00085 vector<vector<int> > vect(10); 00086 vector<vector<int> >::iterator it(vect.begin()), end(vect.end()); 00087 for (; it != end; ++it) { 00088 CPPUNIT_ASSERT( (*it).empty() ); 00089 CPPUNIT_ASSERT( (*it).size() == 0 ); 00090 CPPUNIT_ASSERT( (*it).capacity() == 0 ); 00091 CPPUNIT_ASSERT( (*it).begin() == (*it).end() ); 00092 } 00093 } 00094 } 00095 00096 void VectorTest::vec_test_2() 00097 { 00098 vector<double> v1; // Empty vector of doubles. 00099 v1.push_back(32.1); 00100 v1.push_back(40.5); 00101 vector<double> v2; // Another empty vector of doubles. 00102 v2.push_back(3.56); 00103 00104 CPPUNIT_ASSERT( v1.size() == 2 ); 00105 CPPUNIT_ASSERT( v1[0] == 32.1 ); 00106 CPPUNIT_ASSERT( v1[1] == 40.5 ); 00107 00108 CPPUNIT_ASSERT( v2.size() == 1 ); 00109 CPPUNIT_ASSERT( v2[0] == 3.56 ); 00110 size_t v1Cap = v1.capacity(); 00111 size_t v2Cap = v2.capacity(); 00112 00113 v1.swap(v2); // Swap the vector's contents. 00114 00115 CPPUNIT_ASSERT( v1.size() == 1 ); 00116 CPPUNIT_ASSERT( v1.capacity() == v2Cap ); 00117 CPPUNIT_ASSERT( v1[0] == 3.56 ); 00118 00119 CPPUNIT_ASSERT( v2.size() == 2 ); 00120 CPPUNIT_ASSERT( v2.capacity() == v1Cap ); 00121 CPPUNIT_ASSERT( v2[0] == 32.1 ); 00122 CPPUNIT_ASSERT( v2[1] == 40.5 ); 00123 00124 v2 = v1; // Assign one vector to another. 00125 00126 CPPUNIT_ASSERT( v2.size() == 1 ); 00127 CPPUNIT_ASSERT( v2[0] == 3.56 ); 00128 } 00129 00130 void VectorTest::vec_test_3() 00131 { 00132 typedef vector<char> vec_type; 00133 00134 vec_type v1; // Empty vector of characters. 00135 v1.push_back('h'); 00136 v1.push_back('i'); 00137 00138 CPPUNIT_ASSERT( v1.size() == 2 ); 00139 CPPUNIT_ASSERT( v1[0] == 'h' ); 00140 CPPUNIT_ASSERT( v1[1] == 'i' ); 00141 00142 vec_type v2(v1.begin(), v1.end()); 00143 v2[1] = 'o'; // Replace second character. 00144 00145 CPPUNIT_ASSERT( v2.size() == 2 ); 00146 CPPUNIT_ASSERT( v2[0] == 'h' ); 00147 CPPUNIT_ASSERT( v2[1] == 'o' ); 00148 00149 CPPUNIT_ASSERT( (v1 == v2) == false ); 00150 00151 CPPUNIT_ASSERT( (v1 < v2) == true ); 00152 } 00153 00154 void VectorTest::vec_test_4() 00155 { 00156 vector<int> v(4); 00157 00158 v[0] = 1; 00159 v[1] = 4; 00160 v[2] = 9; 00161 v[3] = 16; 00162 00163 CPPUNIT_ASSERT( v.front() == 1 ); 00164 CPPUNIT_ASSERT( v.back() == 16 ); 00165 00166 v.push_back(25); 00167 00168 CPPUNIT_ASSERT( v.back() == 25 ); 00169 CPPUNIT_ASSERT( v.size() == 5 ); 00170 00171 v.pop_back(); 00172 00173 CPPUNIT_ASSERT( v.back() == 16 ); 00174 CPPUNIT_ASSERT( v.size() == 4 ); 00175 } 00176 00177 void VectorTest::vec_test_5() 00178 { 00179 int array [] = { 1, 4, 9, 16 }; 00180 00181 vector<int> v(array, array + 4); 00182 00183 CPPUNIT_ASSERT( v.size() == 4 ); 00184 00185 CPPUNIT_ASSERT( v[0] == 1 ); 00186 CPPUNIT_ASSERT( v[1] == 4 ); 00187 CPPUNIT_ASSERT( v[2] == 9 ); 00188 CPPUNIT_ASSERT( v[3] == 16 ); 00189 } 00190 00191 void VectorTest::vec_test_6() 00192 { 00193 int array [] = { 1, 4, 9, 16, 25, 36 }; 00194 00195 vector<int> v(array, array + 6); 00196 vector<int>::iterator vit; 00197 00198 CPPUNIT_ASSERT( v.size() == 6 ); 00199 CPPUNIT_ASSERT( v[0] == 1 ); 00200 CPPUNIT_ASSERT( v[1] == 4 ); 00201 CPPUNIT_ASSERT( v[2] == 9 ); 00202 CPPUNIT_ASSERT( v[3] == 16 ); 00203 CPPUNIT_ASSERT( v[4] == 25 ); 00204 CPPUNIT_ASSERT( v[5] == 36 ); 00205 00206 vit = v.erase( v.begin() ); // Erase first element. 00207 CPPUNIT_ASSERT( *vit == 4 ); 00208 00209 CPPUNIT_ASSERT( v.size() == 5 ); 00210 CPPUNIT_ASSERT( v[0] == 4 ); 00211 CPPUNIT_ASSERT( v[1] == 9 ); 00212 CPPUNIT_ASSERT( v[2] == 16 ); 00213 CPPUNIT_ASSERT( v[3] == 25 ); 00214 CPPUNIT_ASSERT( v[4] == 36 ); 00215 00216 vit = v.erase(v.end() - 1); // Erase last element. 00217 CPPUNIT_ASSERT( vit == v.end() ); 00218 00219 CPPUNIT_ASSERT( v.size() == 4 ); 00220 CPPUNIT_ASSERT( v[0] == 4 ); 00221 CPPUNIT_ASSERT( v[1] == 9 ); 00222 CPPUNIT_ASSERT( v[2] == 16 ); 00223 CPPUNIT_ASSERT( v[3] == 25 ); 00224 00225 00226 v.erase(v.begin() + 1, v.end() - 1); // Erase all but first and last. 00227 00228 CPPUNIT_ASSERT( v.size() == 2 ); 00229 CPPUNIT_ASSERT( v[0] == 4 ); 00230 CPPUNIT_ASSERT( v[1] == 25 ); 00231 00232 } 00233 00234 void VectorTest::vec_test_7() 00235 { 00236 int array1 [] = { 1, 4, 25 }; 00237 int array2 [] = { 9, 16 }; 00238 00239 vector<int> v(array1, array1 + 3); 00240 vector<int>::iterator vit; 00241 vit = v.insert(v.begin(), 0); // Insert before first element. 00242 CPPUNIT_ASSERT( *vit == 0 ); 00243 00244 vit = v.insert(v.end(), 36); // Insert after last element. 00245 CPPUNIT_ASSERT( *vit == 36 ); 00246 00247 CPPUNIT_ASSERT( v.size() == 5 ); 00248 CPPUNIT_ASSERT( v[0] == 0 ); 00249 CPPUNIT_ASSERT( v[1] == 1 ); 00250 CPPUNIT_ASSERT( v[2] == 4 ); 00251 CPPUNIT_ASSERT( v[3] == 25 ); 00252 CPPUNIT_ASSERT( v[4] == 36 ); 00253 00254 // Insert contents of array2 before fourth element. 00255 v.insert(v.begin() + 3, array2, array2 + 2); 00256 00257 CPPUNIT_ASSERT( v.size() == 7 ); 00258 00259 CPPUNIT_ASSERT( v[0] == 0 ); 00260 CPPUNIT_ASSERT( v[1] == 1 ); 00261 CPPUNIT_ASSERT( v[2] == 4 ); 00262 CPPUNIT_ASSERT( v[3] == 9 ); 00263 CPPUNIT_ASSERT( v[4] == 16 ); 00264 CPPUNIT_ASSERT( v[5] == 25 ); 00265 CPPUNIT_ASSERT( v[6] == 36 ); 00266 00267 v.clear(); 00268 CPPUNIT_ASSERT( v.empty() ); 00269 00270 v.insert(v.begin(), 5, 10); 00271 CPPUNIT_ASSERT( v.size() == 5 ); 00272 CPPUNIT_ASSERT( v[0] == 10 ); 00273 CPPUNIT_ASSERT( v[1] == 10 ); 00274 CPPUNIT_ASSERT( v[2] == 10 ); 00275 CPPUNIT_ASSERT( v[3] == 10 ); 00276 CPPUNIT_ASSERT( v[4] == 10 ); 00277 00278 /* 00279 { 00280 vector<float> vf(2.0f, 3.0f); 00281 CPPUNIT_ASSERT( vf.size() == 2 ); 00282 CPPUNIT_ASSERT( vf.front() == 3.0f ); 00283 CPPUNIT_ASSERT( vf.back() == 3.0f ); 00284 } 00285 */ 00286 } 00287 00288 struct TestStruct 00289 { 00290 unsigned int a[3]; 00291 }; 00292 00293 void VectorTest::capacity() 00294 { 00295 { 00296 vector<int> v; 00297 00298 CPPUNIT_ASSERT( v.capacity() == 0 ); 00299 v.push_back(42); 00300 CPPUNIT_ASSERT( v.capacity() >= 1 ); 00301 v.reserve(5000); 00302 CPPUNIT_ASSERT( v.capacity() >= 5000 ); 00303 } 00304 00305 { 00306 //Test that used to generate an assertion when using __debug_alloc. 00307 vector<TestStruct> va; 00308 va.reserve(1); 00309 va.reserve(2); 00310 } 00311 } 00312 00313 void VectorTest::at() { 00314 vector<int> v; 00315 vector<int> const& cv = v; 00316 00317 v.push_back(10); 00318 CPPUNIT_ASSERT( v.at(0) == 10 ); 00319 v.at(0) = 20; 00320 CPPUNIT_ASSERT( cv.at(0) == 20 ); 00321 00322 #if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS) 00323 try { 00324 v.at(1) = 20; 00325 CPPUNIT_FAIL; 00326 } 00327 catch (out_of_range const&) { 00328 } 00329 catch (...) { 00330 CPPUNIT_FAIL; 00331 } 00332 #endif 00333 } 00334 00335 void VectorTest::pointer() 00336 { 00337 vector<int *> v1; 00338 vector<int *> v2 = v1; 00339 vector<int *> v3; 00340 00341 v3.insert( v3.end(), v1.begin(), v1.end() ); 00342 } 00343 00344 void VectorTest::auto_ref() 00345 { 00346 vector<int> ref; 00347 for (int i = 0; i < 5; ++i) { 00348 ref.push_back(i); 00349 } 00350 00351 vector<vector<int> > v_v_int(1, ref); 00352 v_v_int.push_back(v_v_int[0]); 00353 v_v_int.push_back(ref); 00354 v_v_int.push_back(v_v_int[0]); 00355 v_v_int.push_back(v_v_int[0]); 00356 v_v_int.push_back(ref); 00357 00358 vector<vector<int> >::iterator vvit(v_v_int.begin()), vvitEnd(v_v_int.end()); 00359 for (; vvit != vvitEnd; ++vvit) { 00360 CPPUNIT_ASSERT( *vvit == ref ); 00361 } 00362 00363 /* 00364 * Forbidden by the Standard: 00365 v_v_int.insert(v_v_int.end(), v_v_int.begin(), v_v_int.end()); 00366 for (vvit = v_v_int.begin(), vvitEnd = v_v_int.end(); 00367 vvit != vvitEnd; ++vvit) { 00368 CPPUNIT_ASSERT( *vvit == ref ); 00369 } 00370 */ 00371 } 00372 00373 void VectorTest::allocator_with_state() 00374 { 00375 char buf1[1024]; 00376 StackAllocator<int> stack1(buf1, buf1 + sizeof(buf1)); 00377 00378 char buf2[1024]; 00379 StackAllocator<int> stack2(buf2, buf2 + sizeof(buf2)); 00380 00381 { 00382 typedef vector<int, StackAllocator<int> > VectorInt; 00383 VectorInt vint1(10, 0, stack1); 00384 VectorInt vint1Cpy(vint1); 00385 00386 VectorInt vint2(10, 1, stack2); 00387 VectorInt vint2Cpy(vint2); 00388 00389 vint1.swap(vint2); 00390 00391 CPPUNIT_ASSERT( vint1.get_allocator().swaped() ); 00392 CPPUNIT_ASSERT( vint2.get_allocator().swaped() ); 00393 00394 CPPUNIT_ASSERT( vint1 == vint2Cpy ); 00395 CPPUNIT_ASSERT( vint2 == vint1Cpy ); 00396 CPPUNIT_ASSERT( vint1.get_allocator() == stack2 ); 00397 CPPUNIT_ASSERT( vint2.get_allocator() == stack1 ); 00398 } 00399 CPPUNIT_ASSERT( stack1.ok() ); 00400 CPPUNIT_ASSERT( stack2.ok() ); 00401 } 00402 00403 struct Point { 00404 int x, y; 00405 }; 00406 00407 struct PointEx : public Point { 00408 PointEx() : builtFromBase(false) {} 00409 PointEx(const Point&) : builtFromBase(true) {} 00410 00411 bool builtFromBase; 00412 }; 00413 00414 #if defined (STLPORT) 00415 # if defined (_STLP_USE_NAMESPACES) 00416 namespace std { 00417 # endif 00418 _STLP_TEMPLATE_NULL 00419 struct __type_traits<PointEx> { 00420 typedef __false_type has_trivial_default_constructor; 00421 typedef __true_type has_trivial_copy_constructor; 00422 typedef __true_type has_trivial_assignment_operator; 00423 typedef __true_type has_trivial_destructor; 00424 typedef __true_type is_POD_type; 00425 }; 00426 # if defined (_STLP_USE_NAMESPACES) 00427 } 00428 # endif 00429 #endif 00430 00431 //This test check that vector implementation do not over optimize 00432 //operation as PointEx copy constructor is trivial 00433 void VectorTest::optimizations_check() 00434 { 00435 #if !defined (STLPORT) || !defined (_STLP_NO_MEMBER_TEMPLATES) 00436 vector<Point> v1(1); 00437 CPPUNIT_ASSERT( v1.size() == 1 ); 00438 00439 vector<PointEx> v2(v1.begin(), v1.end()); 00440 CPPUNIT_ASSERT( v2.size() == 1 ); 00441 CPPUNIT_ASSERT( v2[0].builtFromBase == true ); 00442 #endif 00443 } 00444 00445 void VectorTest::assign_check() 00446 { 00447 #if !defined (STLPORT) || !defined (_STLP_NO_MEMBER_TEMPLATES) 00448 vector<int> v(3,1); 00449 int array[] = { 1, 2, 3, 4, 5 }; 00450 00451 v.assign( array, array + 5 ); 00452 CPPUNIT_CHECK( v[4] == 5 ); 00453 CPPUNIT_CHECK( v[0] == 1 ); 00454 CPPUNIT_CHECK( v[1] == 2 ); 00455 #endif 00456 } 00457 00458 void VectorTest::iterators() 00459 { 00460 vector<int> vint(10, 0); 00461 vector<int> const& crvint = vint; 00462 00463 CPPUNIT_ASSERT( vint.begin() == vint.begin() ); 00464 CPPUNIT_ASSERT( crvint.begin() == vint.begin() ); 00465 CPPUNIT_ASSERT( vint.begin() == crvint.begin() ); 00466 CPPUNIT_ASSERT( crvint.begin() == crvint.begin() ); 00467 00468 CPPUNIT_ASSERT( vint.begin() != vint.end() ); 00469 CPPUNIT_ASSERT( crvint.begin() != vint.end() ); 00470 CPPUNIT_ASSERT( vint.begin() != crvint.end() ); 00471 CPPUNIT_ASSERT( crvint.begin() != crvint.end() ); 00472 00473 CPPUNIT_ASSERT( vint.rbegin() == vint.rbegin() ); 00474 // Not Standard: 00475 //CPPUNIT_ASSERT( vint.rbegin() == crvint.rbegin() ); 00476 //CPPUNIT_ASSERT( crvint.rbegin() == vint.rbegin() ); 00477 CPPUNIT_ASSERT( crvint.rbegin() == crvint.rbegin() ); 00478 00479 CPPUNIT_ASSERT( vint.rbegin() != vint.rend() ); 00480 // Not Standard: 00481 //CPPUNIT_ASSERT( vint.rbegin() != crvint.rend() ); 00482 //CPPUNIT_ASSERT( crvint.rbegin() != vint.rend() ); 00483 CPPUNIT_ASSERT( crvint.rbegin() != crvint.rend() ); 00484 } 00485 00486 00487 #if !defined (STLPORT) || \ 00488 !defined (_STLP_USE_PTR_SPECIALIZATIONS) || defined (_STLP_CLASS_PARTIAL_SPECIALIZATION) 00489 /* Simple compilation test: Check that nested types like iterator 00490 * can be access even if type used to instanciate container is not 00491 * yet completely defined. 00492 */ 00493 class IncompleteClass 00494 { 00495 vector<IncompleteClass> instances; 00496 typedef vector<IncompleteClass>::iterator it; 00497 }; 00498 #endif 00499 00500 #if defined (STLPORT) 00501 # define NOTHROW _STLP_NOTHROW 00502 #else 00503 # define NOTHROW throw() 00504 #endif 00505 00506 /* This allocator implementation purpose is simply to break some 00507 * internal STLport mecanism specific to the STLport own allocator 00508 * implementation. */ 00509 template <class _Tp> 00510 struct NotSTLportAllocator : public allocator<_Tp> { 00511 #if !defined (STLPORT) || defined (_STLP_MEMBER_TEMPLATE_CLASSES) 00512 template <class _Tp1> struct rebind { 00513 typedef NotSTLportAllocator<_Tp1> other; 00514 }; 00515 #endif 00516 NotSTLportAllocator() NOTHROW {} 00517 #if !defined (STLPORT) || defined (_STLP_MEMBER_TEMPLATES) 00518 template <class _Tp1> NotSTLportAllocator(const NotSTLportAllocator<_Tp1>&) NOTHROW {} 00519 #endif 00520 NotSTLportAllocator(const NotSTLportAllocator<_Tp>&) NOTHROW {} 00521 ~NotSTLportAllocator() NOTHROW {} 00522 }; 00523 00524 /* This test check a potential issue with empty base class 00525 * optimization. Some compilers (VC6) do not implement it 00526 * correctly resulting ina wrong behavior. */ 00527 void VectorTest::ebo() 00528 { 00529 // We use heap memory as test failure can corrupt vector internal 00530 // representation making executable crash on vector destructor invocation. 00531 // We prefer a simple memory leak, internal corruption should be reveal 00532 // by size or capacity checks. 00533 typedef vector<int, NotSTLportAllocator<int> > V; 00534 V *pv1 = new V(1, 1); 00535 V *pv2 = new V(10, 2); 00536 00537 size_t v1Capacity = pv1->capacity(); 00538 size_t v2Capacity = pv2->capacity(); 00539 00540 pv1->swap(*pv2); 00541 00542 CPPUNIT_ASSERT( pv1->size() == 10 ); 00543 CPPUNIT_ASSERT( pv1->capacity() == v2Capacity ); 00544 CPPUNIT_ASSERT( (*pv1)[5] == 2 ); 00545 00546 CPPUNIT_ASSERT( pv2->size() == 1 ); 00547 CPPUNIT_ASSERT( pv2->capacity() == v1Capacity ); 00548 CPPUNIT_ASSERT( (*pv2)[0] == 1 ); 00549 00550 delete pv2; 00551 delete pv1; 00552 } 00553 Generated on Mon May 28 2012 04:35:41 for ReactOS by
1.7.6.1
|