corelib/tests/ref-count.cc
Emmanuel BENOîT a4a2a9eda4 Reference-counting helpers - Equality operators
* Added == and != operators; they can only be used if the referenced types are
from the same hierarchy
 * Tests for the above
2019-01-02 17:52:56 +01:00

504 lines
12 KiB
C++

#include <ebcl/RefCount.hh>
#include <cppunit/extensions/HelperMacros.h>
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( testEq );
CPPUNIT_TEST( testEqChild );
CPPUNIT_TEST( testNEq );
CPPUNIT_TEST( testNEqChild );
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( );
void testEq( );
void testEqChild( );
void testNEq( );
void testNEqChild( );
};
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 );
}
/*----------------------------------------------------------------------------*/
template< bool A >
void RefCountTest< A >::testEq( )
{
P_Test p1{ P_Test::New( ) },
p2{ p1 } ,
p3{ P_Test::New( ) },
p4;
CPPUNIT_ASSERT( ( p1 == p1 ) );
CPPUNIT_ASSERT( ( p1 == p2 ) );
CPPUNIT_ASSERT( !( p1 == p3 ) );
CPPUNIT_ASSERT( !( p1 == p4 ) );
CPPUNIT_ASSERT( ( p2 == p1 ) );
CPPUNIT_ASSERT( ( p2 == p2 ) );
CPPUNIT_ASSERT( !( p2 == p3 ) );
CPPUNIT_ASSERT( !( p2 == p4 ) );
CPPUNIT_ASSERT( !( p3 == p1 ) );
CPPUNIT_ASSERT( !( p3 == p2 ) );
CPPUNIT_ASSERT( ( p3 == p3 ) );
CPPUNIT_ASSERT( !( p3 == p4 ) );
CPPUNIT_ASSERT( !( p4 == p1 ) );
CPPUNIT_ASSERT( !( p4 == p2 ) );
CPPUNIT_ASSERT( !( p4 == p3 ) );
CPPUNIT_ASSERT( ( p4 == p4 ) );
}
template< bool A >
void RefCountTest< A >::testEqChild( )
{
P_Child p1{ P_Child::New( ) } ,
p2{ P_Child::New( ) };
P_Test p3{ p1 } , p4{ p2 };
CPPUNIT_ASSERT( ( p1 == p1 ) );
CPPUNIT_ASSERT( !( p1 == p2 ) );
CPPUNIT_ASSERT( ( p1 == p3 ) );
CPPUNIT_ASSERT( !( p1 == p4 ) );
CPPUNIT_ASSERT( !( p2 == p1 ) );
CPPUNIT_ASSERT( ( p2 == p2 ) );
CPPUNIT_ASSERT( !( p2 == p3 ) );
CPPUNIT_ASSERT( ( p2 == p4 ) );
CPPUNIT_ASSERT( ( p3 == p1 ) );
CPPUNIT_ASSERT( !( p3 == p2 ) );
CPPUNIT_ASSERT( ( p3 == p3 ) );
CPPUNIT_ASSERT( !( p3 == p4 ) );
CPPUNIT_ASSERT( !( p4 == p1 ) );
CPPUNIT_ASSERT( ( p4 == p2 ) );
CPPUNIT_ASSERT( !( p4 == p3 ) );
CPPUNIT_ASSERT( ( p4 == p4 ) );
}
/*----------------------------------------------------------------------------*/
template< bool A >
void RefCountTest< A >::testNEq( )
{
P_Test p1{ P_Test::New( ) },
p2{ p1 } ,
p3{ P_Test::New( ) },
p4;
CPPUNIT_ASSERT( !( p1 != p1 ) );
CPPUNIT_ASSERT( !( p1 != p2 ) );
CPPUNIT_ASSERT( ( p1 != p3 ) );
CPPUNIT_ASSERT( ( p1 != p4 ) );
CPPUNIT_ASSERT( !( p2 != p1 ) );
CPPUNIT_ASSERT( !( p2 != p2 ) );
CPPUNIT_ASSERT( ( p2 != p3 ) );
CPPUNIT_ASSERT( ( p2 != p4 ) );
CPPUNIT_ASSERT( ( p3 != p1 ) );
CPPUNIT_ASSERT( ( p3 != p2 ) );
CPPUNIT_ASSERT( !( p3 != p3 ) );
CPPUNIT_ASSERT( ( p3 != p4 ) );
CPPUNIT_ASSERT( ( p4 != p1 ) );
CPPUNIT_ASSERT( ( p4 != p2 ) );
CPPUNIT_ASSERT( ( p4 != p3 ) );
CPPUNIT_ASSERT( !( p4 != p4 ) );
}
template< bool A >
void RefCountTest< A >::testNEqChild( )
{
P_Child p1{ P_Child::New( ) } ,
p2{ P_Child::New( ) };
P_Test p3{ p1 } , p4{ p2 };
CPPUNIT_ASSERT( !( p1 != p1 ) );
CPPUNIT_ASSERT( ( p1 != p2 ) );
CPPUNIT_ASSERT( !( p1 != p3 ) );
CPPUNIT_ASSERT( ( p1 != p4 ) );
CPPUNIT_ASSERT( ( p2 != p1 ) );
CPPUNIT_ASSERT( !( p2 != p2 ) );
CPPUNIT_ASSERT( ( p2 != p3 ) );
CPPUNIT_ASSERT( !( p2 != p4 ) );
CPPUNIT_ASSERT( !( p3 != p1 ) );
CPPUNIT_ASSERT( ( p3 != p2 ) );
CPPUNIT_ASSERT( !( p3 != p3 ) );
CPPUNIT_ASSERT( ( p3 != p4 ) );
CPPUNIT_ASSERT( ( p4 != p1 ) );
CPPUNIT_ASSERT( !( p4 != p2 ) );
CPPUNIT_ASSERT( ( p4 != p3 ) );
CPPUNIT_ASSERT( !( p4 != p4 ) );
}