Teuchos Package Browser (Single Doxygen Collection) Version of the Day
RCPNodeHandle_UnitTests.cpp
Go to the documentation of this file.
00001 /*
00002 // @HEADER
00003 // ***********************************************************************
00004 //
00005 //                    Teuchos: Common Tools Package
00006 //                 Copyright (2004) Sandia Corporation
00007 //
00008 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00009 // license for use of this work by or on behalf of the U.S. Government.
00010 //
00011 // Redistribution and use in source and binary forms, with or without
00012 // modification, are permitted provided that the following conditions are
00013 // met:
00014 //
00015 // 1. Redistributions of source code must retain the above copyright
00016 // notice, this list of conditions and the following disclaimer.
00017 //
00018 // 2. Redistributions in binary form must reproduce the above copyright
00019 // notice, this list of conditions and the following disclaimer in the
00020 // documentation and/or other materials provided with the distribution.
00021 //
00022 // 3. Neither the name of the Corporation nor the names of the
00023 // contributors may be used to endorse or promote products derived from
00024 // this software without specific prior written permission.
00025 //
00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037 //
00038 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00039 //
00040 // ***********************************************************************
00041 // @HEADER
00042 */
00043 
00044 #include "Teuchos_UnitTestHarness.hpp"
00045 #include "Teuchos_RCPNode.hpp"
00046 #include "Teuchos_getConst.hpp"
00047 #include "Teuchos_TypeNameTraits.hpp"
00048 #include "TestClasses.hpp"
00049 
00050 
00051 namespace Teuchos {
00052 
00053 
00054 template<class T>
00055 class MockRCP {
00056 public:
00057   T* access_private_ptr() const
00058     {
00059       return (T*)(0x777777); // Just some bogus address printed to out
00060     }
00061 };
00062 
00063 
00064 template<class T>
00065 RCPNode* basicRCPNodeNoAlloc(T* p, const bool has_ownership)
00066 {
00067   RCPNodeTmpl<T,DeallocDelete<T> > *rcpNode = 
00068     new RCPNodeTmpl<T,DeallocDelete<T> >(p, DeallocDelete<T>(), has_ownership);
00069   return rcpNode;
00070 }
00071 
00072 
00073 template<class T>
00074 RCPNode* basicRCPNode(const bool has_ownership, T **p_out = 0)
00075 {
00076   T *p = new T;
00077   if (p_out)
00078     *p_out = p;
00079   RCPNode *rcpNode = basicRCPNodeNoAlloc<T>(p, has_ownership);
00080   return rcpNode;
00081 }
00082 
00083 
00084 void deleteRCPNode( RCPNode **node )
00085 {
00086   TEUCHOS_ASSERT(node);
00087   TEUCHOS_ASSERT(*node);
00088   (*node)->delete_obj();
00089   delete (*node);
00090   *node = 0;
00091 }
00092 
00093 
00094 template<class T>
00095 RCPNodeHandle basicRCPNodeHandle(const bool has_ownership, T **p_out = 0)
00096 {
00097   T *p = 0;
00098   RCPNode *rcpNode = basicRCPNode(has_ownership, &p);
00099   if (p_out)
00100     *p_out = p;
00101 #ifdef TEUCHOS_DEBUG
00102   return RCPNodeHandle(rcpNode, p, typeName(*p), concreteTypeName(*p), has_ownership);
00103 #else
00104   return RCPNodeHandle(rcpNode);
00105 #endif
00106 }
00107 
00108 
00109 TEUCHOS_STATIC_SETUP()
00110 {
00111 }
00112 
00113 
00114 //
00115 // Non-templated tests
00116 //
00117 
00118 
00119 TEUCHOS_UNIT_TEST( RCPNodeHandle, assignSelf )
00120 {
00121   RCPNodeHandle nodeRef;
00122   nodeRef = nodeRef;
00123 }
00124 
00125 
00126 TEUCHOS_UNIT_TEST( RCPNodeHandle, defaultConstruct)
00127 {
00128   RCPNodeHandle nodeRef;
00129   TEST_EQUALITY_CONST( nodeRef.count(), 0 );
00130   TEST_EQUALITY_CONST( nodeRef.has_ownership(), false );
00131   nodeRef.has_ownership(true);
00132   TEST_EQUALITY_CONST( nodeRef.has_ownership(), false );
00133 #ifdef TEUCHOS_DEBUG
00134   TEST_EQUALITY_CONST( nodeRef.get_base_obj_map_key_void_ptr(), static_cast<void*>(0) );
00135   TEST_THROW({nodeRef.set_extra_data(any(),"", PRE_DESTROY, true);},
00136     NullReferenceError);
00137   TEST_THROW({any &a = nodeRef.get_extra_data("int","blob"); (void)a;},
00138     NullReferenceError);
00139   TEST_THROW({const any &a = getConst(nodeRef).get_extra_data("int","blob"); (void)a;},
00140     NullReferenceError);
00141   TEST_THROW({any *a = nodeRef.get_optional_extra_data("int","blob"); (void)a;},
00142     NullReferenceError);
00143   TEST_THROW({const any *a = getConst(nodeRef).get_optional_extra_data("int","blob"); (void)a;},
00144     NullReferenceError);
00145 #endif // TEUCHOS_DEBUG
00146 }
00147 
00148 
00149 #ifdef TEUCHOS_DEBUG
00150 
00151 
00152 TEUCHOS_UNIT_TEST( RCPNodeHandle, add_New_RCPNode_basic )
00153 {
00154 
00155   typedef RCPNodeTracer::RCPNodeStatistics RCPNodeStatistics;
00156 
00157   SET_RCPNODE_TRACING();
00158 
00159   RCPNode *node = basicRCPNode<A>(true);
00160 
00161   const int numActiveNodesBase = RCPNodeTracer::numActiveRCPNodes();
00162   const RCPNodeStatistics rcpNodeStatisticsBefore = RCPNodeTracer::getRCPNodeStatistics();
00163 
00164   out << std::endl;
00165   ECHO(RCPNodeTracer::addNewRCPNode(node, "dummy"));
00166 
00167   out << std::endl;
00168   TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase+1);
00169 
00170   out << std::endl;
00171   const RCPNodeStatistics rcpNodeStatistics1 = RCPNodeTracer::getRCPNodeStatistics();
00172   TEST_COMPARE(rcpNodeStatistics1.maxNumRCPNodes, >=,
00173     rcpNodeStatisticsBefore.maxNumRCPNodes);
00174   TEST_EQUALITY(rcpNodeStatistics1.totalNumRCPNodeAllocations,
00175     rcpNodeStatisticsBefore.totalNumRCPNodeAllocations+1);
00176   TEST_EQUALITY(rcpNodeStatistics1.totalNumRCPNodeDeletions,
00177     rcpNodeStatisticsBefore.totalNumRCPNodeDeletions);
00178 
00179   out << std::endl;
00180   ECHO(RCPNodeTracer::removeRCPNode(node));
00181 
00182   out << std::endl;
00183   TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase);
00184 
00185   out << std::endl;
00186   const RCPNodeStatistics rcpNodeStatistics2 = RCPNodeTracer::getRCPNodeStatistics();
00187   TEST_COMPARE(rcpNodeStatistics2.maxNumRCPNodes, >=,
00188     rcpNodeStatisticsBefore.maxNumRCPNodes);
00189   TEST_EQUALITY(rcpNodeStatistics2.totalNumRCPNodeAllocations,
00190     rcpNodeStatisticsBefore.totalNumRCPNodeAllocations+1);
00191   TEST_EQUALITY(rcpNodeStatistics2.totalNumRCPNodeDeletions,
00192     rcpNodeStatisticsBefore.totalNumRCPNodeDeletions+1);
00193 
00194   out << std::endl;
00195   std::ostringstream statsOut_oss;
00196   RCPNodeTracer::printRCPNodeStatistics(rcpNodeStatistics2, statsOut_oss);
00197   std::ostringstream expectedStatsOut_oss;
00198   expectedStatsOut_oss
00199     << "\n***"
00200     << "\n*** RCPNode Tracing statistics:"
00201     << "\n**\n"
00202     << "\n    maxNumRCPNodes             = "<<rcpNodeStatistics2.maxNumRCPNodes
00203     << "\n    totalNumRCPNodeAllocations = "<<rcpNodeStatistics2.totalNumRCPNodeAllocations
00204     << "\n    totalNumRCPNodeDeletions   = "<<rcpNodeStatistics2.totalNumRCPNodeDeletions
00205     << "\n";
00206   TEST_EQUALITY(statsOut_oss.str(), expectedStatsOut_oss.str());
00207 
00208   deleteRCPNode(&node);
00209 
00210 }
00211 
00212 
00213 TEUCHOS_UNIT_TEST( RCPNodeHandle, add_New_RCPNode_add_owning_twice_error )
00214 {
00215   SET_RCPNODE_TRACING();
00216 #ifdef HAVE_TEUCHOS_STACKTRACE
00217   // Make sure that you store a stacktrace so as not to affect the RCPNode count below!
00218   Teuchos::store_stacktrace();
00219 #endif
00220   A *a_ptr = new A;
00221   RCPNode *node1 = basicRCPNodeNoAlloc<A>(a_ptr, true);
00222   const int numActiveNodesBase = RCPNodeTracer::numActiveRCPNodes();
00223   ECHO(RCPNodeTracer::addNewRCPNode(node1, "dummy1"));
00224   TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase+1);
00225   RCPNode *node2 = basicRCPNodeNoAlloc<A>(a_ptr, true);
00226   TEST_THROW(RCPNodeTracer::addNewRCPNode(node2, "dummy2"), DuplicateOwningRCPError);
00227   ECHO(RCPNodeTracer::removeRCPNode(node1));
00228   deleteRCPNode(&node1);
00229   TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase);
00230   node2->has_ownership(false);
00231   deleteRCPNode(&node2);
00232 }
00233 
00234 
00235 TEUCHOS_UNIT_TEST( RCPNodeHandle, add_New_RCPNode_add_nonowning_twice_okay_1 )
00236 {
00237   SET_RCPNODE_TRACING();
00238   A *a_ptr = new A;
00239   RCPNode *node1 = basicRCPNodeNoAlloc<A>(a_ptr, true);
00240   const int numActiveNodesBase = RCPNodeTracer::numActiveRCPNodes();
00241   ECHO(RCPNodeTracer::addNewRCPNode(node1, "dummy1"));
00242   TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase+1);
00243   RCPNode *node2 = basicRCPNodeNoAlloc<A>(a_ptr, false);
00244   ECHO(RCPNodeTracer::addNewRCPNode(node2, "dummy2"));
00245   TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase+2);
00246   TEST_EQUALITY(RCPNodeTracer::getExistingRCPNode(a_ptr), node1);
00247   ECHO(RCPNodeTracer::removeRCPNode(node2));
00248   deleteRCPNode(&node2);
00249   TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase+1);
00250   ECHO(RCPNodeTracer::removeRCPNode(node1));
00251   deleteRCPNode(&node1);
00252   TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase);
00253 }
00254 
00255 
00256 TEUCHOS_UNIT_TEST( RCPNodeHandle, add_New_RCPNode_add_nonowning_twice_okay_2 )
00257 {
00258   SET_RCPNODE_TRACING();
00259   A *a_ptr = new A;
00260   RCPNode *node1 = basicRCPNodeNoAlloc<A>(a_ptr, false);
00261   const int numActiveNodesBase = RCPNodeTracer::numActiveRCPNodes();
00262   ECHO(RCPNodeTracer::addNewRCPNode(node1, "dummy1"));
00263   TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase+1);
00264   RCPNode *node2 = basicRCPNodeNoAlloc<A>(a_ptr, true);
00265   ECHO(RCPNodeTracer::addNewRCPNode(node2, "dummy2"));
00266   TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase+2);
00267   TEST_EQUALITY(RCPNodeTracer::getExistingRCPNode(a_ptr), node2);
00268   ECHO(RCPNodeTracer::removeRCPNode(node2));
00269   deleteRCPNode(&node2);
00270   TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase+1);
00271   ECHO(RCPNodeTracer::removeRCPNode(node1));
00272   deleteRCPNode(&node1);
00273   TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase);
00274 }
00275 
00276 
00277 TEUCHOS_UNIT_TEST( RCPNodeHandle, add_New_RCPNode_add_two_nodes_same_obj )
00278 {
00279   SET_RCPNODE_TRACING();
00280   ECHO(C *c_ptr = new C);
00281   ECHO(RCPNode *node_c = basicRCPNodeNoAlloc<C>(c_ptr, true));
00282   ECHO(RCPNode *node_b1 = basicRCPNodeNoAlloc<B1>(c_ptr, true));
00283   ECHO(const int numActiveNodesBase = RCPNodeTracer::numActiveRCPNodes());
00284   ECHO(RCPNodeTracer::addNewRCPNode(node_c, "dummy"));
00285   TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase+1);
00286 #ifdef HAS_TEUCHOS_GET_BASE_OBJ_VOID_PTR
00287   // We can detect that these are the same object!
00288   TEST_THROW(RCPNodeTracer::addNewRCPNode(node_b1, "dummy"), DuplicateOwningRCPError);
00289 #else
00290   // We can not detect if these are the same object!
00291   ECHO(RCPNodeTracer::addNewRCPNode(node_b1, "dummy"));
00292   TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase+2);
00293   ECHO(RCPNodeTracer::removeRCPNode(node_b1));
00294 #endif
00295   TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase+1);
00296   ECHO(RCPNodeTracer::removeRCPNode(node_c));
00297   TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase);
00298   ECHO(node_b1->has_ownership(false));
00299   ECHO(deleteRCPNode(&node_b1));
00300   ECHO(deleteRCPNode(&node_c));
00301 }
00302 
00303 
00304 #ifdef HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING
00305 TEUCHOS_UNIT_TEST( RCPNodeHandle, remove_RCPNode_missing_node )
00306 {
00307   SET_RCPNODE_TRACING();
00308   RCPNode *node = basicRCPNode<A>(true);
00309   TEST_THROW(RCPNodeTracer::removeRCPNode(node), std::logic_error);
00310   deleteRCPNode(&node);
00311 }
00312 #endif // HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING
00313 
00314 
00315 #endif // TEUCHOS_DEBUG
00316 
00317 
00318 //
00319 // Templated tests
00320 //
00321 
00322 
00323 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCPNodeHandle, basicConstruct_owns_mem, T )
00324 {
00325   T *p = 0;
00326   RCPNodeHandle nodeRef(basicRCPNodeHandle<T>(true, &p));
00327   TEST_EQUALITY_CONST( nodeRef.count(), 1 );
00328   TEST_EQUALITY_CONST( nodeRef.has_ownership(), true );
00329   nodeRef.has_ownership(false);
00330   TEST_EQUALITY_CONST( nodeRef.has_ownership(), false );
00331 #ifdef TEUCHOS_DEBUG
00332   TEST_INEQUALITY_CONST( nodeRef.get_base_obj_map_key_void_ptr(), static_cast<void*>(0) );
00333   TEST_EQUALITY( nodeRef.get_base_obj_map_key_void_ptr(), static_cast<void*>(p) );
00334   TEST_THROW({any &a = nodeRef.get_extra_data("int","blob"); (void)a;},
00335     std::invalid_argument);
00336   TEST_THROW({const any &a = getConst(nodeRef).get_extra_data("int","blob"); (void)a;},
00337     std::invalid_argument);
00338 #endif // TEUCHOS_DEBUG
00339   TEST_EQUALITY_CONST(nodeRef.get_optional_extra_data("int","blob"), 0);
00340   TEST_EQUALITY_CONST(getConst(nodeRef).get_optional_extra_data("int","blob"), 0);
00341   nodeRef.has_ownership(true);
00342 }
00343 
00344 
00345 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCPNodeHandle, basicConstruct_no_owns_mem, T )
00346 {
00347   RCPNodeHandle nodeRef(basicRCPNodeHandle<T>(false));
00348   TEST_EQUALITY_CONST( nodeRef.count(), 1 );
00349   TEST_EQUALITY_CONST( nodeRef.has_ownership(), false );
00350   nodeRef.has_ownership(true);
00351   TEST_EQUALITY_CONST( nodeRef.has_ownership(), true );
00352 }
00353 
00354 
00355 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCPNodeHandle, weakPtr_basic_1, T )
00356 {
00357 
00358   ECHO(RCPNodeHandle nodeRef1(basicRCPNodeHandle<T>(true)));
00359   TEST_EQUALITY_CONST( nodeRef1.strength(), RCP_STRONG );
00360 
00361   ECHO(RCPNodeHandle nodeRef2 = nodeRef1.create_weak());
00362 
00363   TEST_EQUALITY_CONST( nodeRef2.strength(), RCP_WEAK );
00364   TEST_EQUALITY_CONST( nodeRef1.strong_count(), 1 );
00365   TEST_EQUALITY_CONST( nodeRef1.weak_count(), 1 );
00366   TEST_EQUALITY_CONST( nodeRef2.strong_count(), 1 );
00367   TEST_EQUALITY_CONST( nodeRef2.weak_count(), 1 );
00368 
00369   ECHO(RCPNodeHandle nodeRef3 = nodeRef2.create_strong());
00370 
00371   TEST_EQUALITY_CONST( nodeRef3.strength(), RCP_STRONG );
00372   TEST_EQUALITY_CONST( nodeRef1.strong_count(), 2 );
00373   TEST_EQUALITY_CONST( nodeRef1.weak_count(), 1 );
00374   TEST_EQUALITY_CONST( nodeRef2.strong_count(), 2 );
00375   TEST_EQUALITY_CONST( nodeRef2.weak_count(), 1 );
00376   
00377   MockRCP<T> mockRCP;
00378   ECHO(nodeRef2.debug_assert_valid_ptr(mockRCP)); // Should not throw!
00379 
00380   // This will make the underlying object T get deleted!
00381   ECHO(nodeRef1 = null);
00382   ECHO(nodeRef3 = null);
00383 
00384   TEST_EQUALITY_CONST( nodeRef1.node_ptr()==0, true );
00385   TEST_EQUALITY_CONST( nodeRef1.is_node_null(), true );
00386   TEST_EQUALITY_CONST( nodeRef1.is_valid_ptr(), true );
00387 
00388   TEST_EQUALITY_CONST( nodeRef2.node_ptr()!=0, true );
00389   TEST_EQUALITY_CONST( nodeRef2.is_node_null(), false );
00390   TEST_EQUALITY_CONST( nodeRef2.is_valid_ptr(), false );
00391 
00392 #ifdef TEUCHOS_DEBUG
00393   TEST_THROW( nodeRef2.debug_assert_valid_ptr(mockRCP),
00394     DanglingReferenceError );
00395 #endif
00396 
00397   ECHO(nodeRef2 = null); // Should make the underlying node go away
00398 
00399 }
00400 
00401 
00402 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCPNodeHandle, weakPtr_basic_2, T )
00403 {
00404 
00405   ECHO(RCPNodeHandle nodeRef1(basicRCPNodeHandle<T>(true)));
00406   TEST_EQUALITY_CONST( nodeRef1.strength(), RCP_STRONG );
00407 
00408   ECHO(RCPNodeHandle nodeRef2 = nodeRef1.create_weak());
00409   TEST_EQUALITY_CONST( nodeRef2.strength(), RCP_WEAK );
00410   TEST_EQUALITY_CONST( nodeRef1.strong_count(), 1 );
00411   TEST_EQUALITY_CONST( nodeRef1.weak_count(), 1 );
00412   TEST_EQUALITY_CONST( nodeRef2.strong_count(), 1 );
00413   TEST_EQUALITY_CONST( nodeRef2.weak_count(), 1 );
00414   
00415   MockRCP<T> mockRCP;
00416 
00417   ECHO(nodeRef2.debug_assert_valid_ptr(mockRCP)); // Should not throw!
00418 
00419   ECHO(nodeRef2 = null); // The underlying object stays alive!
00420 
00421   TEST_EQUALITY_CONST( nodeRef2.node_ptr()==0, true );
00422   TEST_EQUALITY_CONST( nodeRef2.is_node_null(), true );
00423   TEST_EQUALITY_CONST( nodeRef2.is_valid_ptr(), true );
00424 
00425   TEST_EQUALITY_CONST( nodeRef1.node_ptr()!=0, true );
00426   TEST_EQUALITY_CONST( nodeRef1.is_node_null(), false );
00427   TEST_EQUALITY_CONST( nodeRef1.is_valid_ptr(), true );
00428 
00429   nodeRef1.debug_assert_valid_ptr(mockRCP); // Should not throw!
00430 
00431 }
00432 
00433 //
00434 // Test behavior of RCP node tracing but only if it is off by default
00435 //
00436 // NOTE: If node tracing is on by default then we can't control how many nodes
00437 // get created in other code not in the unit test.
00438 //
00439 
00440 #if defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING)
00441 #  define DO_RCPNODE_TRACING_TESTS 1
00442 #endif
00443 
00444 
00445 #ifdef DO_RCPNODE_TRACING_TESTS
00446 
00447 
00448 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCPNodeHandle, debugWithNodeTracingPrint, T )
00449 {
00450 
00451   TEST_EQUALITY_CONST(RCPNodeTracer::isTracingActiveRCPNodes(), false);
00452   RCPNodeTracer::setTracingActiveRCPNodes(true);
00453   TEST_EQUALITY_CONST(RCPNodeTracer::isTracingActiveRCPNodes(), true);
00454 
00455   {
00456 
00457     T *p = new T; // Never do this in production code!
00458     const std::string T_name = "T_name";
00459     const std::string concreateT_name = "concreateT_name";
00460     const bool has_ownership = true;
00461     RCPNode *node = new RCPNodeTmpl<T,DeallocDelete<T> >(
00462       p, DeallocDelete<T>(), has_ownership);
00463 
00464     RCPNodeHandle nodeRef(node, p, T_name, concreateT_name, has_ownership);
00465 
00466     TEST_EQUALITY_CONST(RCPNodeTracer::numActiveRCPNodes(), 1);
00467 
00468     out << "\nMake sure output is printed when there is an active node with tracing ...\n";
00469 
00470     const void* rcpNodeKey = RCPNodeTracer::getRCPNodeBaseObjMapKeyVoidPtr(p);
00471 
00472     std::ostringstream expendedOutput_oss;
00473     expendedOutput_oss
00474         << RCPNodeTracer::getActiveRCPNodeHeaderString()
00475         << "\n"
00476         << "  0: RCPNode (map_key_void_ptr=" << rcpNodeKey << ")\n"
00477         << "       Information = {T="<<T_name<<", ConcreteT="<<concreateT_name<<", p="<<p<<", has_ownership="<<has_ownership<<"}\n"
00478         << "       RCPNode address = " << node << "\n"
00479         << "       insertionNumber = " << node->insertion_number()
00480         << "\n\n"
00481         << RCPNodeTracer::getCommonDebugNotesString();
00482 
00483     std::ostringstream printActiveRCPNodes_out;
00484     RCPNodeTracer::printActiveRCPNodes(printActiveRCPNodes_out);
00485     TEST_EQUALITY( printActiveRCPNodes_out.str(), expendedOutput_oss.str() );
00486 
00487     // NOTE: The above test basically copied and pasted the ouptut stream code
00488     // from printActiveRCPNodes(...) and will need to be maintained
00489     // with this code.  However, this is a good test because it ensures that
00490     // the arguments node, p, T_name, and concreateT_name are passed, stored,
00491     // and retrieved correctly.  It is also a good test because it ensures
00492     // that output is printed when node tracing is turned on.
00493     //
00494     // This is the very definition of a "white box" test but that is just fine
00495     // for a unit test.
00496 
00497   }
00498 
00499   TEST_EQUALITY_CONST(RCPNodeTracer::numActiveRCPNodes(), 0);
00500 
00501   out << "\nMake sure no output is printed when there are no active nodes ...\n";
00502   const std::string expendedOutput = "";
00503   std::ostringstream printActiveRCPNodes_out;
00504   RCPNodeTracer::printActiveRCPNodes(printActiveRCPNodes_out);
00505   TEST_EQUALITY( printActiveRCPNodes_out.str(), expendedOutput );
00506 
00507   RCPNodeTracer::setTracingActiveRCPNodes(false);
00508   TEST_EQUALITY_CONST(RCPNodeTracer::isTracingActiveRCPNodes(), false);
00509 
00510 }
00511 
00512 
00513 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCPNodeHandle, debugWithoutNodeTracingPrint, T )
00514 {
00515 
00516   TEST_EQUALITY_CONST(RCPNodeTracer::isTracingActiveRCPNodes(), false);
00517   RCPNodeTracer::setTracingActiveRCPNodes(false);
00518   TEST_EQUALITY_CONST(RCPNodeTracer::isTracingActiveRCPNodes(), false);
00519 
00520   T *p = new T; // Never do this in production code!
00521   const std::string T_name = "T_name";
00522   const std::string concreateT_name = "concreateT_name";
00523   const bool has_ownership = true;
00524   RCPNode *node = new RCPNodeTmpl<T,DeallocDelete<T> >(
00525     p, DeallocDelete<T>(), has_ownership);
00526   
00527   RCPNodeHandle nodeRef(node, p, T_name, concreateT_name, has_ownership);
00528 
00529   TEST_EQUALITY_CONST(RCPNodeTracer::numActiveRCPNodes(), 0);
00530   
00531   out << "\nMake sure no output is printed when there are no active nodes without tracing ...\n";
00532   const std::string expendedOutput = "";
00533   std::ostringstream printActiveRCPNodes_out;
00534   RCPNodeTracer::printActiveRCPNodes(printActiveRCPNodes_out);
00535   TEST_EQUALITY( printActiveRCPNodes_out.str(), expendedOutput );
00536 
00537 }
00538 
00539 
00540 #endif // DO_RCPNODE_TRACING_TESTS
00541 
00542 
00543 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCPNodeHandle, copyConstruct, T )
00544 {
00545   RCPNodeHandle nodeRef1(basicRCPNodeHandle<T>(true));
00546   RCPNodeHandle nodeRef2(nodeRef1);
00547   TEST_EQUALITY_CONST( nodeRef1.count(), 2 );
00548   TEST_EQUALITY_CONST( nodeRef2.count(), 2 );
00549   TEST_EQUALITY_CONST( nodeRef1.has_ownership(), true );
00550   TEST_EQUALITY_CONST( nodeRef2.has_ownership(), true );
00551 }
00552 
00553 
00554 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCPNodeHandle, assignmentOperator, T )
00555 {
00556   RCPNodeHandle nodeRef1(basicRCPNodeHandle<T>(true));
00557   RCPNodeHandle nodeRef2;
00558   nodeRef2 = nodeRef1;
00559   TEST_EQUALITY_CONST( nodeRef1.count(), 2 );
00560   TEST_EQUALITY_CONST( nodeRef2.count(), 2 );
00561   TEST_EQUALITY_CONST( nodeRef1.has_ownership(), true );
00562   TEST_EQUALITY_CONST( nodeRef2.has_ownership(), true );
00563 }
00564 
00565 
00566 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCPNodeHandle, extraData_basic, T )
00567 {
00568 
00569   RCPNodeHandle nodeRef(basicRCPNodeHandle<T>(true));
00570 
00571   const int v1 = 2;
00572   const any a1(v1);
00573   nodeRef.set_extra_data(a1, "a1", PRE_DESTROY, true); 
00574 
00575   any &a2 = nodeRef.get_extra_data(a1.typeName(), "a1");
00576   TEST_EQUALITY_CONST( a1.same(a2), true );
00577   TEST_EQUALITY( any_cast<int>(a2), v1 );
00578 
00579   any *a3 = nodeRef.get_optional_extra_data(a1.typeName(), "a1");
00580   TEST_EQUALITY_CONST( a3!=0, true );
00581   TEST_EQUALITY( &a2, a3 );
00582   TEST_EQUALITY_CONST( a3->same(a1), true );
00583 
00584   RCPNodeHandle nodeRef2 = nodeRef;
00585 
00586   const int v2 = 3;
00587   a2 = v2;
00588   TEST_EQUALITY( any_cast<int>(a1), v1 );
00589   TEST_EQUALITY( any_cast<int>(*a3), v2 );
00590 
00591   any &a4 = nodeRef2.get_extra_data(a1.typeName(), "a1");
00592   TEST_EQUALITY( &a4, &a2 );
00593   TEST_EQUALITY( &a4, a3 );
00594   TEST_EQUALITY( any_cast<int>(a4), v2 );
00595   
00596 }
00597 
00598 
00599 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCPNodeHandle, extraData_basic_const, T )
00600 {
00601 
00602   RCPNodeHandle nodeRef(basicRCPNodeHandle<T>(true));
00603 
00604   const int v1 = 2;
00605   const any a1(v1);
00606   nodeRef.set_extra_data(a1, "a1", PRE_DESTROY, true); 
00607   
00608   const RCPNodeHandle nodeRef2 = nodeRef;
00609 
00610   const any &a2 = nodeRef2.get_extra_data(a1.typeName(), "a1");
00611   TEST_EQUALITY_CONST( a1.same(a2), true );
00612   TEST_EQUALITY( any_cast<int>(a2), v1 );
00613 
00614   const any *a3 = nodeRef2.get_optional_extra_data(a1.typeName(), "a1");
00615   TEST_EQUALITY_CONST( a3!=0, true );
00616   TEST_EQUALITY( &a2, a3 );
00617   TEST_EQUALITY_CONST( a3->same(a1), true );
00618   
00619 }
00620 
00621 
00622 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCPNodeHandle, extraData_failed, T )
00623 {
00624 
00625   RCPNodeHandle nodeRef(basicRCPNodeHandle<T>(true));
00626 
00627   const int v1 = 2;
00628   const any a1(v1);
00629   nodeRef.set_extra_data(a1, "a1", PRE_DESTROY, true); 
00630 
00631 #ifdef TEUCHOS_DEBUG
00632 
00633   TEST_THROW({nodeRef.get_extra_data("wrong type", "a1");},
00634     std::invalid_argument);
00635 
00636   TEST_THROW({nodeRef.get_extra_data(a1.typeName(), "wrong name");},
00637     std::invalid_argument);
00638 
00639 #endif // TEUCHOS_DEBUG
00640 
00641   any *a2 = nodeRef.get_optional_extra_data("wrong type", "a1");
00642   TEST_EQUALITY_CONST( a2, 0 );
00643 
00644   any *a3 = nodeRef.get_optional_extra_data(a1.typeName(), "wrong name");
00645   TEST_EQUALITY_CONST( a3, 0 );
00646   
00647 }
00648 
00649 
00650 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCPNodeHandle, extraData_failed_const, T )
00651 {
00652 
00653   RCPNodeHandle nodeRef(basicRCPNodeHandle<T>(true));
00654 
00655   const int v1 = 2;
00656   const any a1(v1);
00657   nodeRef.set_extra_data(a1, "a1", PRE_DESTROY, true); 
00658   
00659   const RCPNodeHandle nodeRef2 = nodeRef;
00660 
00661 #ifdef TEUCHOS_DEBUG
00662 
00663   TEST_THROW({nodeRef2.get_extra_data("wrong type", "a1");},
00664     std::invalid_argument);
00665 
00666   TEST_THROW({nodeRef2.get_extra_data(a1.typeName(), "wrong name");},
00667     std::invalid_argument);
00668 
00669 #endif // TEUCHOS_DEBUG
00670 
00671   const any *a2 = nodeRef2.get_optional_extra_data("wrong type", "a1");
00672   TEST_EQUALITY_CONST( a2, 0 );
00673 
00674   const any *a3 = nodeRef2.get_optional_extra_data(a1.typeName(), "wrong name");
00675   TEST_EQUALITY_CONST( a3, 0 );
00676   
00677 }
00678 
00679 
00680 //
00681 // Instantiations
00682 //
00683 
00684 
00685 #ifdef DO_RCPNODE_TRACING_TESTS
00686 
00687 #  define DEBUG_UNIT_TEST_GROUP( T ) \
00688     TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, debugWithNodeTracingPrint, T ) \
00689     TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, debugWithoutNodeTracingPrint, T )
00690 
00691 #else
00692 
00693 #  define DEBUG_UNIT_TEST_GROUP( T )
00694 
00695 #endif
00696 
00697 
00698 #define UNIT_TEST_GROUP( T ) \
00699   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, basicConstruct_owns_mem, T ) \
00700   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, basicConstruct_no_owns_mem, T ) \
00701   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, weakPtr_basic_1, T ) \
00702   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, weakPtr_basic_2, T ) \
00703   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, copyConstruct, T ) \
00704   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, assignmentOperator, T ) \
00705   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, extraData_basic, T ) \
00706   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, extraData_basic_const, T ) \
00707   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, extraData_failed, T ) \
00708   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, extraData_failed_const, T ) \
00709   DEBUG_UNIT_TEST_GROUP(T)
00710 
00711 
00712 UNIT_TEST_GROUP(A)
00713 //UNIT_TEST_GROUP(B1)
00714 //UNIT_TEST_GROUP(B2)
00715 UNIT_TEST_GROUP(C)
00716 //UNIT_TEST_GROUP(D)
00717 UNIT_TEST_GROUP(E)
00718 
00719 // 2008/09/22: rabartl: Above: We don't need to test with all of these classes
00720 // in order to test this functionality.
00721 
00722 
00723 } // namespace Teuchos 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines