corelib/tests/ring-buffer.cc

358 lines
8.2 KiB
C++
Raw Normal View History

#include <lw/lib/Threading.hh>
#include <cppunit/extensions/HelperMacros.h>
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 );
}