#include "stdafx.h" #include "tl/ptr.h" #include // each test module could contain no more then one 'main' file with init function defined // alternatively you could define init function yourself #include // These are sample tests that show the different features of the framework struct ExpectedAssertGuard { ExpectedAssertGuard(tl::string msg) { s_msgs.push_back(std::move(msg)); s_oldHandlers.push_back(tl::assert::set_handler(assertHandler)); } ~ExpectedAssertGuard() { tl::assert::set_handler(s_oldHandlers.back()); s_oldHandlers.pop_back(); s_msgs.pop_back(); } private: static tl::assert::response assertHandler(const char* condition, const char* file, int line, const char* msg) { BOOST_CHECK(s_msgs.back() == msg); return tl::assert::response::CONTINUE; } static tl::vector s_msgs; static tl::vector s_oldHandlers; }; tl::vector ExpectedAssertGuard::s_msgs; tl::vector ExpectedAssertGuard::s_oldHandlers; struct NoAssertsGuard { NoAssertsGuard() { s_oldHandlers.push_back(tl::assert::set_handler(assertHandler)); } ~NoAssertsGuard() { tl::assert::set_handler(s_oldHandlers.back()); s_oldHandlers.pop_back(); } private: static tl::assert::response assertHandler(const char* condition, const char* file, int line, const char* msg) { BOOST_FAIL(tl::format("Unexpected assert: [{}] {}({}): {}", condition ? condition : "", file ? file : "", line, msg ? msg : "").c_str()); return tl::assert::response::CONTINUE; } static tl::vector s_oldHandlers; }; tl::vector NoAssertsGuard::s_oldHandlers; struct ExpectedCrashGuard { ExpectedCrashGuard(tl::string msg) { s_msgs.push_back(std::move(msg)); s_oldHandlers.push_back(tl::crash::set_handler(crashHandler)); } ~ExpectedCrashGuard() { tl::crash::set_handler(s_oldHandlers.back()); s_oldHandlers.pop_back(); s_msgs.pop_back(); } private: static tl::crash::response crashHandler(const char* file, int line, const char* msg) { BOOST_CHECK(s_msgs.back() == msg); return tl::crash::response::CONTINUE; } static tl::vector s_msgs; static tl::vector s_oldHandlers; }; tl::vector ExpectedCrashGuard::s_msgs; tl::vector ExpectedCrashGuard::s_oldHandlers; struct NoCrashesGuard { NoCrashesGuard() { s_oldHandlers.push_back(tl::crash::set_handler(crashHandler)); } ~NoCrashesGuard() { tl::crash::set_handler(s_oldHandlers.back()); s_oldHandlers.pop_back(); } private: static tl::crash::response crashHandler(const char* file, int line, const char* msg) { BOOST_FAIL(tl::format("Unexpected crash: {}({}): {}", file ? file : "", line, msg ? msg : "").c_str()); return tl::crash::response::CONTINUE; } static tl::vector s_oldHandlers; }; tl::vector NoCrashesGuard::s_oldHandlers; struct Counters { auto operator<=>(Counters const& other) const noexcept = default; bool operator==(Counters const& other) const noexcept = default; size_t ctor = 0; size_t dtor = 0; size_t copyCtor = 0; size_t moveCtor = 0; size_t copyAss = 0; size_t moveAss = 0; void resetCounters() { ctor = 0; dtor = 0; copyCtor = 0; moveCtor = 0; copyAss = 0; moveAss = 0; } }; struct Test { Test(size_t data = 0) : data(data) { s_counters.ctor++; } ~Test() { s_counters.dtor++; } Test(const Test&) { s_counters.copyCtor++; } Test(Test&&) { s_counters.moveCtor++; } Test& operator=(const Test&) { s_counters.copyAss++; return *this; } Test& operator=(Test&&) { s_counters.moveAss++; return *this; } static void resetCounters() { s_counters.resetCounters(); } size_t data = 0; static Counters s_counters; }; Counters Test::s_counters; BOOST_AUTO_TEST_CASE(lent_ptr_ctor) { NoAssertsGuard eassert; Test::resetCounters(); tl::lent_ptr lptr; BOOST_CHECK(lptr.get() == nullptr); BOOST_CHECK(Test::s_counters == Counters{}); } BOOST_AUTO_TEST_CASE(lent_ptr_ctor_ptr) { NoAssertsGuard eassert; Test::resetCounters(); tl::lendable t; tl::lent_ptr lptr(tl::lend(t)); BOOST_CHECK(lptr.get() == &t.get()); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); } BOOST_AUTO_TEST_CASE(lent_ptr_copy_ctor) { NoAssertsGuard eassert; { Test::resetCounters(); tl::lent_ptr lptr1; tl::lent_ptr lptr2(lptr1); BOOST_CHECK(lptr2.get() == nullptr); BOOST_CHECK(Test::s_counters == Counters{}); } { Test::resetCounters(); tl::lendable t; tl::lent_ptr lptr1(tl::lend(t)); tl::lent_ptr lptr2(lptr1); BOOST_CHECK(lptr1.get() == &t.get()); BOOST_CHECK(lptr2.get() == &t.get()); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); } } BOOST_AUTO_TEST_CASE(lent_ptr_move_ctor) { NoAssertsGuard eassert; { Test::resetCounters(); tl::lent_ptr lptr1; tl::lent_ptr lptr2(std::move(lptr1)); BOOST_CHECK(lptr1.get() == nullptr); BOOST_CHECK(lptr2.get() == nullptr); BOOST_CHECK(Test::s_counters == Counters{}); } { Test::resetCounters(); tl::lendable t; tl::lent_ptr lptr1(tl::lend(t)); tl::lent_ptr lptr2(std::move(lptr1)); BOOST_CHECK(lptr1.get() == nullptr); BOOST_CHECK(lptr2.get() == &t.get()); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); } } BOOST_AUTO_TEST_CASE(lent_ptr_copy_ass) { NoAssertsGuard eassert; { Test::resetCounters(); tl::lent_ptr lptr1; tl::lent_ptr lptr2; lptr2 = lptr1; BOOST_CHECK(lptr2.get() == nullptr); BOOST_CHECK(Test::s_counters == Counters{}); } { Test::resetCounters(); tl::lendable t; tl::lent_ptr lptr1(tl::lend(t)); tl::lent_ptr lptr2; lptr2 = lptr1; BOOST_CHECK(lptr1.get() == &t.get()); BOOST_CHECK(lptr2.get() == &t.get()); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); } } BOOST_AUTO_TEST_CASE(lent_ptr_move_ass) { NoAssertsGuard eassert; { Test::resetCounters(); tl::lent_ptr lptr1; tl::lent_ptr lptr2; lptr2 = std::move(lptr1); BOOST_CHECK(lptr1.get() == nullptr); BOOST_CHECK(lptr2.get() == nullptr); BOOST_CHECK(Test::s_counters == Counters{}); } { Test::resetCounters(); tl::lendable t; tl::lent_ptr lptr1(tl::lend(t)); tl::lent_ptr lptr2; lptr2 = std::move(lptr1); BOOST_CHECK(lptr1.get() == nullptr); BOOST_CHECK(lptr2.get() == &t.get()); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); } } BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr) { NoAssertsGuard eassert; Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); tl::lent_ptr lptr1 = uptr; BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); BOOST_CHECK(lptr1.get() == uptr.get()); BOOST_CHECK((bool)lptr1 != false); BOOST_CHECK(lptr1 == uptr); BOOST_CHECK(lptr1 == uptr.get()); BOOST_CHECK(lptr1.get() == uptr); BOOST_CHECK(lptr1->data = 1234); lptr1 = nullptr; BOOST_CHECK(lptr1.get() == nullptr); BOOST_CHECK((bool)lptr1 == false); BOOST_CHECK(lptr1 == nullptr); } BOOST_AUTO_TEST_CASE(lent_ptr_unique_ref) { Test::resetCounters(); tl::unique_ref uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); tl::lent_ptr lptr1 = uptr; BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); BOOST_CHECK(lptr1.get() == uptr.get()); BOOST_CHECK(lptr1 == uptr); BOOST_CHECK(lptr1 == uptr.get()); BOOST_CHECK(lptr1.get() == uptr); BOOST_CHECK(lptr1->data = 1234); lptr1 = nullptr; BOOST_CHECK(lptr1.get() == nullptr); BOOST_CHECK((bool)lptr1 == false); BOOST_CHECK(lptr1 == nullptr); } BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_no_dangling) { NoAssertsGuard eassert; Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); tl::lent_ptr lptr = uptr; lptr = nullptr; uptr = nullptr; //no dangling here! lptr = uptr; //no dangling here! } BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_move_no_dangling) { NoAssertsGuard eassert; Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); tl::unique_ptr uptr2; BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); tl::lent_ptr lptr = uptr; uptr2 = std::move(uptr); //no dangling here! lptr = uptr2; //no dangling here! } BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_assign_nullptr_dangling) { { Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); tl::lent_ptr lptr = uptr; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr = nullptr; //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = nullptr; //dangling here! } } { //destructor Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); tl::lent_ptr lptr = uptr; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr = nullptr; //dangling here! } } //dangling here! } { //reset Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); tl::lent_ptr lptr = uptr; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr = nullptr; //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = nullptr; //dangling here! } } { //copy assignment to empty ptr Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); tl::lent_ptr lptr = uptr; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr = nullptr; //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = {}; //dangling here! } } { //copy assignment to another valid ptr Test::resetCounters(); tl::unique_ptr uptr1(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ptr lptr1 = uptr1; tl::lent_ptr lptr2 = uptr2; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr1 = nullptr; //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr1 = lptr2; //dangling here! } } { //move assignment to a valid ptr Test::resetCounters(); tl::unique_ptr uptr1(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ptr lptr1 = uptr1; tl::lent_ptr lptr2 = uptr2; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr1 = nullptr; //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr1 = std::move(lptr2); //dangling here! } } { //move assignment to a valid ptr Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); tl::lent_ptr lptr1 = uptr; tl::lent_ptr lptr2 = uptr; tl::lent_ptr lptr3 = uptr; tl::lent_ptr lptr4 = uptr; { ExpectedAssertGuard eassert("unique: 4 dangling lent ptrs detected"); uptr = nullptr; //dangling here! } { ExpectedAssertGuard eassert("lent: 4 dangling lent ptrs detected"); lptr1 = {}; //dangling here! } { ExpectedAssertGuard eassert("lent: 3 dangling lent ptrs detected"); lptr2 = {}; //dangling here! } { ExpectedAssertGuard eassert("lent: 2 dangling lent ptrs detected"); lptr3 = {}; //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr4 = {}; //dangling here! } } { //move assignment to a valid ptr Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); tl::lent_ptr lptr1 = uptr; tl::lent_ptr lptr2 = std::move(lptr1); { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr = nullptr; //dangling here! } { NoAssertsGuard eassert; lptr1 = {}; //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr2 = {}; //dangling here! } } } BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_assign_new_dangling) { { Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); tl::lent_ptr lptr = uptr; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr = {}; //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = nullptr; //dangling here! } } { //destructor Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); tl::lent_ptr lptr = uptr; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr = {}; //dangling here! } } //dangling here! } { //reset Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); tl::lent_ptr lptr = uptr; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr = {}; //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = nullptr; //dangling here! } } { //copy assignment to empty ptr Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); tl::lent_ptr lptr = uptr; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr = {}; //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = {}; //dangling here! } } { //copy assignment to another valid ptr Test::resetCounters(); tl::unique_ptr uptr1(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ptr lptr1 = uptr1; tl::lent_ptr lptr2 = uptr2; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr1 = {}; //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr1 = lptr2; //dangling here! } } { //move assignment to a valid ptr Test::resetCounters(); tl::unique_ptr uptr1(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ptr lptr1 = uptr1; tl::lent_ptr lptr2 = uptr2; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr1 = {}; //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr1 = std::move(lptr2); //dangling here! } } { //move assignment to a valid ptr Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); tl::lent_ptr lptr1 = uptr; tl::lent_ptr lptr2 = uptr; tl::lent_ptr lptr3 = uptr; tl::lent_ptr lptr4 = uptr; { ExpectedAssertGuard eassert("unique: 4 dangling lent ptrs detected"); uptr = {}; //dangling here! } { ExpectedAssertGuard eassert("lent: 4 dangling lent ptrs detected"); lptr1 = {}; //dangling here! } { ExpectedAssertGuard eassert("lent: 3 dangling lent ptrs detected"); lptr2 = {}; //dangling here! } { ExpectedAssertGuard eassert("lent: 2 dangling lent ptrs detected"); lptr3 = {}; //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr4 = {}; //dangling here! } } } BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_reset_dangling) { { Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); tl::lent_ptr lptr = uptr; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr.reset(); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = nullptr; //dangling here! } } { //destructor Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); tl::lent_ptr lptr = uptr; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr.reset(); //dangling here! } } //dangling here! } { //reset Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); tl::lent_ptr lptr = uptr; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr.reset(); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = nullptr; //dangling here! } } { //copy assignment to empty ptr Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); tl::lent_ptr lptr = uptr; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr.reset(); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = {}; //dangling here! } } { //copy assignment to another valid ptr Test::resetCounters(); tl::unique_ptr uptr1(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ptr lptr1 = uptr1; tl::lent_ptr lptr2 = uptr2; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr1.reset(); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr1 = lptr2; //dangling here! } } { //move assignment to a valid ptr Test::resetCounters(); tl::unique_ptr uptr1(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ptr lptr1 = uptr1; tl::lent_ptr lptr2 = uptr2; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr1.reset(); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr1 = std::move(lptr2); //dangling here! } } { //move assignment to a valid ptr Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); tl::lent_ptr lptr1 = uptr; tl::lent_ptr lptr2 = uptr; tl::lent_ptr lptr3 = uptr; tl::lent_ptr lptr4 = uptr; { ExpectedAssertGuard eassert("unique: 4 dangling lent ptrs detected"); uptr.reset(); //dangling here! } { ExpectedAssertGuard eassert("lent: 4 dangling lent ptrs detected"); lptr1 = {}; //dangling here! } { ExpectedAssertGuard eassert("lent: 3 dangling lent ptrs detected"); lptr2 = {}; //dangling here! } { ExpectedAssertGuard eassert("lent: 2 dangling lent ptrs detected"); lptr3 = {}; //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr4 = {}; //dangling here! } } } BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_assign_move_dangling) { { Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ptr lptr = uptr; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr = std::move(uptr2); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = nullptr; //dangling here! } } { //destructor Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); tl::lent_ptr lptr = uptr; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr = std::move(uptr2); //dangling here! } } //dangling here! } { //reset Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ptr lptr = uptr; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr = std::move(uptr2); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = nullptr; //dangling here! } } { //copy assignment to empty ptr Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ptr lptr = uptr; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr = std::move(uptr2); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = {}; //dangling here! } } { //copy assignment to another valid ptr Test::resetCounters(); tl::unique_ptr uptr1(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); tl::unique_ptr uptr3(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 3}); tl::lent_ptr lptr1 = uptr1; tl::lent_ptr lptr2 = uptr2; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr1 = std::move(uptr3); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr1 = lptr2; //dangling here! } } { //move assignment to a valid ptr Test::resetCounters(); tl::unique_ptr uptr1(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); tl::unique_ptr uptr3(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 3}); tl::lent_ptr lptr1 = uptr1; tl::lent_ptr lptr2 = uptr2; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr1 = std::move(uptr3); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr1 = std::move(lptr2); //dangling here! } } { //move assignment to a valid ptr Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ptr lptr1 = uptr; tl::lent_ptr lptr2 = uptr; tl::lent_ptr lptr3 = uptr; tl::lent_ptr lptr4 = uptr; { ExpectedAssertGuard eassert("unique: 4 dangling lent ptrs detected"); uptr = std::move(uptr2); //dangling here! } { ExpectedAssertGuard eassert("lent: 4 dangling lent ptrs detected"); lptr1 = {}; //dangling here! } { ExpectedAssertGuard eassert("lent: 3 dangling lent ptrs detected"); lptr2 = {}; //dangling here! } { ExpectedAssertGuard eassert("lent: 2 dangling lent ptrs detected"); lptr3 = {}; //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr4 = {}; //dangling here! } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// BOOST_AUTO_TEST_CASE(lent_ptr_unique_ref_no_dangling) { NoAssertsGuard eassert; tl::lent_ptr lptr; { Test::resetCounters(); tl::unique_ref uref(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); lptr = uref; lptr = nullptr; } lptr = {}; //no dangling here! } BOOST_AUTO_TEST_CASE(lent_ptr_unique_ref_move_no_dangling) { NoAssertsGuard eassert; Test::resetCounters(); tl::unique_ref uref(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); tl::lent_ptr lptr = uref; tl::unique_ref uref2 = std::move(uref); //no dangling here! lptr = uref2; //no dangling here! lptr = nullptr; //to avoid a legit dangling when the uref2 goes out of scope } BOOST_AUTO_TEST_CASE(lent_ptr_unique_ref_assign_nullptr_dangling) { { Test::resetCounters(); tl::unique_ref uref(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); tl::lent_ptr lptr = uref; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref = tl::unique_ref(new Test(1234)); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = nullptr; //dangling here! } } { //destructor Test::resetCounters(); tl::unique_ref uref(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); tl::lent_ptr lptr = uref; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref = tl::unique_ref(new Test(1234)); //dangling here! } } //dangling here! } { //reset Test::resetCounters(); tl::unique_ref uref(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); tl::lent_ptr lptr = uref; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref = tl::unique_ref(new Test(1234)); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = nullptr; //dangling here! } } { //copy assignment to empty ptr Test::resetCounters(); tl::unique_ref uref(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); tl::lent_ptr lptr = uref; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref = tl::unique_ref(new Test(1234)); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = {}; //dangling here! } } { //copy assignment to another valid ptr Test::resetCounters(); tl::unique_ref uref1(new Test(1234)); tl::unique_ref uref2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ptr lptr1 = uref1; tl::lent_ptr lptr2 = uref2; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref1 = tl::unique_ref(new Test(1234)); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr1 = lptr2; //dangling here! } } { //move assignment to a valid ptr Test::resetCounters(); tl::unique_ref uref1(new Test(1234)); tl::unique_ref uref2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ptr lptr1 = uref1; tl::lent_ptr lptr2 = uref2; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref1 = tl::unique_ref(new Test(1234)); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr1 = std::move(lptr2); //dangling here! } } { //move assignment to a valid ptr Test::resetCounters(); tl::unique_ref uref(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); tl::lent_ptr lptr1 = uref; tl::lent_ptr lptr2 = uref; tl::lent_ptr lptr3 = uref; tl::lent_ptr lptr4 = uref; { ExpectedAssertGuard eassert("unique: 4 dangling lent ptrs detected"); uref = tl::unique_ref(new Test(1234)); //dangling here! } { ExpectedAssertGuard eassert("lent: 4 dangling lent ptrs detected"); lptr1 = {}; //dangling here! } { ExpectedAssertGuard eassert("lent: 3 dangling lent ptrs detected"); lptr2 = {}; //dangling here! } { ExpectedAssertGuard eassert("lent: 2 dangling lent ptrs detected"); lptr3 = {}; //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr4 = {}; //dangling here! } } } BOOST_AUTO_TEST_CASE(lent_ptr_unique_ref_reset_dangling) { { Test::resetCounters(); tl::unique_ref uref(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); tl::lent_ptr lptr = uref; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref.reset(new Test(1234)); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = nullptr; //dangling here! } } { //destructor Test::resetCounters(); tl::unique_ref uref(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); tl::lent_ptr lptr = uref; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref.reset(new Test(1234)); //dangling here! } } //dangling here! } { //reset Test::resetCounters(); tl::unique_ref uref(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); tl::lent_ptr lptr = uref; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref.reset(new Test(1234)); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = nullptr; //dangling here! } } { //copy assignment to empty ptr Test::resetCounters(); tl::unique_ref uref(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); tl::lent_ptr lptr = uref; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref.reset(new Test(1234)); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = {}; //dangling here! } } { //copy assignment to another valid ptr Test::resetCounters(); tl::unique_ref uref1(new Test(1234)); tl::unique_ref uref2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ptr lptr1 = uref1; tl::lent_ptr lptr2 = uref2; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref1.reset(new Test(1234)); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr1 = lptr2; //dangling here! } } { //move assignment to a valid ptr Test::resetCounters(); tl::unique_ref uref1(new Test(1234)); tl::unique_ref uref2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ptr lptr1 = uref1; tl::lent_ptr lptr2 = uref2; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref1.reset(new Test(1234)); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr1 = std::move(lptr2); //dangling here! } } { //move assignment to a valid ptr Test::resetCounters(); tl::unique_ref uref(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); tl::lent_ptr lptr1 = uref; tl::lent_ptr lptr2 = uref; tl::lent_ptr lptr3 = uref; tl::lent_ptr lptr4 = uref; { ExpectedAssertGuard eassert("unique: 4 dangling lent ptrs detected"); uref.reset(new Test(1234)); //dangling here! } { ExpectedAssertGuard eassert("lent: 4 dangling lent ptrs detected"); lptr1 = {}; //dangling here! } { ExpectedAssertGuard eassert("lent: 3 dangling lent ptrs detected"); lptr2 = {}; //dangling here! } { ExpectedAssertGuard eassert("lent: 2 dangling lent ptrs detected"); lptr3 = {}; //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr4 = {}; //dangling here! } } } BOOST_AUTO_TEST_CASE(lent_ptr_unique_ref_assign_move_dangling) { { Test::resetCounters(); tl::unique_ref uref(new Test(1234)); tl::unique_ref uref2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ptr lptr = uref; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref = std::move(uref2); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = nullptr; //dangling here! } } { //destructor Test::resetCounters(); tl::unique_ref uref(new Test(1234)); tl::unique_ref uref2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); tl::lent_ptr lptr = uref; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref = std::move(uref2); //dangling here! } } //dangling here! } { //reset Test::resetCounters(); tl::unique_ref uref(new Test(1234)); tl::unique_ref uref2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ptr lptr = uref; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref = std::move(uref2); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = nullptr; //dangling here! } } { //copy assignment to empty ptr Test::resetCounters(); tl::unique_ref uref(new Test(1234)); tl::unique_ref uref2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ptr lptr = uref; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref = std::move(uref2); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = {}; //dangling here! } } { //copy assignment to another valid ptr Test::resetCounters(); tl::unique_ref uref1(new Test(1234)); tl::unique_ref uref2(new Test(1234)); tl::unique_ref uref3(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 3}); tl::lent_ptr lptr1 = uref1; tl::lent_ptr lptr2 = uref2; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref1 = std::move(uref3); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr1 = lptr2; //dangling here! } } { //move assignment to a valid ptr Test::resetCounters(); tl::unique_ref uref1(new Test(1234)); tl::unique_ref uref2(new Test(1234)); tl::unique_ref uref3(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 3}); tl::lent_ptr lptr1 = uref1; tl::lent_ptr lptr2 = uref2; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref1 = std::move(uref3); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr1 = std::move(lptr2); //dangling here! } } { //move assignment to a valid ptr Test::resetCounters(); tl::unique_ref uref(new Test(1234)); tl::unique_ref uref2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ptr lptr1 = uref; tl::lent_ptr lptr2 = uref; tl::lent_ptr lptr3 = uref; tl::lent_ptr lptr4 = uref; { ExpectedAssertGuard eassert("unique: 4 dangling lent ptrs detected"); uref = std::move(uref2); //dangling here! } { ExpectedAssertGuard eassert("lent: 4 dangling lent ptrs detected"); lptr1 = {}; //dangling here! } { ExpectedAssertGuard eassert("lent: 3 dangling lent ptrs detected"); lptr2 = {}; //dangling here! } { ExpectedAssertGuard eassert("lent: 2 dangling lent ptrs detected"); lptr3 = {}; //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr4 = {}; //dangling here! } } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// BOOST_AUTO_TEST_CASE(lent_ref_ctor_ptr) { NoAssertsGuard eassert; Test::resetCounters(); tl::lendable t; tl::lent_ref lptr(tl::lend(t)); BOOST_CHECK(lptr.get() == &t.get()); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); } BOOST_AUTO_TEST_CASE(lent_ref_copy_ctor) { NoAssertsGuard eassert; { Test::resetCounters(); tl::lendable t; tl::lent_ref lptr1(tl::lend(t)); tl::lent_ref lptr2(lptr1); BOOST_CHECK(lptr1.get() == &t.get()); BOOST_CHECK(lptr2.get() == &t.get()); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); } } BOOST_AUTO_TEST_CASE(lent_ref_move_ctor) { NoAssertsGuard eassert; { Test::resetCounters(); tl::lendable t; tl::lent_ref lptr1(tl::lend(t)); tl::lent_ref lptr2(std::move(lptr1)); { ExpectedCrashGuard ecrash("nullptr"); BOOST_CHECK(lptr1.get() == nullptr); } BOOST_CHECK(lptr2.get() == &t.get()); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); } } BOOST_AUTO_TEST_CASE(lent_ref_copy_ass) { NoAssertsGuard eassert; { Test::resetCounters(); tl::lendable t1; tl::lendable t2; tl::lent_ref lptr1(tl::lend(t1)); tl::lent_ref lptr2(tl::lend(t2)); lptr2 = lptr1; BOOST_CHECK(lptr1.get() == &t1.get()); BOOST_CHECK(lptr2.get() == &t1.get()); BOOST_CHECK(t1->s_counters == Counters{.ctor = 2}); } } BOOST_AUTO_TEST_CASE(lent_ref_move_ass) { NoAssertsGuard eassert; { Test::resetCounters(); tl::lendable t1; tl::lendable t2; tl::lent_ref lptr1(tl::lend(t1)); tl::lent_ref lptr2(tl::lend(t2)); lptr2 = std::move(lptr1); { ExpectedCrashGuard ecrash("nullptr"); BOOST_CHECK(lptr1.get() == nullptr); } BOOST_CHECK(lptr2.get() == &t1.get()); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); } } BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr) { NoAssertsGuard eassert; Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); tl::lent_ref lptr1 = tl::promote(uptr); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); BOOST_CHECK(lptr1.get() == uptr.get()); BOOST_CHECK(lptr1 == uptr); BOOST_CHECK(lptr1 == uptr.get()); BOOST_CHECK(lptr1.get() == uptr); BOOST_CHECK(lptr1->data = 1234); } BOOST_AUTO_TEST_CASE(lent_ref_unique_ref) { Test::resetCounters(); tl::unique_ref uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); tl::lent_ref lptr1 = uptr; BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); BOOST_CHECK(lptr1.get() == uptr.get()); BOOST_CHECK(lptr1 == uptr); BOOST_CHECK(lptr1 == uptr.get()); BOOST_CHECK(lptr1.get() == uptr); BOOST_CHECK(lptr1->data = 1234); } BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_no_dangling) { NoAssertsGuard eassert; Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); { tl::lent_ref lptr = tl::promote(uptr); } //no dangling here! uptr = nullptr; } BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_move_no_dangling) { NoAssertsGuard eassert; Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); tl::unique_ptr uptr2; BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); tl::lent_ref lptr = tl::promote(uptr); uptr2 = std::move(uptr); //no dangling here! lptr = tl::promote(uptr2); //no dangling here! } BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_assign_nullptr_dangling) { { Test::resetCounters(); tl::lendable t; tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ref lptr = tl::promote(uptr); { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr = nullptr; //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } { //destructor Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); tl::lent_ref lptr = tl::promote(uptr); { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr = nullptr; //dangling here! } } //dangling here! } { //reset Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); tl::lent_ref lptr = tl::promote(uptr); { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr = nullptr; //dangling here! } } { //copy assignment to empty ptr Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); tl::lent_ref lptr = tl::promote(uptr); { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr = nullptr; //dangling here! } } { //copy assignment to another valid ptr Test::resetCounters(); tl::unique_ptr uptr1(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ref lptr1 = tl::promote(uptr1); tl::lent_ref lptr2 = tl::promote(uptr2); { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr1 = nullptr; //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr1 = lptr2; //dangling here! } } { //move assignment to a valid ptr Test::resetCounters(); tl::unique_ptr uptr1(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ref lptr1 = tl::promote(uptr1); tl::lent_ref lptr2 = tl::promote(uptr2); { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr1 = nullptr; //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr1 = std::move(lptr2); //dangling here! } } { //move assignment to a valid ptr Test::resetCounters(); tl::lendable t; tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ref lptr1 = tl::promote(uptr); tl::lent_ref lptr2 = tl::promote(uptr); tl::lent_ref lptr3 = tl::promote(uptr); tl::lent_ref lptr4 = tl::promote(uptr); { ExpectedAssertGuard eassert("unique: 4 dangling lent ptrs detected"); uptr = nullptr; //dangling here! } { ExpectedAssertGuard eassert("lent: 4 dangling lent ptrs detected"); lptr1 = tl::lend(t); //dangling here! } { ExpectedAssertGuard eassert("lent: 3 dangling lent ptrs detected"); lptr2 = tl::lend(t); //dangling here! } { ExpectedAssertGuard eassert("lent: 2 dangling lent ptrs detected"); lptr3 = tl::lend(t); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr4 = tl::lend(t); //dangling here! } } } BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_assign_new_dangling) { { Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); tl::lendable t; tl::lent_ref lptr = tl::promote(uptr); { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr = {}; //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } { //destructor Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); tl::lent_ref lptr = tl::promote(uptr); { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr = {}; //dangling here! } } //dangling here! } { //reset Test::resetCounters(); tl::lendable t; tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ref lptr = tl::promote(uptr); { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr = {}; //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } { //copy assignment to empty ptr Test::resetCounters(); tl::lendable t; tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ref lptr = tl::promote(uptr); { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr = {}; //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } { //copy assignment to another valid ptr Test::resetCounters(); tl::unique_ptr uptr1(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ref lptr1 = tl::promote(uptr1); tl::lent_ref lptr2 = tl::promote(uptr2); { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr1 = {}; //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr1 = lptr2; //dangling here! } } { //move assignment to a valid ptr Test::resetCounters(); tl::unique_ptr uptr1(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ref lptr1 = tl::promote(uptr1); tl::lent_ref lptr2 = tl::promote(uptr2); { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr1 = {}; //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr1 = std::move(lptr2); //dangling here! } } { //move assignment to a valid ptr Test::resetCounters(); tl::lendable t; tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ref lptr1 = tl::promote(uptr); tl::lent_ref lptr2 = tl::promote(uptr); tl::lent_ref lptr3 = tl::promote(uptr); tl::lent_ref lptr4 = tl::promote(uptr); { ExpectedAssertGuard eassert("unique: 4 dangling lent ptrs detected"); uptr = {}; //dangling here! } { ExpectedAssertGuard eassert("lent: 4 dangling lent ptrs detected"); lptr1 = tl::lend(t); //dangling here! } { ExpectedAssertGuard eassert("lent: 3 dangling lent ptrs detected"); lptr2 = tl::lend(t); //dangling here! } { ExpectedAssertGuard eassert("lent: 2 dangling lent ptrs detected"); lptr3 = tl::lend(t); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr4 = tl::lend(t); //dangling here! } } } BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_reset_dangling) { { Test::resetCounters(); tl::lendable t; tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ref lptr = tl::promote(uptr); { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr.reset(); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } { //destructor Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); tl::lent_ref lptr = tl::promote(uptr); { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr.reset(); //dangling here! } } //dangling here! } { //reset Test::resetCounters(); tl::lendable t; tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ref lptr = tl::promote(uptr); { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr.reset(); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } { //copy assignment to empty ptr Test::resetCounters(); tl::lendable t; tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ref lptr = tl::promote(uptr); { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr.reset(); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } { //copy assignment to another valid ptr Test::resetCounters(); tl::unique_ptr uptr1(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ref lptr1 = tl::promote(uptr1); tl::lent_ref lptr2 = tl::promote(uptr2); { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr1.reset(); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr1 = lptr2; //dangling here! } } { //move assignment to a valid ptr Test::resetCounters(); tl::unique_ptr uptr1(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ref lptr1 = tl::promote(uptr1); tl::lent_ref lptr2 = tl::promote(uptr2); { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr1.reset(); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr1 = std::move(lptr2); //dangling here! } } { //move assignment to a valid ptr Test::resetCounters(); tl::lendable t; tl::unique_ptr uptr(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ref lptr1 = tl::promote(uptr); tl::lent_ref lptr2 = tl::promote(uptr); tl::lent_ref lptr3 = tl::promote(uptr); tl::lent_ref lptr4 = tl::promote(uptr); { ExpectedAssertGuard eassert("unique: 4 dangling lent ptrs detected"); uptr.reset(); //dangling here! } { ExpectedAssertGuard eassert("lent: 4 dangling lent ptrs detected"); lptr1 = tl::lend(t); //dangling here! } { ExpectedAssertGuard eassert("lent: 3 dangling lent ptrs detected"); lptr2 = tl::lend(t); //dangling here! } { ExpectedAssertGuard eassert("lent: 2 dangling lent ptrs detected"); lptr3 = tl::lend(t); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr4 = tl::lend(t); //dangling here! } } } BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_assign_move_dangling) { { Test::resetCounters(); tl::lendable t; tl::unique_ptr uptr(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 3}); tl::lent_ref lptr = tl::promote(uptr); { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr = std::move(uptr2); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } { //destructor Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); tl::lent_ref lptr = tl::promote(uptr); { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr = std::move(uptr2); //dangling here! } } //dangling here! } { //reset Test::resetCounters(); tl::lendable t; tl::unique_ptr uptr(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 3}); tl::lent_ref lptr = tl::promote(uptr); { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr = std::move(uptr2); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } { //copy assignment to empty ptr Test::resetCounters(); tl::lendable t; tl::unique_ptr uptr(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 3}); tl::lent_ref lptr = tl::promote(uptr); { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr = std::move(uptr2); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } { //copy assignment to another valid ptr Test::resetCounters(); tl::unique_ptr uptr1(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); tl::unique_ptr uptr3(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 3}); tl::lent_ref lptr1 = tl::promote(uptr1); tl::lent_ref lptr2 = tl::promote(uptr2); { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr1 = std::move(uptr3); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr1 = lptr2; //dangling here! } } { //move assignment to a valid ptr Test::resetCounters(); tl::unique_ptr uptr1(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); tl::unique_ptr uptr3(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 3}); tl::lent_ref lptr1 = tl::promote(uptr1); tl::lent_ref lptr2 = tl::promote(uptr2); { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uptr1 = std::move(uptr3); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr1 = std::move(lptr2); //dangling here! } } { //move assignment to a valid ptr Test::resetCounters(); tl::lendable t; tl::unique_ptr uptr(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 3}); tl::lent_ref lptr1 = tl::promote(uptr); tl::lent_ref lptr2 = tl::promote(uptr); tl::lent_ref lptr3 = tl::promote(uptr); tl::lent_ref lptr4 = tl::promote(uptr); { ExpectedAssertGuard eassert("unique: 4 dangling lent ptrs detected"); uptr = std::move(uptr2); //dangling here! } { ExpectedAssertGuard eassert("lent: 4 dangling lent ptrs detected"); lptr1 = tl::lend(t); //dangling here! } { ExpectedAssertGuard eassert("lent: 3 dangling lent ptrs detected"); lptr2 = tl::lend(t); //dangling here! } { ExpectedAssertGuard eassert("lent: 2 dangling lent ptrs detected"); lptr3 = tl::lend(t); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr4 = tl::lend(t); //dangling here! } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// BOOST_AUTO_TEST_CASE(lent_ref_unique_ref_assign_nullptr_dangling) { { Test::resetCounters(); tl::lendable t; tl::unique_ref uref(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ref lptr = uref; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref = tl::unique_ref(new Test(1234)); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } { //destructor Test::resetCounters(); tl::unique_ref uref(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); tl::lent_ref lptr = uref; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref = tl::unique_ref(new Test(1234)); //dangling here! } } //dangling here! } { //reset Test::resetCounters(); tl::lendable t; tl::unique_ref uref(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ref lptr = uref; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref = tl::unique_ref(new Test(1234)); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } { //copy assignment to empty ptr Test::resetCounters(); tl::lendable t; tl::unique_ref uref(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ref lptr = uref; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref = tl::unique_ref(new Test(1234)); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } { //copy assignment to another valid ptr Test::resetCounters(); tl::unique_ref uref1(new Test(1234)); tl::unique_ref uref2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ref lptr1 = uref1; tl::lent_ref lptr2 = uref2; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref1 = tl::unique_ref(new Test(1234)); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr1 = lptr2; //dangling here! } } { //move assignment to a valid ptr Test::resetCounters(); tl::unique_ref uref1(new Test(1234)); tl::unique_ref uref2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ref lptr1 = uref1; tl::lent_ref lptr2 = uref2; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref1 = tl::unique_ref(new Test(1234)); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr1 = std::move(lptr2); //dangling here! } } { //move assignment to a valid ptr Test::resetCounters(); tl::lendable t; tl::unique_ref uref(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ref lptr1 = uref; tl::lent_ref lptr2 = uref; tl::lent_ref lptr3 = uref; tl::lent_ref lptr4 = uref; { ExpectedAssertGuard eassert("unique: 4 dangling lent ptrs detected"); uref = tl::unique_ref(new Test(1234)); //dangling here! } { ExpectedAssertGuard eassert("lent: 4 dangling lent ptrs detected"); lptr1 = tl::lend(t); //dangling here! } { ExpectedAssertGuard eassert("lent: 3 dangling lent ptrs detected"); lptr2 = tl::lend(t); //dangling here! } { ExpectedAssertGuard eassert("lent: 2 dangling lent ptrs detected"); lptr3 = tl::lend(t); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr4 = tl::lend(t); //dangling here! } } } BOOST_AUTO_TEST_CASE(lent_ref_unique_ref_reset_dangling) { { Test::resetCounters(); tl::lendable t; tl::unique_ref uref(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ref lptr = uref; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref.reset(new Test(1234)); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } { //destructor Test::resetCounters(); tl::unique_ref uref(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); tl::lent_ref lptr = uref; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref.reset(new Test(1234)); //dangling here! } } //dangling here! } { //reset Test::resetCounters(); tl::lendable t; tl::unique_ref uref(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ref lptr = uref; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref.reset(new Test(1234)); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } { //copy assignment to empty ptr Test::resetCounters(); tl::lendable t; tl::unique_ref uref(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ref lptr = uref; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref.reset(new Test(1234)); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } { //copy assignment to another valid ptr Test::resetCounters(); tl::unique_ref uref1(new Test(1234)); tl::unique_ref uref2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ref lptr1 = uref1; tl::lent_ref lptr2 = uref2; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref1.reset(new Test(1234)); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr1 = lptr2; //dangling here! } } { //move assignment to a valid ptr Test::resetCounters(); tl::unique_ref uref1(new Test(1234)); tl::unique_ref uref2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ref lptr1 = uref1; tl::lent_ref lptr2 = uref2; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref1.reset(new Test(1234)); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr1 = std::move(lptr2); //dangling here! } } { //move assignment to a valid ptr Test::resetCounters(); tl::lendable t; tl::unique_ref uref(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); tl::lent_ref lptr1 = uref; tl::lent_ref lptr2 = uref; tl::lent_ref lptr3 = uref; tl::lent_ref lptr4 = uref; { ExpectedAssertGuard eassert("unique: 4 dangling lent ptrs detected"); uref.reset(new Test(1234)); //dangling here! } { ExpectedAssertGuard eassert("lent: 4 dangling lent ptrs detected"); lptr1 = tl::lend(t); //dangling here! } { ExpectedAssertGuard eassert("lent: 3 dangling lent ptrs detected"); lptr2 = tl::lend(t); //dangling here! } { ExpectedAssertGuard eassert("lent: 2 dangling lent ptrs detected"); lptr3 = tl::lend(t); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr4 = tl::lend(t); //dangling here! } } } BOOST_AUTO_TEST_CASE(lent_ref_unique_ref_assign_move_dangling) { { Test::resetCounters(); tl::lendable t; tl::unique_ref uref(new Test(1234)); tl::unique_ref uref2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 3}); tl::lent_ref lptr = uref; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref = std::move(uref2); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } { //destructor Test::resetCounters(); tl::unique_ref uref(new Test(1234)); tl::unique_ref uref2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); tl::lent_ref lptr = uref; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref = std::move(uref2); //dangling here! } } //dangling here! } { //reset Test::resetCounters(); tl::lendable t; tl::unique_ref uref(new Test(1234)); tl::unique_ref uref2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 3}); tl::lent_ref lptr = uref; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref = std::move(uref2); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } { //copy assignment to empty ptr Test::resetCounters(); tl::lendable t; tl::unique_ref uref(new Test(1234)); tl::unique_ref uref2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 3}); tl::lent_ref lptr = uref; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref = std::move(uref2); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } { //copy assignment to another valid ptr Test::resetCounters(); tl::unique_ref uref1(new Test(1234)); tl::unique_ref uref2(new Test(1234)); tl::unique_ref uref3(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 3}); tl::lent_ref lptr1 = uref1; tl::lent_ref lptr2 = uref2; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref1 = std::move(uref3); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr1 = lptr2; //dangling here! } } { //move assignment to a valid ptr Test::resetCounters(); tl::unique_ref uref1(new Test(1234)); tl::unique_ref uref2(new Test(1234)); tl::unique_ref uref3(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 3}); tl::lent_ref lptr1 = uref1; tl::lent_ref lptr2 = uref2; { ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); uref1 = std::move(uref3); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr1 = std::move(lptr2); //dangling here! } } { //move assignment to a valid ptr Test::resetCounters(); tl::lendable t; tl::unique_ref uref(new Test(1234)); tl::unique_ref uref2(new Test(1234)); BOOST_CHECK(Test::s_counters == Counters{.ctor = 3}); tl::lent_ref lptr1 = uref; tl::lent_ref lptr2 = uref; tl::lent_ref lptr3 = uref; tl::lent_ref lptr4 = uref; { ExpectedAssertGuard eassert("unique: 4 dangling lent ptrs detected"); uref = std::move(uref2); //dangling here! } { ExpectedAssertGuard eassert("lent: 4 dangling lent ptrs detected"); lptr1 = tl::lend(t); //dangling here! } { ExpectedAssertGuard eassert("lent: 3 dangling lent ptrs detected"); lptr2 = tl::lend(t); //dangling here! } { ExpectedAssertGuard eassert("lent: 2 dangling lent ptrs detected"); lptr3 = tl::lend(t); //dangling here! } { ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); lptr4 = tl::lend(t); //dangling here! } } }