/* * Copyright information and license terms for this software can be * found in the file LICENSE that is included with the distribution */ /* Author: Michael Davidsaver */ #include #include #include #include #include #include #include #if __cplusplus>=201103L #include namespace { void show(const epics::debug::shared_ptr_base& ref) { epics::debug::ptr_base::ref_set_t refs; ref.spy_refs(refs); std::ostringstream strm; std::copy(refs.begin(), refs.end(), std::ostream_iterator(strm, ", ")); testDiag("refs: %s", strm.str().c_str()); ref.show_refs(std::cout); } void testEmpty() { testDiag("testEmpty()"); epics::debug::shared_ptr empty; testOk1(!empty); epics::debug::ptr_base::ref_set_t refs; empty.spy_refs(refs); testOk1(refs.empty()); } void testSimple() { testDiag("testSimple()"); testDiag("ctor"); epics::debug::shared_ptr one(new int(42)), two; testDiag("one = %p two = %p", &one, &two); show(one); show(two); { epics::debug::ptr_base::ref_set_t refs; one.spy_refs(refs); testOk1(refs.size()==1); testOk1(refs.find(&one)!=refs.end()); testOk1(refs.find(&two)==refs.end()); } testDiag("assign non-NULL"); two = one; show(one); show(two); { epics::debug::ptr_base::ref_set_t refs; one.spy_refs(refs); testOk1(refs.size()==2); testOk1(refs.find(&one)!=refs.end()); testOk1(refs.find(&two)!=refs.end()); } testDiag("reset"); one.reset(); show(one); show(two); { epics::debug::ptr_base::ref_set_t refs; one.spy_refs(refs); testOk1(refs.size()==0); } { epics::debug::ptr_base::ref_set_t refs; two.spy_refs(refs); testOk1(refs.size()==1); testOk1(refs.find(&one)==refs.end()); testOk1(refs.find(&two)!=refs.end()); } testDiag("copy ctor"); epics::debug::shared_ptr three(two), empty(one); show(three); show(empty); testDiag("three = %p empty = %p", &three, &empty); { epics::debug::ptr_base::ref_set_t refs; empty.spy_refs(refs); testOk1(refs.size()==0); } { epics::debug::ptr_base::ref_set_t refs; three.spy_refs(refs); testOk1(refs.size()==2); testOk1(refs.find(&one)==refs.end()); testOk1(refs.find(&two)!=refs.end()); testOk1(refs.find(&three)!=refs.end()); testOk1(refs.find(&empty)==refs.end()); } } struct Base {virtual ~Base(){}}; struct Derv : public Base {virtual ~Derv(){}}; void testCast() { testDiag("testCast()"); epics::debug::shared_ptr one(new int(42)); testOk1(!!one); epics::debug::shared_ptr two(one); testOk1(one.get()==two.get()); epics::debug::shared_ptr three(one); testOk1(one.get()==three.get()); epics::debug::shared_ptr four(epics::debug::const_pointer_cast(three)); testOk1(one.get()==four.get()); epics::debug::shared_ptr X(new Derv); epics::debug::shared_ptr Y(epics::debug::static_pointer_cast(X)); testOk1(X.get()==Y.get()); } void testWeak() { testDiag("testWeak()"); epics::debug::shared_ptr one(new int(42)); { epics::debug::weak_ptr two(one); epics::debug::shared_ptr three(two); testOk1(three.get()==one.get()); } { epics::debug::weak_ptr two(one); epics::debug::shared_ptr three(two.lock()); testOk1(three.get()==one.get()); } } struct MySelf : public epics::debug::enable_shared_from_this {}; void testEnable() { testDiag("testEnable()"); epics::debug::shared_ptr self(new MySelf), other(self->shared_from_this()); testOk1(!!self); testOk1(self.get()==other.get()); } template struct set_flag_dtor { bool *pflag; set_flag_dtor(bool *pflag) :pflag(pflag) {} void operator()(T* x) { delete x; *pflag = true; pflag = 0; // paranoia } }; void testDtor() { testDiag("testDtor()"); bool flag = false; { epics::debug::shared_ptr x(new Derv, set_flag_dtor(&flag)); testOk1(!!x); testOk1(!flag); } testOk1(flag); flag = false; bool flag2 = false; { epics::debug::shared_ptr x(new Derv, set_flag_dtor(&flag)); testOk1(!!x); Derv *old = x.get(); testOk1(!flag); testOk1(!flag2); x.reset(new Derv, set_flag_dtor(&flag2)); testOk1(!!x); testOk1(old!=x.get()); testOk1(flag); testOk1(!flag2); } testOk1(flag2); testDiag("destroy Derv as Base"); flag = false; { epics::debug::shared_ptr x(new Derv, set_flag_dtor(&flag)); testOk1(!!x); testOk1(!flag); } testOk1(flag); } struct BaseEnable { virtual ~BaseEnable() {} virtual epics::debug::shared_ptr self() =0; }; struct DervEnable : public BaseEnable, public epics::debug::enable_shared_from_this { virtual ~DervEnable() {} virtual epics::debug::shared_ptr self() { return shared_from_this(); } }; void testEnableDerv() { testDiag("testEnableDerv()"); epics::debug::shared_ptr x(new DervEnable), y(x->self()); testOk1(!!x); testOk1(x.get()==y.get()); BaseEnable *old = x.get(); x.reset(); testOk1(!x); testOk1(y.unique()); x.reset(new DervEnable); y = x->self(); testOk1(!!x); testOk1(x.get()!=old); testOk1(x.get()==y.get()); } } // namespace MAIN(testDebugPtr) { testPlan(48); try { testEmpty(); testSimple(); testCast(); testWeak(); testEnable(); testDtor(); testEnableDerv(); }catch(std::exception& e){ testAbort("Unhandled exception: %s", e.what()); } return testDone(); } #else // __cplusplus>=201103L MAIN(testDebugPtr) { testPlan(1); testSkip(1, "Not c++11"); return testDone(); } #endif // __cplusplus>=201103L