#include #include using namespace ebcl; class ArraysStaticObjectsTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE( ArraysStaticObjectsTest ); CPPUNIT_TEST( testCopyCons ); CPPUNIT_TEST( testCopyAss ); CPPUNIT_TEST( testMoveCons ); CPPUNIT_TEST( testMoveAss ); CPPUNIT_TEST( testSwap ); CPPUNIT_TEST( testAppendCopy ); CPPUNIT_TEST( testAppendMove ); CPPUNIT_TEST( testAppendNew ); CPPUNIT_TEST( testAppendTwo ); CPPUNIT_TEST( testInsertCopyEmpty ); CPPUNIT_TEST( testInsertCopyBefore ); CPPUNIT_TEST( testInsertCopyAfter ); CPPUNIT_TEST( testInsertMoveEmpty ); CPPUNIT_TEST( testInsertMoveBefore ); CPPUNIT_TEST( testInsertMoveAfter ); CPPUNIT_TEST( testInsertNewEmpty ); CPPUNIT_TEST( testInsertNewBefore ); CPPUNIT_TEST( testInsertNewAfter ); CPPUNIT_TEST( testRemoveEnd ); CPPUNIT_TEST( testRemoveMiddle ); CPPUNIT_TEST( testRemoveSwapEnd ); CPPUNIT_TEST( testRemoveSwapMiddle ); CPPUNIT_TEST( testClear ); CPPUNIT_TEST( testIndexOf ); CPPUNIT_TEST( testIndexOfMissing ); CPPUNIT_TEST( testContains ); CPPUNIT_TEST( testContainsMissing ); CPPUNIT_TEST( testSort ); CPPUNIT_TEST( testSortComparator ); CPPUNIT_TEST( testSortPartial ); CPPUNIT_TEST( testCopyRangeOutside ); CPPUNIT_TEST( testCopyRangeLarger ); CPPUNIT_TEST( testCopyRangeSub ); CPPUNIT_TEST( testMoveRangeOutside ); CPPUNIT_TEST( testMoveRangeLarger ); CPPUNIT_TEST( testMoveRangeSub ); CPPUNIT_TEST_SUITE_END( ); public: void tearDown( ) override; void testCopyCons( ); void testCopyAss( ); void testMoveCons( ); void testMoveAss( ); void testSwap( ); void testAppendCopy( ); void testAppendMove( ); void testAppendNew( ); void testAppendTwo( ); void testInsertCopyEmpty( ); void testInsertCopyBefore( ); void testInsertCopyAfter( ); void testInsertMoveEmpty( ); void testInsertMoveBefore( ); void testInsertMoveAfter( ); void testInsertNewEmpty( ); void testInsertNewBefore( ); void testInsertNewAfter( ); void testRemoveEnd( ); void testRemoveMiddle( ); void testRemoveSwapEnd( ); void testRemoveSwapMiddle( ); void testClear( ); void testIndexOf( ); void testIndexOfMissing( ); void testContains( ); void testContainsMissing( ); void testSort( ); void testSortComparator( ); void testSortPartial( ); void testCopyRangeOutside( ); void testCopyRangeLarger( ); void testCopyRangeSub( ); void testMoveRangeOutside( ); void testMoveRangeLarger( ); void testMoveRangeSub( ); }; CPPUNIT_TEST_SUITE_REGISTRATION( ArraysStaticObjectsTest ); /*----------------------------------------------------------------------------*/ namespace { struct T_TestObject_ { static uint32_t nConsDefault; static uint32_t nConsCopy; static uint32_t nConsMove; static uint32_t nDestr; static void reset( ) { nConsDefault = 0; nConsCopy = 0; nConsMove = 0; nDestr = 0; } uint32_t serial; T_TestObject_( ) noexcept { nConsDefault ++; } T_TestObject_( uint32_t serial ) noexcept : serial( serial ) { } T_TestObject_( T_TestObject_ const& o ) noexcept : serial( o.serial ) { nConsCopy ++; } T_TestObject_( T_TestObject_ && o ) noexcept : serial( o.serial ) { nConsMove ++; } ~T_TestObject_( ) { nDestr ++; } T_TestObject_& operator =( T_TestObject_ const& source ) noexcept { serial = source.serial; nConsCopy ++; return *this; } T_TestObject_& operator =( T_TestObject_ && source ) noexcept { std::swap( source.serial , serial ); nConsMove ++; return *this; } bool operator ==( T_TestObject_ const& other ) const noexcept { return other.serial == serial; } bool operator !=( T_TestObject_ const& other ) const noexcept { return other.serial != serial; } }; uint32_t T_TestObject_::nConsDefault = 0; uint32_t T_TestObject_::nConsCopy = 0; uint32_t T_TestObject_::nConsMove = 0; uint32_t T_TestObject_::nDestr = 0; void swap( T_TestObject_& lhs , T_TestObject_& rhs ) { using std::swap; swap( lhs.serial , rhs.serial ); } } // namespace namespace ebcl { M_DECLARE_COMPARATOR( T_TestObject_ ); } M_DEFINE_COMPARATOR( T_TestObject_ ) { return T_Comparator< uint32_t >::compare( a.serial , b.serial ); } void ArraysStaticObjectsTest::tearDown( ) { T_TestObject_::reset( ); } using T_Test_ = T_StaticArray< T_TestObject_ , 8 >; using T_LargeTest_ = T_StaticArray< T_TestObject_ , 5000 >; #define M_CHECK_(ncd,ncc,ncm,nd) \ do { \ CPPUNIT_ASSERT_EQUAL( uint32_t( ncd ) , \ T_TestObject_::nConsDefault ); \ CPPUNIT_ASSERT_EQUAL( uint32_t( ncc ) , T_TestObject_::nConsCopy ); \ CPPUNIT_ASSERT_EQUAL( uint32_t( ncm ) , T_TestObject_::nConsMove ); \ CPPUNIT_ASSERT_EQUAL( uint32_t( nd ) , T_TestObject_::nDestr ); \ } while ( 0 ) /*----------------------------------------------------------------------------*/ void ArraysStaticObjectsTest::testCopyCons( ) { { T_Test_ array; array.addNew( 0 ); T_Test_ copy( array ); M_CHECK_( 0 , 1 , 0 , 0 ); CPPUNIT_ASSERT_EQUAL( 1u , copy.size( ) ); CPPUNIT_ASSERT_EQUAL( 0u , copy[ 0 ].serial ); copy.addNew( 1 ); M_CHECK_( 0 , 1 , 0 , 0 ); CPPUNIT_ASSERT_EQUAL( 1u , array.size( ) ); } M_CHECK_( 0 , 1 , 0 , 3 ); } void ArraysStaticObjectsTest::testCopyAss( ) { { T_Test_ array; array.addNew( 0 ); T_Test_ copy; copy.addNew( 1 ); copy = array; M_CHECK_( 0 , 1 , 0 , 1 ); CPPUNIT_ASSERT_EQUAL( 1u , copy.size( ) ); CPPUNIT_ASSERT_EQUAL( 0u , copy[ 0 ].serial ); copy.addNew( 1 ); M_CHECK_( 0 , 1 , 0 , 1 ); CPPUNIT_ASSERT_EQUAL( 1u , array.size( ) ); } M_CHECK_( 0 , 1 , 0 , 4 ); } /*----------------------------------------------------------------------------*/ void ArraysStaticObjectsTest::testMoveCons( ) { { T_Test_ source; source.addNew( 0 ); T_Test_ array( std::move( source ) ); M_CHECK_( 0 , 0 , 1 , 1 ); CPPUNIT_ASSERT_EQUAL( 0u , source.size( ) ); CPPUNIT_ASSERT_EQUAL( 1u , array.size( ) ); CPPUNIT_ASSERT_EQUAL( 0u , array[ 0 ].serial ); } M_CHECK_( 0 , 0 , 1 , 2 ); } void ArraysStaticObjectsTest::testMoveAss( ) { { T_Test_ source; source.addNew( 0 ); T_Test_ array; array.addNew( 1 ); array = std::move( source ); M_CHECK_( 0 , 0 , 1 , 2 ); CPPUNIT_ASSERT_EQUAL( 0u , source.size( ) ); CPPUNIT_ASSERT_EQUAL( 1u , array.size( ) ); CPPUNIT_ASSERT_EQUAL( 0u , array[ 0 ].serial ); } M_CHECK_( 0 , 0 , 1 , 3 ); } /*----------------------------------------------------------------------------*/ void ArraysStaticObjectsTest::testSwap( ) { T_Test_ a1 , a2; a1 << 1 << 2 << 3; a2 << 2 << 4 << 6 << 8; swap( a1 , a2 ); CPPUNIT_ASSERT_EQUAL( 4u , a1.size( ) ); CPPUNIT_ASSERT_EQUAL( 3u , a2.size( ) ); for ( uint32_t i = 0 ; i < 3 ; i ++ ) { CPPUNIT_ASSERT( a1[ i ].serial == a2[ i ].serial * 2 ); } CPPUNIT_ASSERT( a1[ 3 ].serial == 8 ); } /*----------------------------------------------------------------------------*/ void ArraysStaticObjectsTest::testAppendCopy( ) { { T_Test_ array; T_TestObject_ obj( 0 ); array.add( obj ); M_CHECK_( 0 , 1 , 0 , 0 ); CPPUNIT_ASSERT_EQUAL( 1u , array.size( ) ); CPPUNIT_ASSERT_EQUAL( 0u , array[ 0 ].serial ); } M_CHECK_( 0 , 1 , 0 , 2 ); } void ArraysStaticObjectsTest::testAppendMove( ) { { T_Test_ array; array.add( T_TestObject_( 0 ) ); M_CHECK_( 0 , 0 , 1 , 1 ); CPPUNIT_ASSERT_EQUAL( 1u , array.size( ) ); CPPUNIT_ASSERT_EQUAL( 0u , array[ 0 ].serial ); } M_CHECK_( 0 , 0 , 1 , 2 ); } void ArraysStaticObjectsTest::testAppendNew( ) { { T_Test_ array; array.addNew( 0 ); M_CHECK_( 0 , 0 , 0 , 0 ); CPPUNIT_ASSERT_EQUAL( 1u , array.size( ) ); CPPUNIT_ASSERT_EQUAL( 0u , array[ 0 ].serial ); } M_CHECK_( 0 , 0 , 0 , 1 ); } void ArraysStaticObjectsTest::testAppendTwo( ) { { T_Test_ array; T_TestObject_ obj1( 0 ) , obj2( 1 ); array << obj1 << obj2; M_CHECK_( 0 , 2 , 0 , 0 ); CPPUNIT_ASSERT_EQUAL( 2u , array.size( ) ); CPPUNIT_ASSERT_EQUAL( 0u , array[ 0 ].serial ); CPPUNIT_ASSERT_EQUAL( 1u , array[ 1 ].serial ); } M_CHECK_( 0 , 2 , 0 , 4 ); } /*----------------------------------------------------------------------------*/ void ArraysStaticObjectsTest::testInsertCopyEmpty( ) { { T_Test_ array; T_TestObject_ obj( 0 ); array.insert( 0 , obj ); M_CHECK_( 0 , 1 , 0 , 0 ); CPPUNIT_ASSERT_EQUAL( 1u , array.size( ) ); CPPUNIT_ASSERT_EQUAL( 0u , array[ 0 ].serial ); } M_CHECK_( 0 , 1 , 0 , 2 ); } void ArraysStaticObjectsTest::testInsertCopyBefore( ) { { T_Test_ array; for ( uint32_t i = 0 ; i < 4 ; i ++ ) { array << i; } T_TestObject_::reset( ); T_TestObject_ obj( 15 ); array.insert( 0 , obj ); M_CHECK_( 0 , 1 , 0 , 0 ); CPPUNIT_ASSERT_EQUAL( 5u , array.size( ) ); CPPUNIT_ASSERT_EQUAL( 15u , array[ 0 ].serial ); } M_CHECK_( 0 , 1 , 0 , 6 ); } void ArraysStaticObjectsTest::testInsertCopyAfter( ) { { T_Test_ array; for ( uint32_t i = 0 ; i < 4 ; i ++ ) { array << i; } T_TestObject_::reset( ); T_TestObject_ obj( 15 ); array.insert( 4 , obj ); M_CHECK_( 0 , 1 , 0 , 0 ); CPPUNIT_ASSERT_EQUAL( 5u , array.size( ) ); CPPUNIT_ASSERT_EQUAL( 15u , array[ 4 ].serial ); } M_CHECK_( 0 , 1 , 0 , 6 ); } /*----------------------------------------------------------------------------*/ void ArraysStaticObjectsTest::testInsertMoveEmpty( ) { { T_Test_ array; T_TestObject_ obj( 15 ); array.insert( 0 , std::move( obj ) ); M_CHECK_( 0 , 0 , 1 , 0 ); CPPUNIT_ASSERT_EQUAL( 1u , array.size( ) ); CPPUNIT_ASSERT_EQUAL( 15u , array[ 0 ].serial ); } M_CHECK_( 0 , 0 , 1 , 2 ); } void ArraysStaticObjectsTest::testInsertMoveBefore( ) { { T_Test_ array; for ( uint32_t i = 0 ; i < 4 ; i ++ ) { array << i; } T_TestObject_::reset( ); T_TestObject_ obj( 15 ); array.insert( 0 , std::move( obj ) ); M_CHECK_( 0 , 0 , 1 , 0 ); CPPUNIT_ASSERT_EQUAL( 5u , array.size( ) ); CPPUNIT_ASSERT_EQUAL( 15u , array[ 0 ].serial ); } M_CHECK_( 0 , 0 , 1 , 6 ); } void ArraysStaticObjectsTest::testInsertMoveAfter( ) { { T_Test_ array; for ( uint32_t i = 0 ; i < 4 ; i ++ ) { array << i; } T_TestObject_::reset( ); T_TestObject_ obj( 15 ); array.insert( 4 , std::move( obj ) ); M_CHECK_( 0 , 0 , 1 , 0 ); CPPUNIT_ASSERT_EQUAL( 5u , array.size( ) ); CPPUNIT_ASSERT_EQUAL( 15u , array[ 4 ].serial ); } M_CHECK_( 0 , 0 , 1 , 6 ); } /*----------------------------------------------------------------------------*/ void ArraysStaticObjectsTest::testInsertNewEmpty( ) { { T_Test_ array; array.insertNew( 0 , 15 ); M_CHECK_( 0 , 0 , 0 , 0 ); CPPUNIT_ASSERT_EQUAL( 1u , array.size( ) ); CPPUNIT_ASSERT_EQUAL( 15u , array[ 0 ].serial ); } M_CHECK_( 0 , 0 , 0 , 1 ); } void ArraysStaticObjectsTest::testInsertNewBefore( ) { { T_Test_ array; for ( uint32_t i = 0 ; i < 4 ; i ++ ) { array << ( i + 2 ); } T_TestObject_::reset( ); array.insertNew( 0 , 15 ); M_CHECK_( 0 , 0 , 0 , 0 ); CPPUNIT_ASSERT_EQUAL( 5u , array.size( ) ); CPPUNIT_ASSERT_EQUAL( 15u , array[ 0 ].serial ); } M_CHECK_( 0 , 0 , 0 , 5 ); } void ArraysStaticObjectsTest::testInsertNewAfter( ) { { T_Test_ array; for ( uint32_t i = 0 ; i < 4 ; i ++ ) { array << ( i + 2 ); } T_TestObject_::reset( ); array.insertNew( 4 , 15 ); M_CHECK_( 0 , 0 , 0 , 0 ); CPPUNIT_ASSERT_EQUAL( 5u , array.size( ) ); CPPUNIT_ASSERT_EQUAL( 15u , array[ 4 ].serial ); } M_CHECK_( 0 , 0 , 0 , 5 ); } /*----------------------------------------------------------------------------*/ void ArraysStaticObjectsTest::testRemoveEnd( ) { { T_Test_ array; array << 0 << 1 << 2; T_TestObject_::reset( ); array.remove( 2 ); M_CHECK_( 0 , 0 , 0 , 1 ); CPPUNIT_ASSERT_EQUAL( 2u , array.size( ) ); CPPUNIT_ASSERT_EQUAL( 0u , array[ 0 ].serial ); CPPUNIT_ASSERT_EQUAL( 1u , array[ 1 ].serial ); } M_CHECK_( 0 , 0 , 0 , 3 ); } void ArraysStaticObjectsTest::testRemoveMiddle( ) { { T_Test_ array; array << 0 << 1 << 2; T_TestObject_::reset( ); array.remove( 1 ); M_CHECK_( 0 , 0 , 1 , 1 ); CPPUNIT_ASSERT_EQUAL( 2u , array.size( ) ); CPPUNIT_ASSERT_EQUAL( 0u , array[ 0 ].serial ); CPPUNIT_ASSERT_EQUAL( 2u , array[ 1 ].serial ); } M_CHECK_( 0 , 0 , 1 , 3 ); } void ArraysStaticObjectsTest::testRemoveSwapEnd( ) { { T_Test_ array; array << 0 << 1 << 2; T_TestObject_::reset( ); array.removeSwap( 2 ); M_CHECK_( 0 , 0 , 0 , 1 ); CPPUNIT_ASSERT_EQUAL( 2u , array.size( ) ); CPPUNIT_ASSERT_EQUAL( 0u , array[ 0 ].serial ); CPPUNIT_ASSERT_EQUAL( 1u , array[ 1 ].serial ); } M_CHECK_( 0 , 0 , 0 , 3 ); } void ArraysStaticObjectsTest::testRemoveSwapMiddle( ) { { T_Test_ array; array << 0 << 1 << 2; T_TestObject_::reset( ); array.removeSwap( 0 ); M_CHECK_( 0 , 0 , 1 , 1 ); CPPUNIT_ASSERT_EQUAL( 2u , array.size( ) ); CPPUNIT_ASSERT_EQUAL( 2u , array[ 0 ].serial ); CPPUNIT_ASSERT_EQUAL( 1u , array[ 1 ].serial ); } M_CHECK_( 0 , 0 , 1 , 3 ); } /*----------------------------------------------------------------------------*/ void ArraysStaticObjectsTest::testClear( ) { const uint32_t n = 8u; { T_Test_ array; for ( uint32_t i = 0 ; i < n ; i ++ ) { array << T_TestObject_( i ); } array.clear( ); M_CHECK_( 0 , 0 , n , n * 2 ); CPPUNIT_ASSERT_EQUAL( 0u , array.size( ) ); } M_CHECK_( 0 , 0 , n , n * 2 ); } /*----------------------------------------------------------------------------*/ void ArraysStaticObjectsTest::testIndexOf( ) { T_Test_ a1; a1 << 1 << 2 << 3; CPPUNIT_ASSERT_EQUAL( 1 , a1.indexOf( T_TestObject_( 2 ) ) ); } void ArraysStaticObjectsTest::testIndexOfMissing( ) { T_Test_ a1; a1 << 1 << 2 << 3; CPPUNIT_ASSERT_EQUAL( -1 , a1.indexOf( T_TestObject_( 8 ) ) ); } void ArraysStaticObjectsTest::testContains( ) { T_Test_ a1; a1 << 1 << 2 << 3; CPPUNIT_ASSERT( a1.contains( T_TestObject_( 2 ) ) ); } void ArraysStaticObjectsTest::testContainsMissing( ) { T_Test_ a1; a1 << 1 << 2 << 3; CPPUNIT_ASSERT( !a1.contains( T_TestObject_( 4 ) ) ); } /*----------------------------------------------------------------------------*/ void ArraysStaticObjectsTest::testSort( ) { T_LargeTest_ array; for ( uint32_t i = 0 ; i < 5000 ; i ++ ) { array << T_TestObject_( std::rand( ) ); } array.sort( ); for ( uint32_t i = 1 ; i < 5000 ; i ++ ) { CPPUNIT_ASSERT( array[ i ].serial >= array[ i - 1 ].serial ); } } void ArraysStaticObjectsTest::testSortComparator( ) { T_LargeTest_ array; for ( uint32_t i = 0 ; i < 5000 ; i ++ ) { array << T_TestObject_( std::rand( ) ); } array.sort( []( T_TestObject_ const& a , T_TestObject_ const& b ){ return T_Comparator< T_TestObject_ >::compare( b , a ); } ); for ( uint32_t i = 1 ; i < 5000 ; i ++ ) { CPPUNIT_ASSERT( array[ i ].serial <= array[ i - 1 ].serial ); } } void ArraysStaticObjectsTest::testSortPartial( ) { T_LargeTest_ array; for ( uint32_t i = 0 ; i < 5000 ; i ++ ) { array << T_TestObject_( std::rand( ) ); } T_LargeTest_ copy( array ); array.sort( 1000 , 1000 ); for ( uint32_t i = 0 ; i < 1000 ; i ++ ) { CPPUNIT_ASSERT_EQUAL( copy[ i ].serial , array[ i ].serial ); } for ( uint32_t i = 1001 ; i < 2000 ; i ++ ) { CPPUNIT_ASSERT( array[ i ].serial >= array[ i - 1 ].serial ); } for ( uint32_t i = 2000 ; i < 5000 ; i ++ ) { CPPUNIT_ASSERT_EQUAL( copy[ i ].serial , array[ i ].serial ); } } /*----------------------------------------------------------------------------*/ void ArraysStaticObjectsTest::testCopyRangeOutside( ) { T_LargeTest_ array; for ( uint32_t i = 0 ; i < 5000 ; i ++ ) { array.addNew( std::rand( ) ); } T_LargeTest_ range( array.copyRange( 7000 , 1000 ) ); M_CHECK_( 0 , 0 , 0 , 0 ); CPPUNIT_ASSERT_EQUAL( 0u , range.size( ) ); } void ArraysStaticObjectsTest::testCopyRangeLarger( ) { T_LargeTest_ array; for ( uint32_t i = 0 ; i < 5000 ; i ++ ) { array.addNew( std::rand( ) ); } T_LargeTest_ range( array.copyRange( 1000 ) ); CPPUNIT_ASSERT_EQUAL( 4000u , range.size( ) ); M_CHECK_( 0 , 4000 , 4000 , 4000 ); for ( uint32_t i = 0 ; i < 4000 ; i ++ ) { CPPUNIT_ASSERT_EQUAL( array[ i + 1000 ].serial , range[ i ].serial ); } } void ArraysStaticObjectsTest::testCopyRangeSub( ) { T_LargeTest_ array; for ( uint32_t i = 0 ; i < 5000 ; i ++ ) { array.addNew( std::rand( ) ); } T_LargeTest_ range( array.copyRange( 1000 , 1999 ) ); CPPUNIT_ASSERT_EQUAL( 1000u , range.size( ) ); M_CHECK_( 0 , 1000 , 1000 , 1000 ); for ( uint32_t i = 0 ; i < 1000 ; i ++ ) { CPPUNIT_ASSERT_EQUAL( array[ i + 1000 ].serial , range[ i ].serial ); } } /*----------------------------------------------------------------------------*/ void ArraysStaticObjectsTest::testMoveRangeOutside( ) { T_LargeTest_ array; for ( uint32_t i = 0 ; i < 5000 ; i ++ ) { array.addNew( std::rand( ) ); } T_LargeTest_ range( array.moveRange( 7000 , 1000 ) ); M_CHECK_( 0 , 0 , 0 , 0 ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , range.size( ) ); } void ArraysStaticObjectsTest::testMoveRangeLarger( ) { T_LargeTest_ array; for ( uint32_t i = 0 ; i < 5000 ; i ++ ) { array.addNew( std::rand( ) ); } T_LargeTest_ range( array.moveRange( 1000 ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 4000 ) , range.size( ) ); M_CHECK_( 0 , 0 , 8000 , 4000 ); for ( uint32_t i = 0 ; i < 4000 ; i ++ ) { CPPUNIT_ASSERT_EQUAL( array[ i + 1000 ].serial , range[ i ].serial ); } } void ArraysStaticObjectsTest::testMoveRangeSub( ) { T_LargeTest_ array; for ( uint32_t i = 0 ; i < 5000 ; i ++ ) { array.addNew( std::rand( ) ); } T_LargeTest_ range( array.moveRange( 1000 , 1999 ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1000 ) , range.size( ) ); M_CHECK_( 0 , 0 , 2000 , 1000 ); for ( uint32_t i = 0 ; i < 1000 ; i ++ ) { CPPUNIT_ASSERT_EQUAL( array[ i + 1000 ].serial , range[ i ].serial ); } }