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