2015-02-16 21:31:07 +01:00
# include "google/gtest/gtest.h"
2015-06-21 17:31:19 +02:00
# include "../../pointer/cast.h"
2015-06-21 18:18:43 +02:00
# include "../../pointer/unique_ref.h"
# include "../../pointer/unique_ref_boost_optional_gtest_workaround.h"
# include "google/gmock/gmock.h"
2015-02-16 21:31:07 +01:00
2015-06-21 18:18:43 +02:00
//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.
2015-02-16 21:31:07 +01:00
2015-06-21 18:18:43 +02:00
using namespace cpputils ;
2015-02-16 21:31:07 +01:00
using std : : unique_ptr ;
2015-06-21 18:18:43 +02:00
using std : : make_unique ;
using boost : : optional ;
using boost : : none ;
2015-02-16 21:31:07 +01:00
2015-06-21 18:18:43 +02:00
class DestructorCallback {
public :
MOCK_CONST_METHOD0 ( call , void ( ) ) ;
} ;
2015-06-21 17:14:35 +02:00
2015-06-21 18:18:43 +02:00
class Parent {
public :
virtual ~ Parent ( ) { }
} ;
2015-06-21 17:14:35 +02:00
2015-06-21 18:18:43 +02:00
class Child : public Parent {
public :
Child ( const DestructorCallback * childDestructorCallback ) : _destructorCallback ( childDestructorCallback ) { }
Child ( ) : Child ( nullptr ) { }
~ Child ( ) {
if ( _destructorCallback ! = nullptr ) {
_destructorCallback - > call ( ) ;
}
}
private :
const DestructorCallback * _destructorCallback ;
} ;
2015-06-17 00:38:02 +02:00
2015-06-21 18:18:43 +02:00
class Child2 : public Parent { } ;
TEST ( UniquePtr_DynamicPointerMoveTest , NullPtrParentToChildCast ) {
2015-02-16 21:31:07 +01:00
unique_ptr < Parent > source ( nullptr ) ;
unique_ptr < Child > casted = dynamic_pointer_move < Child > ( source ) ;
EXPECT_EQ ( nullptr , source . get ( ) ) ;
EXPECT_EQ ( nullptr , casted . get ( ) ) ;
}
2015-06-21 18:18:43 +02:00
TEST ( UniquePtr_DynamicPointerMoveTest , NullPtrChildToParentCast ) {
2015-02-16 21:31:07 +01:00
unique_ptr < Child > source ( nullptr ) ;
unique_ptr < Parent > casted = dynamic_pointer_move < Parent > ( source ) ;
EXPECT_EQ ( nullptr , source . get ( ) ) ;
EXPECT_EQ ( nullptr , casted . get ( ) ) ;
}
2015-06-21 18:18:43 +02:00
TEST ( UniquePtr_DynamicPointerMoveTest , NullPtrSelfCast ) {
2015-02-16 21:31:07 +01:00
unique_ptr < Parent > source ( nullptr ) ;
unique_ptr < Parent > casted = dynamic_pointer_move < Parent > ( source ) ;
EXPECT_EQ ( nullptr , source . get ( ) ) ;
EXPECT_EQ ( nullptr , casted . get ( ) ) ;
}
2015-06-21 18:18:43 +02:00
TEST ( UniqueRef_DynamicPointerMoveTest , ValidParentToChildCast ) {
Child * obj = new Child ( ) ;
unique_ref < Parent > source ( std : : move ( nullcheck ( unique_ptr < Parent > ( obj ) ) . get ( ) ) ) ;
unique_ref < Child > casted = std : : move ( dynamic_pointer_move < Child > ( source ) . get ( ) ) ;
EXPECT_EQ ( nullptr , source . get ( ) ) ; // source lost ownership
EXPECT_EQ ( obj , casted . get ( ) ) ;
}
TEST ( UniquePtr_DynamicPointerMoveTest , ValidParentToChildCast ) {
2015-02-16 21:31:07 +01:00
Child * obj = new Child ( ) ;
unique_ptr < Parent > source ( obj ) ;
unique_ptr < Child > casted = dynamic_pointer_move < Child > ( source ) ;
EXPECT_EQ ( nullptr , source . get ( ) ) ; // source lost ownership
EXPECT_EQ ( obj , casted . get ( ) ) ;
}
2015-06-21 18:18:43 +02:00
TEST ( UniqueRef_DynamicPointerMoveTest , InvalidParentToChildCast1 ) {
Parent * obj = new Parent ( ) ;
unique_ref < Parent > source ( std : : move ( nullcheck ( unique_ptr < Parent > ( obj ) ) . get ( ) ) ) ;
optional < unique_ref < Child > > casted = dynamic_pointer_move < Child > ( source ) ;
EXPECT_EQ ( obj , source . get ( ) ) ; // source still has ownership
EXPECT_EQ ( none , casted ) ;
}
TEST ( UniquePtr_DynamicPointerMoveTest , InvalidParentToChildCast1 ) {
2015-02-16 21:31:07 +01:00
Parent * obj = new Parent ( ) ;
unique_ptr < Parent > source ( obj ) ;
unique_ptr < Child > casted = dynamic_pointer_move < Child > ( source ) ;
EXPECT_EQ ( obj , source . get ( ) ) ; // source still has ownership
EXPECT_EQ ( nullptr , casted . get ( ) ) ;
}
2015-06-21 18:18:43 +02:00
TEST ( UniqueRef_DynamicPointerMoveTest , InvalidParentToChildCast2 ) {
Child2 * obj = new Child2 ( ) ;
unique_ref < Parent > source ( std : : move ( nullcheck ( unique_ptr < Parent > ( obj ) ) . get ( ) ) ) ;
optional < unique_ref < Child > > casted = dynamic_pointer_move < Child > ( source ) ;
EXPECT_EQ ( obj , source . get ( ) ) ; // source still has ownership
EXPECT_EQ ( none , casted ) ;
}
TEST ( UniquePtr_DynamicPointerMoveTest , InvalidParentToChildCast2 ) {
2015-02-16 21:31:07 +01:00
Child2 * obj = new Child2 ( ) ;
unique_ptr < Parent > source ( obj ) ;
unique_ptr < Child > casted = dynamic_pointer_move < Child > ( source ) ;
EXPECT_EQ ( obj , source . get ( ) ) ; // source still has ownership
EXPECT_EQ ( nullptr , casted . get ( ) ) ;
}
2015-06-21 18:18:43 +02:00
TEST ( UniqueRef_DynamicPointerMoveTest , ChildToParentCast ) {
Child * obj = new Child ( ) ;
unique_ref < Child > source ( std : : move ( nullcheck ( unique_ptr < Child > ( obj ) ) . get ( ) ) ) ;
unique_ref < Parent > casted = std : : move ( dynamic_pointer_move < Parent > ( source ) . get ( ) ) ;
EXPECT_EQ ( nullptr , source . get ( ) ) ; // source lost ownership
EXPECT_EQ ( obj , casted . get ( ) ) ;
}
TEST ( UniquePtr_DynamicPointerMoveTest , ChildToParentCast ) {
2015-02-16 21:31:07 +01:00
Child * obj = new Child ( ) ;
unique_ptr < Child > source ( obj ) ;
unique_ptr < Parent > casted = dynamic_pointer_move < Parent > ( source ) ;
EXPECT_EQ ( nullptr , source . get ( ) ) ; // source lost ownership
EXPECT_EQ ( obj , casted . get ( ) ) ;
}
2015-06-21 18:18:43 +02:00
class UniqueRef_DynamicPointerMoveDestructorTest : public : : testing : : Test {
public :
DestructorCallback childDestructorCallback ;
unique_ref < Child > createChild ( ) {
return make_unique_ref < Child > ( & childDestructorCallback ) ;
}
void EXPECT_CHILD_DESTRUCTOR_CALLED ( ) {
EXPECT_CALL ( childDestructorCallback , call ( ) ) . Times ( 1 ) ;
}
} ;
class UniquePtr_DynamicPointerMoveDestructorTest : public : : testing : : Test {
public :
DestructorCallback childDestructorCallback ;
unique_ptr < Child > createChild ( ) {
return make_unique < Child > ( & childDestructorCallback ) ;
}
void EXPECT_CHILD_DESTRUCTOR_CALLED ( ) {
EXPECT_CALL ( childDestructorCallback , call ( ) ) . Times ( 1 ) ;
}
} ;
TEST_F ( UniqueRef_DynamicPointerMoveDestructorTest , ChildInParentPtr ) {
unique_ref < Parent > parent = createChild ( ) ;
EXPECT_CHILD_DESTRUCTOR_CALLED ( ) ;
}
TEST_F ( UniquePtr_DynamicPointerMoveDestructorTest , ChildInParentPtr ) {
unique_ptr < Parent > parent = createChild ( ) ;
EXPECT_CHILD_DESTRUCTOR_CALLED ( ) ;
}
TEST_F ( UniqueRef_DynamicPointerMoveDestructorTest , ChildToParentCast ) {
unique_ref < Child > child = createChild ( ) ;
unique_ref < Parent > parent = std : : move ( dynamic_pointer_move < Parent > ( child ) . get ( ) ) ;
EXPECT_CHILD_DESTRUCTOR_CALLED ( ) ;
}
TEST_F ( UniquePtr_DynamicPointerMoveDestructorTest , ChildToParentCast ) {
unique_ptr < Child > child = createChild ( ) ;
unique_ptr < Parent > parent = dynamic_pointer_move < Parent > ( child ) ;
EXPECT_CHILD_DESTRUCTOR_CALLED ( ) ;
}
TEST_F ( UniqueRef_DynamicPointerMoveDestructorTest , ParentToChildCast ) {
unique_ref < Parent > parent = createChild ( ) ;
unique_ref < Child > child = std : : move ( dynamic_pointer_move < Child > ( parent ) . get ( ) ) ;
EXPECT_CHILD_DESTRUCTOR_CALLED ( ) ;
}
TEST_F ( UniquePtr_DynamicPointerMoveDestructorTest , ParentToChildCast ) {
unique_ptr < Parent > parent = createChild ( ) ;
unique_ptr < Child > child = dynamic_pointer_move < Child > ( parent ) ;
EXPECT_CHILD_DESTRUCTOR_CALLED ( ) ;
}