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 // @HEADER
2 // *****************************************************************************
3 // Teuchos: Common Tools Package
4 //
5 // Copyright 2004 NTESS and the Teuchos contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
11 #include "Teuchos_RCPNode.hpp"
12 #include "Teuchos_getConst.hpp"
14 #include "TestClasses.hpp"
15 
16 
17 namespace Teuchos {
18 
19 
20 template<class T>
21 class MockRCP {
22 public:
23  T* access_private_ptr() const
24  {
25  return (T*)(0x777777); // Just some bogus address printed to out
26  }
27 };
28 
29 
30 template<class T>
31 RCPNode* basicRCPNodeNoAlloc(T* p, const bool has_ownership)
32 {
34  new RCPNodeTmpl<T,DeallocDelete<T> >(p, DeallocDelete<T>(), has_ownership);
35  return rcpNode;
36 }
37 
38 
39 template<class T>
40 RCPNode* basicRCPNode(const bool has_ownership, T **p_out = 0)
41 {
42  T *p = new T;
43  if (p_out)
44  *p_out = p;
45  RCPNode *rcpNode = basicRCPNodeNoAlloc<T>(p, has_ownership);
46  return rcpNode;
47 }
48 
49 
50 void deleteRCPNode( RCPNode **node )
51 {
52  TEUCHOS_ASSERT(node);
53  TEUCHOS_ASSERT(*node);
54  (*node)->delete_obj();
55  delete (*node);
56  *node = 0;
57 }
58 
59 
60 template<class T>
61 RCPNodeHandle basicRCPNodeHandle(const bool has_ownership, T **p_out = 0)
62 {
63  T *p = 0;
64  RCPNode *rcpNode = basicRCPNode(has_ownership, &p);
65  if (p_out)
66  *p_out = p;
67 #ifdef TEUCHOS_DEBUG
68  return RCPNodeHandle(rcpNode, p, typeName(*p), concreteTypeName(*p), has_ownership);
69 #else
70  return RCPNodeHandle(rcpNode);
71 #endif
72 }
73 
74 
76 {
77 }
78 
79 
80 //
81 // Non-templated tests
82 //
83 
84 
86 {
87  RCPNodeHandle nodeRef;
88  nodeRef = nodeRef;
89 }
90 
91 
92 TEUCHOS_UNIT_TEST( RCPNodeHandle, defaultConstruct)
93 {
94  RCPNodeHandle nodeRef;
95  TEST_EQUALITY_CONST( nodeRef.strong_count(), 0 );
96  TEST_EQUALITY_CONST( nodeRef.has_ownership(), false );
97  nodeRef.has_ownership(true);
98  TEST_EQUALITY_CONST( nodeRef.has_ownership(), false );
99 #ifdef TEUCHOS_DEBUG
100  TEST_EQUALITY_CONST( nodeRef.get_base_obj_map_key_void_ptr(), static_cast<void*>(0) );
101  TEST_THROW({nodeRef.set_extra_data(any(),"", PRE_DESTROY, true);},
103  TEST_THROW({any &a = nodeRef.get_extra_data("int","blob"); (void)a;},
105  TEST_THROW({const any &a = getConst(nodeRef).get_extra_data("int","blob"); (void)a;},
107  TEST_THROW({any *a = nodeRef.get_optional_extra_data("int","blob"); (void)a;},
109  TEST_THROW({const any *a = getConst(nodeRef).get_optional_extra_data("int","blob"); (void)a;},
111 #endif // TEUCHOS_DEBUG
112 }
113 
114 
115 #ifdef TEUCHOS_DEBUG
116 
117 
118 TEUCHOS_UNIT_TEST( RCPNodeHandle, add_New_RCPNode_basic )
119 {
120 
121  typedef RCPNodeTracer::RCPNodeStatistics RCPNodeStatistics;
122 
124 
125  RCPNode *node = basicRCPNode<A>(true);
126 
127  const int numActiveNodesBase = RCPNodeTracer::numActiveRCPNodes();
128  const RCPNodeStatistics rcpNodeStatisticsBefore = RCPNodeTracer::getRCPNodeStatistics();
129 
130  out << std::endl;
131  ECHO(RCPNodeTracer::addNewRCPNode(node, "dummy"));
132 
133  out << std::endl;
134  TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase+1);
135 
136  out << std::endl;
137  const RCPNodeStatistics rcpNodeStatistics1 = RCPNodeTracer::getRCPNodeStatistics();
138  TEST_COMPARE(rcpNodeStatistics1.maxNumRCPNodes, >=,
139  rcpNodeStatisticsBefore.maxNumRCPNodes);
140  TEST_EQUALITY(rcpNodeStatistics1.totalNumRCPNodeAllocations,
141  rcpNodeStatisticsBefore.totalNumRCPNodeAllocations+1);
142  TEST_EQUALITY(rcpNodeStatistics1.totalNumRCPNodeDeletions,
143  rcpNodeStatisticsBefore.totalNumRCPNodeDeletions);
144 
145  out << std::endl;
147 
148  out << std::endl;
149  TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase);
150 
151  out << std::endl;
152  const RCPNodeStatistics rcpNodeStatistics2 = RCPNodeTracer::getRCPNodeStatistics();
153  TEST_COMPARE(rcpNodeStatistics2.maxNumRCPNodes, >=,
154  rcpNodeStatisticsBefore.maxNumRCPNodes);
155  TEST_EQUALITY(rcpNodeStatistics2.totalNumRCPNodeAllocations,
156  rcpNodeStatisticsBefore.totalNumRCPNodeAllocations+1);
157  TEST_EQUALITY(rcpNodeStatistics2.totalNumRCPNodeDeletions,
158  rcpNodeStatisticsBefore.totalNumRCPNodeDeletions+1);
159 
160  out << std::endl;
161  std::ostringstream statsOut_oss;
162  RCPNodeTracer::printRCPNodeStatistics(rcpNodeStatistics2, statsOut_oss);
163  std::ostringstream expectedStatsOut_oss;
164  expectedStatsOut_oss
165  << "\n***"
166  << "\n*** RCPNode Tracing statistics:"
167  << "\n**\n"
168  << "\n maxNumRCPNodes = "<<rcpNodeStatistics2.maxNumRCPNodes
169  << "\n totalNumRCPNodeAllocations = "<<rcpNodeStatistics2.totalNumRCPNodeAllocations
170  << "\n totalNumRCPNodeDeletions = "<<rcpNodeStatistics2.totalNumRCPNodeDeletions
171  << "\n";
172  TEST_EQUALITY(statsOut_oss.str(), expectedStatsOut_oss.str());
173 
174  deleteRCPNode(&node);
175 
176 }
177 
178 
179 TEUCHOS_UNIT_TEST( RCPNodeHandle, add_New_RCPNode_add_owning_twice_error )
180 {
182 #ifdef HAVE_TEUCHOS_STACKTRACE
183  // Make sure that you store a stacktrace so as not to affect the RCPNode count below!
184  Teuchos::store_stacktrace();
185 #endif
186  A *a_ptr = new A;
187  RCPNode *node1 = basicRCPNodeNoAlloc<A>(a_ptr, true);
188  const int numActiveNodesBase = RCPNodeTracer::numActiveRCPNodes();
189  ECHO(RCPNodeTracer::addNewRCPNode(node1, "dummy1"));
190  TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase+1);
191  RCPNode *node2 = basicRCPNodeNoAlloc<A>(a_ptr, true);
192  TEST_THROW(RCPNodeTracer::addNewRCPNode(node2, "dummy2"), DuplicateOwningRCPError);
194  deleteRCPNode(&node1);
195  TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase);
196  node2->has_ownership(false);
197  deleteRCPNode(&node2);
198 }
199 
200 
201 TEUCHOS_UNIT_TEST( RCPNodeHandle, add_New_RCPNode_add_nonowning_twice_okay_1 )
202 {
204  A *a_ptr = new A;
205  RCPNode *node1 = basicRCPNodeNoAlloc<A>(a_ptr, true);
206  const int numActiveNodesBase = RCPNodeTracer::numActiveRCPNodes();
207  ECHO(RCPNodeTracer::addNewRCPNode(node1, "dummy1"));
208  TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase+1);
209  RCPNode *node2 = basicRCPNodeNoAlloc<A>(a_ptr, false);
210  ECHO(RCPNodeTracer::addNewRCPNode(node2, "dummy2"));
211  TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase+2);
214  deleteRCPNode(&node2);
215  TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase+1);
217  deleteRCPNode(&node1);
218  TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase);
219 }
220 
221 
222 TEUCHOS_UNIT_TEST( RCPNodeHandle, add_New_RCPNode_add_nonowning_twice_okay_2 )
223 {
225  A *a_ptr = new A;
226  RCPNode *node1 = basicRCPNodeNoAlloc<A>(a_ptr, false);
227  const int numActiveNodesBase = RCPNodeTracer::numActiveRCPNodes();
228  ECHO(RCPNodeTracer::addNewRCPNode(node1, "dummy1"));
229  TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase+1);
230  RCPNode *node2 = basicRCPNodeNoAlloc<A>(a_ptr, true);
231  ECHO(RCPNodeTracer::addNewRCPNode(node2, "dummy2"));
232  TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase+2);
235  deleteRCPNode(&node2);
236  TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase+1);
238  deleteRCPNode(&node1);
239  TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase);
240 }
241 
242 
243 TEUCHOS_UNIT_TEST( RCPNodeHandle, add_New_RCPNode_add_two_nodes_same_obj )
244 {
246  ECHO(C *c_ptr = new C);
247  ECHO(RCPNode *node_c = basicRCPNodeNoAlloc<C>(c_ptr, true));
248  ECHO(RCPNode *node_b1 = basicRCPNodeNoAlloc<B1>(c_ptr, true));
249  ECHO(const int numActiveNodesBase = RCPNodeTracer::numActiveRCPNodes());
250  ECHO(RCPNodeTracer::addNewRCPNode(node_c, "dummy"));
251  TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase+1);
252 #ifdef HAS_TEUCHOS_GET_BASE_OBJ_VOID_PTR
253  // We can detect that these are the same object!
254  TEST_THROW(RCPNodeTracer::addNewRCPNode(node_b1, "dummy"), DuplicateOwningRCPError);
255 #else
256  // We can not detect if these are the same object!
257  ECHO(RCPNodeTracer::addNewRCPNode(node_b1, "dummy"));
258  TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase+2);
260 #endif
261  TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase+1);
263  TEST_EQUALITY(RCPNodeTracer::numActiveRCPNodes(), numActiveNodesBase);
264  ECHO(node_b1->has_ownership(false));
265  ECHO(deleteRCPNode(&node_b1));
266  ECHO(deleteRCPNode(&node_c));
267 }
268 
269 
270 #ifdef HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING
271 TEUCHOS_UNIT_TEST( RCPNodeHandle, remove_RCPNode_missing_node )
272 {
274  RCPNode *node = basicRCPNode<A>(true);
275  TEST_THROW(RCPNodeTracer::removeRCPNode(node), std::logic_error);
276  deleteRCPNode(&node);
277 }
278 #endif // HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING
279 
280 
281 #endif // TEUCHOS_DEBUG
282 
283 
284 //
285 // Templated tests
286 //
287 
288 
289 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCPNodeHandle, basicConstruct_owns_mem, T )
290 {
291  T *p = 0;
292  RCPNodeHandle nodeRef(basicRCPNodeHandle<T>(true, &p));
293  TEST_EQUALITY_CONST( nodeRef.strong_count(), 1 );
294  TEST_EQUALITY_CONST( nodeRef.has_ownership(), true );
295  nodeRef.has_ownership(false);
296  TEST_EQUALITY_CONST( nodeRef.has_ownership(), false );
297 #ifdef TEUCHOS_DEBUG
298  TEST_INEQUALITY_CONST( nodeRef.get_base_obj_map_key_void_ptr(), static_cast<void*>(0) );
299  TEST_EQUALITY( nodeRef.get_base_obj_map_key_void_ptr(), static_cast<void*>(p) );
300  TEST_THROW({any &a = nodeRef.get_extra_data("int","blob"); (void)a;},
301  std::invalid_argument);
302  TEST_THROW({const any &a = getConst(nodeRef).get_extra_data("int","blob"); (void)a;},
303  std::invalid_argument);
304 #endif // TEUCHOS_DEBUG
305  TEST_EQUALITY_CONST(nodeRef.get_optional_extra_data("int","blob"), 0);
306  TEST_EQUALITY_CONST(getConst(nodeRef).get_optional_extra_data("int","blob"), 0);
307  nodeRef.has_ownership(true);
308 }
309 
310 
311 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCPNodeHandle, basicConstruct_no_owns_mem, T )
312 {
313  RCPNodeHandle nodeRef(basicRCPNodeHandle<T>(false));
314  TEST_EQUALITY_CONST( nodeRef.strong_count(), 1 );
315  TEST_EQUALITY_CONST( nodeRef.has_ownership(), false );
316  nodeRef.has_ownership(true);
317  TEST_EQUALITY_CONST( nodeRef.has_ownership(), true );
318 }
319 
320 
322 {
323 
324  ECHO(RCPNodeHandle nodeRef1(basicRCPNodeHandle<T>(true)));
325  TEST_EQUALITY_CONST( nodeRef1.strength(), RCP_STRONG );
326 
327  ECHO(RCPNodeHandle nodeRef2 = nodeRef1.create_weak());
328 
329  TEST_EQUALITY_CONST( nodeRef2.strength(), RCP_WEAK );
330  TEST_EQUALITY_CONST( nodeRef1.strong_count(), 1 );
331  TEST_EQUALITY_CONST( nodeRef1.weak_count(), 1 );
332  TEST_EQUALITY_CONST( nodeRef2.strong_count(), 1 );
333  TEST_EQUALITY_CONST( nodeRef2.weak_count(), 1 );
334 
335  ECHO(RCPNodeHandle nodeRef3 = nodeRef2.create_strong());
336 
337  TEST_EQUALITY_CONST( nodeRef3.strength(), RCP_STRONG );
338  TEST_EQUALITY_CONST( nodeRef1.strong_count(), 2 );
339  TEST_EQUALITY_CONST( nodeRef1.weak_count(), 1 );
340  TEST_EQUALITY_CONST( nodeRef2.strong_count(), 2 );
341  TEST_EQUALITY_CONST( nodeRef2.weak_count(), 1 );
342 
343  MockRCP<T> mockRCP;
344  ECHO(nodeRef2.debug_assert_valid_ptr(mockRCP)); // Should not throw!
345 
346  // This will make the underlying object T get deleted!
347  ECHO(nodeRef1 = null);
348  ECHO(nodeRef3 = null);
349 
350  TEST_EQUALITY_CONST( nodeRef1.node_ptr()==0, true );
351  TEST_EQUALITY_CONST( nodeRef1.is_node_null(), true );
352  TEST_EQUALITY_CONST( nodeRef1.is_valid_ptr(), true );
353 
354  TEST_EQUALITY_CONST( nodeRef2.node_ptr()!=0, true );
355  TEST_EQUALITY_CONST( nodeRef2.is_node_null(), false );
356  TEST_EQUALITY_CONST( nodeRef2.is_valid_ptr(), false );
357 
358 #ifdef TEUCHOS_DEBUG
359  TEST_THROW( nodeRef2.debug_assert_valid_ptr(mockRCP),
361 #endif
362 
363  ECHO(nodeRef2 = null); // Should make the underlying node go away
364 
365 }
366 
367 
369 {
370 
371  ECHO(RCPNodeHandle nodeRef1(basicRCPNodeHandle<T>(true)));
372  TEST_EQUALITY_CONST( nodeRef1.strength(), RCP_STRONG );
373 
374  ECHO(RCPNodeHandle nodeRef2 = nodeRef1.create_weak());
375  TEST_EQUALITY_CONST( nodeRef2.strength(), RCP_WEAK );
376  TEST_EQUALITY_CONST( nodeRef1.strong_count(), 1 );
377  TEST_EQUALITY_CONST( nodeRef1.weak_count(), 1 );
378  TEST_EQUALITY_CONST( nodeRef2.strong_count(), 1 );
379  TEST_EQUALITY_CONST( nodeRef2.weak_count(), 1 );
380 
381  MockRCP<T> mockRCP;
382 
383  ECHO(nodeRef2.debug_assert_valid_ptr(mockRCP)); // Should not throw!
384 
385  ECHO(nodeRef2 = null); // The underlying object stays alive!
386 
387  TEST_EQUALITY_CONST( nodeRef2.node_ptr()==0, true );
388  TEST_EQUALITY_CONST( nodeRef2.is_node_null(), true );
389  TEST_EQUALITY_CONST( nodeRef2.is_valid_ptr(), true );
390 
391  TEST_EQUALITY_CONST( nodeRef1.node_ptr()!=0, true );
392  TEST_EQUALITY_CONST( nodeRef1.is_node_null(), false );
393  TEST_EQUALITY_CONST( nodeRef1.is_valid_ptr(), true );
394 
395  nodeRef1.debug_assert_valid_ptr(mockRCP); // Should not throw!
396 
397 }
398 
399 //
400 // Test behavior of RCP node tracing but only if it is off by default
401 //
402 // NOTE: If node tracing is on by default then we can't control how many nodes
403 // get created in other code not in the unit test.
404 //
405 
406 #if defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING)
407 # define DO_RCPNODE_TRACING_TESTS 1
408 #endif
409 
410 
411 #ifdef DO_RCPNODE_TRACING_TESTS
412 
413 
414 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCPNodeHandle, debugWithNodeTracingPrint, T )
415 {
416 
418  RCPNodeTracer::setTracingActiveRCPNodes(true);
420 
421  {
422 
423  T *p = new T; // Never do this in production code!
424  const std::string T_name = "T_name";
425  const std::string concreateT_name = "concreateT_name";
426  const bool has_ownership = true;
427  RCPNode *node = new RCPNodeTmpl<T,DeallocDelete<T> >(
428  p, DeallocDelete<T>(), has_ownership);
429 
430  RCPNodeHandle nodeRef(node, p, T_name, concreateT_name, has_ownership);
431 
433 
434  out << "\nMake sure output is printed when there is an active node with tracing ...\n";
435 
436  const void* rcpNodeKey = RCPNodeTracer::getRCPNodeBaseObjMapKeyVoidPtr(p);
437 
438  std::ostringstream expendedOutput_oss;
439  expendedOutput_oss
441  << "\n"
442  << " 0: RCPNode (map_key_void_ptr=" << rcpNodeKey << ")\n"
443  << " Information = {T="<<T_name<<", ConcreteT="<<concreateT_name<<", p="<<p<<", has_ownership="<<has_ownership<<"}\n"
444  << " RCPNode address = " << node << "\n"
445  << " insertionNumber = " << node->insertion_number()
446  << "\n\n"
448 
449  std::ostringstream printActiveRCPNodes_out;
450  RCPNodeTracer::printActiveRCPNodes(printActiveRCPNodes_out);
451  TEST_EQUALITY( printActiveRCPNodes_out.str(), expendedOutput_oss.str() );
452 
453  // NOTE: The above test basically copied and pasted the ouptut stream code
454  // from printActiveRCPNodes(...) and will need to be maintained
455  // with this code. However, this is a good test because it ensures that
456  // the arguments node, p, T_name, and concreateT_name are passed, stored,
457  // and retrieved correctly. It is also a good test because it ensures
458  // that output is printed when node tracing is turned on.
459  //
460  // This is the very definition of a "white box" test but that is just fine
461  // for a unit test.
462 
463  }
464 
466 
467  out << "\nMake sure no output is printed when there are no active nodes ...\n";
468  const std::string expendedOutput = "";
469  std::ostringstream printActiveRCPNodes_out;
470  RCPNodeTracer::printActiveRCPNodes(printActiveRCPNodes_out);
471  TEST_EQUALITY( printActiveRCPNodes_out.str(), expendedOutput );
472 
473  RCPNodeTracer::setTracingActiveRCPNodes(false);
475 
476 }
477 
478 
479 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCPNodeHandle, debugWithoutNodeTracingPrint, T )
480 {
481 
483  RCPNodeTracer::setTracingActiveRCPNodes(false);
485 
486  T *p = new T; // Never do this in production code!
487  const std::string T_name = "T_name";
488  const std::string concreateT_name = "concreateT_name";
489  const bool has_ownership = true;
490  RCPNode *node = new RCPNodeTmpl<T,DeallocDelete<T> >(
491  p, DeallocDelete<T>(), has_ownership);
492 
493  RCPNodeHandle nodeRef(node, p, T_name, concreateT_name, has_ownership);
494 
496 
497  out << "\nMake sure no output is printed when there are no active nodes without tracing ...\n";
498  const std::string expendedOutput = "";
499  std::ostringstream printActiveRCPNodes_out;
500  RCPNodeTracer::printActiveRCPNodes(printActiveRCPNodes_out);
501  TEST_EQUALITY( printActiveRCPNodes_out.str(), expendedOutput );
502 
503 }
504 
505 
506 #endif // DO_RCPNODE_TRACING_TESTS
507 
508 
510 {
511  RCPNodeHandle nodeRef1(basicRCPNodeHandle<T>(true));
512  RCPNodeHandle nodeRef2(nodeRef1);
513  TEST_EQUALITY( nodeRef1.node_ptr(), nodeRef2.node_ptr() );
514  TEST_EQUALITY_CONST( nodeRef1.same_node(nodeRef2), true );
515  TEST_EQUALITY_CONST( nodeRef1.strong_count(), 2 );
516  TEST_EQUALITY_CONST( nodeRef2.strong_count(), 2 );
517  TEST_EQUALITY_CONST( nodeRef1.has_ownership(), true );
518  TEST_EQUALITY_CONST( nodeRef2.has_ownership(), true );
519 }
520 
521 
523 {
524  RCPNodeHandle nodeRef1(basicRCPNodeHandle<T>(true));
525  RCPNodeHandle nodeRef2(std::move(nodeRef1));
526  TEST_EQUALITY_CONST( nodeRef1.node_ptr(), 0 );
527  TEST_INEQUALITY_CONST( nodeRef2.node_ptr(), 0 );
528  TEST_EQUALITY_CONST( nodeRef1.same_node(nodeRef2), false );
529  TEST_EQUALITY_CONST( nodeRef1.strong_count(), 0 );
530  TEST_EQUALITY_CONST( nodeRef2.strong_count(), 1 );
531  TEST_EQUALITY_CONST( nodeRef1.has_ownership(), false );
532  TEST_EQUALITY_CONST( nodeRef2.has_ownership(), true );
533 }
534 
535 
537 {
538  RCPNodeHandle nodeRef1(basicRCPNodeHandle<T>(true));
539  RCPNodeHandle nodeRef2;
540  nodeRef2 = nodeRef1;
541  TEST_EQUALITY_CONST( nodeRef1.strong_count(), 2 );
542  TEST_EQUALITY_CONST( nodeRef2.strong_count(), 2 );
543  TEST_EQUALITY_CONST( nodeRef1.has_ownership(), true );
544  TEST_EQUALITY_CONST( nodeRef2.has_ownership(), true );
545 }
546 
547 
549 {
550  RCPNodeHandle nodeRef1(basicRCPNodeHandle<T>(true));
551  RCPNodeHandle nodeRef2;
552  nodeRef2 = std::move(nodeRef1);
553  TEST_EQUALITY_CONST( nodeRef1.node_ptr(), 0 );
554  TEST_INEQUALITY_CONST( nodeRef2.node_ptr(), 0 );
555  TEST_EQUALITY_CONST( nodeRef1.same_node(nodeRef2), false );
556  TEST_EQUALITY_CONST( nodeRef1.strong_count(), 0 );
557  TEST_EQUALITY_CONST( nodeRef2.strong_count(), 1 );
558  TEST_EQUALITY_CONST( nodeRef1.has_ownership(), false );
559  TEST_EQUALITY_CONST( nodeRef2.has_ownership(), true );
560 }
561 
562 
564 {
565 
566  RCPNodeHandle nodeRef(basicRCPNodeHandle<T>(true));
567 
568  const int v1 = 2;
569  const any a1(v1);
570  nodeRef.set_extra_data(a1, "a1", PRE_DESTROY, true);
571 
572  any &a2 = nodeRef.get_extra_data(a1.typeName(), "a1");
573  TEST_EQUALITY_CONST( a1.same(a2), true );
574  TEST_EQUALITY( any_cast<int>(a2), v1 );
575 
576  any *a3 = nodeRef.get_optional_extra_data(a1.typeName(), "a1");
577  TEST_EQUALITY_CONST( a3!=0, true );
578  TEST_EQUALITY( &a2, a3 );
579  TEST_EQUALITY_CONST( a3->same(a1), true );
580 
581  RCPNodeHandle nodeRef2 = nodeRef;
582 
583  const int v2 = 3;
584  a2 = v2;
585  TEST_EQUALITY( any_cast<int>(a1), v1 );
586  TEST_EQUALITY( any_cast<int>(*a3), v2 );
587 
588  any &a4 = nodeRef2.get_extra_data(a1.typeName(), "a1");
589  TEST_EQUALITY( &a4, &a2 );
590  TEST_EQUALITY( &a4, a3 );
591  TEST_EQUALITY( any_cast<int>(a4), v2 );
592 
593 }
594 
595 
597 {
598 
599  RCPNodeHandle nodeRef(basicRCPNodeHandle<T>(true));
600 
601  const int v1 = 2;
602  const any a1(v1);
603  nodeRef.set_extra_data(a1, "a1", PRE_DESTROY, true);
604 
605  const RCPNodeHandle nodeRef2 = nodeRef;
606 
607  const any &a2 = nodeRef2.get_extra_data(a1.typeName(), "a1");
608  TEST_EQUALITY_CONST( a1.same(a2), true );
609  TEST_EQUALITY( any_cast<int>(a2), v1 );
610 
611  const any *a3 = nodeRef2.get_optional_extra_data(a1.typeName(), "a1");
612  TEST_EQUALITY_CONST( a3!=0, true );
613  TEST_EQUALITY( &a2, a3 );
614  TEST_EQUALITY_CONST( a3->same(a1), true );
615 
616 }
617 
618 
620 {
621 
622  RCPNodeHandle nodeRef(basicRCPNodeHandle<T>(true));
623 
624  const int v1 = 2;
625  const any a1(v1);
626  nodeRef.set_extra_data(a1, "a1", PRE_DESTROY, true);
627 
628 #ifdef TEUCHOS_DEBUG
629 
630  TEST_THROW({nodeRef.get_extra_data("wrong type", "a1");},
631  std::invalid_argument);
632 
633  TEST_THROW({nodeRef.get_extra_data(a1.typeName(), "wrong name");},
634  std::invalid_argument);
635 
636 #endif // TEUCHOS_DEBUG
637 
638  any *a2 = nodeRef.get_optional_extra_data("wrong type", "a1");
639  TEST_EQUALITY_CONST( a2, 0 );
640 
641  any *a3 = nodeRef.get_optional_extra_data(a1.typeName(), "wrong name");
642  TEST_EQUALITY_CONST( a3, 0 );
643 
644 }
645 
646 
648 {
649 
650  RCPNodeHandle nodeRef(basicRCPNodeHandle<T>(true));
651 
652  const int v1 = 2;
653  const any a1(v1);
654  nodeRef.set_extra_data(a1, "a1", PRE_DESTROY, true);
655 
656  const RCPNodeHandle nodeRef2 = nodeRef;
657 
658 #ifdef TEUCHOS_DEBUG
659 
660  TEST_THROW({nodeRef2.get_extra_data("wrong type", "a1");},
661  std::invalid_argument);
662 
663  TEST_THROW({nodeRef2.get_extra_data(a1.typeName(), "wrong name");},
664  std::invalid_argument);
665 
666 #endif // TEUCHOS_DEBUG
667 
668  const any *a2 = nodeRef2.get_optional_extra_data("wrong type", "a1");
669  TEST_EQUALITY_CONST( a2, 0 );
670 
671  const any *a3 = nodeRef2.get_optional_extra_data(a1.typeName(), "wrong name");
672  TEST_EQUALITY_CONST( a3, 0 );
673 
674 }
675 
676 
677 //
678 // Instantiations
679 //
680 
681 
682 #ifdef DO_RCPNODE_TRACING_TESTS
683 
684 # define DEBUG_UNIT_TEST_GROUP( T ) \
685  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, debugWithNodeTracingPrint, T ) \
686  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, debugWithoutNodeTracingPrint, T )
687 
688 #else
689 
690 # define DEBUG_UNIT_TEST_GROUP( T )
691 
692 #endif
693 
694 
695 #define UNIT_TEST_GROUP( T ) \
696  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, basicConstruct_owns_mem, T ) \
697  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, basicConstruct_no_owns_mem, T ) \
698  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, weakPtr_basic_1, T ) \
699  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, weakPtr_basic_2, T ) \
700  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, copyConstruct, T ) \
701  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, moveConstruct, T ) \
702  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, copyAssignmentOperator, T ) \
703  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, moveAssignmentOperator, T ) \
704  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, extraData_basic, T ) \
705  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, extraData_basic_const, T ) \
706  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, extraData_failed, T ) \
707  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCPNodeHandle, extraData_failed_const, T ) \
708  DEBUG_UNIT_TEST_GROUP(T)
709 
710 
712 //UNIT_TEST_GROUP(B1)
713 //UNIT_TEST_GROUP(B2)
715 //UNIT_TEST_GROUP(D)
717 
718 // 2008/09/22: rabartl: Above: We don't need to test with all of these classes
719 // in order to test this functionality.
720 
721 
722 } // 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.