corelib/tests/union.cc

386 lines
11 KiB
C++

#include <ebcl/Types.hh>
#include <cppunit/extensions/HelperMacros.h>
using namespace ebcl;
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
}
}