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