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 
336 
337 //
338 // Test rcpCloneNode(...)
339 //
340 
341 
342 TEUCHOS_UNIT_TEST( RCP, rcpCloneNode_null )
343 {
344  ECHO(RCP<RCP<int> > rcp1 = null);
345  ECHO(RCP<RCP<int> > rcp2 = rcpCloneNode(rcp1));
346  TEST_EQUALITY(rcp2, null);
347 }
348 
349 
350 TEUCHOS_UNIT_TEST( RCP, rcpCloneNode_basic )
351 {
352 
353  ECHO(RCP<int> rcp1 = rcp(new int(0)));
354 
355  ECHO(RCP<int> rcp2 = rcpCloneNode(rcp1));
356  TEST_ASSERT(nonnull(rcp2));
357  TEST_EQUALITY(rcp1.strong_count(), 2);
358  TEST_EQUALITY(rcp2.strong_count(), 1);
359 
360  ECHO(RCP<int> rcp3 = rcp2);
361  TEST_EQUALITY(rcp1.strong_count(), 2);
362  TEST_EQUALITY(rcp2.strong_count(), 2);
363  TEST_EQUALITY(rcp3.strong_count(), 2);
364 
365  ECHO(RCP <int> rcp4 = rcp1);
366  TEST_EQUALITY(rcp1.strong_count(), 3);
367  TEST_EQUALITY(rcp2.strong_count(), 2);
368  TEST_EQUALITY(rcp3.strong_count(), 2);
369 
370  ECHO(rcp4 = null);
371  TEST_EQUALITY(rcp1.strong_count(), 2);
372  TEST_EQUALITY(rcp2.strong_count(), 2);
373  TEST_EQUALITY(rcp3.strong_count(), 2);
374  TEST_EQUALITY(rcp4.strong_count(), 0);
375 
376  ECHO(rcp1 = null);
377  TEST_EQUALITY(rcp1.strong_count(), 0);
378  TEST_EQUALITY(rcp2.strong_count(), 2);
379  TEST_EQUALITY(rcp3.strong_count(), 2);
380  TEST_EQUALITY(rcp4.strong_count(), 0);
381 
382  ECHO(rcp2 = null);
383  TEST_EQUALITY(rcp2.strong_count(), 0);
384  TEST_EQUALITY(rcp3.strong_count(), 1);
385 
386  ECHO(rcp3 = null);
387  TEST_EQUALITY(rcp3.strong_count(), 0);
388 
389 }
390 
391 
392 //
393 // Test duplicate owning RCP objects
394 //
395 
396 
397 // Test that shows that we can detect trying to create two owning RCPs
398 // pointing to the same polymorphic object but having different interfaces
399 // with different addresses. This happens due to virtual base classes. Only
400 // works when we have a working getBaseObjVoidPtr(...) function.
401 TEUCHOS_UNIT_TEST( RCP, duplicate_rcp_owning_polymorphic )
402 {
404  ECHO(C *c_ptr = new C);
405  ECHO(A *a_ptr = c_ptr);
406  ECHO(RCP<C> c_rcp = rcp(c_ptr)); // Okay
407 #if defined(TEUCHOS_DEBUG) && defined(HAS_TEUCHOS_GET_BASE_OBJ_VOID_PTR)
408  // With determine they are pointed to the same object!
409  TEST_THROW(RCP<A> a_rcp = rcp(a_ptr), DuplicateOwningRCPError);
410 #else
411  // Will not determine they are point to the same object!
412  ECHO(RCP<A> a_rcp = rcp(a_ptr));
413  TEST_EQUALITY(a_rcp.getRawPtr(), a_ptr);
414  ECHO(a_rcp.release()); // Better or we will get a segfault!
415 #endif
416 }
417 
418 
419 // Test that shows that we can detect trying to create two owning RCPs
420 // pointing to the same polymorphic object with the same type and therefore
421 // the same address. This works even if these use virtual base classes. This
422 // works even without a working getBaseObjVoidPtr(...) function.
423 TEUCHOS_UNIT_TEST( RCP, duplicate_rcp_owning_polymorphic_different_addr )
424 {
426  ECHO(A *a_ptr1 = new C);
427  ECHO(A *a_ptr2 = a_ptr1);
428  ECHO(RCP<A> a_rcp1 = rcp(a_ptr1)); // Okay
429 #if defined(TEUCHOS_DEBUG)
430  // With determine they are pointed to the same object!
431  TEST_THROW(RCP<A> a_rcp2 = rcp(a_ptr2), DuplicateOwningRCPError);
432 #else
433  // Will not determine they are point to the same object!
434  ECHO(RCP<A> a_rcp2 = rcp(a_ptr2));
435  TEST_EQUALITY(a_rcp2.getRawPtr(), a_ptr2);
436  ECHO(a_rcp2.release()); // Better or we will get a segfault!
437 #endif
438 }
439 
440 
441 // Test that shows that we can always detect trying to create two owning RCPs
442 // pointing to the same nonpolymorphic object having different interfaces but
443 // the same address (single non-virtual inheritance). Works just fine without
444 // a working getBaseObjVoidPtr(...) function.
445 TEUCHOS_UNIT_TEST( RCP, duplicate_rcp_owning_nonpolymorphic_same_addr )
446 {
448  ECHO(E *e_ptr = new E);
449  ECHO(E *d_ptr = e_ptr);
450  ECHO(RCP<E> e_rcp = rcp(e_ptr)); // Okay
451 #if defined(TEUCHOS_DEBUG)
452  // With determine they are pointed to the same object even without support
453  // for getBaseObjVoidPtr(...) because no dynamic_cast is needed.
454  TEST_THROW(RCP<D> d_rcp = rcp(d_ptr), DuplicateOwningRCPError);
455 #else
456  // Will not determine they are point to the same object!
457  ECHO(RCP<D> d_rcp = rcp(d_ptr));
458  TEST_EQUALITY(d_rcp.getRawPtr(), d_ptr);
459  ECHO(d_rcp.release()); // Better or we will get a segfault!
460 #endif
461 }
462 
463 
464 //
465 // These next tests shows that we can detect when two RCPs are create to the same
466 // object, one owning and the other non-owning. When we have a working
467 // getBaseObjVoidPtr(...) function, the new non-owning RCP will actually be a
468 // weak RCP that can be used to detect circular dependencies.
469 //
470 
471 
472 // rcp
473 
474 
475 TEUCHOS_UNIT_TEST( RCP, rcp_duplicate_rcp_nonowning_polymorphic_different_addr )
476 {
478  ECHO(RCP<C> c_rcp(new C));
479  ECHO(A &a_ref = *c_rcp);
480  ECHO(RCP<A> a_rcp = rcp(&a_ref, false));
481  ECHO(c_rcp = null);
482 #if defined(TEUCHOS_DEBUG) && defined(HAS_TEUCHOS_GET_BASE_OBJ_VOID_PTR)
483  TEST_THROW(a_rcp->A_g(), DanglingReferenceError);
484 #else
485  TEST_NOTHROW(a_rcp.getRawPtr());
486 #endif
487 }
488 
489 
490 TEUCHOS_UNIT_TEST( RCP, rcp_duplicate_rcp_nonowning_polymorphic_same_addr )
491 {
493  ECHO(RCP<A> a_rcp1(new C));
494  ECHO(A &a_ref = *a_rcp1);
495  ECHO(RCP<A> a_rcp2 = rcp(&a_ref, false));
496  ECHO(a_rcp1 = null);
497 #if defined(TEUCHOS_DEBUG)
498  TEST_THROW(a_rcp2->A_g(), DanglingReferenceError);
499 #else
500  TEST_NOTHROW(a_rcp2.getRawPtr());
501 #endif
502 }
503 
504 
505 TEUCHOS_UNIT_TEST( RCP, rcp_duplicate_rcp_nonowning_nonpolymorphic )
506 {
508  ECHO(RCP<E> e_rcp(new E));
509  ECHO(D &d_ref = *e_rcp);
510  ECHO(RCP<D> d_rcp = rcp(&d_ref, false));
511  ECHO(e_rcp = null);
512 #if defined(TEUCHOS_DEBUG)
513  TEST_THROW(d_rcp->D_g(), DanglingReferenceError);
514 #else
515  TEST_NOTHROW(d_rcp.getRawPtr());
516 #endif
517 }
518 
519 
520 // rcpFromRef
521 
522 
523 TEUCHOS_UNIT_TEST( RCP, rcpFromRef_duplicate_rcp_nonowning_polymorphic_different_addr )
524 {
526  ECHO(RCP<C> c_rcp(new C));
527  ECHO(A &a_ref = *c_rcp);
528  ECHO(RCP<A> a_rcp = rcpFromRef(a_ref));
529  ECHO(c_rcp = null);
530 #if defined(TEUCHOS_DEBUG) && defined(HAS_TEUCHOS_GET_BASE_OBJ_VOID_PTR)
531  TEST_THROW(a_rcp->A_g(), DanglingReferenceError);
532 #else
533  TEST_NOTHROW(a_rcp.getRawPtr());
534 #endif
535 }
536 
537 
538 TEUCHOS_UNIT_TEST( RCP, rcpFromRef_duplicate_rcp_nonowning_polymorphic_same_addr )
539 {
541  ECHO(RCP<A> a_rcp1(new C));
542  ECHO(A &a_ref = *a_rcp1);
543  ECHO(RCP<A> a_rcp2 = rcpFromRef(a_ref));
544  ECHO(a_rcp1 = null);
545 #if defined(TEUCHOS_DEBUG)
546  TEST_THROW(a_rcp2->A_g(), DanglingReferenceError);
547 #else
548  TEST_NOTHROW(a_rcp2.getRawPtr());
549 #endif
550 }
551 
552 
553 TEUCHOS_UNIT_TEST( RCP, rcpFromRef_duplicate_rcp_nonowning_nonpolymorphic )
554 {
556  ECHO(RCP<E> e_rcp(new E));
557  ECHO(D &d_ref = *e_rcp);
558  ECHO(RCP<D> d_rcp = rcpFromRef(d_ref));
559  ECHO(e_rcp = null);
560 #if defined(TEUCHOS_DEBUG)
561  TEST_THROW(d_rcp->D_g(), DanglingReferenceError);
562 #else
563  TEST_NOTHROW(d_rcp.getRawPtr());
564 #endif
565 }
566 
567 
568 // rcpFromUndefRef (Can never detect dangling references)
569 
570 
571 TEUCHOS_UNIT_TEST( RCP, rcpFromUndefRef_duplicate_rcp_nonowning_polymorphic_same_addr )
572 {
574  ECHO(RCP<A> a_rcp1(new C));
575  ECHO(A &a_ref = *a_rcp1);
576  ECHO(RCP<A> a_rcp2 = rcpFromUndefRef(a_ref));
577  ECHO(a_rcp1 = null);
578  TEST_NOTHROW(a_rcp2.getRawPtr());
579 }
580 
581 
582 //
583 // extra data and embedded objects tests
584 //
585 
586 
588 {
589  RCP<A> a_rcp = rcp(new A);
590  set_extra_data( as<int>(1), "blob", outArg(a_rcp) );
591  TEST_EQUALITY_CONST(*get_optional_nonconst_extra_data<int>(a_rcp, "blob"), as<int>(1));
592 }
593 
594 
595 TEUCHOS_UNIT_TEST( RCP, getOptionalEmbeddedObj_null )
596 {
597  ECHO(RCP<A> a_rcp = rcp(new A));
598  const Ptr<const RCP<C> > c_ptr_rcp_1 =
599  getOptionalEmbeddedObj<A, RCP<C> >(a_rcp);
600  TEST_EQUALITY_CONST( c_ptr_rcp_1, null );
601  const Ptr<RCP<C> > c_ptr_rcp_2 =
602  getOptionalNonconstEmbeddedObj<A, RCP<C> >(a_rcp);
603  TEST_EQUALITY_CONST( c_ptr_rcp_2, null );
604 }
605 
606 
607 TEUCHOS_UNIT_TEST( RCP, getOptionalEmbeddedObj_default )
608 {
609 
610  ECHO(RCP<C> c_rcp = rcp(new C));
611  ECHO(RCP<A> a_rcp = rcpWithEmbeddedObj(new A, c_rcp));
612 
613  Ptr<const RCP<C> > c_ptr_rcp_1 =
614  getOptionalEmbeddedObj<A, RCP<C> >(a_rcp);
615  TEST_EQUALITY_CONST( is_null(c_ptr_rcp_1), false );
616  TEST_EQUALITY( (*c_ptr_rcp_1).getRawPtr(), c_rcp.getRawPtr() );
617  TEST_EQUALITY( (*c_ptr_rcp_1)->C_g(), C_g_return );
618 
619  Ptr<RCP<C> > c_ptr_rcp_2 =
620  getOptionalNonconstEmbeddedObj<A, RCP<C> >(a_rcp);
621  TEST_EQUALITY_CONST( is_null(c_ptr_rcp_2), false );
622  TEST_EQUALITY( (*c_ptr_rcp_2).getRawPtr(), c_rcp.getRawPtr() );
623  TEST_EQUALITY( (*c_ptr_rcp_2)->C_f(), C_f_return );
624 
625 }
626 
627 
628 TEUCHOS_UNIT_TEST( RCP, reset_null )
629 {
630  RCP<A> a_rcp = rcp(new A);
631  a_rcp.reset();
632  TEST_ASSERT(is_null(a_rcp));
633 }
634 
635 
636 TEUCHOS_UNIT_TEST( RCP, reset_nonnull )
637 {
638  RCP<A> a_rcp = rcp(new A);
639  C* c_rawp = new C;
640  a_rcp.reset(c_rawp);
641  A* a_rawp = c_rawp;
642  TEST_EQUALITY( a_rcp.getRawPtr(), a_rawp );
643 }
644 
645 
647 {
648  ECHO(RCP<A> a_rcp = rcp(new A));
649  TEST_EQUALITY_CONST(is_null(a_rcp), false);
650  TEST_EQUALITY_CONST(nonnull(a_rcp), true);
651  ECHO(a_rcp = null);
652  TEST_EQUALITY_CONST(is_null(a_rcp), true);
653  TEST_EQUALITY_CONST(nonnull(a_rcp), false);
654 }
655 
656 
657 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( RCP, weakDelete, T )
658 {
659 
660  ECHO(RCP<T> rcp_strong = rcp(new T));
661 
662  TEST_EQUALITY_CONST( rcp_strong.strength(), RCP_STRONG );
663  TEST_EQUALITY_CONST( rcp_strong.is_null(), false );
664  TEST_EQUALITY_CONST( rcp_strong.strong_count(), 1 );
665  TEST_EQUALITY_CONST( rcp_strong.weak_count(), 0 );
666  TEST_EQUALITY_CONST( rcp_strong.total_count(), 1 );
667 
668  ECHO(RCP<T> rcp_weak1 = rcp_strong.create_weak());
669 
670  TEST_EQUALITY_CONST( rcp_weak1.strength(), RCP_WEAK );
671  TEST_EQUALITY_CONST( rcp_weak1.is_null(), false );
672  TEST_EQUALITY_CONST( rcp_weak1.strong_count(), 1 );
673  TEST_EQUALITY_CONST( rcp_weak1.weak_count(), 1 );
674  TEST_EQUALITY_CONST( rcp_weak1.total_count(), 2 );
675 
676  TEST_EQUALITY_CONST( rcp_strong.strong_count(), 1 );
677  TEST_EQUALITY_CONST( rcp_strong.is_null(), false );
678  TEST_EQUALITY_CONST( rcp_strong.weak_count(), 1 );
679  TEST_EQUALITY_CONST( rcp_strong.total_count(), 2 );
680 
681  TEST_EQUALITY_CONST( rcp_weak1.shares_resource(rcp_strong), true );
682 
683  TEST_EQUALITY( rcp_weak1.get(), rcp_weak1.getRawPtr() );
684  TEST_EQUALITY( rcp_weak1.get(), rcp_strong.get() );
685  TEST_EQUALITY( rcp_weak1.getRawPtr(), rcp_strong.getRawPtr() );
686 
687  ECHO(RCP<T> rcp_weak2 = rcp_weak1);
688 
689  TEST_EQUALITY_CONST( rcp_weak2.strength(), RCP_WEAK );
690  TEST_EQUALITY_CONST( rcp_weak2.is_null(), false );
691  TEST_EQUALITY_CONST( rcp_weak2.strong_count(), 1 );
692  TEST_EQUALITY_CONST( rcp_weak2.weak_count(), 2 );
693  TEST_EQUALITY_CONST( rcp_weak2.total_count(), 3 );
694 
695  TEST_EQUALITY_CONST( rcp_strong.strong_count(), 1 );
696  TEST_EQUALITY_CONST( rcp_strong.is_null(), false );
697  TEST_EQUALITY_CONST( rcp_strong.weak_count(), 2 );
698  TEST_EQUALITY_CONST( rcp_strong.total_count(), 3 );
699 
700  TEST_EQUALITY_CONST( rcp_weak1.shares_resource(rcp_strong), true );
701  TEST_EQUALITY_CONST( rcp_weak1.shares_resource(rcp_weak2), true );
702  TEST_EQUALITY_CONST( rcp_weak2.shares_resource(rcp_strong), true );
703 
704  TEST_EQUALITY( rcp_weak2.get(), rcp_strong.get() );
705  TEST_EQUALITY( rcp_weak2.getRawPtr(), rcp_strong.getRawPtr() );
706 
707  ECHO(rcp_strong = null); // This deletes the underlying object of type T!
708 
709  TEST_EQUALITY_CONST( rcp_strong.strength(), RCP_STRONG );
710  TEST_EQUALITY_CONST( rcp_strong.is_null(), true );
711  TEST_EQUALITY_CONST( rcp_strong.strong_count(), 0 );
712  TEST_EQUALITY_CONST( rcp_strong.strong_count(), 0 );
713  TEST_EQUALITY_CONST( rcp_strong.weak_count(), 0 );
714  TEST_EQUALITY_CONST( rcp_strong.total_count(), 0 );
715  TEST_EQUALITY_CONST( rcp_strong.is_valid_ptr(), true );
716 
717  TEST_EQUALITY_CONST( rcp_strong.shares_resource(rcp_weak1), false );
718  TEST_EQUALITY_CONST( rcp_strong.shares_resource(rcp_weak2), false );
719 
720  TEST_EQUALITY_CONST( rcp_weak1.has_ownership(), true );
721  TEST_EQUALITY_CONST( rcp_weak1.strong_count(), 0 );
722  TEST_EQUALITY_CONST( rcp_weak1.strong_count(), 0 );
723  TEST_EQUALITY_CONST( rcp_weak1.weak_count(), 2 );
724  TEST_EQUALITY_CONST( rcp_weak1.total_count(), 2 );
725  TEST_EQUALITY_CONST( rcp_weak1.is_valid_ptr(), false );
726 
727  TEST_EQUALITY_CONST( rcp_weak2.has_ownership(), true );
728  TEST_EQUALITY_CONST( rcp_weak2.strong_count(), 0 );
729  TEST_EQUALITY_CONST( rcp_weak2.strong_count(), 0 );
730  TEST_EQUALITY_CONST( rcp_weak2.weak_count(), 2 );
731  TEST_EQUALITY_CONST( rcp_weak2.total_count(), 2 );
732  TEST_EQUALITY_CONST( rcp_weak2.is_valid_ptr(), false );
733 
734  TEST_EQUALITY_CONST( rcp_weak1.shares_resource(rcp_weak2), true );
735 
736  ECHO(rcp_weak1.assert_not_null()); // Does not throw!
737  ECHO(rcp_weak2.assert_not_null()); // Does not throw!
738 
739  TEST_THROW( rcp_weak1.assert_valid_ptr(), DanglingReferenceError );
740 #ifdef TEUCHOS_DEBUG
741  TEST_THROW( rcp_weak1.operator->(), DanglingReferenceError );
742  TEST_THROW( *rcp_weak1, DanglingReferenceError );
743  TEST_THROW( rcp_weak1.create_weak(), DanglingReferenceError );
744  TEST_THROW( rcp_weak1.get(), DanglingReferenceError );
745  TEST_THROW( rcp_weak1.getRawPtr(), DanglingReferenceError );
746  TEST_THROW( rcp_weak1(), DanglingReferenceError );
747  TEST_THROW( rcp_weak1.release(), DanglingReferenceError );
748 #endif // TEUCHOS_DEBUG
749 
750  ECHO(rcp_weak1 = null); // Just deicrements weak count!
751 
752  TEST_EQUALITY_CONST( rcp_weak1.strength(), RCP_STRONG );
753  TEST_EQUALITY_CONST( rcp_weak1.is_null(), true );
754  TEST_EQUALITY_CONST( rcp_weak1.strong_count(), 0 );
755  TEST_EQUALITY_CONST( rcp_weak1.strong_count(), 0 );
756  TEST_EQUALITY_CONST( rcp_weak1.weak_count(), 0 );
757  TEST_EQUALITY_CONST( rcp_weak1.total_count(), 0 );
758  TEST_EQUALITY_CONST( rcp_weak1.is_valid_ptr(), true );
759 
760  TEST_EQUALITY_CONST( rcp_weak2.has_ownership(), true );
761  TEST_EQUALITY_CONST( rcp_weak2.strong_count(), 0 );
762  TEST_EQUALITY_CONST( rcp_weak2.strong_count(), 0 );
763  TEST_EQUALITY_CONST( rcp_weak2.weak_count(), 1 );
764  TEST_EQUALITY_CONST( rcp_weak2.total_count(), 1 );
765  TEST_EQUALITY_CONST( rcp_weak2.is_valid_ptr(), false );
766 
767  TEST_EQUALITY_CONST( rcp_weak1.shares_resource(rcp_weak2), false );
768 
769  TEST_THROW( rcp_weak2.assert_valid_ptr(), DanglingReferenceError );
770 #ifdef TEUCHOS_DEBUG
771  TEST_THROW( rcp_weak2.operator->(), DanglingReferenceError );
772  TEST_THROW( *rcp_weak2, DanglingReferenceError );
773  TEST_THROW( rcp_weak2.create_weak(), DanglingReferenceError );
774  TEST_THROW( rcp_weak2.get(), DanglingReferenceError );
775  TEST_THROW( rcp_weak2.getRawPtr(), DanglingReferenceError );
776  TEST_THROW( rcp_weak2(), DanglingReferenceError );
777  TEST_THROW( rcp_weak2.release(), DanglingReferenceError );
778 #endif // TEUCHOS_DEBUG
779 
780 }
781 
782 
783 TEUCHOS_UNIT_TEST( RCP, weak_strong )
784 {
785 
786  ECHO(RCP<A> rcp1(rcp(new A)));
787  TEST_EQUALITY_CONST( rcp1.strength(), RCP_STRONG );
788 
789  ECHO(RCP<A> rcp2 = rcp1.create_weak());
790 
791  TEST_EQUALITY_CONST( rcp2.strength(), RCP_WEAK );
792  TEST_EQUALITY_CONST( rcp1.strong_count(), 1 );
793  TEST_EQUALITY_CONST( rcp1.weak_count(), 1 );
794  TEST_EQUALITY_CONST( rcp2.strong_count(), 1 );
795  TEST_EQUALITY_CONST( rcp2.weak_count(), 1 );
796 
797  ECHO(RCP<A> rcp3 = rcp2.create_strong());
798 
799  TEST_EQUALITY_CONST( rcp3.strength(), RCP_STRONG );
800  TEST_EQUALITY_CONST( rcp1.strong_count(), 2 );
801  TEST_EQUALITY_CONST( rcp1.weak_count(), 1 );
802  TEST_EQUALITY_CONST( rcp2.strong_count(), 2 );
803  TEST_EQUALITY_CONST( rcp2.weak_count(), 1 );
804 
805  // This will make the underlying object A gets deleted!
806  ECHO(rcp1 = null);
807  ECHO(rcp3 = null);
808 
809  ECHO(rcp2 = null); // Should make the underlying node go away
810 
811 }
812 
813 
814 //
815 // circularReference
816 //
817 
818 
819 TEUCHOS_UNIT_TEST( RCP, circularReference_a_then_c )
820 {
821  {
822  // Create objects a and c
823  ECHO(RCP<A> a = rcp(new A));
824  ECHO(RCP<C> c = rcp(new C));
825 
826  // Create a circular reference where 'a' owns 'c' strongly but 'c' only
827  // owns 'a' weakly.
828  ECHO(a->set_C(c));
829  ECHO(c->set_A(a.create_weak()));
830 
832  TEST_EQUALITY( c->call_A_g(), A_g_return );
833 
834  // Remove 'a' first and then remove 'c'. Since 'a' is only weakly held by
835  // 'c', this will result in 'a' being deleted right away. In this case,
836  // if anyone tries to access 'a' after this debug mode will throw.
837 
838  ECHO(a = null);
839 
840  // c is now dead!
841 #ifdef TEUCHOS_DEBUG
842  TEST_THROW(c->call_A_g(), DanglingReferenceError);
843 #endif
844 
845  // Finally, when 'c' goes away implicitly, it will do nothing because it
846  // only had weak ownership of a. So it will clean up with any trouble.
847  }
848 }
849 
850 
851 TEUCHOS_UNIT_TEST( RCP, circularReference_c_then_a )
852 {
853  {
854  // Create objects a and c
855  ECHO(RCP<A> a = rcp(new A));
856  ECHO(RCP<C> c = rcp(new C));
857 
858  // Create a circular reference where 'a' owns 'c' strongly but 'c' only
859  // owns 'a' weakly.
860  ECHO(a->set_C(c));
861  ECHO(c->set_A(a.create_weak()));
862 
864  TEST_EQUALITY( c->call_A_g(), A_g_return );
865 
866  // Remove 'c' first and then remove 'a' implicitly at the end of the
867  // block. Since 'c' is held strongly by 'a' and since we are keeping the
868  // strong pointer for 'a' alive, we can call functions on 'a' all we want
869  // with no fear of accessing dead memory.
870 
871  ECHO(c = null);
872 
873  TEST_EQUALITY( a->call_C_f(), C_f_return ); // a is still alive!
874 
875  // Finally, when 'a' goes away implicitly, it will take 'c' with it. In
876  // the complex set of nested calls that take place due to the circular
877  // reference, everything will get cleaned up correctly. Also, if any
878  // client code where to try to access an object as it is being deleted, an
879  // exception will get thrown and no memory error will occur (unless an
880  // abort(...) is called when an exception gets thrown from a destructor
881  // when an exception is already active).
882  }
883 }
884 
885 
886 TEUCHOS_UNIT_TEST( RCP, circularReference_self )
887 {
888  {
889  // Create one 'c' object
890  ECHO(RCP<C> c = rcp(new C));
891  // Create a weak circular reference where 'c' points back to itself
892  ECHO(c->set_A(c.create_weak()));
893  // Now, try to set 'c' to null.
894  ECHO(c = null); // All memory should be cleaned up here!
895  }
896 }
897 
898 
899 TEUCHOS_UNIT_TEST( RCP, danglingPtr1 )
900 {
901  ECHO(RCP<A> a_rcp = rcp(new A));
902  ECHO(Ptr<A> a_ptr = a_rcp());
903  ECHO(A *badPtr = a_rcp.getRawPtr());
904  ECHO(a_rcp = null);
905 #ifdef TEUCHOS_DEBUG
906  TEST_THROW( *a_ptr, DanglingReferenceError );
907  (void)badPtr;
908 #else
909  TEST_EQUALITY( a_ptr.getRawPtr(), badPtr );
910 #endif
911 }
912 
913 
914 TEUCHOS_UNIT_TEST( RCP, danglingPtr2 )
915 {
916  ECHO(Ptr<A> a_ptr);
917  ECHO(A *badPtr = 0);
918  {
919  ECHO(RCP<A> a_rcp = rcp(new A));
920  ECHO(badPtr = a_rcp.getRawPtr());
921  ECHO(a_ptr = a_rcp.ptr());
922  TEST_EQUALITY( a_ptr.getRawPtr(), badPtr );
923  }
924 #ifdef TEUCHOS_DEBUG
925  TEST_THROW( *a_ptr, DanglingReferenceError );
926  (void)badPtr;
927 #else
928  TEST_EQUALITY( a_ptr.getRawPtr(), badPtr );
929 #endif
930 }
931 
932 
933 TEUCHOS_UNIT_TEST( RCP, danglingPtr3 )
934 {
935  ECHO(Ptr<A> a_ptr);
936  ECHO(A *badPtr = 0);
937  {
938  ECHO(RCP<A> a_rcp = rcp(new A));
939  ECHO(badPtr = a_rcp.getRawPtr());
940  ECHO(Ptr<A> a_ptr2(a_rcp.ptr()));
941  ECHO(Ptr<A> a_ptr3(a_ptr2));
942  ECHO(a_ptr = a_ptr3);
943  TEST_EQUALITY( a_ptr.getRawPtr(), badPtr );
944  }
945 #ifdef TEUCHOS_DEBUG
946  TEST_THROW( *a_ptr, DanglingReferenceError );
947  (void)badPtr;
948 #else
949  TEST_EQUALITY( a_ptr.getRawPtr(), badPtr );
950 #endif
951 }
952 
953 
954 TEUCHOS_UNIT_TEST( RCP, danglingPtr4 )
955 {
956  ECHO(Ptr<A> a_ptr);
957  ECHO(A *badPtr = 0);
958  {
959  ECHO(RCP<C> c_rcp = rcp(new C));
960  ECHO(badPtr = c_rcp.getRawPtr());
961  ECHO(Ptr<A> a_ptr2(c_rcp.ptr()));
962  ECHO(a_ptr = a_ptr2);
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 #ifdef TEUCHOS_DEBUG
975 
976 /* ToDo: Comment this back in once I have everything working
977 
978 // Test that the RCPNode tracing machinary can detect if an owning RCPNode is
979 // being created that would result in a double delete.
980 TEUCHOS_UNIT_TEST( RCP, multiRcpCreateError )
981 {
982  C *c_ptr = new C;
983 #if !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING)
984  Teuchos::setTracingActiveRCPNodes(true);
985 #endif
986  RCP<C> c_rcp = rcp(c_ptr); // Okay
987  RCP<C> c_rcp2;
988  TEST_THROW(c_rcp2 = rcp(c_ptr), DuplicateOwningRCPError);
989 #if !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING)
990  Teuchos::setTracingActiveRCPNodes(false);
991 #endif
992  // Clean up memory so no leaks and not double deletes no matter what.
993  c_rcp.release();
994  c_rcp2.release();
995  delete c_ptr;
996 }
997 
998 */
999 
1000 #endif // TEUCHOS_DEBUG
1001 
1002 
1003 //
1004 // invertObjectOwnership
1005 //
1006 
1007 
1008 RCP<C> createCAFactory()
1009 {
1010  RCP<C> c = rcp(new C);
1011  c->set_A(rcp(new A));
1012  return c;
1013 }
1014 
1015 
1016 RCP<A> createACFactory()
1017 {
1018  RCP<C> c = createCAFactory();
1019  return Teuchos::rcpWithInvertedObjOwnership(c->get_A(), c);
1020 }
1021 
1022 
1023 RCP<C> extractCFromA(const RCP<A> &a)
1024 {
1025  return Teuchos::getInvertedObjOwnershipParent<C>(a);
1026 }
1027 
1028 
1029 TEUCHOS_UNIT_TEST( RCP, invertObjectOwnership_basic )
1030 {
1031  RCP<A> a = createACFactory();
1032  RCP<C> c = extractCFromA(a);
1033  TEST_EQUALITY_CONST( a.strong_count(), 1 );
1034  TEST_EQUALITY_CONST( c->get_A().strong_count(), 3 );
1035  TEST_ASSERT( !a.shares_resource(c->get_A()) );
1036  TEST_EQUALITY( a.getRawPtr(), c->get_A().getRawPtr() );
1037  TEST_EQUALITY( a->A_g(), A_g_return );
1038  TEST_EQUALITY( c->C_g(), C_g_return );
1039 }
1040 
1041 
1042 // This unit test shows that you can remove the RCP in the C object
1043 // and the A object will still live on.
1044 TEUCHOS_UNIT_TEST( RCP, invertObjectOwnership_remove_A )
1045 {
1046  RCP<A> a = createACFactory();
1047  extractCFromA(a)->set_A(null);
1048  RCP<C> c = extractCFromA(a);
1049  TEST_EQUALITY_CONST( a.strong_count(), 1 );
1050  TEST_EQUALITY_CONST( c->get_A(), null );
1051  TEST_EQUALITY( a->A_g(), A_g_return );
1052  TEST_EQUALITY( c->C_g(), C_g_return );
1053 }
1054 
1055 
1056 //
1057 // createRCPWithBadDealloc
1058 //
1059 
1060 
1061 RCP<A> createRCPWithBadDealloc()
1062 {
1063  return rcp(new A[1]); // Will use delete but should use delete []!
1064 }
1065 
1066 
1067 template<typename T>
1068 class DeallocArrayDeleteExtraData {
1069 public:
1070  static RCP<DeallocArrayDeleteExtraData<T> > create(T *ptr)
1071  { return rcp(new DeallocArrayDeleteExtraData(ptr)); }
1072  ~DeallocArrayDeleteExtraData() { delete [] ptr_; }
1073 private:
1074  T *ptr_;
1075  DeallocArrayDeleteExtraData(T *ptr) : ptr_(ptr) {}
1076  // Not defined!
1077  DeallocArrayDeleteExtraData();
1078  DeallocArrayDeleteExtraData(const DeallocArrayDeleteExtraData&);
1079  DeallocArrayDeleteExtraData& operator=(const DeallocArrayDeleteExtraData&);
1080 };
1081 
1082 
1083 // This unit test shows how you can use extra data to fix a bad deallocation
1084 // policy
1085 TEUCHOS_UNIT_TEST( RCP, Fix_createRCPWithBadDealloc )
1086 {
1087  using Teuchos::inOutArg;
1088  using Teuchos::set_extra_data;
1089  // Create object with bad deallocator
1090  RCP<A> a = createRCPWithBadDealloc();
1091  TEST_ASSERT(nonnull(a));
1092  // Disable default (incorrect) dealloc and set a new deallocation policy as extra data!
1093  a.release();
1094  set_extra_data( DeallocArrayDeleteExtraData<A>::create(a.getRawPtr()), "dealloc",
1095  inOutArg(a));
1096 }
1097 
1098 
1099 //
1100 // Test RCP/boost::shared_ptr covnersions
1101 //
1102 
1103 
1104 #ifdef HAVE_TEUCHOS_BOOST
1105 
1106 
1107 TEUCHOS_UNIT_TEST( boost_shared_ptr, nonnull_is_null )
1108 {
1109  using boost::shared_ptr;
1110  ECHO(shared_ptr<A> a_sptr(new A));
1111  TEST_EQUALITY_CONST(is_null(a_sptr), false);
1112  TEST_EQUALITY_CONST(nonnull(a_sptr), true);
1113  ECHO(a_sptr = shared_ptr<A>());
1114  TEST_EQUALITY_CONST(is_null(a_sptr), true);
1115  TEST_EQUALITY_CONST(nonnull(a_sptr), false);
1116 }
1117 
1118 
1119 #endif // HAVE_TEUCHOS_BOOST
1120 
1121 
1122 //
1123 // Test RCP/std::shared_ptr covnersions
1124 //
1125 
1126 
1127 #ifdef HAVE_TEUCHOSCORE_CXX11
1128 
1129 
1130 TEUCHOS_UNIT_TEST( std_shared_ptr, nonnull_is_null )
1131 {
1132  using std::shared_ptr;
1133  ECHO(shared_ptr<A> a_sptr(new A));
1134  TEST_EQUALITY_CONST(Teuchos::is_null(a_sptr), false);
1135  TEST_EQUALITY_CONST(Teuchos::nonnull(a_sptr), true);
1136  ECHO(a_sptr = shared_ptr<A>());
1137  TEST_EQUALITY_CONST(Teuchos::is_null(a_sptr), true);
1138  TEST_EQUALITY_CONST(Teuchos::nonnull(a_sptr), false);
1139 }
1140 
1141 
1142 TEUCHOS_UNIT_TEST( std_shared_ptr, convert_to_RCP_null )
1143 {
1144  const std::shared_ptr<A> a_sptr1;
1145  const RCP<A> a_rsptr1 = rcp(a_sptr1);
1146  TEST_EQUALITY( a_rsptr1.get(), a_sptr1.get() );
1147  TEST_ASSERT(is_null(a_rsptr1));
1148 
1149  const std::shared_ptr<A> a_sptr2 = get_shared_ptr(a_rsptr1);
1150  TEST_EQUALITY( a_sptr1.get(), a_sptr1.get() );
1151  TEST_ASSERT(Teuchos::is_null(a_sptr2));
1152 }
1153 
1154 
1155 TEUCHOS_UNIT_TEST( std_shared_ptr, convert_to_RCP )
1156 {
1157  const std::shared_ptr<A> a_sptr1(new C());
1158  const RCP<A> a_rsptr1 = rcp(a_sptr1);
1159  TEST_EQUALITY( a_rsptr1.get(), a_sptr1.get() );
1160  TEST_EQUALITY( a_rsptr1.getRawPtr(), a_sptr1.get() );
1161  TEST_EQUALITY( a_rsptr1.get(), a_rsptr1.getRawPtr() );
1162 
1163  const std::shared_ptr<A> a_sptr2 = get_shared_ptr(a_rsptr1);
1164  TEST_EQUALITY( a_sptr1.get(), a_sptr1.get() );
1165  // NOTE: There is no portable way to check that two std::shared_ptr objects
1166  // share the same underlying shared node :-(
1167 }
1168 
1169 
1170 TEUCHOS_UNIT_TEST( std_shared_ptr, convert_from_RCP_null )
1171 {
1172  const RCP<A> a_rcp1;
1173  const std::shared_ptr<A> a_sptr1(get_shared_ptr(a_rcp1));
1174  TEST_EQUALITY( a_rcp1.get(), a_sptr1.get() );
1175  TEST_ASSERT(Teuchos::is_null(a_sptr1));
1176 
1177  const RCP<A> a_rcp2 = rcp(a_sptr1);
1178  TEST_EQUALITY(a_rcp2.get(), a_sptr1.get());
1179  TEST_ASSERT(is_null(a_rcp2));
1180 }
1181 
1182 
1183 TEUCHOS_UNIT_TEST( std_shared_ptr, convert_from_RCP )
1184 {
1185  const RCP<A> a_rcp1(new C());
1186  const std::shared_ptr<A> a_sptr1(get_shared_ptr(a_rcp1));
1187  TEST_EQUALITY( a_rcp1.get(), a_sptr1.get() );
1188  TEST_EQUALITY( a_rcp1.getRawPtr(), a_sptr1.get() );
1189  TEST_EQUALITY( a_sptr1.get(), a_rcp1.getRawPtr() );
1190 
1191  const RCP<A> a_rcp2 = rcp(a_sptr1);
1192  TEST_EQUALITY( a_rcp2.get(), a_sptr1.get() );
1193  TEST_EQUALITY( a_rcp2.get(), a_rcp1.get() );
1194  TEST_ASSERT( a_rcp1.shares_resource(a_rcp2) );
1195 }
1196 
1197 
1198 #ifdef TEUCHOS_DEBUG
1199 
1200 
1201 TEUCHOS_UNIT_TEST( std_shared_ptr, convert_from_RCP_lookup_node )
1202 {
1203  const RCP<A> a_rcp1(new C());
1204  const std::shared_ptr<A> a_sptr1(get_shared_ptr(a_rcp1));
1205  TEST_EQUALITY( a_sptr1.get(), a_rcp1.get() );
1206 
1207  const RCP<C> c_rcp1 = rcp(std::dynamic_pointer_cast<C>(a_sptr1));
1208  TEST_EQUALITY( c_rcp1.get(), a_rcp1.get() );
1209  TEST_ASSERT( c_rcp1.shares_resource(a_rcp1) );
1210  // NOTE: The above test shows how Teuchos::RCP machinery will automatically
1211  // look up the underlying RCPNode object and use it!
1212 }
1213 
1214 
1215 #endif // TEUCHOS_DEBUG
1216 
1217 
1218 #endif // HAVE_TEUCHOSCORE_CXX11
1219 
1220 
1221 
1222 //
1223 // Template Instantiations
1224 //
1225 
1226 
1227 #ifdef TEUCHOS_DEBUG
1228 
1229 # define DEBUG_UNIT_TEST_GROUP( T ) \
1230 
1231 #else
1232 
1233 # define DEBUG_UNIT_TEST_GROUP( T )
1234 
1235 #endif
1236 
1237 
1238 #define UNIT_TEST_GROUP( T ) \
1239  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( RCP, weakDelete, T ) \
1240  DEBUG_UNIT_TEST_GROUP(T)
1241 
1242 
1247 
1248 
1249 } // 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.
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
#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.
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.
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.
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...
bool nonnull(const ArrayRCP< T > &p)
Returns true if p.get()!=NULL.
#define UNIT_TEST_GROUP(T)