#include #include using namespace lw; class RingBufferTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE( RingBufferTest ); CPPUNIT_TEST( testEmpty ); CPPUNIT_TEST( testEmptyGrowth ); CPPUNIT_TEST( testPutCopy ); CPPUNIT_TEST( testPutMove ); CPPUNIT_TEST( testPutNew ); CPPUNIT_TEST( testPutExpand ); CPPUNIT_TEST( testFree ); CPPUNIT_TEST( testFreeEmpty ); CPPUNIT_TEST( testReadNext ); CPPUNIT_TEST( testReadNextMultiple ); CPPUNIT_TEST( testReadNextEmpty ); CPPUNIT_TEST( testReadAll ); CPPUNIT_TEST( testReadAllEmpty ); CPPUNIT_TEST( testReadAllAppends ); CPPUNIT_TEST( testCopyCons ); CPPUNIT_TEST( testCopyAss ); CPPUNIT_TEST( testMoveCons ); CPPUNIT_TEST( testMoveAss ); CPPUNIT_TEST( testSwap ); CPPUNIT_TEST_SUITE_END( ); public: void tearDown( ) override; void testEmpty( ); void testEmptyGrowth( ); void testPutCopy( ); void testPutMove( ); void testPutNew( ); void testPutExpand( ); void testFree( ); void testFreeEmpty( ); void testReadNext( ); void testReadNextMultiple( ); void testReadNextEmpty( ); void testReadAll( ); void testReadAllEmpty( ); void testReadAllAppends( ); void testCopyCons( ); void testCopyAss( ); void testMoveCons( ); void testMoveAss( ); void testSwap( ); }; CPPUNIT_TEST_SUITE_REGISTRATION( RingBufferTest ); /*----------------------------------------------------------------------------*/ namespace { struct T_Obj { static int cons; static int copy; static int move; static int destr; static void reset( ) { cons = copy = move = destr = 0; } int x; T_Obj( ) = delete; T_Obj( int x ) : x( x ) { cons ++; } T_Obj( T_Obj const& o ) : x( o.x ) { copy ++; } T_Obj( T_Obj&& o ) noexcept : x( o.x ) { move ++; } ~T_Obj( ) { destr ++; } T_Obj& operator =( T_Obj const& ) = default; T_Obj& operator =( T_Obj&& ) noexcept = default; }; int T_Obj::cons = 0; int T_Obj::copy = 0; int T_Obj::move = 0; int T_Obj::destr = 0; using T_Test = T_RingBuffer< T_Obj >; } void RingBufferTest::tearDown( ) { T_Obj::reset( ); } #define M_CHECK_(N,C,M,D) \ do { \ CPPUNIT_ASSERT_EQUAL( int(N) , T_Obj::cons ); \ CPPUNIT_ASSERT_EQUAL( int(C) , T_Obj::copy ); \ CPPUNIT_ASSERT_EQUAL( int(M) , T_Obj::move ); \ CPPUNIT_ASSERT_EQUAL( int(D) , T_Obj::destr ); \ } while ( 0 ) /*----------------------------------------------------------------------------*/ void RingBufferTest::testEmpty( ) { { T_Test rb; CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , rb.size( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , rb.capacity( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 64 ) , rb.growth( ) ); } M_CHECK_( 0 , 0 , 0 , 0 ); } void RingBufferTest::testEmptyGrowth( ) { { T_Test rb( 128 ); CPPUNIT_ASSERT_EQUAL( uint32_t( 128 ) , rb.growth( ) ); } M_CHECK_( 0 , 0 , 0 , 0 ); } /*----------------------------------------------------------------------------*/ void RingBufferTest::testPutCopy( ) { { T_Test rb; T_Obj o( 12 ); rb.put( o ); CPPUNIT_ASSERT_EQUAL( rb.growth( ) , rb.capacity( ) ); M_CHECK_( 1 , 1 , 0 , 0 ); } M_CHECK_( 1 , 1 , 0 , 2 ); } void RingBufferTest::testPutMove( ) { { T_Test rb; rb.put( T_Obj( 12 ) ); CPPUNIT_ASSERT_EQUAL( rb.growth( ) , rb.capacity( ) ); M_CHECK_( 1 , 0 , 1 , 1 ); } M_CHECK_( 1 , 0 , 1 , 2 ); } void RingBufferTest::testPutNew( ) { { T_Test rb; rb.putNew( 12 ); CPPUNIT_ASSERT_EQUAL( rb.growth( ) , rb.capacity( ) ); M_CHECK_( 1 , 0 , 0 , 0 ); } M_CHECK_( 1 , 0 , 0 , 1 ); } void RingBufferTest::testPutExpand( ) { T_Test rb( 4 ); for ( int i = 0 ; i < 5 ; i ++ ) { rb.putNew( i ); if ( i < 4 ) { M_CHECK_( i + 1 , 0 , 0 , 0 ); CPPUNIT_ASSERT_EQUAL( rb.growth( ) , rb.capacity( ) ); } else { M_CHECK_( i + 1 , 0 , i , i ); CPPUNIT_ASSERT_EQUAL( rb.growth( ) * 2 , rb.capacity( ) ); } } } /*----------------------------------------------------------------------------*/ void RingBufferTest::testFree( ) { T_Test rb; rb.putNew( 1 ); rb.free( ); M_CHECK_( 1 , 0 , 0 , 1 ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , rb.size( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , rb.capacity( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 64 ) , rb.growth( ) ); } void RingBufferTest::testFreeEmpty( ) { T_Test rb; rb.free( ); M_CHECK_( 0 , 0 , 0 , 0 ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , rb.size( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , rb.capacity( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 64 ) , rb.growth( ) ); } /*----------------------------------------------------------------------------*/ void RingBufferTest::testReadNext( ) { T_Obj out( 0 ); T_Test rb( 4 ); rb.putNew( 123 ); CPPUNIT_ASSERT( rb.readNext( out ) ); CPPUNIT_ASSERT_EQUAL( 123 , out.x ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , rb.size( ) ); } void RingBufferTest::testReadNextMultiple( ) { T_Obj out( 0 ); T_Test rb( 4 ); rb.putNew( 123 ); rb.putNew( 456 ); CPPUNIT_ASSERT( rb.readNext( out ) ); CPPUNIT_ASSERT_EQUAL( 123 , out.x ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , rb.size( ) ); } void RingBufferTest::testReadNextEmpty( ) { T_Obj out( 0 ); T_Test rb( 4 ); CPPUNIT_ASSERT( !rb.readNext( out ) ); CPPUNIT_ASSERT_EQUAL( 0 , out.x ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , rb.size( ) ); } /*----------------------------------------------------------------------------*/ void RingBufferTest::testReadAll( ) { T_Array< T_Obj > out; T_Test rb( 4 ); rb.putNew( 123 ); rb.putNew( 456 ); CPPUNIT_ASSERT( rb.readAll( out ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , out.size( ) ); CPPUNIT_ASSERT_EQUAL( 123 , out[ 0 ].x ); CPPUNIT_ASSERT_EQUAL( 456 , out[ 1 ].x ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , rb.size( ) ); } void RingBufferTest::testReadAllEmpty( ) { T_Array< T_Obj > out; T_Test rb( 4 ); CPPUNIT_ASSERT( !rb.readAll( out ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , out.size( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , rb.size( ) ); } void RingBufferTest::testReadAllAppends( ) { T_Array< T_Obj > out; out.addNew( 0 ); T_Test rb( 4 ); rb.putNew( 123 ); rb.putNew( 456 ); CPPUNIT_ASSERT( rb.readAll( out ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 3 ) , out.size( ) ); CPPUNIT_ASSERT_EQUAL( 0 , out[ 0 ].x ); CPPUNIT_ASSERT_EQUAL( 123 , out[ 1 ].x ); CPPUNIT_ASSERT_EQUAL( 456 , out[ 2 ].x ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , rb.size( ) ); } /*----------------------------------------------------------------------------*/ void RingBufferTest::testCopyCons( ) { T_Test rb( 4 ); rb.putNew( 123 ); rb.putNew( 456 ); T_Obj::reset( ); T_Test copy( rb ); CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , rb.size( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , copy.size( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 4 ) , copy.growth( ) ); M_CHECK_( 0 , 2 , 0 , 0 ); } void RingBufferTest::testCopyAss( ) { T_Test rb( 4 ); rb.putNew( 123 ); rb.putNew( 456 ); T_Test copy( 128 ); copy.putNew( 789 ); T_Obj::reset( ); copy = rb; CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , rb.size( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , copy.size( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 4 ) , copy.growth( ) ); M_CHECK_( 0 , 2 , 0 , 1 ); } void RingBufferTest::testMoveCons( ) { T_Test rb( 4 ); rb.putNew( 123 ); rb.putNew( 456 ); T_Obj::reset( ); T_Test copy( std::move( rb ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , rb.size( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 4 ) , rb.growth( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , copy.size( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 4 ) , copy.growth( ) ); M_CHECK_( 0 , 0 , 0 , 0 ); } void RingBufferTest::testMoveAss( ) { T_Test rb( 4 ); rb.putNew( 123 ); rb.putNew( 456 ); T_Test copy( 128 ); copy.putNew( 789 ); T_Obj::reset( ); copy = std::move( rb ); CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , rb.size( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 4 ) , rb.growth( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , copy.size( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 4 ) , copy.growth( ) ); M_CHECK_( 0 , 0 , 0 , 1 ); } void RingBufferTest::testSwap( ) { T_Test rb( 4 ); rb.putNew( 123 ); rb.putNew( 456 ); T_Test other( 128 ); other.putNew( 789 ); T_Obj::reset( ); swap( other , rb ); CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , rb.size( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 128 ) , rb.growth( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , other.size( ) ); CPPUNIT_ASSERT_EQUAL( uint32_t( 4 ) , other.growth( ) ); M_CHECK_( 0 , 0 , 0 , 0 ); }