Teuchos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RCP_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_RCP.hpp"
12 #include "Teuchos_getConst.hpp"
14 #ifdef HAVE_TEUCHOS_BOOST
16 #endif
17 #ifdef HAVE_TEUCHOSCORE_CXX11
19 #endif
20 
21 #include "TestClasses.hpp"
22 
24 
25 
26 namespace {
27 
28 
29 using Teuchos::as;
30 using Teuchos::null;
31 using Teuchos::Ptr;
32 using Teuchos::RCP;
33 using Teuchos::rcp;
34 using Teuchos::rcpFromRef;
35 using Teuchos::rcpFromUndefRef;
36 using Teuchos::outArg;
37 using Teuchos::rcpWithEmbeddedObj;
38 using Teuchos::getEmbeddedObj;
39 using Teuchos::getOptionalEmbeddedObj;
40 using Teuchos::getOptionalNonconstEmbeddedObj;
41 using Teuchos::set_extra_data;
42 using Teuchos::get_optional_nonconst_extra_data;
43 using Teuchos::getConst;
48 using Teuchos::RCP_WEAK;
50 
51 
52 TEUCHOS_UNIT_TEST( DeallocNull, free )
53 {
55  d.free(0);
56 }
57 
58 
59 TEUCHOS_UNIT_TEST( RCP, construct_default )
60 {
61  RCP<A> a_rcp;
62  TEST_EQUALITY_CONST(a_rcp.get(), 0);
63  TEST_EQUALITY_CONST(a_rcp.getRawPtr(), 0);
64  TEST_EQUALITY_CONST(a_rcp.strength(), RCP_STRONG);
65  TEST_EQUALITY_CONST(a_rcp.strong_count(), 0);
66  TEST_EQUALITY_CONST(a_rcp.weak_count(), 0);
67  TEST_EQUALITY_CONST(a_rcp.has_ownership(), false);
68 }
69 
70 
71 TEUCHOS_UNIT_TEST( RCP, construct_nonull )
72 {
73  RCP<A> a_rcp(new A);
74  TEST_INEQUALITY_CONST(a_rcp.get(), 0);
75  TEST_INEQUALITY_CONST(a_rcp.getRawPtr(), 0);
76  TEST_EQUALITY_CONST(a_rcp.strength(), RCP_STRONG);
77  TEST_EQUALITY_CONST(a_rcp.strong_count(), 1);
78  TEST_EQUALITY_CONST(a_rcp.weak_count(), 0);
79  TEST_EQUALITY_CONST(a_rcp.has_ownership(), true);
80 }
81 
82 
83 TEUCHOS_UNIT_TEST( RCP, copy_construct_null )
84 {
85  RCP<A> a_rcp;
86  RCP<A> b_rcp(a_rcp);
87  TEST_EQUALITY_CONST(a_rcp.get(), 0);
88  TEST_EQUALITY_CONST(a_rcp.getRawPtr(), 0);
89  TEST_EQUALITY_CONST(a_rcp.strength(), RCP_STRONG);
90  TEST_EQUALITY_CONST(a_rcp.strong_count(), 0);
91  TEST_EQUALITY_CONST(a_rcp.weak_count(), 0);
92  TEST_EQUALITY_CONST(a_rcp.has_ownership(), false);
93  TEST_EQUALITY_CONST(b_rcp.get(), 0);
94  TEST_EQUALITY_CONST(b_rcp.getRawPtr(), 0);
95  TEST_EQUALITY_CONST(b_rcp.strength(), RCP_STRONG);
96  TEST_EQUALITY_CONST(b_rcp.strong_count(), 0);
97  TEST_EQUALITY_CONST(b_rcp.weak_count(), 0);
98  TEST_EQUALITY_CONST(b_rcp.has_ownership(), false);
99 }
100 
101 
102 TEUCHOS_UNIT_TEST( RCP, copy_construct_nonnull )
103 {
104  RCP<A> a_rcp(new A);
105  RCP<A> b_rcp(a_rcp);
106  TEST_EQUALITY(b_rcp.get(), a_rcp.get());
107  TEST_EQUALITY(b_rcp.getRawPtr(), a_rcp.getRawPtr());
108  TEST_EQUALITY_CONST(a_rcp.strength(), RCP_STRONG);
109  TEST_EQUALITY_CONST(b_rcp.strength(), RCP_STRONG);
110  TEST_EQUALITY_CONST(a_rcp.strong_count(), 2);
111  TEST_EQUALITY_CONST(b_rcp.strong_count(), 2);
112  TEST_EQUALITY_CONST(a_rcp.weak_count(), 0);
113  TEST_EQUALITY_CONST(b_rcp.weak_count(), 0);
114  TEST_EQUALITY_CONST(a_rcp.has_ownership(), true);
115  TEST_EQUALITY_CONST(b_rcp.has_ownership(), true);
116 }
117 
118 
119 TEUCHOS_UNIT_TEST( RCP, move_construct_nonnull )
120 {
121  RCP<A> a_rcp(new A);
122  RCP<A> b_rcp(std::move(a_rcp));
123  TEST_EQUALITY_CONST(a_rcp.get(), 0);
124  TEST_EQUALITY_CONST(a_rcp.getRawPtr(), 0);
125  TEST_EQUALITY_CONST(a_rcp.strength(), RCP_STRONG);
126  TEST_EQUALITY_CONST(a_rcp.strong_count(), 0);
127  TEST_EQUALITY_CONST(a_rcp.weak_count(), 0);
128  TEST_EQUALITY_CONST(a_rcp.has_ownership(), false);
129  TEST_INEQUALITY_CONST(b_rcp.get(), 0);
130  TEST_INEQUALITY_CONST(b_rcp.getRawPtr(), 0);
131  TEST_EQUALITY_CONST(b_rcp.strength(), RCP_STRONG);
132  TEST_EQUALITY_CONST(b_rcp.strong_count(), 1);
133  TEST_EQUALITY_CONST(b_rcp.weak_count(), 0);
134  TEST_EQUALITY_CONST(b_rcp.has_ownership(), true);
135 }
136 
137 
138 TEUCHOS_UNIT_TEST( RCP, assign_self_null )
139 {
140  RCP<A> a_rcp;
141  a_rcp = a_rcp;
142  TEST_ASSERT(is_null(a_rcp));
143 }
144 
145 
146 TEUCHOS_UNIT_TEST( RCP, copy_assign_self_nonnull )
147 {
148  RCP<A> a_rcp(new A);
149  A *a_raw_ptr = a_rcp.getRawPtr();
150  a_rcp = a_rcp;
151  TEST_ASSERT(nonnull(a_rcp));
152  TEST_EQUALITY(a_rcp.getRawPtr(), a_raw_ptr);
153 }
154 
155 
156 TEUCHOS_UNIT_TEST( RCP, copy_assign_nonnull )
157 {
158  RCP<A> a_rcp(new A);
159  RCP<A> b_rcp;
160  b_rcp = a_rcp;
161  TEST_EQUALITY(b_rcp.get(), a_rcp.get());
162  TEST_EQUALITY(b_rcp.getRawPtr(), a_rcp.getRawPtr());
163  TEST_EQUALITY_CONST(a_rcp.strength(), RCP_STRONG);
164  TEST_EQUALITY_CONST(b_rcp.strength(), RCP_STRONG);
165  TEST_EQUALITY_CONST(a_rcp.strong_count(), 2);
166  TEST_EQUALITY_CONST(b_rcp.strong_count(), 2);
167  TEST_EQUALITY_CONST(a_rcp.weak_count(), 0);
168  TEST_EQUALITY_CONST(b_rcp.weak_count(), 0);
169  TEST_EQUALITY_CONST(a_rcp.has_ownership(), true);
170  TEST_EQUALITY_CONST(b_rcp.has_ownership(), true);
171 }
172 
173 
174 TEUCHOS_UNIT_TEST( RCP, move_assign_nonnull )
175 {
176  RCP<A> a_rcp(new A);
177  RCP<A> b_rcp;
178  b_rcp = std::move(a_rcp);
179  TEST_EQUALITY_CONST(a_rcp.get(), 0);
180  TEST_EQUALITY_CONST(a_rcp.getRawPtr(), 0);
181  TEST_EQUALITY_CONST(a_rcp.strength(), RCP_STRONG);
182  TEST_EQUALITY_CONST(a_rcp.strong_count(), 0);
183  TEST_EQUALITY_CONST(a_rcp.weak_count(), 0);
184  TEST_EQUALITY_CONST(a_rcp.has_ownership(), false);
185  TEST_INEQUALITY_CONST(b_rcp.get(), 0);
186  TEST_INEQUALITY_CONST(b_rcp.getRawPtr(), 0);
187  TEST_EQUALITY_CONST(b_rcp.strength(), RCP_STRONG);
188  TEST_EQUALITY_CONST(b_rcp.strong_count(), 1);
189  TEST_EQUALITY_CONST(b_rcp.weak_count(), 0);
190  TEST_EQUALITY_CONST(b_rcp.has_ownership(), true);
191 }
192 
193 
194 TEUCHOS_UNIT_TEST( RCP, operator_bool_null )
195 {
196  RCP<A> a_rcp;
197  TEST_EQUALITY_CONST(bool(a_rcp), false);
198 }
199 
200 
201 TEUCHOS_UNIT_TEST( RCP, operator_bool_nonnull )
202 {
203  RCP<A> a_rcp(new A);
204  TEST_EQUALITY_CONST(bool(a_rcp), true);
205 }
206 
207 
208 TEUCHOS_UNIT_TEST( RCP, operator_bool_if )
209 {
210  RCP<A> a_rcp(new A);
211  RCP<A> b_rcp;
212  bool a_is_null;
213  bool b_is_null;
214 
215  if (a_rcp)
216  a_is_null = false;
217  else
218  a_is_null = true;
219  if (b_rcp)
220  b_is_null = false;
221  else
222  b_is_null = true;
223 
224  TEST_EQUALITY_CONST(a_is_null, false);
225  TEST_EQUALITY_CONST(b_is_null, true );
226 }
227 
228 
230 {
231  RCP<A> a_rcp(new A);
232  RCP<const A> ca_rcp = a_rcp.getConst();
233  TEST_EQUALITY(a_rcp.getRawPtr(), ca_rcp.getRawPtr());
234 }
235 
236 
237 TEUCHOS_UNIT_TEST( RCP, explicit_null )
238 {
239  RCP<A> a_rcp(0);
240  TEST_ASSERT(is_null(a_rcp));
241 }
242 
243 
244 TEUCHOS_UNIT_TEST( RCP, explicit_dealloc_null )
245 {
246  RCP<A> a_rcp = rcpWithDealloc(static_cast<A*>(0), Teuchos::DeallocNull<A>(), false);
247  TEST_ASSERT(is_null(a_rcp));
248 }
249 
250 
251 TEUCHOS_UNIT_TEST( RCP, explicit_null_null )
252 {
253  RCP<A> a_rcp(0, null);
254  TEST_ASSERT(is_null(a_rcp));
255 }
256 
257 
258 TEUCHOS_UNIT_TEST( RCP, explicit_null_nonnull )
259 {
260  A *a = new A;
261  RCP<A> a_rcp(a, null);
262  TEST_ASSERT(nonnull(a_rcp));
263  delete a;
264 }
265 
266 
267 TEUCHOS_UNIT_TEST( RCP, rcpFromRef_raw_ref )
268 {
269  A a;
270  RCP<A> a_rcp = rcpFromRef(a);
271  TEST_EQUALITY(a_rcp.getRawPtr(), &a);
272  TEST_ASSERT(nonnull(a_rcp));
273 }
274 
275 
276 TEUCHOS_UNIT_TEST( RCP, rcpFromRef_from_rcp )
277 {
278  RCP<A> a_rcp1 = rcp<A>(new A);
279  RCP<A> a_rcp2 = rcpFromRef(*a_rcp1);
280  TEST_EQUALITY(a_rcp2.getRawPtr(), a_rcp1.getRawPtr());
281  if (RCPNodeTracer::isTracingActiveRCPNodes())
282  {
283  TEST_EQUALITY_CONST(a_rcp2.strong_count(), 1);
284  TEST_EQUALITY_CONST(a_rcp2.weak_count(), 1);
285  TEST_EQUALITY_CONST(a_rcp2.has_ownership(), true);
286  }
287  else {
288  TEST_EQUALITY_CONST(a_rcp2.strong_count(), 1);
289  TEST_EQUALITY_CONST(a_rcp2.weak_count(), 0);
290  TEST_EQUALITY_CONST(a_rcp2.has_ownership(), false);
291  }
292 }
293 
294 
296 {
297  A a;
298  RCP<A> a_rcp = rcpFromUndefRef(a);
299  TEST_ASSERT(nonnull(a_rcp));
300 }
301 
305 TEUCHOS_UNIT_TEST( RCP, make_rcp_no_constructor_arg )
306 {
307  Teuchos::RCP<A> a_rcp = Teuchos::make_rcp<A>();
309 }
310 
315 {
316  Teuchos::RCP<A> a_rcp = Teuchos::make_rcp<A>(1,2);
318  TEST_EQUALITY(a_rcp->A_g(),1);
319  TEST_EQUALITY(a_rcp->A_f(),2);
320 }
321 
322 
323 //
324 // Test rcpCloneNode(...)
325 //
326 
327 
328 TEUCHOS_UNIT_TEST( RCP, rcpCloneNode_null )
329 {
330  ECHO(RCP<RCP<int> > rcp1 = null);
331  ECHO(RCP<RCP<int> > rcp2 = rcpCloneNode(rcp1));
332  TEST_EQUALITY(rcp2, null);
333 }
334 
335 
336 TEUCHOS_UNIT_TEST( RCP, rcpCloneNode_basic )
337 {
338 
339  ECHO(RCP<int> rcp1 = rcp(new int(0)));
340 
341  ECHO(RCP<int> rcp2 = rcpCloneNode(rcp1));
342  TEST_ASSERT(nonnull(rcp2));
343  TEST_EQUALITY(rcp1.strong_count(), 2);
344  TEST_EQUALITY(rcp2.strong_count(), 1);
345 
346  ECHO(RCP<int> rcp3 = rcp2);
347  TEST_EQUALITY(rcp1.strong_count(), 2);
348  TEST_EQUALITY(rcp2.strong_count(), 2);
349  TEST_EQUALITY(rcp3.strong_count(), 2);
350 
351  ECHO(RCP <int> rcp4 = rcp1);
352  TEST_EQUALITY(rcp1.strong_count(), 3);
353  TEST_EQUALITY(rcp2.strong_count(), 2);
354  TEST_EQUALITY(rcp3.strong_count(), 2);
355 
356  ECHO(rcp4 = null);
357  TEST_EQUALITY(rcp1.strong_count(), 2);
358  TEST_EQUALITY(rcp2.strong_count(), 2);
359  TEST_EQUALITY(rcp3.strong_count(), 2);
360  TEST_EQUALITY(rcp4.strong_count(), 0);
361 
362  ECHO(rcp1 = null);
363  TEST_EQUALITY(rcp1.strong_count(), 0);
364  TEST_EQUALITY(rcp2.strong_count(), 2);
365  TEST_EQUALITY(rcp3.strong_count(), 2);
366  TEST_EQUALITY(rcp4.strong_count(), 0);
367 
368  ECHO(rcp2 = null);
369  TEST_EQUALITY(rcp2.strong_count(), 0);
370  TEST_EQUALITY(rcp3.strong_count(), 1);
371 
372  ECHO(rcp3 = null);
373  TEST_EQUALITY(rcp3.strong_count(), 0);
374 
375 }
376 
377 
378 //
379 // Test duplicate owning RCP objects
380 //
381 
382 
383 // Test that shows that we can detect trying to create two owning RCPs
384 // pointing to the same polymorphic object but having different interfaces
385 // with different addresses. This happens due to virtual base classes. Only
386 // works when we have a working getBaseObjVoidPtr(...) function.
387 TEUCHOS_UNIT_TEST( RCP, duplicate_rcp_owning_polymorphic )
388 {
390  ECHO(C *c_ptr = new C);
391  ECHO(A *a_ptr = c_ptr);
392  ECHO(RCP<C> c_rcp = rcp(c_ptr)); // Okay
393 #if defined(TEUCHOS_DEBUG) && defined(HAS_TEUCHOS_GET_BASE_OBJ_VOID_PTR)
394  // With determine they are pointed to the same object!
395  TEST_THROW(RCP<A> a_rcp = rcp(a_ptr), DuplicateOwningRCPError);
396 #else
397  // Will not determine they are point to the same object!
398  ECHO(RCP<A> a_rcp = rcp(a_ptr));
399  TEST_EQUALITY(a_rcp.getRawPtr(), a_ptr);
400  ECHO(a_rcp.release()); // Better or we will get a segfault!
401 #endif
402 }
403 
404 
405 // Test that shows that we can detect trying to create two owning RCPs
406 // pointing to the same polymorphic object with the same type and therefore
407 // the same address. This works even if these use virtual base classes. This
408 // works even without a working getBaseObjVoidPtr(...) function.
409 TEUCHOS_UNIT_TEST( RCP, duplicate_rcp_owning_polymorphic_different_addr )
410 {
412  ECHO(A *a_ptr1 = new C);
413  ECHO(A *a_ptr2 = a_ptr1);
414  ECHO(RCP<A> a_rcp1 = rcp(a_ptr1)); // Okay
415 #if defined(TEUCHOS_DEBUG)
416  // With determine they are pointed to the same object!
417  TEST_THROW(RCP<A> a_rcp2 = rcp(a_ptr2), DuplicateOwningRCPError);
418 #else
419  // Will not determine they are point to the same object!
420  ECHO(RCP<A> a_rcp2 = rcp(a_ptr2));
421  TEST_EQUALITY(a_rcp2.getRawPtr(), a_ptr2);
422  ECHO(a_rcp2.release()); // Better or we will get a segfault!
423 #endif
424 }
425 
426 
427 // Test that shows that we can always detect trying to create two owning RCPs
428 // pointing to the same nonpolymorphic object having different interfaces but
429 // the same address (single non-virtual inheritance). Works just fine without
430 // a working getBaseObjVoidPtr(...) function.
431 TEUCHOS_UNIT_TEST( RCP, duplicate_rcp_owning_nonpolymorphic_same_addr )
432 {
434  ECHO(E *e_ptr = new E);
435  ECHO(E *d_ptr = e_ptr);
436  ECHO(RCP<E> e_rcp = rcp(e_ptr)); // Okay
437 #if defined(TEUCHOS_DEBUG)
438  // With determine they are pointed to the same object even without support
439  // for getBaseObjVoidPtr(...) because no dynamic_cast is needed.
440  TEST_THROW(RCP<D> d_rcp = rcp(d_ptr), DuplicateOwningRCPError);
441 #else
442  // Will not determine they are point to the same object!
443  ECHO(RCP<D> d_rcp = rcp(d_ptr));
444  TEST_EQUALITY(d_rcp.getRawPtr(), d_ptr);
445  ECHO(d_rcp.release()); // Better or we will get a segfault!
446 #endif
447 }
448 
449 
450 //
451 // These next tests shows that we can detect when two RCPs are create to the same
452 // object, one owning and the other non-owning. When we have a working
453 // getBaseObjVoidPtr(...) function, the new non-owning RCP will actually be a
454 // weak RCP that can be used to detect circular dependencies.
455 //
456 
457 
458 // rcp
459 
460 
461 TEUCHOS_UNIT_TEST( RCP, rcp_duplicate_rcp_nonowning_polymorphic_different_addr )
462 {
464  ECHO(RCP<C> c_rcp(new C));
465  ECHO(A &a_ref = *c_rcp);
466  ECHO(RCP<A> a_rcp = rcp(&a_ref, false));
467  ECHO(c_rcp = null);
468 #if defined(TEUCHOS_DEBUG) && defined(HAS_TEUCHOS_GET_BASE_OBJ_VOID_PTR)
469  TEST_THROW(a_rcp->A_g(), DanglingReferenceError);
470 #else
471  TEST_NOTHROW(a_rcp.getRawPtr());
472 #endif
473 }
474 
475 
476 TEUCHOS_UNIT_TEST( RCP, rcp_duplicate_rcp_nonowning_polymorphic_same_addr )
477 {
479  ECHO(RCP<A> a_rcp1(new C));
480  ECHO(A &a_ref = *a_rcp1);
481  ECHO(RCP<A> a_rcp2 = rcp(&a_ref, false));
482  ECHO(a_rcp1 = null);
483 #if defined(TEUCHOS_DEBUG)
484  TEST_THROW(a_rcp2->A_g(), DanglingReferenceError);
485 #else
486  TEST_NOTHROW(a_rcp2.getRawPtr());
487 #endif
488 }
489 
490 
491 TEUCHOS_UNIT_TEST( RCP, rcp_duplicate_rcp_nonowning_nonpolymorphic )
492 {
494  ECHO(RCP<E> e_rcp(new E));
495  ECHO(D &d_ref = *e_rcp);
496  ECHO(RCP<D> d_rcp = rcp(&d_ref, false));
497  ECHO(e_rcp = null);
498 #if defined(TEUCHOS_DEBUG)
499  TEST_THROW(d_rcp->D_g(), DanglingReferenceError);
500 #else
501  TEST_NOTHROW(d_rcp.getRawPtr());
502 #endif
503 }
504 
505 
506 // rcpFromRef
507 
508 
509 TEUCHOS_UNIT_TEST( RCP, rcpFromRef_duplicate_rcp_nonowning_polymorphic_different_addr )
510 {
512  ECHO(RCP<C> c_rcp(new C));
513  ECHO(A &a_ref = *c_rcp);
514  ECHO(RCP<A> a_rcp = rcpFromRef(a_ref));
515  ECHO(c_rcp = null);
516 #if defined(TEUCHOS_DEBUG) && defined(HAS_TEUCHOS_GET_BASE_OBJ_VOID_PTR)
517  TEST_THROW(a_rcp->A_g(), DanglingReferenceError);
518 #else
519  TEST_NOTHROW(a_rcp.getRawPtr());
520 #endif
521 }
522 
523 
524 TEUCHOS_UNIT_TEST( RCP, rcpFromRef_duplicate_rcp_nonowning_polymorphic_same_addr )
525 {
527  ECHO(RCP<A> a_rcp1(new C));
528  ECHO(A &a_ref = *a_rcp1);
529  ECHO(RCP<A> a_rcp2 = rcpFromRef(a_ref));
530  ECHO(a_rcp1 = null);
531 #if defined(TEUCHOS_DEBUG)
532  TEST_THROW(a_rcp2->A_g(), DanglingReferenceError);
533 #else
534  TEST_NOTHROW(a_rcp2.getRawPtr());
535 #endif
536 }
537 
538 
539 TEUCHOS_UNIT_TEST( RCP, rcpFromRef_duplicate_rcp_nonowning_nonpolymorphic )
540 {
542  ECHO(RCP<E> e_rcp(new E));
543  ECHO(D &d_ref = *e_rcp);
544  ECHO(RCP<D> d_rcp = rcpFromRef(d_ref));
545  ECHO(e_rcp = null);
546 #if defined(TEUCHOS_DEBUG)
547  TEST_THROW(d_rcp->D_g(), DanglingReferenceError);
548 #else
549  TEST_NOTHROW(d_rcp.getRawPtr());
550 #endif
551 }
552 
553 
554 // rcpFromUndefRef (Can never detect dangling references)
555 
556 
557 TEUCHOS_UNIT_TEST( RCP, rcpFromUndefRef_duplicate_rcp_nonowning_polymorphic_same_addr )
558 {
560  ECHO(RCP<A> a_rcp1(new C));
561  ECHO(A &a_ref = *a_rcp1);
562  ECHO(RCP<A> a_rcp2 = rcpFromUndefRef(a_ref));
563  ECHO(a_rcp1 = null);
564  TEST_NOTHROW(a_rcp2.getRawPtr());
565 }
566 
567 
568 //
569 // extra data and embedded objects tests
570 //
571 
572 
574 {
575  RCP<A> a_rcp = rcp(new A);
576  set_extra_data( as<int>(1), "blob", outArg(a_rcp) );
577  TEST_EQUALITY_CONST(*get_optional_nonconst_extra_data<int>(a_rcp, "blob"), as<int>(1));
578 }
579 
580 
581 TEUCHOS_UNIT_TEST( RCP, getOptionalEmbeddedObj_null )
582 {
583  ECHO(RCP<A> a_rcp = rcp(new A));
584  const Ptr<const RCP<C> > c_ptr_rcp_1 =
585  getOptionalEmbeddedObj<A, RCP<C> >(a_rcp);
586  TEST_EQUALITY_CONST( c_ptr_rcp_1, null );
587  const Ptr<RCP<C> > c_ptr_rcp_2 =
588  getOptionalNonconstEmbeddedObj<A, RCP<C> >(a_rcp);
589  TEST_EQUALITY_CONST( c_ptr_rcp_2, null );
590 }
591 
592 
593 TEUCHOS_UNIT_TEST( RCP, getOptionalEmbeddedObj_default )
594 {
595 
596  ECHO(RCP<C> c_rcp = rcp(new C));
597  ECHO(RCP<A> a_rcp = rcpWithEmbeddedObj(new A, c_rcp));
598 
599  Ptr<const RCP<C> > c_ptr_rcp_1 =
600  getOptionalEmbeddedObj<A, RCP<C> >(a_rcp);
601  TEST_EQUALITY_CONST( is_null(c_ptr_rcp_1), false );
602  TEST_EQUALITY( (*c_ptr_rcp_1).getRawPtr(), c_rcp.getRawPtr() );
603  TEST_EQUALITY( (*c_ptr_rcp_1)->C_g(), C_g_return );
604 
605  Ptr<RCP<C> > c_ptr_rcp_2 =
606  getOptionalNonconstEmbeddedObj<A, RCP<C> >(a_rcp);
607  TEST_EQUALITY_CONST( is_null(c_ptr_rcp_2), false );
608  TEST_EQUALITY( (*c_ptr_rcp_2).getRawPtr(), c_rcp.getRawPtr() );
609  TEST_EQUALITY( (*c_ptr_rcp_2)->C_f(), C_f_return );
610 
611 }
612 
613 
614 TEUCHOS_UNIT_TEST( RCP, reset_null )
615 {
616  RCP<A> a_rcp = rcp(new A);
617  a_rcp.reset();
618  TEST_ASSERT(is_null(a_rcp));
619 }
620 
621 
622 TEUCHOS_UNIT_TEST( RCP, reset_nonnull )
623 {
624  RCP<A> a_rcp = rcp(new A);
625  C* c_rawp = new C;
626  a_rcp.reset(c_rawp);
627  A* a_rawp = c_rawp;
628  TEST_EQUALITY( a_rcp.getRawPtr(), a_rawp );
629 }
630 
631 
633 {
634  ECHO(RCP<A> a_rcp = rcp(new A));
635  TEST_EQUALITY_CONST(is_null(a_rcp), false);
636  TEST_EQUALITY_CONST(nonnull(a_rcp), true);
637  ECHO(a_rcp = null);
638  TEST_EQUALITY_CONST(is_null(a_rcp), true);
639  TEST_EQUALITY_CONST(nonnull(a_rcp), false);
640 }
641 
642 
643 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCP, weakDelete, T )
644 {
645 
646  ECHO(RCP<T> rcp_strong = rcp(new T));
647 
648  TEST_EQUALITY_CONST( rcp_strong.strength(), RCP_STRONG );
649  TEST_EQUALITY_CONST( rcp_strong.is_null(), false );
650  TEST_EQUALITY_CONST( rcp_strong.strong_count(), 1 );
651  TEST_EQUALITY_CONST( rcp_strong.weak_count(), 0 );
652  TEST_EQUALITY_CONST( rcp_strong.total_count(), 1 );
653 
654  ECHO(RCP<T> rcp_weak1 = rcp_strong.create_weak());
655 
656  TEST_EQUALITY_CONST( rcp_weak1.strength(), RCP_WEAK );
657  TEST_EQUALITY_CONST( rcp_weak1.is_null(), false );
658  TEST_EQUALITY_CONST( rcp_weak1.strong_count(), 1 );
659  TEST_EQUALITY_CONST( rcp_weak1.weak_count(), 1 );
660  TEST_EQUALITY_CONST( rcp_weak1.total_count(), 2 );
661 
662  TEST_EQUALITY_CONST( rcp_strong.strong_count(), 1 );
663  TEST_EQUALITY_CONST( rcp_strong.is_null(), false );
664  TEST_EQUALITY_CONST( rcp_strong.weak_count(), 1 );
665  TEST_EQUALITY_CONST( rcp_strong.total_count(), 2 );
666 
667  TEST_EQUALITY_CONST( rcp_weak1.shares_resource(rcp_strong), true );
668 
669  TEST_EQUALITY( rcp_weak1.get(), rcp_weak1.getRawPtr() );
670  TEST_EQUALITY( rcp_weak1.get(), rcp_strong.get() );
671  TEST_EQUALITY( rcp_weak1.getRawPtr(), rcp_strong.getRawPtr() );
672 
673  ECHO(RCP<T> rcp_weak2 = rcp_weak1);
674 
675  TEST_EQUALITY_CONST( rcp_weak2.strength(), RCP_WEAK );
676  TEST_EQUALITY_CONST( rcp_weak2.is_null(), false );
677  TEST_EQUALITY_CONST( rcp_weak2.strong_count(), 1 );
678  TEST_EQUALITY_CONST( rcp_weak2.weak_count(), 2 );
679  TEST_EQUALITY_CONST( rcp_weak2.total_count(), 3 );
680 
681  TEST_EQUALITY_CONST( rcp_strong.strong_count(), 1 );
682  TEST_EQUALITY_CONST( rcp_strong.is_null(), false );
683  TEST_EQUALITY_CONST( rcp_strong.weak_count(), 2 );
684  TEST_EQUALITY_CONST( rcp_strong.total_count(), 3 );
685 
686  TEST_EQUALITY_CONST( rcp_weak1.shares_resource(rcp_strong), true );
687  TEST_EQUALITY_CONST( rcp_weak1.shares_resource(rcp_weak2), true );
688  TEST_EQUALITY_CONST( rcp_weak2.shares_resource(rcp_strong), true );
689 
690  TEST_EQUALITY( rcp_weak2.get(), rcp_strong.get() );
691  TEST_EQUALITY( rcp_weak2.getRawPtr(), rcp_strong.getRawPtr() );
692 
693  ECHO(rcp_strong = null); // This deletes the underlying object of type T!
694 
695  TEST_EQUALITY_CONST( rcp_strong.strength(), RCP_STRONG );
696  TEST_EQUALITY_CONST( rcp_strong.is_null(), true );
697  TEST_EQUALITY_CONST( rcp_strong.strong_count(), 0 );
698  TEST_EQUALITY_CONST( rcp_strong.strong_count(), 0 );
699  TEST_EQUALITY_CONST( rcp_strong.weak_count(), 0 );
700  TEST_EQUALITY_CONST( rcp_strong.total_count(), 0 );
701  TEST_EQUALITY_CONST( rcp_strong.is_valid_ptr(), true );
702 
703  TEST_EQUALITY_CONST( rcp_strong.shares_resource(rcp_weak1), false );
704  TEST_EQUALITY_CONST( rcp_strong.shares_resource(rcp_weak2), false );
705 
706  TEST_EQUALITY_CONST( rcp_weak1.has_ownership(), true );
707  TEST_EQUALITY_CONST( rcp_weak1.strong_count(), 0 );
708  TEST_EQUALITY_CONST( rcp_weak1.strong_count(), 0 );
709  TEST_EQUALITY_CONST( rcp_weak1.weak_count(), 2 );
710  TEST_EQUALITY_CONST( rcp_weak1.total_count(), 2 );
711  TEST_EQUALITY_CONST( rcp_weak1.is_valid_ptr(), false );
712 
713  TEST_EQUALITY_CONST( rcp_weak2.has_ownership(), true );
714  TEST_EQUALITY_CONST( rcp_weak2.strong_count(), 0 );
715  TEST_EQUALITY_CONST( rcp_weak2.strong_count(), 0 );
716  TEST_EQUALITY_CONST( rcp_weak2.weak_count(), 2 );
717  TEST_EQUALITY_CONST( rcp_weak2.total_count(), 2 );
718  TEST_EQUALITY_CONST( rcp_weak2.is_valid_ptr(), false );
719 
720  TEST_EQUALITY_CONST( rcp_weak1.shares_resource(rcp_weak2), true );
721 
722  ECHO(rcp_weak1.assert_not_null()); // Does not throw!
723  ECHO(rcp_weak2.assert_not_null()); // Does not throw!
724 
725  TEST_THROW( rcp_weak1.assert_valid_ptr(), DanglingReferenceError );
726 #ifdef TEUCHOS_DEBUG
727  TEST_THROW( rcp_weak1.operator->(), DanglingReferenceError );
728  TEST_THROW( *rcp_weak1, DanglingReferenceError );
729  TEST_THROW( rcp_weak1.create_weak(), DanglingReferenceError );
730  TEST_THROW( rcp_weak1.get(), DanglingReferenceError );
731  TEST_THROW( rcp_weak1.getRawPtr(), DanglingReferenceError );
732  TEST_THROW( rcp_weak1(), DanglingReferenceError );
733  TEST_THROW( rcp_weak1.release(), DanglingReferenceError );
734 #endif // TEUCHOS_DEBUG
735 
736  ECHO(rcp_weak1 = null); // Just deicrements weak count!
737 
738  TEST_EQUALITY_CONST( rcp_weak1.strength(), RCP_STRONG );
739  TEST_EQUALITY_CONST( rcp_weak1.is_null(), true );
740  TEST_EQUALITY_CONST( rcp_weak1.strong_count(), 0 );
741  TEST_EQUALITY_CONST( rcp_weak1.strong_count(), 0 );
742  TEST_EQUALITY_CONST( rcp_weak1.weak_count(), 0 );
743  TEST_EQUALITY_CONST( rcp_weak1.total_count(), 0 );
744  TEST_EQUALITY_CONST( rcp_weak1.is_valid_ptr(), true );
745 
746  TEST_EQUALITY_CONST( rcp_weak2.has_ownership(), true );
747  TEST_EQUALITY_CONST( rcp_weak2.strong_count(), 0 );
748  TEST_EQUALITY_CONST( rcp_weak2.strong_count(), 0 );
749  TEST_EQUALITY_CONST( rcp_weak2.weak_count(), 1 );
750  TEST_EQUALITY_CONST( rcp_weak2.total_count(), 1 );
751  TEST_EQUALITY_CONST( rcp_weak2.is_valid_ptr(), false );
752 
753  TEST_EQUALITY_CONST( rcp_weak1.shares_resource(rcp_weak2), false );
754 
755  TEST_THROW( rcp_weak2.assert_valid_ptr(), DanglingReferenceError );
756 #ifdef TEUCHOS_DEBUG
757  TEST_THROW( rcp_weak2.operator->(), DanglingReferenceError );
758  TEST_THROW( *rcp_weak2, DanglingReferenceError );
759  TEST_THROW( rcp_weak2.create_weak(), DanglingReferenceError );
760  TEST_THROW( rcp_weak2.get(), DanglingReferenceError );
761  TEST_THROW( rcp_weak2.getRawPtr(), DanglingReferenceError );
762  TEST_THROW( rcp_weak2(), DanglingReferenceError );
763  TEST_THROW( rcp_weak2.release(), DanglingReferenceError );
764 #endif // TEUCHOS_DEBUG
765 
766 }
767 
768 
769 TEUCHOS_UNIT_TEST( RCP, weak_strong )
770 {
771 
772  ECHO(RCP<A> rcp1(rcp(new A)));
773  TEST_EQUALITY_CONST( rcp1.strength(), RCP_STRONG );
774 
775  ECHO(RCP<A> rcp2 = rcp1.create_weak());
776 
777  TEST_EQUALITY_CONST( rcp2.strength(), RCP_WEAK );
778  TEST_EQUALITY_CONST( rcp1.strong_count(), 1 );
779  TEST_EQUALITY_CONST( rcp1.weak_count(), 1 );
780  TEST_EQUALITY_CONST( rcp2.strong_count(), 1 );
781  TEST_EQUALITY_CONST( rcp2.weak_count(), 1 );
782 
783  ECHO(RCP<A> rcp3 = rcp2.create_strong());
784 
785  TEST_EQUALITY_CONST( rcp3.strength(), RCP_STRONG );
786  TEST_EQUALITY_CONST( rcp1.strong_count(), 2 );
787  TEST_EQUALITY_CONST( rcp1.weak_count(), 1 );
788  TEST_EQUALITY_CONST( rcp2.strong_count(), 2 );
789  TEST_EQUALITY_CONST( rcp2.weak_count(), 1 );
790 
791  // This will make the underlying object A gets deleted!
792  ECHO(rcp1 = null);
793  ECHO(rcp3 = null);
794 
795  ECHO(rcp2 = null); // Should make the underlying node go away
796 
797 }
798 
799 
800 //
801 // circularReference
802 //
803 
804 
805 TEUCHOS_UNIT_TEST( RCP, circularReference_a_then_c )
806 {
807  {
808  // Create objects a and c
809  ECHO(RCP<A> a = rcp(new A));
810  ECHO(RCP<C> c = rcp(new C));
811 
812  // Create a circular reference where 'a' owns 'c' strongly but 'c' only
813  // owns 'a' weakly.
814  ECHO(a->set_C(c));
815  ECHO(c->set_A(a.create_weak()));
816 
818  TEST_EQUALITY( c->call_A_g(), A_g_return );
819 
820  // Remove 'a' first and then remove 'c'. Since 'a' is only weakly held by
821  // 'c', this will result in 'a' being deleted right away. In this case,
822  // if anyone tries to access 'a' after this debug mode will throw.
823 
824  ECHO(a = null);
825 
826  // c is now dead!
827 #ifdef TEUCHOS_DEBUG
828  TEST_THROW(c->call_A_g(), DanglingReferenceError);
829 #endif
830 
831  // Finally, when 'c' goes away implicitly, it will do nothing because it
832  // only had weak ownership of a. So it will clean up with any trouble.
833  }
834 }
835 
836 
837 TEUCHOS_UNIT_TEST( RCP, circularReference_c_then_a )
838 {
839  {
840  // Create objects a and c
841  ECHO(RCP<A> a = rcp(new A));
842  ECHO(RCP<C> c = rcp(new C));
843 
844  // Create a circular reference where 'a' owns 'c' strongly but 'c' only
845  // owns 'a' weakly.
846  ECHO(a->set_C(c));
847  ECHO(c->set_A(a.create_weak()));
848 
850  TEST_EQUALITY( c->call_A_g(), A_g_return );
851 
852  // Remove 'c' first and then remove 'a' implicitly at the end of the
853  // block. Since 'c' is held strongly by 'a' and since we are keeping the
854  // strong pointer for 'a' alive, we can call functions on 'a' all we want
855  // with no fear of accessing dead memory.
856 
857  ECHO(c = null);
858 
859  TEST_EQUALITY( a->call_C_f(), C_f_return ); // a is still alive!
860 
861  // Finally, when 'a' goes away implicitly, it will take 'c' with it. In
862  // the complex set of nested calls that take place due to the circular
863  // reference, everything will get cleaned up correctly. Also, if any
864  // client code where to try to access an object as it is being deleted, an
865  // exception will get thrown and no memory error will occur (unless an
866  // abort(...) is called when an exception gets thrown from a destructor
867  // when an exception is already active).
868  }
869 }
870 
871 
872 TEUCHOS_UNIT_TEST( RCP, circularReference_self )
873 {
874  {
875  // Create one 'c' object
876  ECHO(RCP<C> c = rcp(new C));
877  // Create a weak circular reference where 'c' points back to itself
878  ECHO(c->set_A(c.create_weak()));
879  // Now, try to set 'c' to null.
880  ECHO(c = null); // All memory should be cleaned up here!
881  }
882 }
883 
884 
885 TEUCHOS_UNIT_TEST( RCP, danglingPtr1 )
886 {
887  ECHO(RCP<A> a_rcp = rcp(new A));
888  ECHO(Ptr<A> a_ptr = a_rcp());
889  ECHO(A *badPtr = a_rcp.getRawPtr());
890  ECHO(a_rcp = null);
891 #ifdef TEUCHOS_DEBUG
892  TEST_THROW( *a_ptr, DanglingReferenceError );
893  (void)badPtr;
894 #else
895  TEST_EQUALITY( a_ptr.getRawPtr(), badPtr );
896 #endif
897 }
898 
899 
900 TEUCHOS_UNIT_TEST( RCP, danglingPtr2 )
901 {
902  ECHO(Ptr<A> a_ptr);
903  ECHO(A *badPtr = 0);
904  {
905  ECHO(RCP<A> a_rcp = rcp(new A));
906  ECHO(badPtr = a_rcp.getRawPtr());
907  ECHO(a_ptr = a_rcp.ptr());
908  TEST_EQUALITY( a_ptr.getRawPtr(), badPtr );
909  }
910 #ifdef TEUCHOS_DEBUG
911  TEST_THROW( *a_ptr, DanglingReferenceError );
912  (void)badPtr;
913 #else
914  TEST_EQUALITY( a_ptr.getRawPtr(), badPtr );
915 #endif
916 }
917 
918 
919 TEUCHOS_UNIT_TEST( RCP, danglingPtr3 )
920 {
921  ECHO(Ptr<A> a_ptr);
922  ECHO(A *badPtr = 0);
923  {
924  ECHO(RCP<A> a_rcp = rcp(new A));
925  ECHO(badPtr = a_rcp.getRawPtr());
926  ECHO(Ptr<A> a_ptr2(a_rcp.ptr()));
927  ECHO(Ptr<A> a_ptr3(a_ptr2));
928  ECHO(a_ptr = a_ptr3);
929  TEST_EQUALITY( a_ptr.getRawPtr(), badPtr );
930  }
931 #ifdef TEUCHOS_DEBUG
932  TEST_THROW( *a_ptr, DanglingReferenceError );
933  (void)badPtr;
934 #else
935  TEST_EQUALITY( a_ptr.getRawPtr(), badPtr );
936 #endif
937 }
938 
939 
940 TEUCHOS_UNIT_TEST( RCP, danglingPtr4 )
941 {
942  ECHO(Ptr<A> a_ptr);
943  ECHO(A *badPtr = 0);
944  {
945  ECHO(RCP<C> c_rcp = rcp(new C));
946  ECHO(badPtr = c_rcp.getRawPtr());
947  ECHO(Ptr<A> a_ptr2(c_rcp.ptr()));
948  ECHO(a_ptr = a_ptr2);
949  TEST_EQUALITY( a_ptr.getRawPtr(), badPtr );
950  }
951 #ifdef TEUCHOS_DEBUG
952  TEST_THROW( *a_ptr, DanglingReferenceError );
953  (void)badPtr;
954 #else
955  TEST_EQUALITY( a_ptr.getRawPtr(), badPtr );
956 #endif
957 }
958 
959 
960 #ifdef TEUCHOS_DEBUG
961 
962 /* ToDo: Comment this back in once I have everything working
963 
964 // Test that the RCPNode tracing machinary can detect if an owning RCPNode is
965 // being created that would result in a double delete.
966 TEUCHOS_UNIT_TEST( RCP, multiRcpCreateError )
967 {
968  C *c_ptr = new C;
969 #if !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING)
970  Teuchos::setTracingActiveRCPNodes(true);
971 #endif
972  RCP<C> c_rcp = rcp(c_ptr); // Okay
973  RCP<C> c_rcp2;
974  TEST_THROW(c_rcp2 = rcp(c_ptr), DuplicateOwningRCPError);
975 #if !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING)
976  Teuchos::setTracingActiveRCPNodes(false);
977 #endif
978  // Clean up memory so no leaks and not double deletes no matter what.
979  c_rcp.release();
980  c_rcp2.release();
981  delete c_ptr;
982 }
983 
984 */
985 
986 #endif // TEUCHOS_DEBUG
987 
988 
989 //
990 // invertObjectOwnership
991 //
992 
993 
994 RCP<C> createCAFactory()
995 {
996  RCP<C> c = rcp(new C);
997  c->set_A(rcp(new A));
998  return c;
999 }
1000 
1001 
1002 RCP<A> createACFactory()
1003 {
1004  RCP<C> c = createCAFactory();
1005  return Teuchos::rcpWithInvertedObjOwnership(c->get_A(), c);
1006 }
1007 
1008 
1009 RCP<C> extractCFromA(const RCP<A> &a)
1010 {
1011  return Teuchos::getInvertedObjOwnershipParent<C>(a);
1012 }
1013 
1014 
1015 TEUCHOS_UNIT_TEST( RCP, invertObjectOwnership_basic )
1016 {
1017  RCP<A> a = createACFactory();
1018  RCP<C> c = extractCFromA(a);
1019  TEST_EQUALITY_CONST( a.strong_count(), 1 );
1020  TEST_EQUALITY_CONST( c->get_A().strong_count(), 3 );
1021  TEST_ASSERT( !a.shares_resource(c->get_A()) );
1022  TEST_EQUALITY( a.getRawPtr(), c->get_A().getRawPtr() );
1023  TEST_EQUALITY( a->A_g(), A_g_return );
1024  TEST_EQUALITY( c->C_g(), C_g_return );
1025 }
1026 
1027 
1028 // This unit test shows that you can remove the RCP in the C object
1029 // and the A object will still live on.
1030 TEUCHOS_UNIT_TEST( RCP, invertObjectOwnership_remove_A )
1031 {
1032  RCP<A> a = createACFactory();
1033  extractCFromA(a)->set_A(null);
1034  RCP<C> c = extractCFromA(a);
1035  TEST_EQUALITY_CONST( a.strong_count(), 1 );
1036  TEST_EQUALITY_CONST( c->get_A(), null );
1037  TEST_EQUALITY( a->A_g(), A_g_return );
1038  TEST_EQUALITY( c->C_g(), C_g_return );
1039 }
1040 
1041 
1042 //
1043 // createRCPWithBadDealloc
1044 //
1045 
1046 
1047 RCP<A> createRCPWithBadDealloc()
1048 {
1049  return rcp(new A[1]); // Will use delete but should use delete []!
1050 }
1051 
1052 
1053 template<typename T>
1054 class DeallocArrayDeleteExtraData {
1055 public:
1056  static RCP<DeallocArrayDeleteExtraData<T> > create(T *ptr)
1057  { return rcp(new DeallocArrayDeleteExtraData(ptr)); }
1058  ~DeallocArrayDeleteExtraData() { delete [] ptr_; }
1059 private:
1060  T *ptr_;
1061  DeallocArrayDeleteExtraData(T *ptr) : ptr_(ptr) {}
1062  // Not defined!
1063  DeallocArrayDeleteExtraData();
1064  DeallocArrayDeleteExtraData(const DeallocArrayDeleteExtraData&);
1065  DeallocArrayDeleteExtraData& operator=(const DeallocArrayDeleteExtraData&);
1066 };
1067 
1068 
1069 // This unit test shows how you can use extra data to fix a bad deallocation
1070 // policy
1071 TEUCHOS_UNIT_TEST( RCP, Fix_createRCPWithBadDealloc )
1072 {
1073  using Teuchos::inOutArg;
1074  using Teuchos::set_extra_data;
1075  // Create object with bad deallocator
1076  RCP<A> a = createRCPWithBadDealloc();
1077  TEST_ASSERT(nonnull(a));
1078  // Disable default (incorrect) dealloc and set a new deallocation policy as extra data!
1079  a.release();
1080  set_extra_data( DeallocArrayDeleteExtraData<A>::create(a.getRawPtr()), "dealloc",
1081  inOutArg(a));
1082 }
1083 
1084 
1088 TEUCHOS_UNIT_TEST( RCP, aliasing_constructor )
1089 {
1090  Teuchos::RCP<A> a_rcp = Teuchos::make_rcp<A>(1,2);
1091  Teuchos::RCP<A> b_rcp = Teuchos::make_rcp<A>(2,3);
1092  Teuchos::RCP<A> c_rcp(a_rcp, b_rcp.get());
1093 
1094  TEST_ASSERT(Teuchos::nonnull(c_rcp));
1095  TEST_EQUALITY_CONST(c_rcp.get(), b_rcp.get());
1096  TEST_EQUALITY(c_rcp->A_g(), b_rcp->A_g());
1097  TEST_EQUALITY(c_rcp->A_f(), b_rcp->A_f());
1098  TEST_ASSERT( c_rcp.shares_resource(a_rcp) );
1099 }
1100 
1101 
1102 //
1103 // Test RCP/boost::shared_ptr covnersions
1104 //
1105 
1106 
1107 #ifdef HAVE_TEUCHOS_BOOST
1108 
1109 
1110 TEUCHOS_UNIT_TEST( boost_shared_ptr, nonnull_is_null )
1111 {
1112  using boost::shared_ptr;
1113  ECHO(shared_ptr<A> a_sptr(new A));
1114  TEST_EQUALITY_CONST(is_null(a_sptr), false);
1115  TEST_EQUALITY_CONST(nonnull(a_sptr), true);
1116  ECHO(a_sptr = shared_ptr<A>());
1117  TEST_EQUALITY_CONST(is_null(a_sptr), true);
1118  TEST_EQUALITY_CONST(nonnull(a_sptr), false);
1119 }
1120 
1121 
1122 #endif // HAVE_TEUCHOS_BOOST
1123 
1124 
1125 //
1126 // Test RCP/std::shared_ptr covnersions
1127 //
1128 
1129 
1130 #ifdef HAVE_TEUCHOSCORE_CXX11
1131 
1132 
1133 TEUCHOS_UNIT_TEST( std_shared_ptr, nonnull_is_null )
1134 {
1135  using std::shared_ptr;
1136  ECHO(shared_ptr<A> a_sptr(new A));
1137  TEST_EQUALITY_CONST(Teuchos::is_null(a_sptr), false);
1138  TEST_EQUALITY_CONST(Teuchos::nonnull(a_sptr), true);
1139  ECHO(a_sptr = shared_ptr<A>());
1140  TEST_EQUALITY_CONST(Teuchos::is_null(a_sptr), true);
1141  TEST_EQUALITY_CONST(Teuchos::nonnull(a_sptr), false);
1142 }
1143 
1144 
1145 TEUCHOS_UNIT_TEST( std_shared_ptr, convert_to_RCP_null )
1146 {
1147  const std::shared_ptr<A> a_sptr1;
1148  const RCP<A> a_rsptr1 = rcp(a_sptr1);
1149  TEST_EQUALITY( a_rsptr1.get(), a_sptr1.get() );
1150  TEST_ASSERT(is_null(a_rsptr1));
1151 
1152  const std::shared_ptr<A> a_sptr2 = get_shared_ptr(a_rsptr1);
1153  TEST_EQUALITY( a_sptr1.get(), a_sptr1.get() );
1154  TEST_ASSERT(Teuchos::is_null(a_sptr2));
1155 }
1156 
1157 
1158 TEUCHOS_UNIT_TEST( std_shared_ptr, convert_to_RCP )
1159 {
1160  const std::shared_ptr<A> a_sptr1(new C());
1161  const RCP<A> a_rsptr1 = rcp(a_sptr1);
1162  TEST_EQUALITY( a_rsptr1.get(), a_sptr1.get() );
1163  TEST_EQUALITY( a_rsptr1.getRawPtr(), a_sptr1.get() );
1164  TEST_EQUALITY( a_rsptr1.get(), a_rsptr1.getRawPtr() );
1165 
1166  const std::shared_ptr<A> a_sptr2 = get_shared_ptr(a_rsptr1);
1167  TEST_EQUALITY( a_sptr1.get(), a_sptr1.get() );
1168  // NOTE: There is no portable way to check that two std::shared_ptr objects
1169  // share the same underlying shared node :-(
1170 }
1171 
1172 
1173 TEUCHOS_UNIT_TEST( std_shared_ptr, convert_from_RCP_null )
1174 {
1175  const RCP<A> a_rcp1;
1176  const std::shared_ptr<A> a_sptr1(get_shared_ptr(a_rcp1));
1177  TEST_EQUALITY( a_rcp1.get(), a_sptr1.get() );
1178  TEST_ASSERT(Teuchos::is_null(a_sptr1));
1179 
1180  const RCP<A> a_rcp2 = rcp(a_sptr1);
1181  TEST_EQUALITY(a_rcp2.get(), a_sptr1.get());
1182  TEST_ASSERT(is_null(a_rcp2));
1183 }
1184 
1185 
1186 TEUCHOS_UNIT_TEST( std_shared_ptr, convert_from_RCP )
1187 {
1188  const RCP<A> a_rcp1(new C());
1189  const std::shared_ptr<A> a_sptr1(get_shared_ptr(a_rcp1));
1190  TEST_EQUALITY( a_rcp1.get(), a_sptr1.get() );
1191  TEST_EQUALITY( a_rcp1.getRawPtr(), a_sptr1.get() );
1192  TEST_EQUALITY( a_sptr1.get(), a_rcp1.getRawPtr() );
1193 
1194  const RCP<A> a_rcp2 = rcp(a_sptr1);
1195  TEST_EQUALITY( a_rcp2.get(), a_sptr1.get() );
1196  TEST_EQUALITY( a_rcp2.get(), a_rcp1.get() );
1197  TEST_ASSERT( a_rcp1.shares_resource(a_rcp2) );
1198 }
1199 
1200 
1201 #ifdef TEUCHOS_DEBUG
1202 
1203 
1204 TEUCHOS_UNIT_TEST( std_shared_ptr, convert_from_RCP_lookup_node )
1205 {
1206  const RCP<A> a_rcp1(new C());
1207  const std::shared_ptr<A> a_sptr1(get_shared_ptr(a_rcp1));
1208  TEST_EQUALITY( a_sptr1.get(), a_rcp1.get() );
1209 
1210  const RCP<C> c_rcp1 = rcp(std::dynamic_pointer_cast<C>(a_sptr1));
1211  TEST_EQUALITY( c_rcp1.get(), a_rcp1.get() );
1212  TEST_ASSERT( c_rcp1.shares_resource(a_rcp1) );
1213  // NOTE: The above test shows how Teuchos::RCP machinery will automatically
1214  // look up the underlying RCPNode object and use it!
1215 }
1216 
1217 
1218 #endif // TEUCHOS_DEBUG
1219 
1220 
1221 #endif // HAVE_TEUCHOSCORE_CXX11
1222 
1223 
1224 
1225 //
1226 // Template Instantiations
1227 //
1228 
1229 
1230 #ifdef TEUCHOS_DEBUG
1231 
1232 # define DEBUG_UNIT_TEST_GROUP( T ) \
1233 
1234 #else
1235 
1236 # define DEBUG_UNIT_TEST_GROUP( T )
1237 
1238 #endif
1239 
1240 
1241 #define UNIT_TEST_GROUP( T ) \
1242  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCP, weakDelete, T ) \
1243  DEBUG_UNIT_TEST_GROUP(T)
1244 
1245 
1250 
1251 
1252 } // namespace
Dangling reference error exception class.
Null reference error exception class.
RCP< T > rcp(const boost::shared_ptr< T > &sptr)
Conversion function that takes in a boost::shared_ptr object and spits out a Teuchos::RCP object...
void set_extra_data(const T1 &extra_data, const std::string &name, const Ptr< ArrayRCP< T2 > > &p, EPrePostDestruction destroy_when=POST_DESTROY, bool force_unique=true)
Set extra data associated with a ArrayRCP object.
void set_C(const Teuchos::RCP< C > &c)
Definition: TestClasses.hpp:73
#define TEST_ASSERT(v1)
Assert the given statement is true.
Ptr< T > inOutArg(T &arg)
create a non-persisting (required or optional) input/output argument for a function call...
#define TEST_INEQUALITY_CONST(v1, v2)
Assert the inequality of v1 and constant v2.
virtual int A_g()
Definition: TestClasses.hpp:67
Ptr< T1 > get_optional_nonconst_extra_data(RCP< T2 > &p, const std::string &name)
Get a pointer to non-const extra data (if it exists) associated with a RCP object.
#define TEST_NOTHROW(code)
Asserr that the statement &#39;code&#39; does not thrown any excpetions.
int call_C_f()
#define ECHO(statement)
Echo the given statement before it is executed.
bool nonnull(const std::shared_ptr< T > &p)
Returns true if p.get()!=NULL.
bool is_null(const std::shared_ptr< T > &p)
Returns true if p.get()==NULL.
#define TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL(TEST_GROUP, TEST_NAME, TYPE)
Macro for defining a templated unit test with one template parameter.
#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)...
const T & getConst(T &t)
Return a constant reference to an object given a non-const reference.
const int C_g_return
Definition: TestClasses.hpp:24
const int C_f_return
Definition: TestClasses.hpp:25
T * get() const
Get the raw C++ pointer to the underlying object.
#define TEUCHOS_UNIT_TEST(TEST_GROUP, TEST_NAME)
Macro for defining a (non-templated) unit test.
bool is_null(const ArrayRCP< T > &p)
Returns true if p.get()==NULL.
RCP< T > rcpWithEmbeddedObj(T *p, const Embedded &embedded, bool owns_mem=true)
Create an RCP with and also put in an embedded object.
void free(T *ptr)
Deallocates a pointer ptr using delete ptr (required).
Debug-mode RCPNode tracing class.
T * getRawPtr() const
Get the raw C++ pointer to the underlying object.
RCP< T > rcpCloneNode(const RCP< T > &p)
Allocate a new RCP object with a new RCPNode with memory pointing to the initial node.
#define SET_RCPNODE_TRACING()
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Deprecated.
Unit testing support.
#define TEST_EQUALITY_CONST(v1, v2)
Assert the equality of v1 and constant v2.
TypeTo as(const TypeFrom &t)
Convert from one value type to another.
Ptr< T > release()
Release the ownership of the underlying dynamically allocated object.
RCP< T > rcpFromUndefRef(T &r)
Return a non-owning weak RCP object from a raw object reference for an undefined type.
std::shared_ptr< T > get_shared_ptr(const RCP< T > &rcp)
Conversion function that takes in a Teuchos::RCP object and spits out a std::shared_ptr object...
RCP< T > rcpFromRef(T &r)
Return a non-owning weak RCP object from a raw object reference for a defined type.
Policy class for deallocator for non-owned RCPs.
Smart reference counting pointer class for automatic garbage collection.
virtual int A_f() const
Definition: TestClasses.hpp:68
RCP< T > rcpWithDealloc(T *p, Dealloc_T dealloc, bool owns_mem=true)
Initialize from a raw pointer with a deallocation policy.
Ptr< T > outArg(T &arg)
create a non-persisting (required or optional) output argument for a function call.
Thrown if a duplicate owning RCP is creatd the the same object.
Reference-counted pointer class and non-member templated function implementations.
const int A_g_return
Definition: TestClasses.hpp:18
Simple wrapper class for raw pointers to single objects where no persisting relationship exists...
auto make_rcp(Args &&...args)
bool nonnull(const ArrayRCP< T > &p)
Returns true if p.get()!=NULL.
#define UNIT_TEST_GROUP(T)