#include #include using namespace ebcl; class OptionalTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE( OptionalTest ); CPPUNIT_TEST( testDefaultCons ); CPPUNIT_TEST( testConstructCons ); CPPUNIT_TEST( testDestruct ); CPPUNIT_TEST( testCopyCons ); CPPUNIT_TEST( testCopyAss ); CPPUNIT_TEST( testMoveCons ); CPPUNIT_TEST( testMoveAss ); CPPUNIT_TEST( testSwapEE ); CPPUNIT_TEST( testSwapVV ); CPPUNIT_TEST( testSwapVE ); CPPUNIT_TEST( testValueCopyCons ); CPPUNIT_TEST( testValueCopyAss ); CPPUNIT_TEST( testValueMoveCons ); CPPUNIT_TEST( testValueMoveAss ); CPPUNIT_TEST( testSetNew ); CPPUNIT_TEST( testClear ); CPPUNIT_TEST( testCast ); CPPUNIT_TEST( testCastException ); CPPUNIT_TEST_SUITE_END( ); public: void tearDown( ) override; void testDefaultCons( ); void testConstructCons( ); void testDestruct( ); void testCopyCons( ); void testCopyAss( ); void testMoveCons( ); void testMoveAss( ); void testSwapEE( ); void testSwapVV( ); void testSwapVE( ); void testValueCopyCons( ); void testValueCopyAss( ); void testValueMoveCons( ); void testValueMoveAss( ); void testSetNew( ); void testClear( ); void testCast( ); void testCastException( ); }; CPPUNIT_TEST_SUITE_REGISTRATION( OptionalTest ); /*----------------------------------------------------------------------------*/ namespace { 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 ) #define M_EMPTY_( O ) \ do { \ CPPUNIT_ASSERT( ! ( O ).present( ) ); \ CPPUNIT_ASSERT( ( O ).target( ) == nullptr ); \ } while ( 0 ) #define M_VALUE_( O , V ) \ do { \ CPPUNIT_ASSERT( ( O ).present( ) ); \ CPPUNIT_ASSERT( ( O ).target( ) != nullptr ); \ CPPUNIT_ASSERT_EQUAL( int( V ) , ( O ).target( )->value ); \ } while ( 0 ) } // namespace void OptionalTest::tearDown( ) { consCounter = delCounter = mvCounter = cpCounter = 0; } /*----------------------------------------------------------------------------*/ void OptionalTest::testDefaultCons( ) { const T_Optional< T_Counter_ > o; M_EMPTY_( o ); M_COUNTS_( 0 , 0 , 0 , 0 ); } void OptionalTest::testConstructCons( ) { const T_Optional< T_Counter_ > o{ Construct< T_Counter_ >( ) , 12 }; M_VALUE_( o , 12 ); M_COUNTS_( 1 , 0 , 0 , 0 ); } void OptionalTest::testDestruct( ) { { T_Optional< T_Counter_ > o{ Construct< T_Counter_ >( ) }; } M_COUNTS_( 1 , 1 , 0 , 0 ); } /*----------------------------------------------------------------------------*/ void OptionalTest::testCopyCons( ) { const T_Optional< T_Counter_ > s{ Construct< T_Counter_ >( ) , 12 }; const T_Optional< T_Counter_ > d( s ); M_COUNTS_( 1 , 0 , 1 , 0 ); M_VALUE_( s , 12 ); M_VALUE_( d , 12 ); } void OptionalTest::testCopyAss( ) { const T_Optional< T_Counter_ > s{ Construct< T_Counter_ >( ) , 12 }; const T_Optional< T_Counter_ > empty; T_Optional< T_Counter_ > d; d = s; M_COUNTS_( 1 , 0 , 1 , 0 ); M_VALUE_( s , 12 ); M_VALUE_( d , 12 ); d = empty; M_COUNTS_( 1 , 1 , 1 , 0 ); M_EMPTY_( d ); } void OptionalTest::testMoveCons( ) { T_Optional< T_Counter_ > s{ Construct< T_Counter_ >( ) , 12 }; const T_Optional< T_Counter_ > d( std::move( s ) ); M_COUNTS_( 1 , 1 , 0 , 1 ); M_VALUE_( d , 12 ); M_EMPTY_( s ); } void OptionalTest::testMoveAss( ) { T_Optional< T_Counter_ > s{ Construct< T_Counter_ >( ) , 12 }; T_Optional< T_Counter_ > empty; T_Optional< T_Counter_ > d; d = std::move( s ); M_COUNTS_( 1 , 1 , 0 , 1 ); M_EMPTY_( s ); M_VALUE_( d , 12 ); d = std::move( empty ); M_COUNTS_( 1 , 2 , 0 , 1 ); M_EMPTY_( d ); } /*----------------------------------------------------------------------------*/ void OptionalTest::testSwapEE( ) { T_Optional< T_Counter_ > o1 , o2; swap( o1 , o2 ); M_COUNTS_( 0 , 0 , 0 , 0 ); M_EMPTY_( o1 ); M_EMPTY_( o2 ); } void OptionalTest::testSwapVV( ) { T_Optional< T_Counter_ > o1{ Construct< T_Counter_ >( ) , 1 } , o2{ Construct< T_Counter_ >( ) , 2 }; swap( o1 , o2 ); M_COUNTS_( 2 , 3 , 0 , 3 ); M_VALUE_( o1 , 2 ); M_VALUE_( o2 , 1 ); } void OptionalTest::testSwapVE( ) { T_Optional< T_Counter_ > o1{ Construct< T_Counter_ >( ) , 1 } , o2; swap( o1 , o2 ); M_COUNTS_( 1 , 1 , 0 , 1 ); M_EMPTY_( o1 ); M_VALUE_( o2 , 1 ); } /*----------------------------------------------------------------------------*/ void OptionalTest::testValueCopyCons( ) { const T_Counter_ c( 12 ); T_Optional< T_Counter_ > o( c ); M_COUNTS_( 1 , 0 , 1 , 0 ); M_VALUE_( o , 12 ); } void OptionalTest::testValueCopyAss( ) { const T_Counter_ c( 12 ); T_Optional< T_Counter_ > o; o = c; M_COUNTS_( 1 , 0 , 1 , 0 ); M_VALUE_( o , 12 ); } void OptionalTest::testValueMoveCons( ) { T_Counter_ c( 12 ); T_Optional< T_Counter_ > o( std::move( c ) ); M_COUNTS_( 1 , 0 , 0 , 1 ); M_VALUE_( o , 12 ); } void OptionalTest::testValueMoveAss( ) { T_Counter_ c( 12 ); T_Optional< T_Counter_ > o; o = std::move( c ); M_COUNTS_( 1 , 0 , 0 , 1 ); M_VALUE_( o , 12 ); } /*----------------------------------------------------------------------------*/ void OptionalTest::testSetNew( ) { T_Optional< T_Counter_ > s{ Construct< T_Counter_ >( ) , 12 }; s.setNew( 34 ); M_COUNTS_( 2 , 1 , 0 , 0 ); M_VALUE_( s , 34 ); } void OptionalTest::testClear( ) { T_Optional< T_Counter_ > s{ Construct< T_Counter_ >( ) , 12 }; s.clear( ); M_COUNTS_( 1 , 1 , 0 , 0 ); M_EMPTY_( s ); } /*----------------------------------------------------------------------------*/ void OptionalTest::testCast( ) { const T_Optional< T_Counter_ > s{ Construct< T_Counter_ >( ) , 12 }; T_Counter_ cnt( s ); CPPUNIT_ASSERT_EQUAL( 12 , cnt.value ); } void OptionalTest::testCastException( ) { const T_Optional< T_Counter_ > s; try { T_Counter_ cnt( s ); CPPUNIT_FAIL( "std::bad_cast not thrown" ); } catch ( std::bad_cast const& ) { // OK } }