2017-11-01 21:44:54 +01:00
|
|
|
#include <ebcl/Types.hh>
|
2017-11-01 20:14:23 +01:00
|
|
|
#include <cppunit/extensions/HelperMacros.h>
|
2017-11-01 21:44:54 +01:00
|
|
|
using namespace ebcl;
|
2017-11-01 20:14:23 +01:00
|
|
|
|
|
|
|
|
|
|
|
class UnionTest : public CppUnit::TestFixture
|
|
|
|
{
|
|
|
|
CPPUNIT_TEST_SUITE( UnionTest );
|
|
|
|
CPPUNIT_TEST( testDefaultConsSimple );
|
|
|
|
CPPUNIT_TEST( testDefaultConsObject );
|
|
|
|
CPPUNIT_TEST( testNoDefaultCons );
|
|
|
|
CPPUNIT_TEST( testInPlaceCons );
|
|
|
|
CPPUNIT_TEST( testDestruct );
|
|
|
|
|
|
|
|
CPPUNIT_TEST( testMoveCons );
|
|
|
|
CPPUNIT_TEST( testMoveAss );
|
|
|
|
CPPUNIT_TEST( testMoveConsNoCopy );
|
|
|
|
CPPUNIT_TEST( testMoveAssNoCopy );
|
|
|
|
|
|
|
|
CPPUNIT_TEST( testCopyCons );
|
|
|
|
CPPUNIT_TEST( testCopyAss );
|
|
|
|
CPPUNIT_TEST( testCopyConsNoMove );
|
|
|
|
CPPUNIT_TEST( testCopyAssNoMove );
|
|
|
|
|
|
|
|
CPPUNIT_TEST( testMoveContentsCons );
|
|
|
|
CPPUNIT_TEST( testMoveContentsAss );
|
|
|
|
CPPUNIT_TEST( testCopyContentsCons );
|
|
|
|
CPPUNIT_TEST( testCopyContentsAss );
|
|
|
|
|
|
|
|
CPPUNIT_TEST( testSwap );
|
|
|
|
|
|
|
|
CPPUNIT_TEST( testTypeInfo );
|
|
|
|
CPPUNIT_TEST( testTargetModify );
|
|
|
|
|
|
|
|
CPPUNIT_TEST( testValue );
|
|
|
|
CPPUNIT_TEST( testValueModify );
|
|
|
|
CPPUNIT_TEST( testValueException );
|
|
|
|
CPPUNIT_TEST_SUITE_END( );
|
|
|
|
|
|
|
|
public:
|
|
|
|
void tearDown( ) override;
|
|
|
|
|
|
|
|
void testDefaultConsSimple( );
|
|
|
|
void testDefaultConsObject( );
|
|
|
|
void testNoDefaultCons( );
|
|
|
|
void testInPlaceCons( );
|
|
|
|
void testDestruct( );
|
|
|
|
|
|
|
|
void testMoveCons( );
|
|
|
|
void testMoveAss( );
|
|
|
|
void testMoveConsNoCopy( );
|
|
|
|
void testMoveAssNoCopy( );
|
|
|
|
|
|
|
|
void testCopyCons( );
|
|
|
|
void testCopyAss( );
|
|
|
|
void testCopyConsNoMove( );
|
|
|
|
void testCopyAssNoMove( );
|
|
|
|
|
|
|
|
void testMoveContentsCons( );
|
|
|
|
void testMoveContentsAss( );
|
|
|
|
void testCopyContentsCons( );
|
|
|
|
void testCopyContentsAss( );
|
|
|
|
|
|
|
|
void testSwap( );
|
|
|
|
|
|
|
|
void testTypeInfo( );
|
|
|
|
void testTargetModify( );
|
|
|
|
|
|
|
|
void testValue( );
|
|
|
|
void testValueModify( );
|
|
|
|
void testValueException( );
|
|
|
|
};
|
|
|
|
CPPUNIT_TEST_SUITE_REGISTRATION( UnionTest );
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
struct T_DefCons_
|
|
|
|
{
|
|
|
|
int x;
|
|
|
|
T_DefCons_( ) noexcept : x( 123 ) { }
|
|
|
|
};
|
|
|
|
|
|
|
|
struct T_NoDefCons_
|
|
|
|
{
|
|
|
|
int x;
|
|
|
|
T_NoDefCons_( ) = delete;
|
|
|
|
explicit T_NoDefCons_( int x ) noexcept : x( x ) { }
|
|
|
|
};
|
|
|
|
|
|
|
|
struct T_NoMove_
|
|
|
|
{
|
|
|
|
int x;
|
|
|
|
T_NoMove_( ) = delete;
|
|
|
|
explicit T_NoMove_( int x ) noexcept : x( x ) { }
|
|
|
|
T_NoMove_( T_NoMove_ const& o ) noexcept : x( o.x ) { }
|
|
|
|
T_NoMove_( T_NoMove_&& ) noexcept = delete;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct T_NoCopy_
|
|
|
|
{
|
|
|
|
int x;
|
|
|
|
T_NoCopy_( ) = delete;
|
|
|
|
explicit T_NoCopy_( int x ) noexcept : x( x ) { }
|
|
|
|
T_NoCopy_( T_NoCopy_ const& ) noexcept = delete;
|
|
|
|
T_NoCopy_( T_NoCopy_&& o ) noexcept : x( o.x ) { }
|
|
|
|
};
|
|
|
|
|
|
|
|
int consCounter = 0;
|
|
|
|
int delCounter = 0;
|
|
|
|
int mvCounter = 0;
|
|
|
|
int cpCounter = 0;
|
|
|
|
|
|
|
|
struct T_Counter_
|
|
|
|
{
|
|
|
|
int value;
|
|
|
|
|
|
|
|
T_Counter_( ) noexcept : value( 0 ) { consCounter ++; }
|
|
|
|
explicit T_Counter_( int x ) noexcept : value( x ) { consCounter ++; }
|
|
|
|
|
|
|
|
T_Counter_( T_Counter_ const& o ) noexcept : value( o.value ) { cpCounter ++; }
|
|
|
|
T_Counter_( T_Counter_&& o ) noexcept : value( o.value ) { mvCounter ++; }
|
|
|
|
|
|
|
|
~T_Counter_( ) { delCounter ++; }
|
|
|
|
};
|
|
|
|
|
|
|
|
#define M_COUNTS_(C,D,CP,M) \
|
|
|
|
do { \
|
|
|
|
CPPUNIT_ASSERT_EQUAL( int( C ) , consCounter ); \
|
|
|
|
CPPUNIT_ASSERT_EQUAL( int( D ) , delCounter ); \
|
|
|
|
CPPUNIT_ASSERT_EQUAL( int( CP ) , cpCounter ); \
|
|
|
|
CPPUNIT_ASSERT_EQUAL( int( M ) , mvCounter ); \
|
|
|
|
} while ( 0 )
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
void UnionTest::tearDown( )
|
|
|
|
{
|
|
|
|
consCounter = delCounter = mvCounter = cpCounter = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
void UnionTest::testDefaultConsSimple( )
|
|
|
|
{
|
|
|
|
const T_Union< uint32_t , T_DefCons_ > u;
|
|
|
|
CPPUNIT_ASSERT( u.hasType< uint32_t >( ) );
|
|
|
|
CPPUNIT_ASSERT( u.target< uint32_t >( ) != nullptr );
|
|
|
|
CPPUNIT_ASSERT_EQUAL( 0u , *( u.target< uint32_t >( ) ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
void UnionTest::testDefaultConsObject( )
|
|
|
|
{
|
|
|
|
const T_Union< T_DefCons_ , uint32_t > u;
|
|
|
|
CPPUNIT_ASSERT( u.hasType< T_DefCons_ >( ) );
|
|
|
|
CPPUNIT_ASSERT( u.target< T_DefCons_ >( ) != nullptr );
|
|
|
|
CPPUNIT_ASSERT_EQUAL( 123 , u.target< T_DefCons_ >( )->x );
|
|
|
|
}
|
|
|
|
|
|
|
|
void UnionTest::testNoDefaultCons( )
|
|
|
|
{
|
|
|
|
constexpr bool r( !std::is_default_constructible< T_Union< T_NoDefCons_ , uint32_t > >::value );
|
|
|
|
CPPUNIT_ASSERT( r );
|
|
|
|
}
|
|
|
|
|
|
|
|
void UnionTest::testInPlaceCons( )
|
|
|
|
{
|
|
|
|
const T_Union< uint32_t , T_NoDefCons_ > u( Construct< T_NoDefCons_ >( ) , 456 );
|
|
|
|
CPPUNIT_ASSERT( u.hasType< T_NoDefCons_ >( ) );
|
|
|
|
CPPUNIT_ASSERT( u.target< T_NoDefCons_ >( ) != nullptr );
|
|
|
|
CPPUNIT_ASSERT_EQUAL( 456 , u.target< T_NoDefCons_ >( )->x );
|
|
|
|
}
|
|
|
|
|
|
|
|
void UnionTest::testDestruct( )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
T_Union< T_Counter_ , uint32_t > u0( Construct< T_Counter_ >( ) , 123 );
|
|
|
|
}
|
|
|
|
M_COUNTS_( 1 , 1 , 0 , 0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
void UnionTest::testMoveCons( )
|
|
|
|
{
|
|
|
|
T_Union< T_Counter_ , uint32_t > u0( Construct< T_Counter_ >( ) , 123 );
|
|
|
|
T_Union< T_Counter_ , uint32_t > u1( std::move( u0 ) );
|
|
|
|
M_COUNTS_( 1 , 0 , 0 , 1 );
|
|
|
|
CPPUNIT_ASSERT( u1.hasType< T_Counter_ >( ) );
|
|
|
|
CPPUNIT_ASSERT( u1.target< T_Counter_ >( ) != nullptr );
|
|
|
|
CPPUNIT_ASSERT_EQUAL( 123 , u1.target< T_Counter_ >( )->value );
|
|
|
|
}
|
|
|
|
|
|
|
|
void UnionTest::testMoveAss( )
|
|
|
|
{
|
|
|
|
T_Union< T_Counter_ , uint32_t > u0( Construct< T_Counter_ >( ) , 123 );
|
|
|
|
T_Union< T_Counter_ , uint32_t > u1( Construct< T_Counter_ >( ) , 456 );
|
|
|
|
M_COUNTS_( 2 , 0 , 0 , 0 );
|
|
|
|
u1 = std::move( u0 );
|
|
|
|
M_COUNTS_( 2 , 1 , 0 , 1 );
|
|
|
|
CPPUNIT_ASSERT( u1.hasType< T_Counter_ >( ) );
|
|
|
|
CPPUNIT_ASSERT( u1.target< T_Counter_ >( ) != nullptr );
|
|
|
|
CPPUNIT_ASSERT_EQUAL( 123 , u1.target< T_Counter_ >( )->value );
|
|
|
|
}
|
|
|
|
|
|
|
|
void UnionTest::testMoveConsNoCopy( )
|
|
|
|
{
|
|
|
|
T_Union< T_Counter_ , T_NoCopy_ > u0( Construct< T_Counter_ >( ) , 123 );
|
|
|
|
T_Union< T_Counter_ , T_NoCopy_ > u1( std::move( u0 ) );
|
|
|
|
M_COUNTS_( 1 , 0 , 0 , 1 );
|
|
|
|
CPPUNIT_ASSERT( u1.hasType< T_Counter_ >( ) );
|
|
|
|
CPPUNIT_ASSERT( u1.target< T_Counter_ >( ) != nullptr );
|
|
|
|
CPPUNIT_ASSERT_EQUAL( 123 , u1.target< T_Counter_ >( )->value );
|
|
|
|
}
|
|
|
|
|
|
|
|
void UnionTest::testMoveAssNoCopy( )
|
|
|
|
{
|
|
|
|
T_Union< T_Counter_ , T_NoCopy_ > u0( Construct< T_Counter_ >( ) , 123 );
|
|
|
|
T_Union< T_Counter_ , T_NoCopy_ > u1( Construct< T_Counter_ >( ) , 456 );
|
|
|
|
M_COUNTS_( 2 , 0 , 0 , 0 );
|
|
|
|
u1 = std::move( u0 );
|
|
|
|
M_COUNTS_( 2 , 1 , 0 , 1 );
|
|
|
|
CPPUNIT_ASSERT( u1.hasType< T_Counter_ >( ) );
|
|
|
|
CPPUNIT_ASSERT( u1.target< T_Counter_ >( ) != nullptr );
|
|
|
|
CPPUNIT_ASSERT_EQUAL( 123 , u1.target< T_Counter_ >( )->value );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
void UnionTest::testCopyCons( )
|
|
|
|
{
|
|
|
|
T_Union< T_Counter_ , uint32_t > u0( Construct< T_Counter_ >( ) , 123 );
|
|
|
|
T_Union< T_Counter_ , uint32_t > u1( u0 );
|
|
|
|
M_COUNTS_( 1 , 0 , 1 , 0 );
|
|
|
|
CPPUNIT_ASSERT( u1.hasType< T_Counter_ >( ) );
|
|
|
|
CPPUNIT_ASSERT( u1.target< T_Counter_ >( ) != nullptr );
|
|
|
|
CPPUNIT_ASSERT_EQUAL( 123 , u1.target< T_Counter_ >( )->value );
|
|
|
|
}
|
|
|
|
|
|
|
|
void UnionTest::testCopyAss( )
|
|
|
|
{
|
|
|
|
T_Union< T_Counter_ , uint32_t > u0( Construct< T_Counter_ >( ) , 123 );
|
|
|
|
T_Union< T_Counter_ , uint32_t > u1( Construct< T_Counter_ >( ) , 456 );
|
|
|
|
M_COUNTS_( 2 , 0 , 0 , 0 );
|
|
|
|
u1 = u0;
|
|
|
|
M_COUNTS_( 2 , 1 , 1 , 0 );
|
|
|
|
CPPUNIT_ASSERT( u1.hasType< T_Counter_ >( ) );
|
|
|
|
CPPUNIT_ASSERT( u1.target< T_Counter_ >( ) != nullptr );
|
|
|
|
CPPUNIT_ASSERT_EQUAL( 123 , u1.target< T_Counter_ >( )->value );
|
|
|
|
}
|
|
|
|
|
|
|
|
void UnionTest::testCopyConsNoMove( )
|
|
|
|
{
|
|
|
|
T_Union< T_Counter_ , T_NoMove_ > u0( Construct< T_Counter_ >( ) , 123 );
|
|
|
|
T_Union< T_Counter_ , T_NoMove_ > u1( u0 );
|
|
|
|
M_COUNTS_( 1 , 0 , 1 , 0 );
|
|
|
|
CPPUNIT_ASSERT( u1.hasType< T_Counter_ >( ) );
|
|
|
|
CPPUNIT_ASSERT( u1.target< T_Counter_ >( ) != nullptr );
|
|
|
|
CPPUNIT_ASSERT_EQUAL( 123 , u1.target< T_Counter_ >( )->value );
|
|
|
|
}
|
|
|
|
|
|
|
|
void UnionTest::testCopyAssNoMove( )
|
|
|
|
{
|
|
|
|
T_Union< T_Counter_ , T_NoMove_ > u0( Construct< T_Counter_ >( ) , 123 );
|
|
|
|
T_Union< T_Counter_ , T_NoMove_ > u1( Construct< T_Counter_ >( ) , 456 );
|
|
|
|
M_COUNTS_( 2 , 0 , 0 , 0 );
|
|
|
|
u1 = u0;
|
|
|
|
M_COUNTS_( 2 , 1 , 1 , 0 );
|
|
|
|
CPPUNIT_ASSERT( u1.hasType< T_Counter_ >( ) );
|
|
|
|
CPPUNIT_ASSERT( u1.target< T_Counter_ >( ) != nullptr );
|
|
|
|
CPPUNIT_ASSERT_EQUAL( 123 , u1.target< T_Counter_ >( )->value );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
void UnionTest::testMoveContentsCons( )
|
|
|
|
{
|
|
|
|
T_Counter_ c( 123 );
|
|
|
|
T_Union< T_Counter_ , uint32_t > u( std::move( c ) );
|
|
|
|
M_COUNTS_( 1 , 0 , 0 , 1 );
|
|
|
|
CPPUNIT_ASSERT( u.hasType< T_Counter_ >( ) );
|
|
|
|
CPPUNIT_ASSERT( u.target< T_Counter_ >( ) != nullptr );
|
|
|
|
CPPUNIT_ASSERT_EQUAL( 123 , u.target< T_Counter_ >( )->value );
|
|
|
|
}
|
|
|
|
|
|
|
|
void UnionTest::testMoveContentsAss( )
|
|
|
|
{
|
|
|
|
T_Union< T_Counter_ , uint32_t > u( Construct< T_Counter_ >( ) , 456 );
|
|
|
|
M_COUNTS_( 1 , 0 , 0 , 0 );
|
|
|
|
u = T_Counter_( 123 );
|
|
|
|
M_COUNTS_( 2 , 2 , 0 , 1 );
|
|
|
|
CPPUNIT_ASSERT( u.hasType< T_Counter_ >( ) );
|
|
|
|
CPPUNIT_ASSERT( u.target< T_Counter_ >( ) != nullptr );
|
|
|
|
CPPUNIT_ASSERT_EQUAL( 123 , u.target< T_Counter_ >( )->value );
|
|
|
|
}
|
|
|
|
|
|
|
|
void UnionTest::testCopyContentsCons( )
|
|
|
|
{
|
|
|
|
T_Counter_ c( 123 );
|
|
|
|
T_Union< T_Counter_ , uint32_t > u( c );
|
|
|
|
M_COUNTS_( 1 , 0 , 1 , 0 );
|
|
|
|
CPPUNIT_ASSERT( u.hasType< T_Counter_ >( ) );
|
|
|
|
CPPUNIT_ASSERT( u.target< T_Counter_ >( ) != nullptr );
|
|
|
|
CPPUNIT_ASSERT_EQUAL( 123 , u.target< T_Counter_ >( )->value );
|
|
|
|
}
|
|
|
|
|
|
|
|
void UnionTest::testCopyContentsAss( )
|
|
|
|
{
|
|
|
|
T_Counter_ c( 123 );
|
|
|
|
T_Union< T_Counter_ , uint32_t > u( Construct< T_Counter_ >( ) , 456 );
|
|
|
|
M_COUNTS_( 2 , 0 , 0 , 0 );
|
|
|
|
u = c;
|
|
|
|
M_COUNTS_( 2 , 1 , 1 , 0 );
|
|
|
|
CPPUNIT_ASSERT( u.hasType< T_Counter_ >( ) );
|
|
|
|
CPPUNIT_ASSERT( u.target< T_Counter_ >( ) != nullptr );
|
|
|
|
CPPUNIT_ASSERT_EQUAL( 123 , u.target< T_Counter_ >( )->value );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
void UnionTest::testSwap( )
|
|
|
|
{
|
|
|
|
T_Union< T_Counter_ , uint32_t > u0( Construct< T_Counter_ >( ) , 123 );
|
|
|
|
T_Union< T_Counter_ , uint32_t > u1( Construct< T_Counter_ >( ) , 456 );
|
|
|
|
M_COUNTS_( 2 , 0 , 0 , 0 );
|
|
|
|
swap( u0 , u1 );
|
|
|
|
M_COUNTS_( 2 , 3 , 0 , 3 );
|
|
|
|
CPPUNIT_ASSERT( u0.hasType< T_Counter_ >( ) );
|
|
|
|
CPPUNIT_ASSERT( u0.target< T_Counter_ >( ) != nullptr );
|
|
|
|
CPPUNIT_ASSERT_EQUAL( 456 , u0.target< T_Counter_ >( )->value );
|
|
|
|
CPPUNIT_ASSERT( u1.hasType< T_Counter_ >( ) );
|
|
|
|
CPPUNIT_ASSERT( u1.target< T_Counter_ >( ) != nullptr );
|
|
|
|
CPPUNIT_ASSERT_EQUAL( 123 , u1.target< T_Counter_ >( )->value );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
void UnionTest::testTypeInfo( )
|
|
|
|
{
|
|
|
|
T_Union< T_DefCons_ , uint32_t > u;
|
|
|
|
CPPUNIT_ASSERT( u.typeInfo( ) == typeid( T_DefCons_ ) );
|
|
|
|
u = 1u;
|
|
|
|
CPPUNIT_ASSERT( u.typeInfo( ) == typeid( uint32_t ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
void UnionTest::testTargetModify( )
|
|
|
|
{
|
|
|
|
T_Union< T_DefCons_ , uint32_t > u;
|
|
|
|
u.target< T_DefCons_ >( )->x = 987;
|
|
|
|
CPPUNIT_ASSERT( u.hasType< T_DefCons_ >( ) );
|
|
|
|
CPPUNIT_ASSERT( u.target< T_DefCons_ >( ) != nullptr );
|
|
|
|
CPPUNIT_ASSERT_EQUAL( 987 , u.target< T_DefCons_ >( )->x );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
void UnionTest::testValue( )
|
|
|
|
{
|
|
|
|
T_Union< uint32_t , T_DefCons_ > u( 123u );
|
|
|
|
CPPUNIT_ASSERT( u.hasType< uint32_t >( ) );
|
|
|
|
CPPUNIT_ASSERT( u.target< uint32_t >( ) != nullptr );
|
|
|
|
CPPUNIT_ASSERT_EQUAL( 123u , u.value< uint32_t >( ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
void UnionTest::testValueModify( )
|
|
|
|
{
|
|
|
|
T_Union< uint32_t , T_DefCons_ > u( 123u );
|
|
|
|
CPPUNIT_ASSERT( u.hasType< uint32_t >( ) );
|
|
|
|
CPPUNIT_ASSERT( u.target< uint32_t >( ) != nullptr );
|
|
|
|
u.value< uint32_t >( ) = 456;
|
|
|
|
CPPUNIT_ASSERT_EQUAL( 456u , u.value< uint32_t >( ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
void UnionTest::testValueException( )
|
|
|
|
{
|
|
|
|
T_Union< uint32_t , T_DefCons_ > u( T_DefCons_{} );
|
|
|
|
CPPUNIT_ASSERT( u.hasType< T_DefCons_ >( ) );
|
|
|
|
try {
|
|
|
|
u.value< uint32_t >( ) = 456u;
|
|
|
|
CPPUNIT_FAIL( "exception not thrown" );
|
|
|
|
} catch ( std::bad_cast const& ) {
|
|
|
|
// OK
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|