lkptr - simple reference LinKed PoinTeR:
test_lkptr.cpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines