Teuchos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RCPNodeHandle_UnitTests.cpp
Go to the documentation of this file.
1 /*
2 // @HEADER
3 // ***********************************************************************
4 //
5 // Teuchos: Common Tools Package
6 // Copyright (2004) Sandia Corporation
7 //
8 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
9 // license for use of this work by or on behalf of the U.S. Government.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
39 //
40 // ***********************************************************************
41 // @HEADER
42 */
43 
45 #include "Teuchos_RCPNode.hpp"
46 #include "Teuchos_getConst.hpp"
48 #include "TestClasses.hpp"
49 
50 
51 namespace Teuchos {
52 
53 
54 template<class T>
55 class MockRCP {
56 public:
57  T* access_private_ptr() const
58  {
59  return (T*)(0x777777); // Just some bogus address printed to out
60  }
61 };
62 
63 
64 template<class T>
65 RCPNode* basicRCPNodeNoAlloc(T* p, const bool has_ownership)
66 {
68  new RCPNodeTmpl<T,DeallocDelete<T> >(p, DeallocDelete<T>(), has_ownership);
69  return rcpNode;
70 }
71 
72 
73 template<class T>
74 RCPNode* basicRCPNode(const bool has_ownership, T **p_out = 0)
75 {
76  T *p = new T;
77  if (p_out)
78  *p_out = p;
79  RCPNode *rcpNode = basicRCPNodeNoAlloc<T>(p, has_ownership);
80  return rcpNode;
81 }
82 
83 
84 void deleteRCPNode( RCPNode **node )
85 {
86  TEUCHOS_ASSERT(node);
87  TEUCHOS_ASSERT(*node);
88  (*node)->delete_obj();
89  delete (*node);
90  *node = 0;
91 }
92 
93 
94 template<class T>
95 RCPNodeHandle basicRCPNodeHandle(const bool has_ownership, T **p_out = 0)
96 {
97  T *p = 0;
98  RCPNode *rcpNode = basicRCPNode(has_ownership, &p);
99  if (p_out)
100  *p_out = p;
101 #ifdef TEUCHOS_DEBUG
102  return RCPNodeHandle(rcpNode, p, typeName(*p), concreteTypeName(*p), has_ownership);
103 #else
104  return RCPNodeHandle(rcpNode);
105 #endif
106 }
107 
108 
110 {
111 }
112 
113 
114 //
115 // Non-templated tests
116 //
117 
118 
120 {
121  RCPNodeHandle nodeRef;
122  nodeRef = nodeRef;
123 }
124 
125 
126 TEUCHOS_UNIT_TEST( RCPNodeHandle, defaultConstruct)
127 {
128  RCPNodeHandle nodeRef;
129  TEST_EQUALITY_CONST( nodeRef.strong_count(), 0 );
130  TEST_EQUALITY_CONST( nodeRef.has_ownership(), false );
131  nodeRef.has_ownership(true);
132  TEST_EQUALITY_CONST( nodeRef.has_ownership(), false );
133 #ifdef TEUCHOS_DEBUG
134  TEST_EQUALITY_CONST( nodeRef.get_base_obj_map_key_void_ptr(), static_cast<void*>(0) );
135  TEST_THROW({nodeRef.set_extra_data(any(),"", PRE_DESTROY, true);},
137  TEST_THROW({any &a = nodeRef.get_extra_data("int","blob"); (void)a;},
139  TEST_THROW({const any &a = getConst(nodeRef).get_extra_data("int","blob"); (void)a;},
141  TEST_THROW({any *a = nodeRef.get_optional_extra_data("int","blob"); (void)a;},
143  TEST_THROW({const any *a = getConst(nodeRef).get_optional_extra_data("int","blob"); (void)a;},
145 #endif // TEUCHOS_DEBUG
146 }
147 
148 
149 #ifdef TEUCHOS_DEBUG
150 
151 
152 TEUCHOS_UNIT_TEST( RCPNodeHandle, add_New_RCPNode_basic )
153 {
154 
155  typedef RCPNodeTracer::RCPNodeStatistics RCPNodeStatistics;
156 
158 
159  RCPNode *node = basicRCPNode<A>(true);
160 
161  const int numActiveNodesBase = RCPNodeTracer::numActiveRCPNodes();
162  const RCPNodeStatistics rcpNodeStatisticsBefore = RCPNodeTracer::getRCPNodeStatistics();
163 
164  out << std::endl;
165  ECHO(RCPNodeTracer::addNewRCPNode(node, "dummy"));
166 
167  out << std::endl;
168  TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase+1);
169 
170  out << std::endl;
171  const RCPNodeStatistics rcpNodeStatistics1 = RCPNodeTracer::getRCPNodeStatistics();
172  TEST_COMPARE(rcpNodeStatistics1.maxNumRCPNodes, >=,
173  rcpNodeStatisticsBefore.maxNumRCPNodes);
174  TEST_EQUALITY(rcpNodeStatistics1.totalNumRCPNodeAllocations,
175  rcpNodeStatisticsBefore.totalNumRCPNodeAllocations+1);
176  TEST_EQUALITY(rcpNodeStatistics1.totalNumRCPNodeDeletions,
177  rcpNodeStatisticsBefore.totalNumRCPNodeDeletions);
178 
179  out << std::endl;
181 
182  out << std::endl;
183  TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase);
184 
185  out << std::endl;
186  const RCPNodeStatistics rcpNodeStatistics2 = RCPNodeTracer::getRCPNodeStatistics();
187  TEST_COMPARE(rcpNodeStatistics2.maxNumRCPNodes, >=,
188  rcpNodeStatisticsBefore.maxNumRCPNodes);
189  TEST_EQUALITY(rcpNodeStatistics2.totalNumRCPNodeAllocations,
190  rcpNodeStatisticsBefore.totalNumRCPNodeAllocations+1);
191  TEST_EQUALITY(rcpNodeStatistics2.totalNumRCPNodeDeletions,
192  rcpNodeStatisticsBefore.totalNumRCPNodeDeletions+1);
193 
194  out << std::endl;
195  std::ostringstream statsOut_oss;
196  RCPNodeTracer::printRCPNodeStatistics(rcpNodeStatistics2, statsOut_oss);
197  std::ostringstream expectedStatsOut_oss;
198  expectedStatsOut_oss
199  << "\n***"
200  << "\n*** RCPNode Tracing statistics:"
201  << "\n**\n"
202  << "\n maxNumRCPNodes = "<<rcpNodeStatistics2.maxNumRCPNodes
203  << "\n totalNumRCPNodeAllocations = "<<rcpNodeStatistics2.totalNumRCPNodeAllocations
204  << "\n totalNumRCPNodeDeletions = "<<rcpNodeStatistics2.totalNumRCPNodeDeletions
205  << "\n";
206  TEST_EQUALITY(statsOut_oss.str(), expectedStatsOut_oss.str());
207 
208  deleteRCPNode(&node);
209 
210 }
211 
212 
213 TEUCHOS_UNIT_TEST( RCPNodeHandle, add_New_RCPNode_add_owning_twice_error )
214 {
216 #ifdef HAVE_TEUCHOS_STACKTRACE
217  // Make sure that you store a stacktrace so as not to affect the RCPNode count below!
218  Teuchos::store_stacktrace();
219 #endif
220  A *a_ptr = new A;
221  RCPNode *node1 = basicRCPNodeNoAlloc<A>(a_ptr, true);
222  const int numActiveNodesBase = RCPNodeTracer::numActiveRCPNodes();
223  ECHO(RCPNodeTracer::addNewRCPNode(node1, "dummy1"));
224  TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase+1);
225  RCPNode *node2 = basicRCPNodeNoAlloc<A>(a_ptr, true);
226  TEST_THROW(RCPNodeTracer::addNewRCPNode(node2, "dummy2"), DuplicateOwningRCPError);
228  deleteRCPNode(&node1);
229  TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase);
230  node2->has_ownership(false);
231  deleteRCPNode(&node2);
232 }
233 
234 
235 TEUCHOS_UNIT_TEST( RCPNodeHandle, add_New_RCPNode_add_nonowning_twice_okay_1 )
236 {
238  A *a_ptr = new A;
239  RCPNode *node1 = basicRCPNodeNoAlloc<A>(a_ptr, true);
240  const int numActiveNodesBase = RCPNodeTracer::numActiveRCPNodes();
241  ECHO(RCPNodeTracer::addNewRCPNode(node1, "dummy1"));
242  TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase+1);
243  RCPNode *node2 = basicRCPNodeNoAlloc<A>(a_ptr, false);
244  ECHO(RCPNodeTracer::addNewRCPNode(node2, "dummy2"));
245  TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase+2);
248  deleteRCPNode(&node2);
249  TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase+1);
251  deleteRCPNode(&node1);
252  TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase);
253 }
254 
255 
256 TEUCHOS_UNIT_TEST( RCPNodeHandle, add_New_RCPNode_add_nonowning_twice_okay_2 )
257 {
259  A *a_ptr = new A;
260  RCPNode *node1 = basicRCPNodeNoAlloc<A>(a_ptr, false);
261  const int numActiveNodesBase = RCPNodeTracer::numActiveRCPNodes();
262  ECHO(RCPNodeTracer::addNewRCPNode(node1, "dummy1"));
263  TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase+1);
264  RCPNode *node2 = basicRCPNodeNoAlloc<A>(a_ptr, true);
265  ECHO(RCPNodeTracer::addNewRCPNode(node2, "dummy2"));
266  TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase+2);
269  deleteRCPNode(&node2);
270  TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase+1);
272  deleteRCPNode(&node1);
273  TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase);
274 }
275 
276 
277 TEUCHOS_UNIT_TEST( RCPNodeHandle, add_New_RCPNode_add_two_nodes_same_obj )
278 {
280  ECHO(C *c_ptr = new C);
281  ECHO(RCPNode *node_c = basicRCPNodeNoAlloc<C>(c_ptr, true));
282  ECHO(RCPNode *node_b1 = basicRCPNodeNoAlloc<B1>(c_ptr, true));
283  ECHO(const int numActiveNodesBase = RCPNodeTracer::numActiveRCPNodes());
284  ECHO(RCPNodeTracer::addNewRCPNode(node_c, "dummy"));
285  TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase+1);
286 #ifdef HAS_TEUCHOS_GET_BASE_OBJ_VOID_PTR
287  // We can detect that these are the same object!
288  TEST_THROW(RCPNodeTracer::addNewRCPNode(node_b1, "dummy"), DuplicateOwningRCPError);
289 #else
290  // We can not detect if these are the same object!
291  ECHO(RCPNodeTracer::addNewRCPNode(node_b1, "dummy"));
292  TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase+2);
294 #endif
295  TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase+1);
297  TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase);
298  ECHO(node_b1->has_ownership(false));
299  ECHO(deleteRCPNode(&node_b1));
300  ECHO(deleteRCPNode(&node_c));
301 }
302 
303 
304 #ifdef HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING
305 TEUCHOS_UNIT_TEST( RCPNodeHandle, remove_RCPNode_missing_node )
306 {
308  RCPNode *node = basicRCPNode<A>(true);
309  TEST_THROW(RCPNodeTracer::removeRCPNode(node), std::logic_error);
310  deleteRCPNode(&node);
311 }
312 #endif // HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING
313 
314 
315 #endif // TEUCHOS_DEBUG
316 
317 
318 //
319 // Templated tests
320 //
321 
322 
323 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCPNodeHandle, basicConstruct_owns_mem, T )
324 {
325  T *p = 0;
326  RCPNodeHandle nodeRef(basicRCPNodeHandle<T>(true, &p));
327  TEST_EQUALITY_CONST( nodeRef.strong_count(), 1 );
328  TEST_EQUALITY_CONST( nodeRef.has_ownership(), true );
329  nodeRef.has_ownership(false);
330  TEST_EQUALITY_CONST( nodeRef.has_ownership(), false );
331 #ifdef TEUCHOS_DEBUG
332  TEST_INEQUALITY_CONST( nodeRef.get_base_obj_map_key_void_ptr(), static_cast<void*>(0) );
333  TEST_EQUALITY( nodeRef.get_base_obj_map_key_void_ptr(), static_cast<void*>(p) );
334  TEST_THROW({any &a = nodeRef.get_extra_data("int","blob"); (void)a;},
335  std::invalid_argument);
336  TEST_THROW({const any &a = getConst(nodeRef).get_extra_data("int","blob"); (void)a;},
337  std::invalid_argument);
338 #endif // TEUCHOS_DEBUG
339  TEST_EQUALITY_CONST(nodeRef.get_optional_extra_data("int","blob"), 0);
340  TEST_EQUALITY_CONST(getConst(nodeRef).get_optional_extra_data("int","blob"), 0);
341  nodeRef.has_ownership(true);
342 }
343 
344 
345 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCPNodeHandle, basicConstruct_no_owns_mem, T )
346 {
347  RCPNodeHandle nodeRef(basicRCPNodeHandle<T>(false));
348  TEST_EQUALITY_CONST( nodeRef.strong_count(), 1 );
349  TEST_EQUALITY_CONST( nodeRef.has_ownership(), false );
350  nodeRef.has_ownership(true);
351  TEST_EQUALITY_CONST( nodeRef.has_ownership(), true );
352 }
353 
354 
356 {
357 
358  ECHO(RCPNodeHandle nodeRef1(basicRCPNodeHandle<T>(true)));
359  TEST_EQUALITY_CONST( nodeRef1.strength(), RCP_STRONG );
360 
361  ECHO(RCPNodeHandle nodeRef2 = nodeRef1.create_weak());
362 
363  TEST_EQUALITY_CONST( nodeRef2.strength(), RCP_WEAK );
364  TEST_EQUALITY_CONST( nodeRef1.strong_count(), 1 );
365  TEST_EQUALITY_CONST( nodeRef1.weak_count(), 1 );
366  TEST_EQUALITY_CONST( nodeRef2.strong_count(), 1 );
367  TEST_EQUALITY_CONST( nodeRef2.weak_count(), 1 );
368 
369  ECHO(RCPNodeHandle nodeRef3 = nodeRef2.create_strong());
370 
371  TEST_EQUALITY_CONST( nodeRef3.strength(), RCP_STRONG );
372  TEST_EQUALITY_CONST( nodeRef1.strong_count(), 2 );
373  TEST_EQUALITY_CONST( nodeRef1.weak_count(), 1 );
374  TEST_EQUALITY_CONST( nodeRef2.strong_count(), 2 );
375  TEST_EQUALITY_CONST( nodeRef2.weak_count(), 1 );
376 
377  MockRCP<T> mockRCP;
378  ECHO(nodeRef2.debug_assert_valid_ptr(mockRCP)); // Should not throw!
379 
380  // This will make the underlying object T get deleted!
381  ECHO(nodeRef1 = null);
382  ECHO(nodeRef3 = null);
383 
384  TEST_EQUALITY_CONST( nodeRef1.node_ptr()==0, true );
385  TEST_EQUALITY_CONST( nodeRef1.is_node_null(), true );
386  TEST_EQUALITY_CONST( nodeRef1.is_valid_ptr(), true );
387 
388  TEST_EQUALITY_CONST( nodeRef2.node_ptr()!=0, true );
389  TEST_EQUALITY_CONST( nodeRef2.is_node_null(), false );
390  TEST_EQUALITY_CONST( nodeRef2.is_valid_ptr(), false );
391 
392 #ifdef TEUCHOS_DEBUG
393  TEST_THROW( nodeRef2.debug_assert_valid_ptr(mockRCP),
395 #endif
396 
397  ECHO(nodeRef2 = null); // Should make the underlying node go away
398 
399 }
400 
401 
403 {
404 
405  ECHO(RCPNodeHandle nodeRef1(basicRCPNodeHandle<T>(true)));
406  TEST_EQUALITY_CONST( nodeRef1.strength(), RCP_STRONG );
407 
408  ECHO(RCPNodeHandle nodeRef2 = nodeRef1.create_weak());
409  TEST_EQUALITY_CONST( nodeRef2.strength(), RCP_WEAK );
410  TEST_EQUALITY_CONST( nodeRef1.strong_count(), 1 );
411  TEST_EQUALITY_CONST( nodeRef1.weak_count(), 1 );
412  TEST_EQUALITY_CONST( nodeRef2.strong_count(), 1 );
413  TEST_EQUALITY_CONST( nodeRef2.weak_count(), 1 );
414 
415  MockRCP<T> mockRCP;
416 
417  ECHO(nodeRef2.debug_assert_valid_ptr(mockRCP)); // Should not throw!
418 
419  ECHO(nodeRef2 = null); // The underlying object stays alive!
420 
421  TEST_EQUALITY_CONST( nodeRef2.node_ptr()==0, true );
422  TEST_EQUALITY_CONST( nodeRef2.is_node_null(), true );
423  TEST_EQUALITY_CONST( nodeRef2.is_valid_ptr(), true );
424 
425  TEST_EQUALITY_CONST( nodeRef1.node_ptr()!=0, true );
426  TEST_EQUALITY_CONST( nodeRef1.is_node_null(), false );
427  TEST_EQUALITY_CONST( nodeRef1.is_valid_ptr(), true );
428 
429  nodeRef1.debug_assert_valid_ptr(mockRCP); // Should not throw!
430 
431 }
432 
433 //
434 // Test behavior of RCP node tracing but only if it is off by default
435 //
436 // NOTE: If node tracing is on by default then we can't control how many nodes
437 // get created in other code not in the unit test.
438 //
439 
440 #if defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING)
441 # define DO_RCPNODE_TRACING_TESTS 1
442 #endif
443 
444 
445 #ifdef DO_RCPNODE_TRACING_TESTS
446 
447 
448 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCPNodeHandle, debugWithNodeTracingPrint, T )
449 {
450 
452  RCPNodeTracer::setTracingActiveRCPNodes(true);
454 
455  {
456 
457  T *p = new T; // Never do this in production code!
458  const std::string T_name = "T_name";
459  const std::string concreateT_name = "concreateT_name";
460  const bool has_ownership = true;
461  RCPNode *node = new RCPNodeTmpl<T,DeallocDelete<T> >(
462  p, DeallocDelete<T>(), has_ownership);
463 
464  RCPNodeHandle nodeRef(node, p, T_name, concreateT_name, has_ownership);
465 
467 
468  out << "\nMake sure output is printed when there is an active node with tracing ...\n";
469 
470  const void* rcpNodeKey = RCPNodeTracer::getRCPNodeBaseObjMapKeyVoidPtr(p);
471 
472  std::ostringstream expendedOutput_oss;
473  expendedOutput_oss
475  << "\n"
476  << " 0: RCPNode (map_key_void_ptr=" << rcpNodeKey << ")\n"
477  << " Information = {T="<<T_name<<", ConcreteT="<<concreateT_name<<", p="<<p<<", has_ownership="<<has_ownership<<"}\n"
478  << " RCPNode address = " << node << "\n"
479  << " insertionNumber = " << node->insertion_number()
480  << "\n\n"
482 
483  std::ostringstream printActiveRCPNodes_out;
484  RCPNodeTracer::printActiveRCPNodes(printActiveRCPNodes_out);
485  TEST_EQUALITY( printActiveRCPNodes_out.str(), expendedOutput_oss.str() );
486 
487  // NOTE: The above test basically copied and pasted the ouptut stream code
488  // from printActiveRCPNodes(...) and will need to be maintained
489  // with this code. However, this is a good test because it ensures that
490  // the arguments node, p, T_name, and concreateT_name are passed, stored,
491  // and retrieved correctly. It is also a good test because it ensures
492  // that output is printed when node tracing is turned on.
493  //
494  // This is the very definition of a "white box" test but that is just fine
495  // for a unit test.
496 
497  }
498 
500 
501  out << "\nMake sure no output is printed when there are no active nodes ...\n";
502  const std::string expendedOutput = "";
503  std::ostringstream printActiveRCPNodes_out;
504  RCPNodeTracer::printActiveRCPNodes(printActiveRCPNodes_out);
505  TEST_EQUALITY( printActiveRCPNodes_out.str(), expendedOutput );
506 
507  RCPNodeTracer::setTracingActiveRCPNodes(false);
509 
510 }
511 
512 
513 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCPNodeHandle, debugWithoutNodeTracingPrint, T )
514 {
515 
517  RCPNodeTracer::setTracingActiveRCPNodes(false);
519 
520  T *p = new T; // Never do this in production code!
521  const std::string T_name = "T_name";
522  const std::string concreateT_name = "concreateT_name";
523  const bool has_ownership = true;
524  RCPNode *node = new RCPNodeTmpl<T,DeallocDelete<T> >(
525  p, DeallocDelete<T>(), has_ownership);
526 
527  RCPNodeHandle nodeRef(node, p, T_name, concreateT_name, has_ownership);
528 
530 
531  out << "\nMake sure no output is printed when there are no active nodes without tracing ...\n";
532  const std::string expendedOutput = "";
533  std::ostringstream printActiveRCPNodes_out;
534  RCPNodeTracer::printActiveRCPNodes(printActiveRCPNodes_out);
535  TEST_EQUALITY( printActiveRCPNodes_out.str(), expendedOutput );
536 
537 }
538 
539 
540 #endif // DO_RCPNODE_TRACING_TESTS
541 
542 
544 {
545  RCPNodeHandle nodeRef1(basicRCPNodeHandle<T>(true));
546  RCPNodeHandle nodeRef2(nodeRef1);
547  TEST_EQUALITY( nodeRef1.node_ptr(), nodeRef2.node_ptr() );
548  TEST_EQUALITY_CONST( nodeRef1.same_node(nodeRef2), true );
549  TEST_EQUALITY_CONST( nodeRef1.strong_count(), 2 );
550  TEST_EQUALITY_CONST( nodeRef2.strong_count(), 2 );
551  TEST_EQUALITY_CONST( nodeRef1.has_ownership(), true );
552  TEST_EQUALITY_CONST( nodeRef2.has_ownership(), true );
553 }
554 
555 
557 {
558  RCPNodeHandle nodeRef1(basicRCPNodeHandle<T>(true));
559  RCPNodeHandle nodeRef2(std::move(nodeRef1));
560  TEST_EQUALITY_CONST( nodeRef1.node_ptr(), 0 );
561  TEST_INEQUALITY_CONST( nodeRef2.node_ptr(), 0 );
562  TEST_EQUALITY_CONST( nodeRef1.same_node(nodeRef2), false );
563  TEST_EQUALITY_CONST( nodeRef1.strong_count(), 0 );
564  TEST_EQUALITY_CONST( nodeRef2.strong_count(), 1 );
565  TEST_EQUALITY_CONST( nodeRef1.has_ownership(), false );
566  TEST_EQUALITY_CONST( nodeRef2.has_ownership(), true );
567 }
568 
569 
571 {
572  RCPNodeHandle nodeRef1(basicRCPNodeHandle<T>(true));
573  RCPNodeHandle nodeRef2;
574  nodeRef2 = nodeRef1;
575  TEST_EQUALITY_CONST( nodeRef1.strong_count(), 2 );
576  TEST_EQUALITY_CONST( nodeRef2.strong_count(), 2 );
577  TEST_EQUALITY_CONST( nodeRef1.has_ownership(), true );
578  TEST_EQUALITY_CONST( nodeRef2.has_ownership(), true );
579 }
580 
581 
583 {
584  RCPNodeHandle nodeRef1(basicRCPNodeHandle<T>(true));
585  RCPNodeHandle nodeRef2;
586  nodeRef2 = std::move(nodeRef1);
587  TEST_EQUALITY_CONST( nodeRef1.node_ptr(), 0 );
588  TEST_INEQUALITY_CONST( nodeRef2.node_ptr(), 0 );
589  TEST_EQUALITY_CONST( nodeRef1.same_node(nodeRef2), false );
590  TEST_EQUALITY_CONST( nodeRef1.strong_count(), 0 );
591  TEST_EQUALITY_CONST( nodeRef2.strong_count(), 1 );
592  TEST_EQUALITY_CONST( nodeRef1.has_ownership(), false );
593  TEST_EQUALITY_CONST( nodeRef2.has_ownership(), true );
594 }
595 
596 
598 {
599 
600  RCPNodeHandle nodeRef(basicRCPNodeHandle<T>(true));
601 
602  const int v1 = 2;
603  const any a1(v1);
604  nodeRef.set_extra_data(a1, "a1", PRE_DESTROY, true);
605 
606  any &a2 = nodeRef.get_extra_data(a1.typeName(), "a1");
607  TEST_EQUALITY_CONST( a1.same(a2), true );
608  TEST_EQUALITY( any_cast<int>(a2), v1 );
609 
610  any *a3 = nodeRef.get_optional_extra_data(a1.typeName(), "a1");
611  TEST_EQUALITY_CONST( a3!=0, true );
612  TEST_EQUALITY( &a2, a3 );
613  TEST_EQUALITY_CONST( a3->same(a1), true );
614 
615  RCPNodeHandle nodeRef2 = nodeRef;
616 
617  const int v2 = 3;
618  a2 = v2;
619  TEST_EQUALITY( any_cast<int>(a1), v1 );
620  TEST_EQUALITY( any_cast<int>(*a3), v2 );
621 
622  any &a4 = nodeRef2.get_extra_data(a1.typeName(), "a1");
623  TEST_EQUALITY( &a4, &a2 );
624  TEST_EQUALITY( &a4, a3 );
625  TEST_EQUALITY( any_cast<int>(a4), v2 );
626 
627 }
628 
629 
631 {
632 
633  RCPNodeHandle nodeRef(basicRCPNodeHandle<T>(true));
634 
635  const int v1 = 2;
636  const any a1(v1);
637  nodeRef.set_extra_data(a1, "a1", PRE_DESTROY, true);
638 
639  const RCPNodeHandle nodeRef2 = nodeRef;
640 
641  const any &a2 = nodeRef2.get_extra_data(a1.typeName(), "a1");
642  TEST_EQUALITY_CONST( a1.same(a2), true );
643  TEST_EQUALITY( any_cast<int>(a2), v1 );
644 
645  const any *a3 = nodeRef2.get_optional_extra_data(a1.typeName(), "a1");
646  TEST_EQUALITY_CONST( a3!=0, true );
647  TEST_EQUALITY( &a2, a3 );
648  TEST_EQUALITY_CONST( a3->same(a1), true );
649 
650 }
651 
652 
654 {
655 
656  RCPNodeHandle nodeRef(basicRCPNodeHandle<T>(true));
657 
658  const int v1 = 2;
659  const any a1(v1);
660  nodeRef.set_extra_data(a1, "a1", PRE_DESTROY, true);
661 
662 #ifdef TEUCHOS_DEBUG
663 
664  TEST_THROW({nodeRef.get_extra_data("wrong type", "a1");},
665  std::invalid_argument);
666 
667  TEST_THROW({nodeRef.get_extra_data(a1.typeName(), "wrong name");},
668  std::invalid_argument);
669 
670 #endif // TEUCHOS_DEBUG
671 
672  any *a2 = nodeRef.get_optional_extra_data("wrong type", "a1");
673  TEST_EQUALITY_CONST( a2, 0 );
674 
675  any *a3 = nodeRef.get_optional_extra_data(a1.typeName(), "wrong name");
676  TEST_EQUALITY_CONST( a3, 0 );
677 
678 }
679 
680 
682 {
683 
684  RCPNodeHandle nodeRef(basicRCPNodeHandle<T>(true));
685 
686  const int v1 = 2;
687  const any a1(v1);
688  nodeRef.set_extra_data(a1, "a1", PRE_DESTROY, true);
689 
690  const RCPNodeHandle nodeRef2 = nodeRef;
691 
692 #ifdef TEUCHOS_DEBUG
693 
694  TEST_THROW({nodeRef2.get_extra_data("wrong type", "a1");},
695  std::invalid_argument);
696 
697  TEST_THROW({nodeRef2.get_extra_data(a1.typeName(), "wrong name");},
698  std::invalid_argument);
699 
700 #endif // TEUCHOS_DEBUG
701 
702  const any *a2 = nodeRef2.get_optional_extra_data("wrong type", "a1");
703  TEST_EQUALITY_CONST( a2, 0 );
704 
705  const any *a3 = nodeRef2.get_optional_extra_data(a1.typeName(), "wrong name");
706  TEST_EQUALITY_CONST( a3, 0 );
707 
708 }
709 
710 
711 //
712 // Instantiations
713 //
714 
715 
716 #ifdef DO_RCPNODE_TRACING_TESTS
717 
718 # define DEBUG_UNIT_TEST_GROUP( T ) \
719  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, debugWithNodeTracingPrint, T ) \
720  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, debugWithoutNodeTracingPrint, T )
721 
722 #else
723 
724 # define DEBUG_UNIT_TEST_GROUP( T )
725 
726 #endif
727 
728 
729 #define UNIT_TEST_GROUP( T ) \
730  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, basicConstruct_owns_mem, T ) \
731  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, basicConstruct_no_owns_mem, T ) \
732  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, weakPtr_basic_1, T ) \
733  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, weakPtr_basic_2, T ) \
734  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, copyConstruct, T ) \
735  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, moveConstruct, T ) \
736  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, copyAssignmentOperator, T ) \
737  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, moveAssignmentOperator, T ) \
738  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, extraData_basic, T ) \
739  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, extraData_basic_const, T ) \
740  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, extraData_failed, T ) \
741  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, extraData_failed_const, T ) \
742  DEBUG_UNIT_TEST_GROUP(T)
743 
744 
746 //UNIT_TEST_GROUP(B1)
747 //UNIT_TEST_GROUP(B2)
749 //UNIT_TEST_GROUP(D)
751 
752 // 2008/09/22: rabartl: Above: We don't need to test with all of these classes
753 // in order to test this functionality.
754 
755 
756 } // namespace Teuchos
Dangling reference error exception class.
Null reference error exception class.
std::string typeName(const T &t)
Template function for returning the concrete type name of a passed-in object.
#define TEST_INEQUALITY_CONST(v1, v2)
Assert the inequality of v1 and constant v2.
static void printRCPNodeStatistics(const RCPNodeStatistics &rcpNodeStatistics, std::ostream &out)
Print the RCPNode allocation statistics.
static const void * getRCPNodeBaseObjMapKeyVoidPtr(T *p)
Get a const void* address to be used as the lookup key for an RCPNode given its embedded object&#39;s typ...
#define ECHO(statement)
Echo the given statement before it is executed.
static bool isTracingActiveRCPNodes()
Return if we are tracing active nodes or not.
bool same(const any &other) const
Return if two any objects are the same or not.
any & get_extra_data(const std::string &type_name, const std::string &name)
#define TEST_EQUALITY(v1, v2)
Assert the equality of v1 and v2.
#define TEST_THROW(code, ExceptType)
Assert that the statement &#39;code&#39; throws the exception &#39;ExceptType&#39; (otherwise the test fails)...
any * get_optional_extra_data(const std::string &type_name, const std::string &name)
static RCPNodeStatistics getRCPNodeStatistics()
Return the statistics on RCPNode allocations.
#define TEST_COMPARE(v1, comp, v2)
Assert that v1 comp v2 (where comp = &#39;==&#39;, &#39;&gt;=&quot;, &quot;!=", etc).
const T & getConst(T &t)
Return a constant reference to an object given a non-const reference.
#define UNIT_TEST_GROUP(T)
Modified boost::any class, which is a container for a templated value.
static std::string getCommonDebugNotesString()
Common error message string on how to debug RCPNode problems.
RCPNodeHandle basicRCPNodeHandle(const bool has_ownership, T **p_out=0)
Policy class for deallocator that uses delete to delete a pointer which is used by RCP...
TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL(RCPNodeHandle, basicConstruct_owns_mem, T)
Node class to keep track of address and the reference count for a reference-counted utility class and...
TEUCHOS_UNIT_TEST(ConstNonconstObjectContainer, create)
#define SET_RCPNODE_TRACING()
Templated implementation class of RCPNode that has the responsibility for deleting the reference-coun...
std::string concreteTypeName(const T &t)
Template function for returning the type name of the actual concrete name of a passed-in object...
void deleteRCPNode(RCPNode **node)
RCPNode * basicRCPNodeNoAlloc(T *p, const bool has_ownership)
RCPNodeHandle create_strong() const
Return a strong handle.
Unit testing support.
#define TEST_EQUALITY_CONST(v1, v2)
Assert the equality of v1 and constant v2.
void set_extra_data(const any &extra_data, const std::string &name, EPrePostDestruction destroy_when, bool force_unique)
static RCPNode * getExistingRCPNode(T *p)
Return a raw pointer to an existing owning RCPNode given the address to the underlying object if it e...
RCPNode * basicRCPNode(const bool has_ownership, T **p_out=0)
Handle class that manages the RCPNode&#39;s reference counting.
int strong_count() const
The strong count for this RCPNode, or 0 if the node is NULL.
void has_ownership(bool has_ownership_in)
static void removeRCPNode(RCPNode *rcp_node)
Remove an RCPNode from global list.
std::string typeName() const
Return the name of the type.
bool same_node(const RCPNodeHandle &node2) const
Whether the RCPNode for which node2 is a handle is the same RCPNode as this object&#39;s RCPNode...
#define TEUCHOS_ASSERT(assertion_test)
This macro is throws when an assert fails.
RCPNode * node_ptr() const
Return a pointer to the underlying RCPNode.
RCPNodeHandle create_weak() const
Return a weak handle.
Reference-counted pointer node classes.
static std::string getActiveRCPNodeHeaderString()
Header string used in printActiveRCPNodes().
Defines basic traits returning the name of a type in a portable and readable way. ...
static int numActiveRCPNodes()
Print the number of active RCPNode objects currently being tracked.
static void addNewRCPNode(RCPNode *rcp_node, const std::string &info)
Add new RCPNode to the global list.
static void printActiveRCPNodes(std::ostream &out)
Print the list of currently active RCP nodes.