RCPNodeHandle_UnitTests.cpp

Go to the documentation of this file.
00001 #include "Teuchos_UnitTestHarness.hpp"
00002 #include "Teuchos_RCPNode.hpp"
00003 #include "Teuchos_getConst.hpp"
00004 #include "TestClasses.hpp"
00005 
00006 
00007 namespace {
00008 
00009 
00010 using Teuchos::null;
00011 using Teuchos::RCPNode;
00012 using Teuchos::RCPNodeHandle;
00013 using Teuchos::getConst;
00014 using Teuchos::NullReferenceError;
00015 using Teuchos::DanglingReferenceError;
00016 using Teuchos::any;
00017 using Teuchos::any_cast;
00018 using Teuchos::DeallocDelete;
00019 using Teuchos::RCPNodeTmpl;
00020 using Teuchos::RCP_WEAK;
00021 using Teuchos::RCP_STRONG;
00022 
00023 
00024 template<class T>
00025 class MockRCP {
00026 public:
00027   T* access_private_ptr() const
00028     {
00029       return (T*)(0x777777); // Just some bogus address printed to out
00030     }
00031 };
00032 
00033 
00034 template<class T>
00035 RCPNodeHandle basicRCPNodeHandle(const bool has_ownership)
00036 {
00037   return RCPNodeHandle(
00038     new RCPNodeTmpl<T,DeallocDelete<T> >(new T, DeallocDelete<T>(), has_ownership)
00039     );
00040 }
00041 
00042 
00043 TEUCHOS_UNIT_TEST( RCPNodeHandle, assignSelf )
00044 {
00045   RCPNodeHandle nodeRef;
00046   nodeRef = nodeRef;
00047 }
00048 
00049 
00050 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCPNodeHandle, defaultConstruct, T )
00051 {
00052   RCPNodeHandle nodeRef;
00053   TEST_EQUALITY_CONST( nodeRef.count(), 0 );
00054   TEST_EQUALITY_CONST( nodeRef.has_ownership(), false );
00055   nodeRef.has_ownership(true);
00056   TEST_EQUALITY_CONST( nodeRef.has_ownership(), false );
00057 #ifdef TEUCHOS_DEBUG
00058   TEST_THROW({nodeRef.set_extra_data(any(),"", Teuchos::PRE_DESTROY, true);},
00059     NullReferenceError);
00060   TEST_THROW({any &a = nodeRef.get_extra_data("int","blob"); (void)a;},
00061     NullReferenceError);
00062   TEST_THROW({const any &a = getConst(nodeRef).get_extra_data("int","blob"); (void)a;},
00063     NullReferenceError);
00064   TEST_THROW({any *a = nodeRef.get_optional_extra_data("int","blob"); (void)a;},
00065     NullReferenceError);
00066   TEST_THROW({const any *a = getConst(nodeRef).get_optional_extra_data("int","blob"); (void)a;},
00067     NullReferenceError);
00068 #endif // TEUCHOS_DEBUG
00069 }
00070 
00071 
00072 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCPNodeHandle, basicConstruct_owns_mem, T )
00073 {
00074   RCPNodeHandle nodeRef(basicRCPNodeHandle<T>(true));
00075   TEST_EQUALITY_CONST( nodeRef.count(), 1 );
00076   TEST_EQUALITY_CONST( nodeRef.has_ownership(), true );
00077   nodeRef.has_ownership(false);
00078   TEST_EQUALITY_CONST( nodeRef.has_ownership(), false );
00079 #ifdef TEUCHOS_DEBUG
00080   TEST_THROW({any &a = nodeRef.get_extra_data("int","blob"); (void)a;},
00081     std::invalid_argument);
00082   TEST_THROW({const any &a = getConst(nodeRef).get_extra_data("int","blob"); (void)a;},
00083     std::invalid_argument);
00084 #endif // TEUCHOS_DEBUG
00085   TEST_EQUALITY_CONST(nodeRef.get_optional_extra_data("int","blob"), 0);
00086   TEST_EQUALITY_CONST(getConst(nodeRef).get_optional_extra_data("int","blob"), 0);
00087   nodeRef.has_ownership(true);
00088 }
00089 
00090 
00091 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCPNodeHandle, basicConstruct_no_owns_mem, T )
00092 {
00093   RCPNodeHandle nodeRef(basicRCPNodeHandle<T>(false));
00094   TEST_EQUALITY_CONST( nodeRef.count(), 1 );
00095   TEST_EQUALITY_CONST( nodeRef.has_ownership(), false );
00096   nodeRef.has_ownership(true);
00097   TEST_EQUALITY_CONST( nodeRef.has_ownership(), true );
00098 }
00099 
00100 
00101 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCPNodeHandle, weakPtr_basic_1, T )
00102 {
00103 
00104   ECHO(RCPNodeHandle nodeRef1(basicRCPNodeHandle<T>(true)));
00105   TEST_EQUALITY_CONST( nodeRef1.strength(), RCP_STRONG );
00106 
00107   ECHO(RCPNodeHandle nodeRef2 = nodeRef1.create_weak());
00108 
00109   TEST_EQUALITY_CONST( nodeRef2.strength(), RCP_WEAK );
00110   TEST_EQUALITY_CONST( nodeRef1.strong_count(), 1 );
00111   TEST_EQUALITY_CONST( nodeRef1.weak_count(), 1 );
00112   TEST_EQUALITY_CONST( nodeRef2.strong_count(), 1 );
00113   TEST_EQUALITY_CONST( nodeRef2.weak_count(), 1 );
00114 
00115   ECHO(RCPNodeHandle nodeRef3 = nodeRef2.create_strong());
00116 
00117   TEST_EQUALITY_CONST( nodeRef3.strength(), RCP_STRONG );
00118   TEST_EQUALITY_CONST( nodeRef1.strong_count(), 2 );
00119   TEST_EQUALITY_CONST( nodeRef1.weak_count(), 1 );
00120   TEST_EQUALITY_CONST( nodeRef2.strong_count(), 2 );
00121   TEST_EQUALITY_CONST( nodeRef2.weak_count(), 1 );
00122   
00123   MockRCP<T> mockRCP;
00124   ECHO(nodeRef2.debug_assert_valid_ptr(mockRCP)); // Should not throw!
00125 
00126   // This will make the underlying object T get deleted!
00127   ECHO(nodeRef1 = null);
00128   ECHO(nodeRef3 = null);
00129 
00130   TEST_EQUALITY_CONST( nodeRef1.node_ptr()==0, true );
00131   TEST_EQUALITY_CONST( nodeRef1.is_node_null(), true );
00132   TEST_EQUALITY_CONST( nodeRef1.is_valid_ptr(), true );
00133 
00134   TEST_EQUALITY_CONST( nodeRef2.node_ptr()!=0, true );
00135   TEST_EQUALITY_CONST( nodeRef2.is_node_null(), false );
00136   TEST_EQUALITY_CONST( nodeRef2.is_valid_ptr(), false );
00137 
00138 #ifdef TEUCHOS_DEBUG
00139   TEST_THROW( nodeRef2.debug_assert_valid_ptr(mockRCP),
00140     DanglingReferenceError );
00141 #endif
00142 
00143   ECHO(nodeRef2 = null); // Should make the underlying node go away
00144 
00145 }
00146 
00147 
00148 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCPNodeHandle, weakPtr_basic_2, T )
00149 {
00150 
00151   ECHO(RCPNodeHandle nodeRef1(basicRCPNodeHandle<T>(true)));
00152   TEST_EQUALITY_CONST( nodeRef1.strength(), RCP_STRONG );
00153 
00154   ECHO(RCPNodeHandle nodeRef2 = nodeRef1.create_weak());
00155   TEST_EQUALITY_CONST( nodeRef2.strength(), RCP_WEAK );
00156   TEST_EQUALITY_CONST( nodeRef1.strong_count(), 1 );
00157   TEST_EQUALITY_CONST( nodeRef1.weak_count(), 1 );
00158   TEST_EQUALITY_CONST( nodeRef2.strong_count(), 1 );
00159   TEST_EQUALITY_CONST( nodeRef2.weak_count(), 1 );
00160   
00161   MockRCP<T> mockRCP;
00162 
00163   ECHO(nodeRef2.debug_assert_valid_ptr(mockRCP)); // Should not throw!
00164 
00165   ECHO(nodeRef2 = null); // The underlying object stays alive!
00166 
00167   TEST_EQUALITY_CONST( nodeRef2.node_ptr()==0, true );
00168   TEST_EQUALITY_CONST( nodeRef2.is_node_null(), true );
00169   TEST_EQUALITY_CONST( nodeRef2.is_valid_ptr(), true );
00170 
00171   TEST_EQUALITY_CONST( nodeRef1.node_ptr()!=0, true );
00172   TEST_EQUALITY_CONST( nodeRef1.is_node_null(), false );
00173   TEST_EQUALITY_CONST( nodeRef1.is_valid_ptr(), true );
00174 
00175   nodeRef1.debug_assert_valid_ptr(mockRCP); // Should not throw!
00176 
00177 }
00178 
00179 
00180 #ifdef TEUCHOS_DEBUG
00181 
00182 
00183 int debugWithNodeTracing_call_number = 0;
00184 
00185 
00186 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCPNodeHandle, debugWithNodeTracing, T )
00187 {
00188 
00189   TEST_EQUALITY_CONST(Teuchos::isTracingActiveRCPNodes(), false);
00190   Teuchos::setTracingActiveRCPNodes(true);
00191   TEST_EQUALITY_CONST(Teuchos::isTracingActiveRCPNodes(), true);
00192 
00193   {
00194 
00195     T *p = new T; // Never do this in production code!
00196     const std::string T_name = "T_name";
00197     const std::string concreateT_name = "concreateT_name";
00198     const bool has_ownership = true;
00199     RCPNode *node = new RCPNodeTmpl<T,DeallocDelete<T> >(
00200       p, DeallocDelete<T>(), has_ownership);
00201 
00202     RCPNodeHandle nodeRef(node, p, T_name, concreateT_name, has_ownership);
00203 
00204     TEST_EQUALITY_CONST(Teuchos::numActiveRCPNodes(), 1);
00205 
00206     out << "\nMake sure output is printed when there is an active node with tracing ...\n";
00207 
00208     std::ostringstream expendedOutput_oss;
00209     expendedOutput_oss
00210         << "\n***"
00211         << "\n*** Warning! The following Teuchos::RCPNode objects were created but have"
00212         << "\n*** not been destroyed yet.  This may be an indication that these objects may"
00213         << "\n*** be involved in a circular dependency!  A memory checking tool may complain"
00214         << "\n*** that these objects are not destroyed correctly."
00215         << "\n***\n"
00216         << "\n  RCPNode address = \'"<<node<<"\',"
00217         << " information = {T=\'"<<T_name<<"\',Concrete T=\'"<<concreateT_name<<"\',p="<<p<<",has_ownership="<<has_ownership<<"},"
00218         << " call number = "<<debugWithNodeTracing_call_number
00219         << "\n";
00220 
00221     std::ostringstream printActiveRCPNodes_out;
00222     Teuchos::printActiveRCPNodes(printActiveRCPNodes_out);
00223     TEST_EQUALITY( printActiveRCPNodes_out.str(), expendedOutput_oss.str() );
00224 
00225     // NOTE: The above test basically copied and pasted the ouptut stream code
00226     // from Teuchos::printActiveRCPNodes(...) and will need to be maintained
00227     // with this code.  However, this is a good test because it ensures that
00228     // the arguments node, p, T_name, and concreateT_name are passed, stored,
00229     // and retrieved correctly.  It is also a good test because it ensures
00230     // that output is printed when node tracing is turned on.
00231     //
00232     // This is the very definition of a "white box" test but that is just fine
00233     // for a unit test.
00234 
00235   }
00236 
00237   TEST_EQUALITY_CONST(Teuchos::numActiveRCPNodes(), 0);
00238 
00239   out << "\nMake sure no output is printed when there are no active nodes ...\n";
00240   const std::string expendedOutput = "";
00241   std::ostringstream printActiveRCPNodes_out;
00242   Teuchos::printActiveRCPNodes(printActiveRCPNodes_out);
00243   TEST_EQUALITY( printActiveRCPNodes_out.str(), expendedOutput );
00244   
00245   ++debugWithNodeTracing_call_number;
00246 
00247   Teuchos::setTracingActiveRCPNodes(false);;
00248   TEST_EQUALITY_CONST(Teuchos::isTracingActiveRCPNodes(), false);
00249 
00250 }
00251 
00252 
00253 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCPNodeHandle, debugWithoutNodeTracing, T )
00254 {
00255 
00256   TEST_EQUALITY_CONST(Teuchos::isTracingActiveRCPNodes(), false);
00257   Teuchos::setTracingActiveRCPNodes(false);
00258   TEST_EQUALITY_CONST(Teuchos::isTracingActiveRCPNodes(), false);
00259 
00260   T *p = new T; // Never do this in production code!
00261   const std::string T_name = "T_name";
00262   const std::string concreateT_name = "concreateT_name";
00263   const bool has_ownership = true;
00264   RCPNode *node = new RCPNodeTmpl<T,DeallocDelete<T> >(
00265     p, DeallocDelete<T>(), has_ownership);
00266   
00267   RCPNodeHandle nodeRef(node, p, T_name, concreateT_name, has_ownership);
00268 
00269   TEST_EQUALITY_CONST(Teuchos::numActiveRCPNodes(), 0);
00270   
00271   out << "\nMake sure not output is printed when there is an active node without tracing ...\n";
00272   const std::string expendedOutput = "";
00273   std::ostringstream printActiveRCPNodes_out;
00274   Teuchos::printActiveRCPNodes(printActiveRCPNodes_out);
00275   TEST_EQUALITY( printActiveRCPNodes_out.str(), expendedOutput );
00276 
00277 }
00278 
00279 
00280 #endif // TEUCHOS_DEBUG
00281 
00282 
00283 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCPNodeHandle, copyConstruct, T )
00284 {
00285   RCPNodeHandle nodeRef1(basicRCPNodeHandle<T>(true));
00286   RCPNodeHandle nodeRef2(nodeRef1);
00287   TEST_EQUALITY_CONST( nodeRef1.count(), 2 );
00288   TEST_EQUALITY_CONST( nodeRef2.count(), 2 );
00289   TEST_EQUALITY_CONST( nodeRef1.has_ownership(), true );
00290   TEST_EQUALITY_CONST( nodeRef2.has_ownership(), true );
00291 }
00292 
00293 
00294 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCPNodeHandle, assignmentOperator, T )
00295 {
00296   RCPNodeHandle nodeRef1(basicRCPNodeHandle<T>(true));
00297   RCPNodeHandle nodeRef2;
00298   nodeRef2 = nodeRef1;
00299   TEST_EQUALITY_CONST( nodeRef1.count(), 2 );
00300   TEST_EQUALITY_CONST( nodeRef2.count(), 2 );
00301   TEST_EQUALITY_CONST( nodeRef1.has_ownership(), true );
00302   TEST_EQUALITY_CONST( nodeRef2.has_ownership(), true );
00303 }
00304 
00305 
00306 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCPNodeHandle, extraData_basic, T )
00307 {
00308 
00309   RCPNodeHandle nodeRef(basicRCPNodeHandle<T>(true));
00310 
00311   const int v1 = 2;
00312   const any a1(v1);
00313   nodeRef.set_extra_data(a1, "a1", Teuchos::PRE_DESTROY, true); 
00314 
00315   any &a2 = nodeRef.get_extra_data(a1.typeName(), "a1");
00316   TEST_EQUALITY_CONST( a1.same(a2), true );
00317   TEST_EQUALITY( any_cast<int>(a2), v1 );
00318 
00319   any *a3 = nodeRef.get_optional_extra_data(a1.typeName(), "a1");
00320   TEST_EQUALITY_CONST( a3!=0, true );
00321   TEST_EQUALITY( &a2, a3 );
00322   TEST_EQUALITY_CONST( a3->same(a1), true );
00323 
00324   RCPNodeHandle nodeRef2 = nodeRef;
00325 
00326   const int v2 = 3;
00327   a2 = v2;
00328   TEST_EQUALITY( any_cast<int>(a1), v1 );
00329   TEST_EQUALITY( any_cast<int>(*a3), v2 );
00330 
00331   any &a4 = nodeRef2.get_extra_data(a1.typeName(), "a1");
00332   TEST_EQUALITY( &a4, &a2 );
00333   TEST_EQUALITY( &a4, a3 );
00334   TEST_EQUALITY( any_cast<int>(a4), v2 );
00335   
00336 }
00337 
00338 
00339 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCPNodeHandle, extraData_basic_const, T )
00340 {
00341 
00342   RCPNodeHandle nodeRef(basicRCPNodeHandle<T>(true));
00343 
00344   const int v1 = 2;
00345   const any a1(v1);
00346   nodeRef.set_extra_data(a1, "a1", Teuchos::PRE_DESTROY, true); 
00347   
00348   const RCPNodeHandle nodeRef2 = nodeRef;
00349 
00350   const any &a2 = nodeRef2.get_extra_data(a1.typeName(), "a1");
00351   TEST_EQUALITY_CONST( a1.same(a2), true );
00352   TEST_EQUALITY( any_cast<int>(a2), v1 );
00353 
00354   const any *a3 = nodeRef2.get_optional_extra_data(a1.typeName(), "a1");
00355   TEST_EQUALITY_CONST( a3!=0, true );
00356   TEST_EQUALITY( &a2, a3 );
00357   TEST_EQUALITY_CONST( a3->same(a1), true );
00358   
00359 }
00360 
00361 
00362 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCPNodeHandle, extraData_failed, T )
00363 {
00364 
00365   RCPNodeHandle nodeRef(basicRCPNodeHandle<T>(true));
00366 
00367   const int v1 = 2;
00368   const any a1(v1);
00369   nodeRef.set_extra_data(a1, "a1", Teuchos::PRE_DESTROY, true); 
00370 
00371 #ifdef TEUCHOS_DEBUG
00372 
00373   TEST_THROW({nodeRef.get_extra_data("wrong type", "a1");},
00374     std::invalid_argument);
00375 
00376   TEST_THROW({nodeRef.get_extra_data(a1.typeName(), "wrong name");},
00377     std::invalid_argument);
00378 
00379 #endif // TEUCHOS_DEBUG
00380 
00381   any *a2 = nodeRef.get_optional_extra_data("wrong type", "a1");
00382   TEST_EQUALITY_CONST( a2, 0 );
00383 
00384   any *a3 = nodeRef.get_optional_extra_data(a1.typeName(), "wrong name");
00385   TEST_EQUALITY_CONST( a3, 0 );
00386   
00387 }
00388 
00389 
00390 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCPNodeHandle, extraData_failed_const, T )
00391 {
00392 
00393   RCPNodeHandle nodeRef(basicRCPNodeHandle<T>(true));
00394 
00395   const int v1 = 2;
00396   const any a1(v1);
00397   nodeRef.set_extra_data(a1, "a1", Teuchos::PRE_DESTROY, true); 
00398   
00399   const RCPNodeHandle nodeRef2 = nodeRef;
00400 
00401 #ifdef TEUCHOS_DEBUG
00402 
00403   TEST_THROW({nodeRef2.get_extra_data("wrong type", "a1");},
00404     std::invalid_argument);
00405 
00406   TEST_THROW({nodeRef2.get_extra_data(a1.typeName(), "wrong name");},
00407     std::invalid_argument);
00408 
00409 #endif // TEUCHOS_DEBUG
00410 
00411   const any *a2 = nodeRef2.get_optional_extra_data("wrong type", "a1");
00412   TEST_EQUALITY_CONST( a2, 0 );
00413 
00414   const any *a3 = nodeRef2.get_optional_extra_data(a1.typeName(), "wrong name");
00415   TEST_EQUALITY_CONST( a3, 0 );
00416   
00417 }
00418 
00419 
00420 //
00421 // Instantiations
00422 //
00423 
00424 
00425 #ifdef TEUCHOS_DEBUG
00426 
00427 #  define DEBUG_UNIT_TEST_GROUP( T ) \
00428     TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, debugWithNodeTracing, T ) \
00429     TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, debugWithoutNodeTracing, T )
00430 
00431 #else
00432 
00433 #  define DEBUG_UNIT_TEST_GROUP( T )
00434 
00435 #endif
00436 
00437 
00438 #define UNIT_TEST_GROUP( T ) \
00439   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, defaultConstruct, T ) \
00440   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, basicConstruct_owns_mem, T ) \
00441   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, basicConstruct_no_owns_mem, T ) \
00442   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, weakPtr_basic_1, T ) \
00443   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, weakPtr_basic_2, T ) \
00444   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, copyConstruct, T ) \
00445   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, assignmentOperator, T ) \
00446   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, extraData_basic, T ) \
00447   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, extraData_basic_const, T ) \
00448   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, extraData_failed, T ) \
00449   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, extraData_failed_const, T ) \
00450   DEBUG_UNIT_TEST_GROUP(T)
00451 
00452 
00453 UNIT_TEST_GROUP(A)
00454 //UNIT_TEST_GROUP(B1)
00455 //UNIT_TEST_GROUP(B2)
00456 UNIT_TEST_GROUP(C)
00457 //UNIT_TEST_GROUP(D)
00458 UNIT_TEST_GROUP(E)
00459 
00460 // 2008/09/22: rabartl: Above: We don't need to test with all of these classes
00461 // in order to test this functionality.
00462 
00463 
00464 } // namespace
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on Tue Oct 20 10:13:59 2009 for Teuchos Package Browser (Single Doxygen Collection) by  doxygen 1.6.1