lkptr
|
00001 // test_lkptr.cpp (C) 2007 adolfo@di-mare.com 00002 00003 /** \file test_lkptr.cpp 00004 \brief Test data for class \c lkptr<X>. 00005 00006 \author Adolfo Di Mare <adolfo@di-mare.com> 00007 \date 2008. 00008 */ 00009 00010 #define lkptr_MERGE_IS_PUBLIC 00011 #include "lkptr.h" 00012 #include "BUnit.h" // Módulo para prueba unitaria de programas 00013 00014 /// Test data for class \c lkptr. 00015 template <typename X> 00016 class test_lkptr : public TestCase { 00017 int * pInt; 00018 public: 00019 test_lkptr() : TestCase(), pInt(0) {} 00020 bool run(); 00021 void swap_4x1(); 00022 void ok_1x2(); 00023 void verify_3x1(); 00024 void boost_test(); 00025 void array_vs_lkptr(); 00026 void null_3x1(); 00027 void inheritance(); 00028 void downcast(); 00029 void selfReturn(); 00030 void multiDestroyInt(); 00031 void multiDestroyClass(); 00032 void multiDestroyVector(); 00033 void test_lkptr_cycle(); 00034 private: 00035 lkptr<int> foo( lkptr<int> r ); 00036 }; 00037 00038 /// Runs the tests. 00039 template <typename X> 00040 bool test_lkptr<X>::run() { 00041 verify_3x1(); 00042 boost_test(); 00043 array_vs_lkptr(); 00044 swap_4x1(); 00045 ok_1x2(); 00046 null_3x1(); 00047 inheritance(); 00048 downcast(); 00049 selfReturn(); 00050 multiDestroyInt(); 00051 multiDestroyClass(); 00052 multiDestroyVector(); 00053 test_lkptr_cycle(); 00054 00055 return wasSuccessful(); 00056 } 00057 00058 /// Tries with 3 pointes to the same value. 00059 template <typename X> 00060 void test_lkptr<X>::null_3x1() { 00061 {{ // test::null_3x1 00062 lkptr<X> A, B, C; 00063 A = B = C; 00064 assertTrue( A.ok() ); assertTrue( check_ok(A) ); 00065 assertTrue( B.ok() ); assertTrue( check_ok(C) ); 00066 assertTrue( C.ok() ); assertTrue( check_ok(C) ); 00067 00068 assertTrue( A.use_count() == 3 ); 00069 assertTrue( B.use_count() == 3 ); 00070 assertTrue( C.use_count() == 3 ); 00071 00072 assertTrue( A == B ); 00073 assertTrue( B == C ); 00074 assertTrue( A.get() == 0 && A.isNull() ); 00075 00076 assertTrue( A.use_count() == 3 ); 00077 assertTrue( B.use_count() == 3 ); 00078 assertTrue( C.use_count() == 3 ); 00079 }} 00080 } 00081 00082 /// Swaps 4 \c lkptr<X>'s. 00083 template <typename X> 00084 void test_lkptr<X>::swap_4x1() { 00085 X* p = new X(); 00086 lkptr<X> A ( p ); 00087 lkptr<X> B, C, D; 00088 00089 assertTrue( A.use_count() == 1 ); 00090 assertTrue( B.use_count() == 1 ); 00091 assertTrue( C.use_count() == 1 ); 00092 assertTrue( A.get() != 0 && *A == *p); 00093 A.swap(A); B.swap(B); 00094 assertTrue( A.ok() && B.ok() && C.ok() ); 00095 A.swap(B); // *B==*p && A==null && C==null 00096 assertTrue( A.ok() && B.ok() && C.ok() ); 00097 assertTrue( A.get() == 0 ); 00098 assertTrue( B.get() != 0 && *B == *p); 00099 assertTrue( C.get() == 0 ); 00100 assertTrue( A.use_count() == 1 ); 00101 assertTrue( B.use_count() == 1 ); 00102 assertTrue( C.use_count() == 1 ); 00103 C.swap(C); B.swap(B); 00104 assertTrue( A.ok() && B.ok() && C.ok() ); 00105 C.swap(B); // *C==*p && A==null && B==null 00106 assertTrue( A.ok() && B.ok() && C.ok() ); 00107 assertTrue( A.get() == 0 ); 00108 assertTrue( B.get() == 0 ); 00109 assertTrue( C.get() != 0 && *C == *p); 00110 00111 A = B; // *C==0 && (A==B==null) 00112 assertTrue( A.use_count() == 2 ); 00113 assertTrue( B.use_count() == 2 ); 00114 assertTrue( C.use_count() == 1 ); 00115 assertTrue( A.ok() && B.ok() && C.ok() ); 00116 00117 B.swap(B); C.swap(C); 00118 B.swap(C); // *B==0 && (A==C==null) 00119 assertTrue( A.use_count() == 2 ); 00120 assertTrue( B.use_count() == 1 ); 00121 assertTrue( C.use_count() == 2 ); 00122 assertTrue( A.ok() && B.ok() && C.ok() ); 00123 00124 assertTrue( A.get() == 0 ); 00125 assertTrue( B.get() != 0 && *B == X()); 00126 assertTrue( C.get() == 0 ); 00127 assertTrue( A.ok() && B.ok() && C.ok() ); 00128 00129 C = B; // A==null && (B==C==p) != null 00130 assertTrue( A.use_count() == 1 ); 00131 assertTrue( B.use_count() == 2 ); 00132 assertTrue( C.use_count() == 2 ); 00133 assertTrue( A.get() == 0 ); 00134 assertTrue( B.get() != 0 && *B == X()); 00135 assertTrue( C.get() != 0 && *C == X()); 00136 assertTrue( A.ok() && B.ok() && C.ok() ); 00137 00138 C.swap(B); // A==null && (B==C==p) != null 00139 assertTrue( B.use_count() == 2 ); 00140 assertTrue( C.use_count() == 2 ); 00141 assertTrue( B.get() != 0 && *B == X()); 00142 assertTrue( C.get() != 0 && *C == X()); 00143 assertTrue( A.ok() && B.ok() && C.ok() ); 00144 00145 X* q = new X(); 00146 C.reset( q ); // A==null && (B==p) != (C==q) 00147 assertTrue( A.use_count() == 1 ); 00148 assertTrue( B.use_count() == 1 ); 00149 assertTrue( C.use_count() == 1 ); 00150 assertTrue( B.get() != 0 && *B == X()); 00151 assertTrue( C.get() != 0 && *C == X()); 00152 assertTrue( B.get() != C.get() ); 00153 assertTrue( A.ok() && B.ok() && C.ok() ); 00154 00155 A=B; D=C; // (A===B==p) != (C==D==q) 00156 assertTrue( A.use_count() == 2 ); 00157 assertTrue( B.use_count() == 2 ); 00158 assertTrue( C.use_count() == 2 ); 00159 assertTrue( D.use_count() == 2 ); 00160 assertTrue( A.get() == B.get() ); 00161 assertTrue( C.get() == D.get() ); 00162 assertTrue( A.get() != C.get() ); 00163 assertTrue( *A == *p && *C == *q ); 00164 assertTrue( A.ok() && B.ok() && C.ok() && D.ok() ); 00165 00166 A.swap(B); D.swap(C); // (A===B==p) != (C==D==q) 00167 assertTrue( A.get() == B.get() ); 00168 assertTrue( C.get() == D.get() ); 00169 assertTrue( A.get() != C.get() ); 00170 assertTrue( A.get() == p && C.get() == q ); 00171 assertTrue( A.ok() && B.ok() && C.ok() && D.ok() ); 00172 00173 A.swap(C); // (C===B==p) != (A==D==q) 00174 assertTrue( C.get() == B.get() ); 00175 assertTrue( A.get() == D.get() ); 00176 assertTrue( A.get() != C.get() ); 00177 assertTrue( A.use_count() == 2 ); 00178 assertTrue( B.use_count() == 2 ); 00179 assertTrue( C.use_count() == 2 ); 00180 assertTrue( D.use_count() == 2 ); 00181 assertTrue( *A == *q && *C == *p ); 00182 assertTrue( A.ok() && B.ok() && C.ok() && D.ok() ); 00183 00184 A = B; // (A==C===B==p) != (D==q) 00185 assertTrue( A.use_count() == 3 ); 00186 assertTrue( B.use_count() == 3 ); 00187 assertTrue( C.use_count() == 3 ); 00188 assertTrue( D.use_count() == 1 ); 00189 assertTrue( A.get() == B.get() ); 00190 assertTrue( B.get() == C.get() ); 00191 assertTrue( A.get() != D.get() ); 00192 assertTrue( A.get() == p && D.get() == q ); 00193 assertTrue( *A == *p && *D == *q ); 00194 assertTrue( A.ok() && B.ok() && C.ok() && D.ok() ); 00195 00196 D = C; // (A==C===B==D==p) && (q->bye->bye) 00197 assertTrue( A.use_count() == 4 ); 00198 assertTrue( B.use_count() == 4 ); 00199 assertTrue( C.use_count() == 4 ); 00200 assertTrue( D.use_count() == 4 ); 00201 assertTrue( A.get() == B.get() ); 00202 assertTrue( B.get() == C.get() ); 00203 assertTrue( C.get() == D.get() ); 00204 assertTrue( A.get() == p && A.get() != q ); 00205 assertTrue( A.ok() && B.ok() && C.ok() && D.ok() ); 00206 00207 A.swap(B); B.swap(C); 00208 C.swap(D); D.swap(A); 00209 A.swap(A); B.swap(B); C.swap(C); D.swap(D); 00210 assertTrue( A.use_count() == 4 ); 00211 assertTrue( B.use_count() == 4 ); 00212 assertTrue( C.use_count() == 4 ); 00213 assertTrue( D.use_count() == 4 ); 00214 assertTrue( A.get() == B.get() ); 00215 assertTrue( B.get() == C.get() ); 00216 assertTrue( C.get() == D.get() ); 00217 assertTrue( A.get() == p && A.get() != q ); 00218 assertTrue( A.ok() && B.ok() && C.ok() && D.ok() ); 00219 00220 D.release(); // (A==C===B==p) && (D==0) 00221 assertTrue( A.use_count() == 3 ); 00222 assertTrue( B.use_count() == 3 ); 00223 assertTrue( C.use_count() == 3 ); 00224 assertTrue( D.use_count() == 1 ); 00225 assertTrue( A.get() == B.get() ); 00226 assertTrue( B.get() == C.get() ); 00227 assertTrue( C.get() != D.get() ); 00228 assertTrue( A.get() == p && A.get() != q ); 00229 assertTrue( D.get() == 0 ); 00230 assertTrue( A.ok() && B.ok() && C.ok() && D.ok() ); 00231 00232 D = A; // (A==C==B==D==p) 00233 A.swap(A); B.swap(B); C.swap(C); D.swap(D); 00234 assertTrue( A.use_count() == 4 ); 00235 assertTrue( B.use_count() == 4 ); 00236 assertTrue( C.use_count() == 4 ); 00237 assertTrue( D.use_count() == 4 ); 00238 assertTrue( A.get() == B.get() ); 00239 assertTrue( B.get() == C.get() ); 00240 assertTrue( C.get() == D.get() ); 00241 assertTrue( A.get() == p && A.get() != q ); 00242 assertTrue( A.ok() && B.ok() && C.ok() && D.ok() ); 00243 00244 D.release(); // (A==C==B==p) && (D==0) 00245 D.swap(A); // (D==C==B==p) && (A==0) 00246 assertTrue( A.use_count() == 1 ); 00247 assertTrue( B.use_count() == 3 ); 00248 assertTrue( C.use_count() == 3 ); 00249 assertTrue( D.use_count() == 3 ); 00250 assertTrue( A.get() != B.get() ); 00251 assertTrue( B.get() == C.get() ); 00252 assertTrue( C.get() == D.get() ); 00253 assertTrue( D.get() == p && D.get() != q ); 00254 assertTrue( A.get() == 0 ); 00255 assertTrue( A.ok() && B.ok() && C.ok() && D.ok() ); 00256 00257 C.release(); // (D==B==p) && (A==0) && (C==0) 00258 assertTrue( A.isNull() && C.isNull() ); 00259 assertTrue( A.get() == C.get() ); 00260 assertTrue( B.get() == D.get() ); 00261 assertTrue( A.use_count() == 1 ); 00262 assertTrue( B.use_count() == 2 ); 00263 assertTrue( C.use_count() == 1 ); 00264 assertTrue( D.use_count() == 2 ); 00265 D.swap(D); B.swap(B); 00266 assertTrue( A.ok() && B.ok() && C.ok() && D.ok() ); 00267 00268 C.swap(B); // (C==D==p) && (A==0) && (B==0) 00269 assertTrue( A.isNull() && B.isNull() ); 00270 assertTrue( A.get() == B.get() ); 00271 assertTrue( C.get() == D.get() ); 00272 assertTrue( A.use_count() == 1 ); 00273 assertTrue( B.use_count() == 1 ); 00274 assertTrue( C.use_count() == 2 ); 00275 assertTrue( D.use_count() == 2 ); 00276 D.swap(D); C.swap(C); A.swap(A); C.swap(D); 00277 assertTrue( A.ok() && B.ok() && C.ok() && D.ok() ); 00278 00279 B = C; // (B==C==D==p) && (A==0) 00280 assertTrue( A.use_count() == 1 ); 00281 assertTrue( B.use_count() == 3 ); 00282 assertTrue( C.use_count() == 3 ); 00283 assertTrue( D.use_count() == 3 ); 00284 assertTrue( B.get() == C.get() ); 00285 assertTrue( C.get() == D.get() ); 00286 assertTrue( A.ok() && B.ok() && C.ok() && D.ok() ); 00287 00288 A.swap(B); // (A==C==D==p) && (B==0) 00289 assertTrue( A.use_count() == 3 ); 00290 assertTrue( B.use_count() == 1 ); 00291 assertTrue( C.use_count() == 3 ); 00292 assertTrue( D.use_count() == 3 ); 00293 assertTrue( A.get() == C.get() ); 00294 assertTrue( C.get() == D.get() ); 00295 assertTrue( B.isNull() ); 00296 assertTrue( A.ok() && B.ok() && C.ok() && D.ok() ); 00297 } 00298 00299 template <typename X> 00300 void test_lkptr<X>::ok_1x2() { 00301 #if 0 00302 [[ A ]] 00303 +-------+-------+ 00304 | | | 00305 ./-->| [**] | [**] |<--\. 00306 ./ | // | \\ | \. 00307 | +-//----+----\\-+ | 00308 | // ^ ^ \\ | 00309 | // | | \\ | 00310 | || | | || | 00311 | || | | || | 00312 | \/ / \ \/ | 00313 +--|---+---|--+ +--|---+---|--+ 00314 | | | | | | | | | | 00315 | [**] | [**] | | [**] | [**] | 00316 | | | | | | 00317 +------+------+ +------+------+ 00318 [[ B ]] [[ C ]] 00319 00320 #endif 00321 00322 lkptr<X> A, B, C; 00323 A.b.prev = &B.b; 00324 A.b.next = &C.b; 00325 00326 B.b.prev = &A.b; C.b.prev = &A.b; 00327 B.b.next = &A.b; C.b.next = &A.b; 00328 00329 assertTrue( ! A.ok() ); 00330 assertTrue( ! B.ok() ); 00331 assertTrue( ! C.ok() ); 00332 } 00333 00334 /// Tries with 3 pointes to the same value. 00335 template <typename X> 00336 void test_lkptr<X>::verify_3x1() { 00337 lkptr<X> A ( new X() ); // A = new X(); won't compile ("explicit" constructor) 00338 lkptr<X> B, C; 00339 B = A; assertTrue( A.use_count() == 2 ); assertTrue( A.use_count() != 1 ); 00340 C = B; assertTrue( B.use_count() == 3 ); assertTrue( C.use_count() != 2 ); 00341 00342 assertTrue( A.ok() ); assertTrue( check_ok(A) ); 00343 assertTrue( B.ok() ); assertTrue( check_ok(C) ); 00344 assertTrue( C.ok() ); assertTrue( check_ok(C) ); 00345 00346 assertTrue( A.use_count() == 3 ); 00347 assertTrue( B.use_count() == 3 ); 00348 assertTrue( C.use_count() == 3 ); 00349 00350 assertTrue( A.get() == B.get() ); 00351 assertTrue( A == B ); 00352 assertTrue( B == C ); 00353 assertTrue( A.get() == C.get() ); 00354 00355 A.release(); 00356 assertTrue( A.use_count() == 1 ); 00357 assertTrue( B.use_count() == 2 ); 00358 assertTrue( C.use_count() == 2 ); 00359 assertTrue( B.get() == C.get() ); 00360 assertTrue( A != C ); 00361 00362 assertTrue( A.get() == 0 ); 00363 00364 B.release(); 00365 assertTrue( A.get() == B.get() ); 00366 assertTrue( C.get() != 0 ); 00367 } 00368 00369 #if 0 00370 00371 class UDT { 00372 long value_; 00373 public: 00374 static int UDT_use_count; // independent of pointer maintained counts 00375 explicit UDT( long value=0 ) : value_(value) { ++UDT_use_count; } 00376 ~UDT() { 00377 --UDT_use_count; 00378 // std::cout << "UDT with value " << value_ << " being destroyed\n"; 00379 } 00380 long value() const { return value_; } 00381 void value( long v ) { value_ = v;; } 00382 }; // UDT 00383 00384 int UDT::UDT_use_count = 0; 00385 00386 #else 00387 #include "figures.h" 00388 #endif 00389 00390 #include <set> 00391 00392 /// \brief http://www.boost.org/doc/libs/1_43_0/libs/smart_ptr/test/smart_ptr_test.cpp 00393 template <typename X> 00394 void test_lkptr<X>::boost_test() 00395 { 00396 #define ck(v1,v2) { BOOST_TEST( *v1 == v2 ); } 00397 #define BOOST_TEST(x) assertTrue(x) 00398 #define boost 00399 #define scoped_ptr lkptr 00400 #define shared_ptr lkptr 00401 #define scoped_array array_lkptr 00402 #define shared_array array_lkptr 00403 00404 BOOST_TEST( UDT::UDT_use_count == 0 ); // reality check 00405 00406 // test scoped_ptr with a built-in type 00407 long * lp = new long; 00408 boost::scoped_ptr<long> sp ( lp ); 00409 BOOST_TEST( sp.get() == lp ); 00410 BOOST_TEST( lp == sp.get() ); 00411 BOOST_TEST( &*sp == lp ); 00412 00413 *sp = 1234568901L; 00414 BOOST_TEST( *sp == 1234568901L ); 00415 BOOST_TEST( *lp == 1234568901L ); 00416 ck( static_cast<long*>(sp.get()), 1234568901L ); 00417 ck( lp, *sp ); 00418 00419 sp.reset(); 00420 BOOST_TEST( sp.get() == 0 ); 00421 00422 // test scoped_ptr with a user defined type 00423 boost::scoped_ptr<UDT> udt_sp ( new UDT( 999888777 ) ); 00424 BOOST_TEST( udt_sp->value() == 999888777 ); 00425 udt_sp.reset(); 00426 udt_sp.reset( new UDT( 111222333 ) ); 00427 BOOST_TEST( udt_sp->value() == 111222333 ); 00428 udt_sp.reset( new UDT( 333222111 ) ); 00429 BOOST_TEST( udt_sp->value() == 333222111 ); 00430 00431 // test scoped_array with a build-in type 00432 char * sap = new char [ 100 ]; 00433 boost::scoped_array<char> sa ( sap ); 00434 BOOST_TEST( sa.get() == sap ); 00435 BOOST_TEST( sap == sa.get() ); 00436 00437 strcpy( sa.get(), "Hot Dog with mustard and relish" ); 00438 BOOST_TEST( strcmp( sa.get(), "Hot Dog with mustard and relish" ) == 0 ); 00439 BOOST_TEST( strcmp( sap, "Hot Dog with mustard and relish" ) == 0 ); 00440 00441 BOOST_TEST( sa[0] == 'H' ); 00442 BOOST_TEST( sa[30] == 'h' ); 00443 00444 sa[0] = 'N'; 00445 sa[4] = 'd'; 00446 BOOST_TEST( strcmp( sap, "Not dog with mustard and relish" ) == 0 ); 00447 00448 sa.reset(); 00449 BOOST_TEST( sa.get() == 0 ); 00450 00451 // test shared_ptr with a built-in type 00452 int * ip = new int; 00453 boost::shared_ptr<int> cp ( ip ); 00454 BOOST_TEST( ip == cp.get() ); 00455 BOOST_TEST( cp.use_count() == 1 ); 00456 00457 *cp = 54321; 00458 BOOST_TEST( *cp == 54321 ); 00459 BOOST_TEST( *ip == 54321 ); 00460 ck( static_cast<int*>(cp.get()), 54321 ); 00461 ck( static_cast<int*>(ip), *cp ); 00462 00463 boost::shared_ptr<int> cp2 ( cp ); 00464 BOOST_TEST( ip == cp2.get() ); 00465 BOOST_TEST( cp.use_count() == 2 ); 00466 BOOST_TEST( cp2.use_count() == 2 ); 00467 00468 BOOST_TEST( *cp == 54321 ); 00469 BOOST_TEST( *cp2 == 54321 ); 00470 ck( static_cast<int*>(cp2.get()), 54321 ); 00471 ck( static_cast<int*>(ip), *cp2 ); 00472 00473 boost::shared_ptr<int> cp3 ( cp ); 00474 BOOST_TEST( cp.use_count() == 3 ); 00475 BOOST_TEST( cp2.use_count() == 3 ); 00476 BOOST_TEST( cp3.use_count() == 3 ); 00477 cp.reset(); 00478 BOOST_TEST( cp2.use_count() == 2 ); 00479 BOOST_TEST( cp3.use_count() == 2 ); 00480 cp.reset( new int ); 00481 *cp = 98765; 00482 BOOST_TEST( *cp == 98765 ); 00483 *cp3 = 87654; 00484 BOOST_TEST( *cp3 == 87654 ); 00485 BOOST_TEST( *cp2 == 87654 ); 00486 cp.swap( cp3 ); 00487 BOOST_TEST( *cp == 87654 ); 00488 BOOST_TEST( *cp2 == 87654 ); 00489 BOOST_TEST( *cp3 == 98765 ); 00490 cp.swap( cp3 ); 00491 BOOST_TEST( *cp == 98765 ); 00492 BOOST_TEST( *cp2 == 87654 ); 00493 BOOST_TEST( *cp3 == 87654 ); 00494 cp2 = cp2; 00495 BOOST_TEST( cp2.use_count() == 2 ); 00496 BOOST_TEST( *cp2 == 87654 ); 00497 cp = cp2; 00498 BOOST_TEST( cp2.use_count() == 3 ); 00499 BOOST_TEST( *cp2 == 87654 ); 00500 BOOST_TEST( cp.use_count() == 3 ); 00501 BOOST_TEST( *cp == 87654 ); 00502 00503 #if defined( BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP ) 00504 using boost::swap; 00505 #endif 00506 00507 boost::shared_ptr<int> cp4; 00508 int 00509 ggg = cp2.use_count(); 00510 ggg = cp4.use_count(); 00511 swap( cp2, cp4 ); 00512 ggg = cp2.use_count(); 00513 ggg = cp4.use_count(); 00514 BOOST_TEST( cp4.use_count() == 3 ); 00515 BOOST_TEST( *cp4 == 87654 ); 00516 BOOST_TEST( cp2.get() == 0 ); 00517 00518 std::set< boost::shared_ptr<int> > scp; 00519 scp.insert(cp4); 00520 BOOST_TEST( scp.find(cp4) != scp.end() ); 00521 BOOST_TEST( scp.find(cp4) == scp.find( boost::shared_ptr<int>(cp4) ) ); 00522 00523 // test shared_array with a built-in type 00524 char * cap = new char [ 100 ]; 00525 boost::shared_array<char> ca ( cap ); 00526 BOOST_TEST( ca.get() == cap ); 00527 BOOST_TEST( cap == ca.get() ); 00528 BOOST_TEST( &ca[0] == cap ); 00529 00530 strcpy( ca.get(), "Hot Dog with mustard and relish" ); 00531 BOOST_TEST( strcmp( ca.get(), "Hot Dog with mustard and relish" ) == 0 ); 00532 BOOST_TEST( strcmp( cap, "Hot Dog with mustard and relish" ) == 0 ); 00533 00534 BOOST_TEST( ca[0] == 'H' ); 00535 BOOST_TEST( ca[30] == 'h' ); 00536 00537 boost::shared_array<char> ca2 ( ca ); 00538 boost::shared_array<char> ca3 ( ca2 ); 00539 00540 ca[0] = 'N'; 00541 ca[4] = 'd'; 00542 BOOST_TEST( strcmp( ca.get(), "Not dog with mustard and relish" ) == 0 ); 00543 BOOST_TEST( strcmp( ca2.get(), "Not dog with mustard and relish" ) == 0 ); 00544 BOOST_TEST( strcmp( ca3.get(), "Not dog with mustard and relish" ) == 0 ); 00545 BOOST_TEST( ca.use_count() == 3 ); 00546 BOOST_TEST( ca2.use_count() == 3 ); 00547 BOOST_TEST( ca3.use_count() == 3 ); 00548 ca2.reset(); 00549 BOOST_TEST( ca.use_count() == 2 ); 00550 BOOST_TEST( ca3.use_count() == 2 ); 00551 BOOST_TEST( ca2.use_count() == 1 ); 00552 00553 ca.reset(); 00554 BOOST_TEST( ca.get() == 0 ); 00555 00556 boost::shared_array<char> ca4; 00557 swap( ca3, ca4 ); 00558 BOOST_TEST( ca4.use_count() == 1 ); 00559 BOOST_TEST( strcmp( ca4.get(), "Not dog with mustard and relish" ) == 0 ); 00560 BOOST_TEST( ca3.get() == 0 ); 00561 00562 std::set< boost::shared_array<char> > sca; 00563 sca.insert(ca4); 00564 BOOST_TEST( sca.find(ca4) != sca.end() ); 00565 BOOST_TEST( sca.find(ca4) == sca.find( boost::shared_array<char>(ca4) ) ); 00566 00567 // test shared_array with user defined type 00568 boost::shared_array<UDT> udta ( new UDT[3] ); 00569 00570 udta[0].value( 111 ); 00571 udta[1].value( 222 ); 00572 udta[2].value( 333 ); 00573 boost::shared_array<UDT> udta2 ( udta ); 00574 00575 BOOST_TEST( udta[0].value() == 111 ); 00576 BOOST_TEST( udta[1].value() == 222 ); 00577 BOOST_TEST( udta[2].value() == 333 ); 00578 BOOST_TEST( udta2[0].value() == 111 ); 00579 BOOST_TEST( udta2[1].value() == 222 ); 00580 BOOST_TEST( udta2[2].value() == 333 ); 00581 udta2.reset(); 00582 BOOST_TEST( udta2.get() == 0 ); 00583 BOOST_TEST( udta.use_count() == 1 ); 00584 BOOST_TEST( udta2.use_count() == 1 ); 00585 00586 BOOST_TEST( UDT::UDT_use_count == 4 ); // reality check 00587 00588 // test shared_ptr with a user defined type 00589 UDT * up = new UDT; 00590 boost::shared_ptr<UDT> sup ( up ); 00591 BOOST_TEST( up == sup.get() ); 00592 BOOST_TEST( sup.use_count() == 1 ); 00593 00594 sup->value( 54321 ) ; 00595 BOOST_TEST( sup->value() == 54321 ); 00596 BOOST_TEST( up->value() == 54321 ); 00597 00598 boost::shared_ptr<UDT> sup2; 00599 sup2 = sup; 00600 BOOST_TEST( sup2->value() == 54321 ); 00601 BOOST_TEST( sup.use_count() == 2 ); 00602 BOOST_TEST( sup2.use_count() == 2 ); 00603 sup2 = sup2; 00604 BOOST_TEST( sup2->value() == 54321 ); 00605 BOOST_TEST( sup.use_count() == 2 ); 00606 BOOST_TEST( sup2.use_count() == 2 ); 00607 00608 // std::cout << "OK\n"; 00609 00610 // new char[12345]; // deliberate memory leak to verify leaks detected 00611 00612 #undef ck 00613 #undef BOOST_TEST 00614 #undef boost 00615 #undef scoped_ptr 00616 #undef shared_ptr 00617 #undef scoped_array 00618 #undef shared_array 00619 } 00620 00621 /// Muestra como el compilador no permite la mescla de \c lkptr<> con \c array_lkptr<> . 00622 template <class E> 00623 void test_lkptr<E>::array_vs_lkptr() { 00624 lkptr<E> lk; 00625 array_lkptr<E> vec; 00626 #if 0 00627 vec = lk; // error: no match for 'operator=' in 'vec = lk' 00628 lk = vec; // error: no match for 'operator=' in 'lk = vec' 00629 lk.merge( vec ); // error: no matching function for call to lkptr<int>::merge(array_lkptr<int>&) 00630 vec.merge( lk ); // error: no matching function for call to array_lkptr<int>::merge(lkptr<int>&) 00631 lk.reset( vec ); // error: no matching function for call to lkptr<int>::reset(array_lkptr<int>&) 00632 vec.reset( lk ); // error: no matching function for call to array_lkptr<int>::reset(lkptr<int>&) 00633 #endif 00634 } 00635 00636 // AutoRef::Auto-Referencia 00637 struct AutoRef { 00638 static int m_cont; ///< Cantidad total de objetos 00639 lkptr<AutoRef> m_otro; ///< Enlace circular a otro objeto 00640 AutoRef() { m_cont++; } ///< Constructor (aumenta cuenta de objetos) 00641 ~AutoRef() { 00642 m_cont--; 00643 #ifndef AutoRef_BOOOOMMMM 00644 m_otro.weak_release(); 00645 #endif 00646 } ///< Destructor (libera \c lkptr<>) 00647 void set( AutoRef * ptr ) { m_otro.reset( ptr ); } ///< Entrelaza a \c ptr. 00648 static int cont() { return m_cont; } ///< Contidad total de objetos 00649 }; 00650 00651 int AutoRef::m_cont = 0; 00652 00653 /// Muestra como no es posible que \c lkptr<> maneje algunos ciclos correctamente. 00654 template <class E> 00655 void test_lkptr<E>::test_lkptr_cycle() { 00656 if (false) // blows when executed 00657 {{ // test::lkptr_cycle() 00658 if ( true ) { 00659 assertTrue( AutoRef::cont() == 0 ); 00660 lkptr<AutoRef> paco ( new AutoRef() ); assertTrue( AutoRef::cont() == 1 ); 00661 lkptr<AutoRef> lola ( new AutoRef() ); assertTrue( AutoRef::cont() == 2 ); 00662 paco->set( lola.get() ); 00663 lola->set( paco.get() ); 00664 } 00665 assertTrue( AutoRef::cont() == 0 ); 00666 }} 00667 } 00668 // AutoRef::Auto-Referencia 00669 00670 // Esta documentación aparece después para que quede de primera la 00671 // implementación a la que se hace referencia en el \dontinclude 00672 00673 /** \struct AutoRef 00674 \brief Clase que se auto-referencia. 00675 00676 \code 00677 paco lola 00678 +---+ +---+ - Al destruir el "AutoRef" al que "paco" apunta 00679 | * | | * | el destructor lkptr<> destruye a lo que "lola" apunta 00680 +---+ +---+ 00681 | | - Antes de destruir el "AutoRef" al que "lola" apunta 00682 v v el destructor lkptr<> destruye a lo que "paco" apunta 00683 +-----+ +-----+ 00684 | *--|--->| | - Esto causa un ciclo infinito de invocaciones de los destructores 00685 | |<---|--* | 00686 +-----+ +-----+ - Por eso este programa se cae, pues tiene lkptr<>'s circulares 00687 AutoRef AutoRef 00688 \endcode 00689 00690 \dontinclude test_lkptr.cpp 00691 \skipline AutoRef::Auto-Referencia 00692 \until AutoRef::Auto-Referencia 00693 \see test_lkptr<E>::test_lkptr_cycle() 00694 */ 00695 00696 /// Number of elements in vector \c V[]. 00697 #define DIM(V) (sizeof(V)/sizeof(*V)) 00698 00699 #if 0 00700 // test::Point 00701 struct Point { virtual int val() const { return 0; } }; 00702 struct Circle : public Point { virtual int val() const { return 1; } }; 00703 struct Cilinder : public Circle { virtual int val() const { return 2; } }; 00704 struct Square : public Point { virtual int val() const { return 3; } }; 00705 struct Rectangle : public Square { virtual int val() const { return 4; } }; 00706 // test::Rectangle 00707 #else 00708 #include "figures.h" // (Point (Circle (Cilinder)) (Square (Rectangle))) 00709 #endif 00710 00711 /// Tests that \c lkptr<X> works well with a class hierarchy. 00712 template <typename X> 00713 void test_lkptr<X>::inheritance() { 00714 {{ // test::inheritance 00715 lkptr<Point> VEC[5]; 00716 VEC[0].reset( new Point() ); 00717 VEC[1].reset( new Circle() ); 00718 VEC[2].reset( new Cilinder() ); 00719 VEC[3].reset( new Square() ); 00720 VEC[4].reset( new Rectangle() ); 00721 00722 for (int i=0; i<int(DIM(VEC)); ++i) { 00723 assertTrue( VEC[i]->val() == i ); 00724 assertTrue( VEC[i].ok() ); 00725 } 00726 }} 00727 } 00728 00729 #if 0 00730 00731 struct grandpa { 00732 const char * g; 00733 grandpa() : g ("grandpa") {} 00734 virtual const char* doit() const { return g; } 00735 virtual ~grandpa() {} 00736 }; 00737 00738 struct pa : public grandpa { 00739 const char * p; 00740 pa() : p("pa") {} 00741 virtual const char* doit() const { return p; } 00742 }; 00743 00744 struct me : public pa { 00745 const char * m; 00746 me() : m("me") {} 00747 virtual const char* doit() const { return m; } 00748 }; 00749 00750 #else 00751 #include "figures.h" // grandpa -> pa -> me 00752 #endif 00753 00754 /// Tries with 3 pointes to the same value. 00755 template <typename X> 00756 void test_lkptr<X>::downcast() { 00757 lkptr<grandpa> G ( new grandpa() ); 00758 lkptr<pa> P ( new pa() ); 00759 lkptr<me> ME ( new me() ); 00760 lkptr<me> up; 00761 lkptr<grandpa> down; 00762 assertTrue( G.ok() && P.ok() && ME.ok() && up.ok() && down.ok() ); 00763 00764 assertTrue( G->doit() != P->doit() ); 00765 assertTrue( P->doit() != ME->doit() ); 00766 assertTrue( ME->doit() != G->doit() ); 00767 00768 grandpa *pG = G.get(); 00769 pa *pP = P.get(); 00770 me *pME = ME.get(); 00771 assertTrue( 0==dynamic_cast<pa*>(pG) ); // base ==> derived 00772 assertTrue( 0==dynamic_cast<me*>(pP) ); 00773 assertTrue( 0==dynamic_cast<me*>(pG) ); 00774 assertTrue( G.ok() && P.ok() && ME.ok() && up.ok() && down.ok() ); 00775 00776 assertTrue( 0!=dynamic_cast<pa*>(pME) ); // derived ==> base 00777 assertTrue( 0!=dynamic_cast<grandpa*>(pP) ); 00778 assertTrue( 0!=dynamic_cast<grandpa*>(pME) ); 00779 assertTrue( G.ok() && P.ok() && ME.ok() && up.ok() && down.ok() ); 00780 00781 down = G; assertTrue( down->doit() == G->doit() ); 00782 down = P; assertTrue( down->doit() == P->doit() ); 00783 down = ME; assertTrue( down->doit() == ME->doit() ); 00784 assertTrue( G.ok() && P.ok() && ME.ok() && up.ok() && down.ok() ); 00785 00786 up = G; assertTrue( up.get() == 0 ); 00787 up = P; assertTrue( up.get() == 0 ); 00788 up = ME; assertTrue( up->doit() == ME->doit() ); 00789 up = lkptr<me>(G); 00790 assertTrue( G.ok() && P.ok() && ME.ok() && up.ok() && down.ok() ); 00791 } 00792 00793 #if 0 00794 struct myself { 00795 int v; 00796 myself() : v(1) { } 00797 ~myself() { v=-1; } 00798 lkptr<myself> eval() { 00799 return lkptr<myself>(this); 00800 } 00801 }; 00802 #endif 00803 00804 /// Tries with 3 pointes to the same value. 00805 template <typename X> 00806 void test_lkptr<X>::selfReturn() { 00807 lkptr<myself> me ( new myself() ); 00808 assertTrue( me->v == 1 ); 00809 lkptr<myself> you; 00810 you = me->eval(); 00811 assertTrue( me->v == 1 ); 00812 assertTrue( you->v == 1 ); 00813 me.merge(you); 00814 assertTrue( you == me ); 00815 assertTrue( me.ok() ); 00816 assertTrue( you.ok() ); 00817 } 00818 00819 /// Returns the pointer within \c ptr. 00820 template <typename X> 00821 lkptr<int> test_lkptr<X>::foo( lkptr<int> r ) { 00822 assertTrue( r.use_count() == 2 ); 00823 assertTrue( *r.b.ptr == 12 ); 00824 assertTrue( *r.b.next->ptr == 12 ); 00825 assertTrue( r.b.prev != &r.b ); 00826 assertTrue( r.b.next != &r.b ); 00827 assertTrue( r.b.next->next == &r.b ); 00828 assertTrue( r.b.prev->prev == &r.b ); 00829 return lkptr<int>( r.get() ); 00830 } 00831 00832 /// Unrelated lkptr<>'s point to the same object. 00833 template <typename X> 00834 void test_lkptr<X>::multiDestroyInt() { 00835 test_lkptr<X>::pInt = new int(12); 00836 assertTrue( *pInt == 12 ); 00837 { 00838 lkptr<int> tik = lkptr<int>( pInt ); 00839 lkptr<int> tak; assertTrue( *tik == 12 ); 00840 tak.reset( foo( tik ) ); // tik && tak point to the same object 00841 assertTrue( tik.ok() ); assertTrue( tak.ok() ); 00842 assertTrue( tik.use_count() == 1 ); // tik && tak are bound together 00843 assertTrue( tak.use_count() == 1 ); 00844 00845 if (true) { // use lktpr<>::merge() to avoid multiple detruction 00846 tik.merge(tak); 00847 assertTrue( tik.ok() ); assertTrue( tak.ok() ); 00848 assertTrue( tik.use_count() == 2 ); // tik && tak are bound together 00849 assertTrue( tak.use_count() == 2 ); 00850 assertTrue( tik == tak ); // both share the same object 00851 assertTrue( *tik == *tak ); 00852 assertTrue( tik.b.next == &tak.b ); 00853 assertTrue( tik.b.prev == &tak.b ); 00854 assertTrue( tak.b.next == &tik.b ); 00855 assertTrue( tak.b.prev == &tik .b); 00856 assertTrue( tak.b.ptr == tik.b.ptr ); 00857 assertTrue( tak.b.ptr != 0 ); 00858 assertTrue( tik.use_count() == 2 ); // tik && tak are bound together 00859 assertTrue( tak.use_count() == 2 ); 00860 *tik = 15; 00861 assertTrue( *tak.b.ptr == 15 ); 00862 *tak = 16; 00863 assertTrue( tik.ok() ); assertTrue( tak.ok() ); 00864 *tak = 17; 00865 // pInt is deleted by tik or tak 00866 pInt = 0; 00867 } 00868 else { // wrong branch 00869 assertTrue( tik.use_count() == 1 ); // tik is unrelated to tak 00870 assertTrue( tak.use_count() == 1 ); 00871 assertTrue( tik == tak ); // both point to the same object 00872 assertTrue( *tik == *tak ); // they don´t share the same object 00873 // Error: double destruction for tik && tak 00874 } 00875 00876 if (false) 00877 {/* Note: 00878 Automatic conversion into a pointer is discouraged because it can lead 00879 to serious errors. If the conversion lktpr<X>::operator X*() exists, it 00880 would convert any lkptr<X> into its X*, which makes it very easy the 00881 following erroneous usage: 00882 tik.reset( tak.get() ); // [ERROR] tik.reset( tak.operator X*() ); 00883 This will causes double destruction of the pointed object because there 00884 are 2 unlinked that own the same object. 00885 */ 00886 X* ptrX = new X(); 00887 lkptr<X> tik ( ptrX ); 00888 lkptr<X> tak; 00889 00890 tik = tak; assertTrue( tik.use_count() == 2 ); // ok 00891 tik.reset( tak.get() ); // [ERROR] tik.reset( tak.operator X*() ); 00892 assertTrue( tik.use_count() == 1 ); 00893 assertTrue( tak.use_count() == 1 ); // unlinked 00894 00895 assertTrue( tik.b.next != &tak.b ); // they are unlinked 00896 assertTrue( tak.b.prev != &tik.b ); 00897 assertTrue( tik.b.ptr == tak.b.ptr ); // both share the same object 00898 } // ptrX gets destroyed twice 00899 } 00900 00901 { /// http://www.di-mare.com/adolfo/p/lkptr.htm#fg-08 00902 #define assert(X) assertTrue(X) 00903 lkptr<int> tik ( new int(12) ); 00904 lkptr<int> tak; assert( *tik == 12 ); 00905 tak.reset( tik.get() ); // tik && tak apuntan al mismo objeto 00906 00907 if (true) { // con lktpr<>::merge() se evita la destrucción múltiple 00908 tik.merge(tak); 00909 assert( tik.use_count() == 2 ); // tik && tak están atados 00910 assert( tak.use_count() == 2 ); 00911 assert( tik == tak ); // ambos comparten el mismo objeto 00912 assert( *tik == *tak ); 00913 } 00914 else { 00915 assert( tik.use_count() == 1 ); // tik no está relacionado a tak 00916 assert( tak.use_count() == 1 ); 00917 assert( tik == tak ); // ambos apuntan al mismo objeto 00918 assert( *tik == *tak ); // no comparten el mismo objeto 00919 // Error: double destrucción de tik && tak 00920 } 00921 #undef assert 00922 } 00923 } 00924 00925 #if 0 00926 00927 struct selfBase { 00928 int v; 00929 int del; // # of times deleted 00930 selfBase( int n ) : v(n),del(0) { } 00931 virtual ~selfBase() { del--; } 00932 operator int() const { return v; } 00933 }; 00934 00935 struct selfDerived : public selfBase { 00936 selfDerived( int n ) : selfBase(n) { } 00937 virtual ~selfDerived() {} 00938 lkptr<selfBase> foo(); 00939 }; 00940 00941 /// Returns an unrelated pointer to \c this. 00942 lkptr<selfBase> selfDerived::foo() 00943 { return lkptr<selfBase>(this); } 00944 00945 #else 00946 #include "figures.h" 00947 #endif 00948 00949 /// Unrelated lkptr<>'s point to the same object. 00950 template <typename X> 00951 void test_lkptr<X>::multiDestroyClass() { 00952 lkptr<selfDerived> tik = lkptr<selfDerived>( new selfDerived(12) ); 00953 lkptr<selfDerived> tak; assertTrue( *tik == 12 ); 00954 tak = tik->foo(); // tik && tak point to the same object 00955 00956 if (true) { // use lktpr<>::merge() to avoid multiple detruction 00957 tik.merge(tak); 00958 assertTrue( tik.use_count() == 2 ); // tik && tak are bound together 00959 assertTrue( tak.use_count() == 2 ); 00960 assertTrue( tik == tak ); // both share the same object 00961 assertTrue( *tik == *tak ); 00962 assertTrue( tik.b.next == &tak.b ); 00963 assertTrue( tik.b.prev == &tak.b ); 00964 assertTrue( tak.b.next == &tik.b ); 00965 assertTrue( tak.b.prev == &tik.b ); 00966 assertTrue( tik.use_count() == 2 ); // tik && tak are bound together 00967 assertTrue( tak.use_count() == 2 ); 00968 00969 assertTrue( tak.b.ptr->del == 0 ); 00970 assertTrue( tik.b.ptr->del == 0 ); 00971 } 00972 else { // wrong branch 00973 assertTrue( tik.use_count() == 1 ); // tik is unrelated to tak 00974 assertTrue( tak.use_count() == 1 ); 00975 assertTrue( tik == tak ); // both point to the same object 00976 assertTrue( *tik == *tak ); // they don´t share the same object 00977 // Error: double destruction for tik && tak 00978 } 00979 } 00980 /// Message for <code> assertTrue( vec[50].use_count() == n ); </code> 00981 // msg = msg_vecB(B, vec[B].use_count(), n+1, i, j ); 00982 const char* msg_vecB( int B, int u, int n, int i, int j ) { 00983 static char buff[128]; 00984 char num[3]; 00985 #define setNum(m) \ 00986 if ((m)<10) { num[0]='0'+(m); num[1]=0; } \ 00987 else { num[0]='0'+(m)/10; num[1]='0'+(m)%10; num[2]=0; } 00988 buff[0] = 0; 00989 00990 strcat( buff, "( " ); 00991 setNum(u); strcat( buff, num ); 00992 strcat( buff, " == vec[" ); 00993 setNum(B); strcat( buff, num ); 00994 strcat( buff, "].use_count() != "); 00995 setNum(n); strcat( buff, num ); 00996 strcat( buff, " ) ==> vec[" ); 00997 setNum(B+i); strcat( buff, num ); 00998 strcat( buff, "]"); 00999 if (j<=n) { 01000 strcat( buff, ".merge( vec[" ); 01001 setNum(B+j); strcat( buff, num ); 01002 strcat( buff, "] )" ); 01003 } 01004 return buff; 01005 #undef setNum 01006 } 01007 01008 /// Unrelated lkptr<>'s point to the same object. 01009 template <typename X> 01010 void test_lkptr<X>::multiDestroyVector() { 01011 { 01012 assertTrue( pInt == 0 ); 01013 pInt = new int(12); 01014 assertTrue( pInt != 0 ); 01015 } 01016 const int SZ = 100; 01017 lkptr<int> vec[SZ]; 01018 01019 for ( int i=0; i<SZ; ++i ) { 01020 vec[i].reset( pInt ); // many unrelated lkptr<>'s 01021 assertTrue( vec[i] == vec[0] ); 01022 assertTrue( vec[i].get() == pInt ); 01023 } 01024 01025 for ( int i=0; i<SZ; ++i ) { 01026 assertTrue( vec[i].use_count() == 1 ); 01027 assertTrue( vec[i].get() == pInt ); // all point to the same object 01028 } 01029 01030 vec[0].merge( vec[0] ) ; // merge(*this) 01031 assertTrue( vec[0].use_count() == 1 ); 01032 assertTrue( vec[0].get() == pInt ); 01033 assertTrue( vec[0].ok() ); 01034 01035 vec[0].merge( vec[1] ) ; // 1 ~ 1 01036 assertTrue( vec[0].use_count() == 2 ); 01037 assertTrue( vec[0].use_count() == vec[1].use_count() ); 01038 assertTrue( vec[0].ok() ); 01039 01040 // [ (10) (11) (12) (13) ] ==> [ (10 11) (12) (13) ] ==> 01041 // [ (10 11 12) (13) ] ==> [ (10 11 12 13) ] 01042 vec[10].merge( vec[11] ) ; // 1 ~ 1 01043 assertTrue( vec[10].ok() ); 01044 vec[11].merge( vec[12] ) ; // 2 ~ 1 01045 assertTrue( vec[10].use_count() == 3 ); 01046 assertTrue( vec[10].use_count() == vec[11].use_count() ); 01047 assertTrue( vec[11].use_count() == vec[12].use_count() ); 01048 assertTrue( vec[10].ok() ); 01049 vec[12].merge( vec[13] ) ; // 3 ~ 1 01050 assertTrue( vec[12].use_count() == 4 ); 01051 assertTrue( vec[12].use_count() == vec[13].use_count() ); 01052 01053 // [ (20) (21) (22) (23) ] ==> [ (20) (21) (22 23) ] ==> 01054 // [ (20) (21 22 23) ] ==> [ (20 21 22 23) ] 01055 vec[22].merge( vec[23] ) ; // 1 ~ 1 [ (20) (21) (22 23) ] 01056 assertTrue( vec[22].ok() ); 01057 vec[22].merge( vec[21] ) ; // 1 ~ 2 [ (20) (21 22 23) ] 01058 assertTrue( vec[22].use_count() == 3 ); 01059 assertTrue( vec[22].use_count() == vec[23].use_count() ); 01060 assertTrue( vec[22].use_count() == vec[21].use_count() ); 01061 assertTrue( vec[22].ok() ); 01062 vec[20].merge( vec[21] ) ; // 1 ~ 3 [ (20 21 22 23) ] 01063 assertTrue( vec[20].use_count() == 4 ); 01064 assertTrue( vec[20].use_count() == vec[23].use_count() ); 01065 01066 // [ (30) (31) (32) ] 01067 vec[30].merge( vec[31] ) ; // 1 ~ 1 [ (30 31) (32) ] 01068 vec[31].merge( vec[32] ) ; // 2 ~ 1 [ (30 31 32) ] 01069 // [ (33) (34) ] 01070 vec[33].merge( vec[34] ) ; // 1 ~ 1 [ (33 34) ] 01071 01072 vec[30].merge( vec[33] ) ; // 3 ~ 2 [ (30 31 32 33 34) ] 01073 assertTrue( vec[30].use_count() == 5 ); 01074 assertTrue( vec[30].use_count() == vec[34].use_count() ); 01075 01076 // [ (40) (41) ] 01077 vec[40].merge( vec[41] ) ; // 1 ~ 1 [ (40 41) ] 01078 // [ (42) (43) (44) ] 01079 vec[42].merge( vec[43] ) ; // 1 ~ 1 [ (42 43) (44) ] 01080 vec[44].merge( vec[43] ) ; // 1 ~ 2 [ (42 43 44) ] 01081 01082 vec[40].merge( vec[43] ) ; // 2 ~ 3 [ (40 41 42 43 44) ] 01083 assertTrue( vec[40].use_count() == 5 ); 01084 assertTrue( vec[40].use_count() == vec[43].use_count() ); 01085 01086 // [ (20 21 22 23) ] [ (40 41 42 43 44) ] 01087 assertTrue( vec[20].use_count() == 4 ); 01088 assertTrue( vec[40].use_count() == 5 ); 01089 vec[20].merge( vec[40] ) ; // 4 ~ 5 [ (20 21 22 23 40 41 42 43 44) ] 01090 assertTrue( vec[40].use_count() == 9 ); 01091 assertTrue( vec[20].use_count() == vec[40].use_count() ); 01092 01093 // [ (30 31 32 33 34) ] [ (10 11 12 13) ] 01094 assertTrue( vec[30].use_count() == 5 ); 01095 assertTrue( vec[10].use_count() == 4 ); 01096 vec[30].merge( vec[10] ) ; // 5 ~ 4 [ (30 31 32 33 34 10 11 12 13) ] 01097 assertTrue( vec[30].use_count() == 9 ); 01098 assertTrue( vec[10].use_count() == vec[30].use_count() ); 01099 01100 01101 vec[0].merge( vec[1] ) ; 01102 vec[1].merge( vec[0] ) ; 01103 vec[0].merge( vec[0] ) ; 01104 vec[1].merge( vec[1] ) ; 01105 assertTrue( vec[0].use_count() == 2 ); 01106 assertTrue( vec[0].use_count() == vec[1].use_count() ); 01107 assertTrue( vec[0].get() == pInt ); 01108 assertTrue( vec[0].ok() ); 01109 vec[1].merge( vec[2] ) ; // 2 ~ 1 01110 01111 vec[0].merge( vec[1] ) ; // [ (0 1 2) ] 01112 vec[1].merge( vec[2] ) ; 01113 vec[2].merge( vec[1] ) ; 01114 vec[1].merge( vec[0] ) ; 01115 01116 assertTrue( vec[0].use_count() == 3 ); 01117 assertTrue( vec[0].use_count() == vec[1].use_count() ); 01118 assertTrue( vec[1].use_count() == vec[2].use_count() ); 01119 assertTrue( vec[0].get() == pInt ); 01120 assertTrue( vec[0].ok() ); 01121 01122 { 01123 assertTrue( 50<SZ ); 01124 for ( int i=0; i<SZ; ++i ) { 01125 char msg[20]; // 0123456789012345678 01126 strcpy( msg, "Error: vec[__].ok()" ); 01127 assertTrue( msg[10]=='[' && ']'==msg[13] ); 01128 msg[11] = ( i/10>0 ? '0'+i : ' ' ); 01129 msg[12] = ( i%10 ); 01130 01131 assertTrue_Msg( msg, vec[i].ok() ); 01132 } 01133 } 01134 01135 if (true) { 01136 const int LG=8; const int B=50; 01137 assertTrue( B+LG<SZ ); 01138 for ( int n=0; n<LG; ++n ) { 01139 assertTrue( vec[B+n].use_count() == 1 ); 01140 assertTrue( vec[n].get()==pInt ); // all point to the same object 01141 } 01142 assertTrue( vec[B].get()==pInt && vec[B].ok() ); 01143 assertTrue( vec[B].use_count() == 1 ); 01144 01145 for ( int n=0; n<LG; ++n ) { 01146 assertTrue( vec[B+n].use_count() == 1 ); 01147 vec[B].merge( vec[B+n] ); 01148 for ( int i=0; i<n; ++i ) { 01149 for ( int j=0; j<n; ++j ) { 01150 vec[B+i].merge( vec[B+j] ); 01151 assertTrue( vec[B+i].ok() && vec[B+j].ok() ); 01152 } 01153 } 01154 } 01155 } 01156 01157 { 01158 assertTrue( 50<SZ ); 01159 for ( int i=0; i<SZ; ++i ) { 01160 char msg[20]; // 0123456789012345678 01161 strcpy( msg, "Error: vec[__].ok()" ); 01162 assertTrue( msg[10]=='[' && ']'==msg[13] ); 01163 msg[11] = ( i/10>0 ? '0'+i : ' ' ); 01164 msg[12] = ( i%10 ); 01165 01166 assertTrue_Msg( msg, vec[i].ok() ); 01167 } 01168 } 01169 { 01170 int max = -1; 01171 for ( int i=1; i<SZ; ++i ) { 01172 vec[i].merge( vec[i-1] ); 01173 assertTrue( vec[i].ok() && vec[i].get()==pInt ); 01174 max = ( max<vec[i].use_count() ? vec[i].use_count() : max ); 01175 if ( max == vec[i].use_count() ) { 01176 max = max; 01177 } 01178 } 01179 assertTrue( vec[SZ-1].use_count() == max ); 01180 assertTrue( vec[SZ-1].use_count() != max-1 ); 01181 assertTrue( vec[0].use_count() == max ); 01182 assertTrue( vec[0].use_count() != max-1 ); 01183 vec[SZ-1].merge( vec[SZ/3] ); 01184 max = ( max<vec[0].use_count() ? vec[0].use_count() : max ); 01185 assertTrue( vec[SZ-1].use_count() == max ); 01186 assertTrue( vec[SZ-1].use_count() != max-1 ); 01187 01188 max = -1; 01189 for ( int i=SZ-1; i>=0; --i ) { 01190 max = ( max<vec[i].use_count() ? vec[i].use_count() : max ); 01191 if ( max == vec[i].use_count() ) { 01192 max = max; 01193 } 01194 assertTrue( vec[i].use_count() == SZ ); 01195 assertTrue( vec[i].use_count() != SZ-1 ); 01196 assertTrue( vec[i].ok() ); 01197 assertTrue( vec[i].get()==pInt ); 01198 assertTrue( vec[i].get()!=0 ); 01199 } 01200 } 01201 { 01202 int max = vec[2*SZ/3].use_count(); 01203 for ( int i=0; i<SZ; ++i ) { 01204 for ( int j=0; j<SZ; ++j ) { 01205 vec[j].merge( vec[i] ); 01206 assertTrue( vec[j].use_count() == max ); 01207 assertTrue( vec[j].use_count() != max-1 ); 01208 } 01209 } 01210 } 01211 { 01212 lkptr<int> hold = vec[33]; 01213 assertTrue( hold.use_count() == SZ+1 ); 01214 for ( int i=0; i<SZ; ++i ) { 01215 vec[i].reset(); 01216 } 01217 assertTrue( hold.use_count() == 1 ); 01218 assertTrue( hold.get() == pInt ); 01219 01220 for ( int i=0; i<SZ; ++i ) { 01221 vec[i] = hold; 01222 for ( int j=SZ-1; j>0; --j ) { 01223 vec[j] = vec[i]; 01224 vec[i] = vec[j]; 01225 } 01226 } 01227 assertTrue( hold.use_count() == SZ+1 ); 01228 assertTrue( hold.use_count() != SZ ); 01229 assertTrue( hold.get() == pInt && !hold.isNull() ); 01230 } 01231 pInt = 0; 01232 } 01233 01234 01235 #include <iostream> // cout 01236 01237 /// Main test program. 01238 int main() { 01239 test_lkptr<int> tester; // create test 01240 tester.run(); // execute 01241 std::cout << tester.report(); // Save results on "cout" 01242 } 01243 01244 // EOF: test_lkptr.cpp