diff --git a/pointer/unique_ref.h b/pointer/unique_ref.h index 6060ae8c..c6bb7d77 100644 --- a/pointer/unique_ref.h +++ b/pointer/unique_ref.h @@ -78,7 +78,6 @@ inline boost::optional> nullcheck(std::unique_ptr ptr) { return boost::none; } -//TODO Write test cases for dynamic_pointer_move //TODO Also allow passing a rvalue reference, otherwise dynamic_pointer_move(func()) won't work template inline boost::optional> dynamic_pointer_move(unique_ref &source) { diff --git a/test/pointer/cast_destructor_test.cpp b/test/pointer/cast_destructor_test.cpp deleted file mode 100644 index e73e216e..00000000 --- a/test/pointer/cast_destructor_test.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include "google/gtest/gtest.h" -#include "google/gmock/gmock.h" -#include "../../pointer/cast.h" - -using namespace cpputils; - -using std::unique_ptr; -using std::make_unique; -using std::function; - -// Putting them in an own namespace is needed, so they don't clash with globally defined Parent/Child classes -namespace withdestructorcallback { - class DestructorCallback { - public: - MOCK_CONST_METHOD0(call, void()); - }; - - class Parent { - public: - virtual ~Parent() { } - }; - - class Child : public Parent { - public: - Child(const DestructorCallback &childDestructorCallback) : _destructorCallback(childDestructorCallback) { } - - ~Child() { - _destructorCallback.call(); - } - - private: - const DestructorCallback &_destructorCallback; - }; -} -using namespace withdestructorcallback; - -class DynamicPointerMoveDestructorTest: public ::testing::Test { -public: - DestructorCallback childDestructorCallback; - unique_ptr createChild() { - return make_unique(childDestructorCallback); - } - void EXPECT_CHILD_DESTRUCTOR_CALLED() { - EXPECT_CALL(childDestructorCallback, call()).Times(1); - } -}; - -TEST_F(DynamicPointerMoveDestructorTest, ChildInParentPtr) { - unique_ptr parent = createChild(); - EXPECT_CHILD_DESTRUCTOR_CALLED(); -} - -TEST_F(DynamicPointerMoveDestructorTest, ChildToParentCast) { - unique_ptr child = createChild(); - unique_ptr parent = dynamic_pointer_move(child); - EXPECT_CHILD_DESTRUCTOR_CALLED(); -} - -TEST_F(DynamicPointerMoveDestructorTest, ParentToChildCast) { - unique_ptr parent = createChild(); - unique_ptr child = dynamic_pointer_move(parent); - EXPECT_CHILD_DESTRUCTOR_CALLED(); -} diff --git a/test/pointer/cast_test.cpp b/test/pointer/cast_test.cpp index cb4540a1..78e38d2e 100644 --- a/test/pointer/cast_test.cpp +++ b/test/pointer/cast_test.cpp @@ -1,47 +1,76 @@ #include "google/gtest/gtest.h" #include "../../pointer/cast.h" +#include "../../pointer/unique_ref.h" +#include "../../pointer/unique_ref_boost_optional_gtest_workaround.h" +#include "google/gmock/gmock.h" + +//TODO There is a lot of duplication here, because each test case is there twice - once for unique_ptr, once for unique_ref. Remove redundancy by using generic test cases. +//TODO Then also move the unique_ref related test cases there - cast_test.cpp should only contain the unique_ptr related ones. using namespace cpputils; - using std::unique_ptr; +using std::make_unique; +using boost::optional; +using boost::none; -// Putting them in an own namespace is needed, so they don't clash with globally defined Parent/Child classes -namespace testobjs { - class Parent { - public: - virtual ~Parent() { } - }; +class DestructorCallback { +public: + MOCK_CONST_METHOD0(call, void()); +}; - class Child : public Parent { - }; +class Parent { +public: + virtual ~Parent() { } +}; - class Child2 : public Parent { - }; -} -using namespace testobjs; +class Child : public Parent { +public: + Child(const DestructorCallback *childDestructorCallback) : _destructorCallback(childDestructorCallback) { } + Child(): Child(nullptr) {} -TEST(DynamicPointerMoveTest, NullPtrParentToChildCast) { + ~Child() { + if (_destructorCallback != nullptr) { + _destructorCallback->call(); + } + } + +private: + const DestructorCallback *_destructorCallback; +}; + +class Child2 : public Parent {}; + + +TEST(UniquePtr_DynamicPointerMoveTest, NullPtrParentToChildCast) { unique_ptr source(nullptr); unique_ptr casted = dynamic_pointer_move(source); EXPECT_EQ(nullptr, source.get()); EXPECT_EQ(nullptr, casted.get()); } -TEST(DynamicPointerMoveTest, NullPtrChildToParentCast) { +TEST(UniquePtr_DynamicPointerMoveTest, NullPtrChildToParentCast) { unique_ptr source(nullptr); unique_ptr casted = dynamic_pointer_move(source); EXPECT_EQ(nullptr, source.get()); EXPECT_EQ(nullptr, casted.get()); } -TEST(DynamicPointerMoveTest, NullPtrSelfCast) { +TEST(UniquePtr_DynamicPointerMoveTest, NullPtrSelfCast) { unique_ptr source(nullptr); unique_ptr casted = dynamic_pointer_move(source); EXPECT_EQ(nullptr, source.get()); EXPECT_EQ(nullptr, casted.get()); } -TEST(DynamicPointerMoveTest, ValidParentToChildCast) { +TEST(UniqueRef_DynamicPointerMoveTest, ValidParentToChildCast) { + Child *obj = new Child(); + unique_ref source(std::move(nullcheck(unique_ptr(obj)).get())); + unique_ref casted = std::move(dynamic_pointer_move(source).get()); + EXPECT_EQ(nullptr, source.get()); // source lost ownership + EXPECT_EQ(obj, casted.get()); +} + +TEST(UniquePtr_DynamicPointerMoveTest, ValidParentToChildCast) { Child *obj = new Child(); unique_ptr source(obj); unique_ptr casted = dynamic_pointer_move(source); @@ -49,7 +78,15 @@ TEST(DynamicPointerMoveTest, ValidParentToChildCast) { EXPECT_EQ(obj, casted.get()); } -TEST(DynamicPointerMoveTest, InvalidParentToChildCast1) { +TEST(UniqueRef_DynamicPointerMoveTest, InvalidParentToChildCast1) { + Parent *obj = new Parent(); + unique_ref source(std::move(nullcheck(unique_ptr(obj)).get())); + optional> casted = dynamic_pointer_move(source); + EXPECT_EQ(obj, source.get()); // source still has ownership + EXPECT_EQ(none, casted); +} + +TEST(UniquePtr_DynamicPointerMoveTest, InvalidParentToChildCast1) { Parent *obj = new Parent(); unique_ptr source(obj); unique_ptr casted = dynamic_pointer_move(source); @@ -57,7 +94,15 @@ TEST(DynamicPointerMoveTest, InvalidParentToChildCast1) { EXPECT_EQ(nullptr, casted.get()); } -TEST(DynamicPointerMoveTest, InvalidParentToChildCast2) { +TEST(UniqueRef_DynamicPointerMoveTest, InvalidParentToChildCast2) { + Child2 *obj = new Child2(); + unique_ref source(std::move(nullcheck(unique_ptr(obj)).get())); + optional> casted = dynamic_pointer_move(source); + EXPECT_EQ(obj, source.get()); // source still has ownership + EXPECT_EQ(none, casted); +} + +TEST(UniquePtr_DynamicPointerMoveTest, InvalidParentToChildCast2) { Child2 *obj = new Child2(); unique_ptr source(obj); unique_ptr casted = dynamic_pointer_move(source); @@ -65,10 +110,75 @@ TEST(DynamicPointerMoveTest, InvalidParentToChildCast2) { EXPECT_EQ(nullptr, casted.get()); } -TEST(DynamicPointerMoveTest, ChildToParentCast) { +TEST(UniqueRef_DynamicPointerMoveTest, ChildToParentCast) { + Child *obj = new Child(); + unique_ref source(std::move(nullcheck(unique_ptr(obj)).get())); + unique_ref casted = std::move(dynamic_pointer_move(source).get()); + EXPECT_EQ(nullptr, source.get()); // source lost ownership + EXPECT_EQ(obj, casted.get()); +} + +TEST(UniquePtr_DynamicPointerMoveTest, ChildToParentCast) { Child *obj = new Child(); unique_ptr source(obj); unique_ptr casted = dynamic_pointer_move(source); EXPECT_EQ(nullptr, source.get()); // source lost ownership EXPECT_EQ(obj, casted.get()); } + + +class UniqueRef_DynamicPointerMoveDestructorTest: public ::testing::Test { +public: + DestructorCallback childDestructorCallback; + unique_ref createChild() { + return make_unique_ref(&childDestructorCallback); + } + void EXPECT_CHILD_DESTRUCTOR_CALLED() { + EXPECT_CALL(childDestructorCallback, call()).Times(1); + } +}; + +class UniquePtr_DynamicPointerMoveDestructorTest: public ::testing::Test { +public: + DestructorCallback childDestructorCallback; + unique_ptr createChild() { + return make_unique(&childDestructorCallback); + } + void EXPECT_CHILD_DESTRUCTOR_CALLED() { + EXPECT_CALL(childDestructorCallback, call()).Times(1); + } +}; + +TEST_F(UniqueRef_DynamicPointerMoveDestructorTest, ChildInParentPtr) { + unique_ref parent = createChild(); + EXPECT_CHILD_DESTRUCTOR_CALLED(); +} + +TEST_F(UniquePtr_DynamicPointerMoveDestructorTest, ChildInParentPtr) { + unique_ptr parent = createChild(); + EXPECT_CHILD_DESTRUCTOR_CALLED(); +} + +TEST_F(UniqueRef_DynamicPointerMoveDestructorTest, ChildToParentCast) { + unique_ref child = createChild(); + unique_ref parent = std::move(dynamic_pointer_move(child).get()); + EXPECT_CHILD_DESTRUCTOR_CALLED(); +} + +TEST_F(UniquePtr_DynamicPointerMoveDestructorTest, ChildToParentCast) { + unique_ptr child = createChild(); + unique_ptr parent = dynamic_pointer_move(child); + EXPECT_CHILD_DESTRUCTOR_CALLED(); +} + +TEST_F(UniqueRef_DynamicPointerMoveDestructorTest, ParentToChildCast) { + unique_ref parent = createChild(); + unique_ref child = std::move(dynamic_pointer_move(parent).get()); + EXPECT_CHILD_DESTRUCTOR_CALLED(); +} + +TEST_F(UniquePtr_DynamicPointerMoveDestructorTest, ParentToChildCast) { + unique_ptr parent = createChild(); + unique_ptr child = dynamic_pointer_move(parent); + EXPECT_CHILD_DESTRUCTOR_CALLED(); +}