Teuchos Package Browser (Single Doxygen Collection) Version of the Day
RCP_test.cpp
Go to the documentation of this file.
00001 // @HEADER
00002 // ***********************************************************************
00003 //
00004 //                    Teuchos: Common Tools Package
00005 //                 Copyright (2004) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00038 //
00039 // ***********************************************************************
00040 // @HEADER
00041 
00042 #include "Teuchos_RCP.hpp"
00043 #include "Teuchos_GlobalMPISession.hpp"
00044 #include "Teuchos_oblackholestream.hpp"
00045 #include "Teuchos_CommandLineProcessor.hpp"
00046 #include "Teuchos_StandardCatchMacros.hpp"
00047 #include "Teuchos_Assert.hpp"
00048 #include "Teuchos_getConst.hpp"
00049 #include "Teuchos_Version.hpp"
00050 
00051 #ifdef HAVE_TEUCHOS_BOOST
00052 #  include "Teuchos_RCPBoostSharedPtrConversions.hpp"
00053 #endif
00054 
00055 #include "TestClasses.hpp"
00056 
00057 
00058 // 
00059 // Uncomment these macros to see example errors
00060 //
00061 
00062 //#define SHOW_COMPILE_TIME_ERRORS
00063 //#define SHOW_RUN_TIME_ERROR_1
00064 //#define SHOW_RUN_TIME_ERROR_2
00065 //#define SHOW_RUN_TIME_ERROR_3
00066 //#define SHOW_RUN_TIME_ERROR_4
00067 #define SHOW_RUN_TIME_ERROR_VIRTUAL_BASE_CLASS
00068 #define SHOW_RUN_TIME_ERROR_VIRTUAL_BASE_CLASS_PRINT
00069 //#define SHOW_MEMORY_LEAK_1
00070 
00071 //
00072 // This program prints minimal output to standard error
00073 //
00074 
00075 int main( int argc, char* argv[] ) {
00076 
00077   using Teuchos::RCP;
00078   using Teuchos::DeallocDelete;
00079   using Teuchos::deallocFunctorDelete;
00080   using Teuchos::deallocFunctorHandleDelete;
00081   using Teuchos::null;
00082   using Teuchos::rcp;
00083   using Teuchos::rcpFromRef;
00084   using Teuchos::inOutArg;
00085   using Teuchos::is_null;
00086   using Teuchos::rcp_implicit_cast;
00087   using Teuchos::rcp_const_cast;
00088   using Teuchos::rcp_static_cast;
00089   using Teuchos::rcp_dynamic_cast;
00090   using Teuchos::set_extra_data;
00091   using Teuchos::get_extra_data;
00092   using Teuchos::get_nonconst_extra_data;
00093   using Teuchos::get_optional_extra_data;
00094   using Teuchos::get_optional_nonconst_extra_data;
00095   using Teuchos::get_dealloc;
00096   using Teuchos::get_nonconst_dealloc;
00097   using Teuchos::get_optional_dealloc;
00098   using Teuchos::get_optional_nonconst_dealloc;
00099   using Teuchos::rcpWithEmbeddedObj;
00100   using Teuchos::rcpWithEmbeddedObjPreDestroy;
00101   using Teuchos::rcpWithEmbeddedObjPostDestroy;
00102   using Teuchos::getEmbeddedObj;
00103   using Teuchos::getNonconstEmbeddedObj;
00104   using Teuchos::getConst;
00105   using Teuchos::CommandLineProcessor;
00106   
00107   bool success = true;
00108   bool createCircRefs = false; // Don't create memory leak by default!
00109 
00110   Teuchos::GlobalMPISession mpiSession(&argc,&argv);
00111   const int procRank = Teuchos::GlobalMPISession::getRank();
00112 
00113   Teuchos::oblackholestream blackhole;
00114   std::ostream &out = ( procRank == 0 ? std::cout : blackhole );
00115 
00116   try {
00117 
00118     // Read options from the commandline
00119     CommandLineProcessor clp(false); // Don't throw exceptions
00120     clp.setOption( "create-circ-refs", "no-create-circ-refs", &createCircRefs,
00121       "Set if output is printed or not." );
00122     CommandLineProcessor::EParseCommandLineReturn parse_return = clp.parse(argc,argv);
00123     if( parse_return != CommandLineProcessor::PARSE_SUCCESSFUL ) {
00124       out << "\nEnd Result: TEST FAILED" << std::endl;
00125       return parse_return;
00126     }
00127 
00128     blackhole << "\nThis should not print anywhere.\n";
00129 
00130     out << std::endl << Teuchos::Teuchos_Version() << std::endl;
00131 
00132     out << "\nTesting basic RCP functionality ...\n";
00133 
00134     // Create some smart pointers
00135 
00136     RCP<A> a_ptr1 = rcp(new C);
00137     out << "\na_ptr1 = " << a_ptr1 << "\n";
00138 #ifndef __sun
00139     // RAB: 2003/11/24: The Sun compiler ("Forte Developer 7 C++
00140     // 5.4 2002/03/09" returned from CC -V) does not seem to be
00141     // following the standard when it comes to the handling of
00142     // temporary objects and therefore the count() is not currect.
00143     // In the above statement, at least one and perhaps two
00144     // temporary RCP objects are created before the object
00145     // a_ptr1 is initialized. However, the standard says that the
00146     // lifetime of temprary objects must not extend past the
00147     // statement in which it was created (see section 10.4.10 in
00148     // Stroustroup, 3ed edition). This compiler stinks!!!!!
00149     TEUCHOS_TEST_FOR_EXCEPT( a_ptr1.count() != 1 );
00150     TEUCHOS_TEST_FOR_EXCEPT( !a_ptr1.shares_resource(a_ptr1) );
00151 #endif // __sun
00152     TEUCHOS_TEST_FOR_EXCEPT( a_ptr1.ptr() == null );
00153     TEUCHOS_TEST_FOR_EXCEPT( a_ptr1 == null );
00154     TEUCHOS_TEST_FOR_EXCEPT( !(a_ptr1 != null) );
00155     TEUCHOS_TEST_FOR_EXCEPT( is_null(a_ptr1) );
00156     RCP<D> d_ptr1 = rcp(new E);
00157     TEUCHOS_TEST_FOR_EXCEPT( d_ptr1.shares_resource(a_ptr1) );
00158 #ifndef __sun
00159     TEUCHOS_TEST_FOR_EXCEPT( d_ptr1.count() != 1 );
00160 #endif
00161     TEUCHOS_TEST_FOR_EXCEPT( d_ptr1.get() == NULL);
00162     TEUCHOS_TEST_FOR_EXCEPT( d_ptr1.getRawPtr() == NULL);
00163 
00164     {
00165 
00166       // Create some more smart points (no new memory!)
00167 
00168       const RCP<const A> ca_ptr1 = rcp_const_cast<const A>(a_ptr1); 
00169       TEUCHOS_TEST_FOR_EXCEPT( !(ca_ptr1 == a_ptr1) );
00170       TEUCHOS_TEST_FOR_EXCEPT( ca_ptr1 != a_ptr1 );
00171       TEUCHOS_TEST_FOR_EXCEPT( !ca_ptr1.shares_resource(a_ptr1) );
00172 #ifndef __sun
00173       TEUCHOS_TEST_FOR_EXCEPT( a_ptr1.count() != 2 );
00174 #endif
00175       TEUCHOS_TEST_FOR_EXCEPT( ca_ptr1.ptr() == null );
00176 #ifndef __sun
00177       TEUCHOS_TEST_FOR_EXCEPT( ca_ptr1.count() != 2 );
00178 #endif
00179       const RCP<const D> cd_ptr1 = rcp_const_cast<const D>(d_ptr1);
00180 #ifndef __sun
00181       TEUCHOS_TEST_FOR_EXCEPT( d_ptr1.count() != 2 );
00182 #endif
00183       TEUCHOS_TEST_FOR_EXCEPT( cd_ptr1.ptr() == null );
00184 #ifndef __sun
00185       TEUCHOS_TEST_FOR_EXCEPT( cd_ptr1.count() != 2 );
00186 #endif
00187 
00188 #ifdef SHOW_RUN_TIME_ERROR_1
00189       // Conversion using get() is a no no! When a_ptr2 is deleted so will the allocated
00190       // object and then a_ptr1 will be corrupted after this block ends!
00191       const RCP<A> a_ptr2 = a_ptr1.get();
00192 #endif
00193 
00194       // Test assignment functions
00195 
00196       a_ptr1 = rcp_const_cast<A>(ca_ptr1.assert_not_null()); // Should be okay, assignment to self
00197 
00198 #ifdef SHOW_COMPILE_TIME_ERRORS
00199       ca_ptr1 = ca_ptr1; // Should not compile since ca_ptr1 is declared constant
00200       ca_ptr1->A_g(); // Should not compile since A_g() is a non-const member function
00201 #endif
00202 
00203       // Test function calls through operaor->(...)
00204 
00205       TEUCHOS_TEST_FOR_EXCEPT( a_ptr1->A_g() != A_g_return );
00206       TEUCHOS_TEST_FOR_EXCEPT( a_ptr1->A_f() != A_f_return );
00207       TEUCHOS_TEST_FOR_EXCEPT( ca_ptr1->A_f() != A_f_return );
00208       TEUCHOS_TEST_FOR_EXCEPT( d_ptr1->D_g() != D_g_return );
00209       TEUCHOS_TEST_FOR_EXCEPT( d_ptr1->D_f() != D_f_return );
00210       TEUCHOS_TEST_FOR_EXCEPT( cd_ptr1->D_f() != D_f_return );
00211     
00212       // Test funciton calls through operator*(...)
00213 
00214       TEUCHOS_TEST_FOR_EXCEPT( (*a_ptr1).A_g() != A_g_return );
00215       TEUCHOS_TEST_FOR_EXCEPT( (*a_ptr1).A_f() != A_f_return );
00216       TEUCHOS_TEST_FOR_EXCEPT( (*ca_ptr1).A_f() != A_f_return );
00217       TEUCHOS_TEST_FOR_EXCEPT( (*d_ptr1).D_g() != D_g_return );
00218       TEUCHOS_TEST_FOR_EXCEPT( (*d_ptr1).D_f() != D_f_return );
00219       TEUCHOS_TEST_FOR_EXCEPT( (*cd_ptr1).D_f() != D_f_return );
00220 
00221       // Test dynamic and static conversions
00222 
00223       // Cast down the inheritance hiearchy (const A -> const B1)
00224       const RCP<const B1> cb1_ptr1 = rcp_dynamic_cast<const B1>(ca_ptr1);
00225       TEUCHOS_TEST_FOR_EXCEPT( cb1_ptr1.ptr() == null );
00226 #ifndef __sun
00227       TEUCHOS_TEST_FOR_EXCEPT( cb1_ptr1.count() != 3 );
00228       TEUCHOS_TEST_FOR_EXCEPT( ca_ptr1.count() != 3 );
00229       TEUCHOS_TEST_FOR_EXCEPT( a_ptr1.count() != 3 );
00230 #endif
00231 
00232       // Cast up the inheritance hiearchy (const B1 -> const A)
00233       TEUCHOS_TEST_FOR_EXCEPT( rcp_implicit_cast<const A>(cb1_ptr1)->A_f() != A_f_return );
00234       TEUCHOS_TEST_FOR_EXCEPT( RCP<const A>(cb1_ptr1)->A_f() != A_f_return );
00235       // Implicit cast from const to non-const (A -> const A)
00236       TEUCHOS_TEST_FOR_EXCEPT( rcp_implicit_cast<const A>(a_ptr1)->A_f() != A_f_return );
00237       TEUCHOS_TEST_FOR_EXCEPT( RCP<const A>(a_ptr1)->A_f() != A_f_return );
00238       // Cast away constantness (const B1 -> B1)
00239       TEUCHOS_TEST_FOR_EXCEPT( rcp_const_cast<B1>(cb1_ptr1)->B1_g() != B1_g_return );
00240       // Cast across the inheritance hiearchy (const B1 -> const B2)
00241       TEUCHOS_TEST_FOR_EXCEPT( rcp_dynamic_cast<const B2>(cb1_ptr1)->B2_f() != B2_f_return );
00242       // Cast down the inheritance hiearchy (const B1 -> const C)
00243       TEUCHOS_TEST_FOR_EXCEPT( rcp_dynamic_cast<const C>(cb1_ptr1)->C_f() != C_f_return );
00244 
00245       // Cast away constantness (const C -> C)
00246       const RCP<C>
00247         c_ptr1 = rcp_const_cast<C>(rcp_dynamic_cast<const C>(ca_ptr1));
00248       TEUCHOS_TEST_FOR_EXCEPT( c_ptr1.ptr() == null );
00249 #ifndef __sun
00250       TEUCHOS_TEST_FOR_EXCEPT( c_ptr1.count() != 4 );
00251       TEUCHOS_TEST_FOR_EXCEPT( ca_ptr1.count() != 4 );
00252       TEUCHOS_TEST_FOR_EXCEPT( a_ptr1.count() != 4 );
00253 #endif
00254 
00255       // Cast down the inheritance hiearchy using static_cast<...> (const D -> const E)
00256       const RCP<const E>
00257         ce_ptr1 = rcp_static_cast<const E>(cd_ptr1); // This is not checked at runtime!
00258       TEUCHOS_TEST_FOR_EXCEPT( ce_ptr1.ptr() == null);
00259 #ifndef __sun
00260       TEUCHOS_TEST_FOR_EXCEPT( ce_ptr1.count() != 3 );
00261       TEUCHOS_TEST_FOR_EXCEPT( cd_ptr1.count() != 3 );
00262       TEUCHOS_TEST_FOR_EXCEPT( d_ptr1.count() != 3 );
00263 #endif
00264 
00265       // Cast up the inheritance hiearchy (const E -> const D)
00266       TEUCHOS_TEST_FOR_EXCEPT( rcp_implicit_cast<const D>(ce_ptr1)->D_f() != D_f_return ); 
00267       // Cast away constantness (const E -> E)
00268       TEUCHOS_TEST_FOR_EXCEPT( rcp_const_cast<E>(ce_ptr1)->E_g() != E_g_return );
00269       TEUCHOS_TEST_FOR_EXCEPT( ce_ptr1->D_f() != D_f_return );
00270 
00271 #ifdef SHOW_COMPILE_TIME_ERRORS
00272       // Try to cast down inheritance hiearchy using dynamic_cast<...> (const D -> const E)
00273       rcp_dynamic_cast<const E>( cd_ptr1 )->E_f(); // This should not compile since D and E are not polymophic
00274 #endif
00275 
00276 #ifndef _INTEL // Intel compiler does not seem to be doing dynamic cast correctly?
00277 #ifdef TEUCHOS_DEBUG // operator->() only throws std::exception when TEUCHOS_DEBUG is defined
00278       try {
00279         // Try to cast form one interface to another that is not supported (B2 -> B1).
00280         // The RCP<B1> returned from rcp_dynamic_cast<...> should be null!
00281         // Note that RCP<...>::optertor->() should throw an std::exception in debug
00282         // mode (i.e. TEUCHOS_DEBUG is defined) but even so no memory leak occurs. If you
00283         // don't believe me then step through with a debugger and see for yourself.
00284         TEUCHOS_TEST_FOR_EXCEPT( rcp_dynamic_cast<B1>( rcp(new B2) )->B1_g() != B1_g_return );
00285         return -1; // Should not be executed!
00286       }
00287       catch( const std::logic_error &excpt )
00288       {}
00289 #endif
00290       try {
00291         // Try to cast form one interface to another that is not supported (B2 -> B1).
00292         // Note that rcp_dynamic_cast<B1>(...,true) should throw an std::exception but even
00293         // so no memory leak occurs. If you don't believe me then step through with a
00294         // debugger and see for yourself.
00295         rcp_dynamic_cast<B1>( rcp(new B2), true );
00296         return -1; // Should not be executed!
00297       }
00298       catch( const std::bad_cast &excpt )
00299       {}
00300 #endif
00301 
00302       // Manually clean up some memory
00303 
00304       delete d_ptr1.release().get(); // Now d_ptr1.get() no longer points to a valid object but okay
00305       // as long as no other access to this object is attempted! (see below)
00306 #ifdef SHOW_RUN_TIME_ERROR_2
00307       TEUCHOS_TEST_FOR_EXCEPT( d_ptr1->D_g() == D_g_return ); // Should cause a segmentation fault since d_ptr.get() was deleted!
00308 #endif
00309 
00310 #ifdef SHOW_MEMORY_LEAK_1
00311       a_ptr1.release(); // If we release but do not delete manually then this is a memory leak!
00312 #endif
00313     
00314       // Here at the end of the block, all of the other smart pointers are deleted!
00315     }
00316     // Check that all of the other references where removed but these
00317 #ifndef __sun
00318     TEUCHOS_TEST_FOR_EXCEPT( a_ptr1.count() != 1 );
00319     TEUCHOS_TEST_FOR_EXCEPT( d_ptr1.count() != 1 );
00320 #endif
00321 
00322     // Assign some other dynamically created objects.
00323   
00324     a_ptr1 = rcp(new A); // In each case the current dynamically allocated object is deleted ...
00325     a_ptr1 = rcp(new B1); // before the new reference is set.
00326     a_ptr1 = rcp(new B2); // ""
00327     a_ptr1 = rcp(new C); // ""
00328     d_ptr1 = rcp(new D); // ""
00329     d_ptr1 = rcp(new E); // ""
00330 
00331     // Assign pointers to some automatic objects that do not need deleted.
00332     // We can do this but we need to remove ownership of the pointer
00333     // from the smart pointer objects so that they do not try to
00334     // delete them. If we forget then delete will be called on these
00335     // pointers and will cause a runtime error.
00336 
00337     C c; // Automatic object what will be deleted by compiler at end of block
00338     a_ptr1 = rcp(&c);
00339 #ifndef SHOW_RUN_TIME_ERROR_3
00340     // Release ownership so that a_ptr1 will not try to delete &c when a_ptr1 goes out of scope
00341     a_ptr1.release();
00342 #endif  
00343 
00344     E e; // Automatic object what will be deleted by compiler at end of block
00345     d_ptr1 = rcp(&e);
00346 #ifndef SHOW_RUN_TIME_ERROR_4
00347     // Release ownership so that d_ptr1 will not try to delete &e when a_ptr1 goes out of scope
00348     d_ptr1.release();
00349 #endif
00350 
00351 #ifdef SHOW_RUN_TIME_ERROR_VIRTUAL_BASE_CLASS
00352     // Allocate an using new and then store the non-base address in in
00353     // a RCP and then try to delete (this is a no-no usually).
00354     C *c_ptr5 = new C; // Okay, no type info lost and address should be same as returned from malloc(...)
00355 #ifdef SHOW_RUN_TIME_ERROR_VIRTUAL_BASE_CLASS_PRINT
00356     const void *c_ptr5_base = dynamic_cast<void*>(c_ptr5);
00357     out << "\nSize of C = " << sizeof(C) << std::endl;
00358     out << "Base address of object of type C = " << dynamic_cast<void*>(c_ptr5) << std::endl;
00359     out << "Offset to address of object of type C = " << ((long int)c_ptr5 - (long int)c_ptr5_base) << std::endl;
00360     out << "Offset of B1 object in object of type C = " << ((long int)static_cast<B1*>(c_ptr5) - (long int)c_ptr5_base) << std::endl;
00361     out << "Offset of B2 object in object of type C = " << ((long int)static_cast<B2*>(c_ptr5) - (long int)c_ptr5_base) << std::endl;
00362     out << "Offset of A object in object of type C = " << ((long int)static_cast<A*>(c_ptr5) - (long int)c_ptr5_base) << std::endl;
00363 #endif // SHOW_RUN_TIME_ERROR_VIRTUAL_BASE_CLASS_PRINT
00364     A *a_rptr5 = c_ptr5; // Here the address has changed and is no longer the same as the base address
00365     a_ptr1 = rcp(a_rptr5); // This is a no-no and could cause trouble!
00366     a_ptr1 = null; // This will cause a segmentation fault in free(...) on many platforms
00367 #endif // SHOW_RUN_TIME_ERROR_VIRTUAL_BASE_CLASS
00368   
00369     // Test out getting the deallocator object
00370     a_ptr1 = rcp( new C, DeallocDelete<C>(), true );
00371     get_dealloc<DeallocDelete<C> >(a_ptr1);
00372     get_nonconst_dealloc<DeallocDelete<C> >(a_ptr1);
00373     TEUCHOS_TEST_FOR_EXCEPT( get_optional_nonconst_dealloc<DeallocDelete<C> >(a_ptr1)==null );
00374     TEUCHOS_TEST_FOR_EXCEPT( get_optional_nonconst_dealloc<DeallocDelete<A> >(a_ptr1)!=null );
00375     TEUCHOS_TEST_FOR_EXCEPT( get_optional_dealloc<DeallocDelete<C> >(const_cast<const RCP<A>&>(a_ptr1))==null );
00376     TEUCHOS_TEST_FOR_EXCEPT( get_optional_dealloc<DeallocDelete<A> >(const_cast<const RCP<A>&>(a_ptr1))!=null );
00377  
00378     // Test storing extra data and then getting it out again
00379     TEUCHOS_TEST_FOR_EXCEPT( get_optional_nonconst_extra_data<RCP<B1> >(a_ptr1,"blahblah") != null );
00380     TEUCHOS_TEST_FOR_EXCEPT( get_optional_extra_data<int>(const_cast<const RCP<A>&>(a_ptr1),"blahblah") != null ); // test const version
00381     set_extra_data( int(-5), "int", inOutArg(a_ptr1) );
00382     TEUCHOS_TEST_FOR_EXCEPT( get_extra_data<int>(a_ptr1,"int") != -5 );
00383     TEUCHOS_TEST_FOR_EXCEPT( get_nonconst_extra_data<int>(a_ptr1,"int") != -5 );
00384     set_extra_data( rcp(new B1), "B1", inOutArg(a_ptr1) );
00385     TEUCHOS_TEST_FOR_EXCEPT( get_extra_data<RCP<B1> >(a_ptr1,"B1")->B1_f() != B1_f_return );
00386     TEUCHOS_TEST_FOR_EXCEPT( get_extra_data<int>(const_cast<const RCP<A>&>(a_ptr1),"int") != -5 ); // test const version
00387     TEUCHOS_TEST_FOR_EXCEPT( (*get_optional_extra_data<RCP<B1> >(a_ptr1,"B1"))->B1_f() != B1_f_return );
00388     TEUCHOS_TEST_FOR_EXCEPT( *get_optional_extra_data<int>(const_cast<const RCP<A>&>(a_ptr1),"int") != -5 ); // test const version
00389     TEUCHOS_TEST_FOR_EXCEPT( get_optional_extra_data<RCP<B1> >(a_ptr1,"blahblah") != null );
00390     TEUCHOS_TEST_FOR_EXCEPT( get_optional_extra_data<int>(const_cast<const RCP<A>&>(a_ptr1),"blahblah") != null ); // test const version
00391 
00392     // Test storage of extra data as embedded objects and then getting it out
00393     // again
00394  
00395     {
00396       RCP<A> a_ptr = rcpWithEmbeddedObj(new C,int(-5));
00397       const int intRtn1 = getEmbeddedObj<C,int>(a_ptr);
00398       TEUCHOS_TEST_FOR_EXCEPT( intRtn1 != -5 );
00399       getNonconstEmbeddedObj<C,int>(a_ptr) = -4;
00400       const int intRtn2 = getEmbeddedObj<C,int>(a_ptr);
00401       TEUCHOS_TEST_FOR_EXCEPT( intRtn2 != -4 );
00402     }
00403  
00404     {
00405       RCP<A> a_ptr = rcpWithEmbeddedObjPreDestroy(new C,int(-5));
00406       const int intRtn1 = getEmbeddedObj<C,int>(a_ptr);
00407       TEUCHOS_TEST_FOR_EXCEPT( intRtn1 != -5 );
00408       getNonconstEmbeddedObj<C,int>(a_ptr) = -4;
00409       const int intRtn2 = getEmbeddedObj<C,int>(a_ptr);
00410       TEUCHOS_TEST_FOR_EXCEPT( intRtn2 != -4 );
00411     }
00412  
00413     {
00414       RCP<A> a_ptr = rcpWithEmbeddedObjPostDestroy(new C,int(-5));
00415       const int intRtn1 = getEmbeddedObj<C,int>(a_ptr);
00416       TEUCHOS_TEST_FOR_EXCEPT( intRtn1 != -5 );
00417       getNonconstEmbeddedObj<C,int>(a_ptr) = -4;
00418       const int intRtn2 = getEmbeddedObj<C,int>(a_ptr);
00419       TEUCHOS_TEST_FOR_EXCEPT( intRtn2 != -4 );
00420     }
00421 
00422     // Test pre-destruction of extra data
00423     int a_f_return = -2;
00424     set_extra_data( rcp(new Get_A_f_return(&*a_ptr1,&a_f_return)),
00425       "a_f_return", inOutArg(a_ptr1), Teuchos::PRE_DESTROY );
00426 
00427     // Set pointers to null to force releasing any owned memory
00428     a_ptr1 = null;
00429     d_ptr1 = null;
00430 
00431 #ifndef __sun
00432     // RAB: 2004/08/12: It appears that SUN compiler is not deleting the piece of extra
00433     // data properly and therefore the destructor of the above Get_A_f_return object
00434     // is not being called (which sets the value of af_return). This compiler stinks!
00435     TEUCHOS_TEST_FOR_EXCEPT( a_f_return != A_f_return ); // Should be been called in destructor of a_ptr1 but before the A object is destroyed!
00436 #endif
00437 
00438     // Testing the deallocFunctorDelete function and DeallocFunctorDelete class
00439     a_ptr1 = rcp( new C, deallocFunctorDelete<A>(deallocA), true );
00440     a_ptr1 = null;
00441 
00442     // Testing the deallocFunctorHandleDelete function and DeallocFunctorHandleDelete class
00443     a_ptr1 = rcp( new C, deallocFunctorHandleDelete<A>(deallocHandleA), true );
00444     a_ptr1 = null;
00445 
00446 #ifdef TEUCHOS_DEBUG
00447  
00448     if (createCircRefs) {
00449       out << "\nCreate a circular reference that will cause a memory leak! ...\n";
00450 #  if !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING)
00451       // Only trun on tracing if you have to
00452       Teuchos::RCPNodeTracer::setTracingActiveRCPNodes(true);
00453 #  endif
00454       RCP<A> a = rcp(new A());
00455       RCP<C> c2 = rcp(new C());
00456       a->set_C(c2);
00457       c2->set_A(a);
00458     }
00459 
00460 #endif // TEUCHOS_DEBUG
00461 
00462 #ifndef TEUCHOS_DEBUG 
00463 
00464     out << "\nTesting using RCP to wrap an undefined opaque object (no TNT) ...\n";
00465     {
00466       RCP<UndefinedType> op_ptr = rcp( createOpaque(),
00467         deallocFunctorHandleDelete<UndefinedType>(destroyOpaque), true );
00468       TEUCHOS_ASSERT_EQUALITY( getOpaqueValue(&*op_ptr), getOpaqueValue_return );
00469     }
00470     // 2008/08/01: rabartl: Above, we can only wrap an undefined type in
00471     // nondebug mode since there is no TypeNameTraits class defined for it and
00472     // the default uses typeid(...) which you can't call on an undefined type.
00473     // If you define a specialization of TypeNameTraits for this class, then
00474     // it will compile just fine!  This is related to bug 4016.
00475 
00476 #endif // not TEUCHOS_DEBUG
00477 
00478     out << "\nTesting using RCP to wrap an undefined opaque object (with TNT) ...\n";
00479     {
00480       RCP<UndefinedType2> op_ptr = rcpWithDeallocUndef( createOpaque2(),
00481         deallocFunctorHandleDelete<UndefinedType2>(destroyOpaque2) );
00482       TEUCHOS_ASSERT_EQUALITY( getOpaque2Value(&*op_ptr), getOpaque2Value_return );
00483     }
00484     // 2008/08/01: rabartl: Above, we can wrap an undefined type in debug mode
00485     // as long as we have a TypeNameTraits specialization of it to avoid
00486     // calling typeid(...).
00487 
00488 #ifdef HAVE_TEUCHOS_BOOST
00489 
00490     out << "\nTesting basic RCP compatibility with boost::shared_ptr ...\n";
00491 
00492     boost::shared_ptr<A> a_sptr1(new C());
00493     RCP<A> a_rsptr1 = rcp(a_sptr1);
00494     TEUCHOS_TEST_FOR_EXCEPT( a_rsptr1.get() != a_sptr1.get() );
00495     TEUCHOS_TEST_FOR_EXCEPT( a_rsptr1.getRawPtr() != a_sptr1.get() );
00496     TEUCHOS_TEST_FOR_EXCEPT( a_rsptr1.get() != a_rsptr1.getRawPtr() );
00497     boost::shared_ptr<A> a_sptr2 = shared_pointer(a_rsptr1);
00498     // There seems no standard way to test that a shared_ptr shares the same node
00499     //TEUCHOS_TEST_FOR_EXCEPT( a_sptr2._internal_equiv(a_sptr1) != true );
00500     RCP<A> a_rsptr2 = rcp(a_sptr2);
00501     TEUCHOS_TEST_FOR_EXCEPT( a_rsptr2.ptr() != a_rsptr1.ptr() );
00502     //TEUCHOS_TEST_FOR_EXCEPT( a_rsptr2 != a_rsptr1 ); // This should work if boost::get_deleter() works correctly!
00503     boost::shared_ptr<A> a_sptr3 = shared_pointer(a_rsptr2);
00504     TEUCHOS_TEST_FOR_EXCEPT( a_sptr3.get() != a_rsptr2.get() );
00505 
00506     out << "\nCompatibility with boost::shared_ptr passed ...\n";
00507 
00508 #endif // HAVE_TEUCHOS_BOOST
00509 
00510     out << "\nAll tests for RCP seem to check out!\n";
00511 
00512   } // end try
00513   TEUCHOS_STANDARD_CATCH_STATEMENTS(true, std::cerr, success);
00514  
00515   try {
00516     // In debug mode, this should show that the A and C RCP objects are still
00517     // around!
00518     if (createCircRefs) {
00519       out << "\nPrinting the active nodes just to see them!\n";
00520       Teuchos::RCPNodeTracer::printActiveRCPNodes(out);
00521 #if defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING)
00522       TEUCHOS_ASSERT_EQUALITY( 2, Teuchos::RCPNodeTracer::numActiveRCPNodes() );
00523 #endif
00524     }
00525   } // end try
00526   TEUCHOS_STANDARD_CATCH_STATEMENTS(true, std::cerr, success);
00527  
00528   if(success)
00529     out << "\nEnd Result: TEST PASSED" << std::endl;
00530 
00531   return ( success ? 0 : 1 );
00532 
00533 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines