#include #include using namespace ebcl; template< bool Atomic > class RefCountTest : public CppUnit::TestFixture { public: class T_Test : public T_ReferenceCountedClass< Atomic > \ { public: static uint32_t cNew; static uint32_t cDel; T_Test( ) noexcept { cNew ++; } virtual ~T_Test( ) noexcept { cDel ++; } }; using P_Test = T_RcPtr< T_Test >; class T_Child : public T_Test { }; using P_Child = T_RcPtr< T_Child >; private: CPPUNIT_TEST_SUITE( RefCountTest ); CPPUNIT_TEST( testStackInstance ); CPPUNIT_TEST( testEmpty ); CPPUNIT_TEST( testConstruct ); CPPUNIT_TEST( testCopyCons ); CPPUNIT_TEST( testCopyConsToBase ); CPPUNIT_TEST( testCopyConsToChildOk ); CPPUNIT_TEST( testCopyConsToChildBad ); CPPUNIT_TEST( testCopyAss ); CPPUNIT_TEST( testCopyAssToBase ); CPPUNIT_TEST( testCopyAssToChildOk ); CPPUNIT_TEST( testCopyAssToChildBad ); CPPUNIT_TEST( testMoveCons ); CPPUNIT_TEST( testMoveConsToBase ); CPPUNIT_TEST( testMoveConsToChildOk ); CPPUNIT_TEST( testMoveConsToChildBad ); CPPUNIT_TEST( testMoveAss ); CPPUNIT_TEST( testMoveAssToBase ); CPPUNIT_TEST( testMoveAssToChildOk ); CPPUNIT_TEST( testMoveAssToChildBad ); CPPUNIT_TEST( testSwap ); CPPUNIT_TEST_SUITE_END( ); public: void setUp( ) override; void testStackInstance( ); void testEmpty( ); void testConstruct( ); void testCopyCons( ); void testCopyConsToBase( ); void testCopyConsToChildOk( ); void testCopyConsToChildBad( ); void testCopyAss( ); void testCopyAssToBase( ); void testCopyAssToChildOk( ); void testCopyAssToChildBad( ); void testMoveCons( ); void testMoveConsToBase( ); void testMoveConsToChildOk( ); void testMoveConsToChildBad( ); void testMoveAss( ); void testMoveAssToBase( ); void testMoveAssToChildOk( ); void testMoveAssToChildBad( ); void testSwap( ); }; CPPUNIT_TEST_SUITE_REGISTRATION( RefCountTest< true > ); CPPUNIT_TEST_SUITE_REGISTRATION( RefCountTest< false > ); template<> uint32_t RefCountTest< true >::T_Test::cNew = 0; template<> uint32_t RefCountTest< true >::T_Test::cDel = 0; template<> uint32_t RefCountTest< false >::T_Test::cNew = 0; template<> uint32_t RefCountTest< false >::T_Test::cDel = 0; /*----------------------------------------------------------------------------*/ template< bool A > void RefCountTest< A >::setUp( ) { T_Test::cNew = T_Test::cDel = 0; } /*----------------------------------------------------------------------------*/ template< bool A > void RefCountTest< A >::testStackInstance( ) { { T_Test t; CPPUNIT_ASSERT_EQUAL( 1u , T_Test::cNew ); CPPUNIT_ASSERT_EQUAL( 0u , t.getReferenceCount( ) ); } CPPUNIT_ASSERT_EQUAL( 1u , T_Test::cDel ); } /*----------------------------------------------------------------------------*/ template< bool A > void RefCountTest< A >::testEmpty( ) { { P_Test p1; CPPUNIT_ASSERT_EQUAL( 0u , T_Test::cNew ); CPPUNIT_ASSERT_EQUAL( false , bool{ p1 } ); CPPUNIT_ASSERT_EQUAL( true , !p1 ); CPPUNIT_ASSERT_EQUAL( (T_Test*) nullptr , p1.get( ) ); CPPUNIT_ASSERT_EQUAL( (T_Test*) nullptr , (T_Test*) p1 ); } CPPUNIT_ASSERT_EQUAL( 0u , T_Test::cDel ); } template< bool A > void RefCountTest< A >::testConstruct( ) { { P_Test p1{ P_Test::New( ) }; CPPUNIT_ASSERT_EQUAL( 1u , T_Test::cNew ); CPPUNIT_ASSERT_EQUAL( true , bool{ p1 } ); CPPUNIT_ASSERT_EQUAL( false , !p1 ); CPPUNIT_ASSERT( (T_Test*) nullptr != p1.get( ) ); CPPUNIT_ASSERT( (T_Test*) nullptr != (T_Test*) p1 ); CPPUNIT_ASSERT_EQUAL( 1u , p1->getReferenceCount( ) ); CPPUNIT_ASSERT_EQUAL( 1u , (*p1).getReferenceCount( ) ); } CPPUNIT_ASSERT_EQUAL( 1u , T_Test::cDel ); } /*----------------------------------------------------------------------------*/ template< bool A > void RefCountTest< A >::testCopyCons( ) { { P_Test p1{ P_Test::New( ) }; { P_Test c1{ p1 }; CPPUNIT_ASSERT_EQUAL( 1u , T_Test::cNew ); CPPUNIT_ASSERT( c1 ); CPPUNIT_ASSERT( p1.get( ) == c1.get( ) ); CPPUNIT_ASSERT_EQUAL( 2u , p1->getReferenceCount( ) ); } CPPUNIT_ASSERT_EQUAL( 0u , T_Test::cDel ); CPPUNIT_ASSERT_EQUAL( 1u , p1->getReferenceCount( ) ); } CPPUNIT_ASSERT_EQUAL( 1u , T_Test::cDel ); } template< bool A > void RefCountTest< A >::testCopyConsToBase( ) { P_Child p1{ P_Child::New( ) }; P_Test p2{ p1 }; CPPUNIT_ASSERT( bool( p2 ) ); CPPUNIT_ASSERT( p1.get( ) == p2.get( ) ); CPPUNIT_ASSERT_EQUAL( 2u , p1->getReferenceCount( ) ); } template< bool A > void RefCountTest< A >::testCopyConsToChildOk( ) { P_Test p1{ P_Test::FromRaw( new T_Child( ) ) }; P_Child p2{ p1 }; CPPUNIT_ASSERT( bool( p2 ) ); CPPUNIT_ASSERT( p1.get( ) == p2.get( ) ); CPPUNIT_ASSERT_EQUAL( 2u , p1->getReferenceCount( ) ); } template< bool A > void RefCountTest< A >::testCopyConsToChildBad( ) { P_Test p1{ P_Test::New( ) }; CPPUNIT_ASSERT_THROW( P_Child p2{ p1 } , std::bad_cast ); CPPUNIT_ASSERT_EQUAL( 1u , p1->getReferenceCount( ) ); } /*----------------------------------------------------------------------------*/ template< bool A > void RefCountTest< A >::testCopyAss( ) { { P_Test p1{ P_Test::New( ) }; { P_Test c1; CPPUNIT_ASSERT( !c1 ); c1 = p1; CPPUNIT_ASSERT_EQUAL( 1u , T_Test::cNew ); CPPUNIT_ASSERT( c1 ); CPPUNIT_ASSERT( p1.get( ) == c1.get( ) ); CPPUNIT_ASSERT_EQUAL( 2u , p1->getReferenceCount( ) ); } CPPUNIT_ASSERT_EQUAL( 0u , T_Test::cDel ); CPPUNIT_ASSERT_EQUAL( 1u , p1->getReferenceCount( ) ); } CPPUNIT_ASSERT_EQUAL( 1u , T_Test::cDel ); } template< bool A > void RefCountTest< A >::testCopyAssToBase( ) { P_Child p1{ P_Child::New( ) }; P_Test p2; p2 = p1; CPPUNIT_ASSERT( bool( p2 ) ); CPPUNIT_ASSERT( p1.get( ) == p2.get( ) ); CPPUNIT_ASSERT_EQUAL( 2u , p1->getReferenceCount( ) ); } template< bool A > void RefCountTest< A >::testCopyAssToChildOk( ) { P_Test p1{ P_Test::FromRaw( new T_Child( ) ) }; P_Child p2; p2 = p1; CPPUNIT_ASSERT( bool( p2 ) ); CPPUNIT_ASSERT( p1.get( ) == p2.get( ) ); CPPUNIT_ASSERT_EQUAL( 2u , p1->getReferenceCount( ) ); } template< bool A > void RefCountTest< A >::testCopyAssToChildBad( ) { P_Test p1{ P_Test::New( ) }; P_Child p2; CPPUNIT_ASSERT_THROW( p2 = p1 , std::bad_cast ); CPPUNIT_ASSERT_EQUAL( 1u , p1->getReferenceCount( ) ); } /*----------------------------------------------------------------------------*/ template< bool A > void RefCountTest< A >::testMoveCons( ) { P_Test p1{ P_Test::New( ) }; { P_Test c1{ std::move( p1 ) }; CPPUNIT_ASSERT_EQUAL( 1u , T_Test::cNew ); CPPUNIT_ASSERT_EQUAL( 0u , T_Test::cDel ); CPPUNIT_ASSERT( c1 ); CPPUNIT_ASSERT( !p1 ); CPPUNIT_ASSERT_EQUAL( 1u , c1->getReferenceCount( ) ); } CPPUNIT_ASSERT_EQUAL( 1u , T_Test::cDel ); } template< bool A > void RefCountTest< A >::testMoveConsToBase( ) { P_Child p1{ P_Child::New( ) }; P_Test p2{ std::move( p1 ) }; CPPUNIT_ASSERT( bool( p2 ) ); CPPUNIT_ASSERT( !p1 ); CPPUNIT_ASSERT_EQUAL( 1u , p2->getReferenceCount( ) ); } template< bool A > void RefCountTest< A >::testMoveConsToChildOk( ) { P_Test p1{ P_Test::FromRaw( new T_Child( ) ) }; P_Child p2{ std::move( p1 ) }; CPPUNIT_ASSERT( bool( p2 ) ); CPPUNIT_ASSERT( !p1 ); CPPUNIT_ASSERT_EQUAL( 1u , p2->getReferenceCount( ) ); } template< bool A > void RefCountTest< A >::testMoveConsToChildBad( ) { P_Test p1{ P_Test::New( ) }; CPPUNIT_ASSERT_THROW( P_Child p2{ std::move( p1 ) } , std::bad_cast ); CPPUNIT_ASSERT( p1 ); CPPUNIT_ASSERT_EQUAL( 1u , p1->getReferenceCount( ) ); } /*----------------------------------------------------------------------------*/ template< bool A > void RefCountTest< A >::testMoveAss( ) { P_Test p1{ P_Test::New( ) }; { P_Test c1; CPPUNIT_ASSERT( !c1 ); c1 = std::move( p1 ); CPPUNIT_ASSERT_EQUAL( 1u , T_Test::cNew ); CPPUNIT_ASSERT_EQUAL( 0u , T_Test::cDel ); CPPUNIT_ASSERT( c1 ); CPPUNIT_ASSERT( !p1 ); CPPUNIT_ASSERT_EQUAL( 1u , c1->getReferenceCount( ) ); } CPPUNIT_ASSERT_EQUAL( 1u , T_Test::cDel ); } template< bool A > void RefCountTest< A >::testMoveAssToBase( ) { P_Child p1{ P_Child::New( ) }; P_Test p2; p2 = std::move( p1 ); CPPUNIT_ASSERT( p2 ); CPPUNIT_ASSERT( !p1 ); CPPUNIT_ASSERT_EQUAL( 1u , p2->getReferenceCount( ) ); } template< bool A > void RefCountTest< A >::testMoveAssToChildOk( ) { P_Test p1{ P_Test::FromRaw( new T_Child( ) ) }; P_Child p2; p2 = std::move( p1 ); CPPUNIT_ASSERT( p2 ); CPPUNIT_ASSERT( !p1 ); CPPUNIT_ASSERT_EQUAL( 1u , p2->getReferenceCount( ) ); } template< bool A > void RefCountTest< A >::testMoveAssToChildBad( ) { P_Test p1{ P_Test::New( ) }; P_Child p2; CPPUNIT_ASSERT_THROW( p2 = std::move( p1 ) , std::bad_cast ); CPPUNIT_ASSERT( p1 ); CPPUNIT_ASSERT_EQUAL( 1u , p1->getReferenceCount( ) ); } /*----------------------------------------------------------------------------*/ template< bool A > void RefCountTest< A >::testSwap( ) { { P_Test p1{ P_Test::New( ) }; P_Test p2{ }; CPPUNIT_ASSERT_EQUAL( 1u , T_Test::cNew ); CPPUNIT_ASSERT_EQUAL( 0u , T_Test::cDel ); CPPUNIT_ASSERT( p1 ); CPPUNIT_ASSERT( !p2 ); CPPUNIT_ASSERT_EQUAL( 1u , p1->getReferenceCount( ) ); p1.swap( p2 ); CPPUNIT_ASSERT( !p1 ); CPPUNIT_ASSERT( p2 ); CPPUNIT_ASSERT_EQUAL( 1u , p2->getReferenceCount( ) ); p1.swap( p2 ); CPPUNIT_ASSERT( p1 ); CPPUNIT_ASSERT( !p2 ); CPPUNIT_ASSERT_EQUAL( 1u , p1->getReferenceCount( ) ); } CPPUNIT_ASSERT_EQUAL( 1u , T_Test::cDel ); }