358 lines
8.2 KiB
C++
358 lines
8.2 KiB
C++
|
#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 );
|
||
|
}
|