Teuchos Package Browser (Single Doxygen Collection)  Version of the Day
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
#define UNIT_TEST_GROUP(T)
#define TEST_INEQUALITY_CONST(v1, v2)
Assert the inequality of v1 and constant v2.
#define TEST_EQUALITY_CONST(v1, v2)
Assert the equality of v1 and constant v2.
#define TEST_THROW(code, ExceptType)
Assert that the statement 'code' throws the exception 'ExceptType' (otherwise the test fails).
#define TEST_COMPARE(v1, comp, v2)
Assert that v1 comp v2 (where comp = '==', '>=", "!=", etc).
#define ECHO(statement)
Echo the given statement before it is executed.
Reference-counted pointer node classes.
#define SET_RCPNODE_TRACING()
Defines basic traits returning the name of a type in a portable and readable way.
Unit testing support.
Dangling reference error exception class.
Policy class for deallocator that uses delete to delete a pointer which is used by RCP.
Null reference error exception class.
Handle class that manages the RCPNode's reference counting.
RCPNode * node_ptr() const
Return a pointer to the underlying RCPNode.
RCPNodeHandle create_strong() const
Return a strong handle.
void set_extra_data(const any &extra_data, const std::string &name, EPrePostDestruction destroy_when, bool force_unique)
RCPNodeHandle create_weak() const
Return a weak handle.
any * get_optional_extra_data(const std::string &type_name, const std::string &name)
any & get_extra_data(const std::string &type_name, const std::string &name)
void has_ownership(bool has_ownership_in)
int strong_count() const
The strong count for this RCPNode, or 0 if the node is NULL.
bool same_node(const RCPNodeHandle &node2) const
Whether the RCPNode for which node2 is a handle is the same RCPNode as this object's RCPNode.
Templated implementation class of RCPNode that has the responsibility for deleting the reference-coun...
static RCPNode * getExistingRCPNode(T *p)
Return a raw pointer to an existing owning RCPNode given the address to the underlying object if it e...
static std::string getCommonDebugNotesString()
Common error message string on how to debug RCPNode problems.
static void printRCPNodeStatistics(const RCPNodeStatistics &rcpNodeStatistics, std::ostream &out)
Print the RCPNode allocation statistics.
static RCPNodeStatistics getRCPNodeStatistics()
Return the statistics on RCPNode allocations.
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's typ...
static int numActiveRCPNodes()
Print the number of active RCPNode objects currently being tracked.
static std::string getActiveRCPNodeHeaderString()
Header string used in printActiveRCPNodes().
static bool isTracingActiveRCPNodes()
Return if we are tracing active nodes or not.
static void removeRCPNode(RCPNode *rcp_node)
Remove an RCPNode from global list.
static void printActiveRCPNodes(std::ostream &out)
Print the list of currently active RCP nodes.
static void addNewRCPNode(RCPNode *rcp_node, const std::string &info)
Add new RCPNode to the global list.
Node class to keep track of address and the reference count for a reference-counted utility class and...
Modified boost::any class, which is a container for a templated value.
bool same(const any &other) const
Return if two any objects are the same or not.
std::string typeName() const
Return the name of the type.
#define TEUCHOS_ASSERT(assertion_test)
This macro is throws when an assert fails.
Definition: PackageA.cpp:3
Definition: PackageC.cpp:3
RCPNodeHandle basicRCPNodeHandle(const bool has_ownership, T **p_out=0)
std::string typeName(const T &t)
Template function for returning the concrete type name of a passed-in object.
void deleteRCPNode(RCPNode **node)
std::string concreteTypeName(const T &t)
Template function for returning the type name of the actual concrete name of a passed-in object.
RCPNode * basicRCPNodeNoAlloc(T *p, const bool has_ownership)
TEUCHOS_UNIT_TEST(ConstNonconstObjectContainer, create)
TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL(RCPNodeHandle, basicConstruct_owns_mem, T)
RCPNode * basicRCPNode(const bool has_ownership, T **p_out=0)
TEST_EQUALITY(rcp_dynamic_cast< const EnhancedNumberValidator< double > >(castedDep1->getValuesAndValidators().find("val1") ->second, true) ->getMax(), double1Vali->getMax())
const T & getConst(T &t)
Return a constant reference to an object given a non-const reference.