corelib/tests/object-table.cc

517 lines
16 KiB
C++

#include <ebcl/HashTables.hh>
#include <cppunit/extensions/HelperMacros.h>
using namespace ebcl;
class ObjectTableTest : public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE( ObjectTableTest );
CPPUNIT_TEST( testEmpty );
CPPUNIT_TEST( testAdd );
CPPUNIT_TEST( testAddMove );
CPPUNIT_TEST( testAddDuplicate );
CPPUNIT_TEST( testUpdate );
CPPUNIT_TEST( testUpdateMove );
CPPUNIT_TEST( testUpdateMissing );
CPPUNIT_TEST( testSetNew );
CPPUNIT_TEST( testSetExisting );
CPPUNIT_TEST( testSetMove );
CPPUNIT_TEST( testRemove );
CPPUNIT_TEST( testRemoveMissing );
CPPUNIT_TEST( testContains );
CPPUNIT_TEST( testContainsMissing );
CPPUNIT_TEST( testIndexOf );
CPPUNIT_TEST( testIndexOfMissing );
CPPUNIT_TEST( testGet );
CPPUNIT_TEST( testGetMissing );
CPPUNIT_TEST( testClear );
CPPUNIT_TEST( testFree );
CPPUNIT_TEST( testCopyCons );
CPPUNIT_TEST( testCopyAss );
CPPUNIT_TEST( testMoveCons );
CPPUNIT_TEST( testMoveAss );
CPPUNIT_TEST( testSwap );
CPPUNIT_TEST_SUITE_END( );
static constexpr uint32_t C_SIZE_ = 16;
public:
void testEmpty( );
void testAdd( );
void testAddMove( );
void testAddDuplicate( );
void testUpdate( );
void testUpdateMove( );
void testUpdateMissing( );
void testSetNew( );
void testSetMove( );
void testSetExisting( );
void testRemove( );
void testRemoveMissing( );
void testContains( );
void testContainsMissing( );
void testIndexOf( );
void testIndexOfMissing( );
void testGet( );
void testGetMissing( );
void testCopyCons( );
void testCopyAss( );
void testMoveCons( );
void testMoveAss( );
void testClear( );
void testFree( );
void testSwap( );
};
CPPUNIT_TEST_SUITE_REGISTRATION( ObjectTableTest );
/*----------------------------------------------------------------------------*/
namespace {
class T_Test_
{
private:
uint32_t key_;
uint32_t value_;
public:
T_Test_( ) : key_( 0 ) , value_( 0 ) { }
T_Test_( uint32_t k ) : key_( k ) , value_( k * 2 ) { }
T_Test_( uint32_t k , uint32_t v ) : key_( k ) , value_( v ) { }
T_Test_( T_Test_ const& other ) : T_Test_( other.key_ , other.value_ ) { }
T_Test_( T_Test_&& other ) : T_Test_( ) { swap( *this , other ); }
T_Test_& operator =( T_Test_ const& other ) = default;
T_Test_& operator =( T_Test_&& other ) noexcept { swap( *this , other ); return *this; }
friend void swap( T_Test_& lhs , T_Test_& rhs )
{
using std::swap;
swap( lhs.key_ , rhs.key_ );
swap( lhs.value_ , rhs.value_ );
}
uint32_t key( ) const { return key_; }
uint32_t value( ) const { return value_; }
void value( uint32_t v ) { value_ = v; }
};
uint32_t KeyGetter_( T_Test_ const& test )
{
return test.key( );
}
}
/*----------------------------------------------------------------------------*/
void ObjectTableTest::testEmpty( )
{
T_ObjectTable< uint32_t , T_Test_ > table( KeyGetter_ );
CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , table.size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , table.keys( ).size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , table.values( ).size( ) );
}
/*----------------------------------------------------------------------------*/
void ObjectTableTest::testAdd( )
{
T_ObjectTable< uint32_t , T_Test_ > table( KeyGetter_ );
T_Test_ test( 123 );
bool ok( table.add( test ) );
CPPUNIT_ASSERT( ok );
CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , table.size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , table.keys( ).size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , table.values( ).size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 123 ) , table.keys( )[ 0 ] );
CPPUNIT_ASSERT_EQUAL( uint32_t( 246 ) , table.values( )[ 0 ].value( ) );
}
void ObjectTableTest::testAddMove( )
{
T_ObjectTable< uint32_t , T_Test_ > table( KeyGetter_ );
T_Test_ test( 123 );
bool ok( table.add( std::move( test ) ) );
CPPUNIT_ASSERT( ok );
CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , test.key( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , table.size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , table.keys( ).size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , table.values( ).size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 123 ) , table.keys( )[ 0 ] );
CPPUNIT_ASSERT_EQUAL( uint32_t( 246 ) , table.values( )[ 0 ].value( ) );
}
void ObjectTableTest::testAddDuplicate( )
{
T_ObjectTable< uint32_t , T_Test_ > table( KeyGetter_ );
table.add( T_Test_( 123 ) );
bool ok( table.add( T_Test_( 123 , 456 ) ) );
CPPUNIT_ASSERT( !ok );
CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , table.size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , table.keys( ).size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , table.values( ).size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 123 ) , table.keys( )[ 0 ] );
CPPUNIT_ASSERT_EQUAL( uint32_t( 246 ) , table.values( )[ 0 ].value( ) );
}
void ObjectTableTest::testUpdate( )
{
T_ObjectTable< uint32_t , T_Test_ > table( KeyGetter_ );
table.add( T_Test_( 123 , 456 ) );
T_Test_ test( 123 );
bool ok( table.update( test ) );
CPPUNIT_ASSERT( ok );
CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , table.size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , table.keys( ).size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , table.values( ).size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 123 ) , table.keys( )[ 0 ] );
CPPUNIT_ASSERT_EQUAL( uint32_t( 246 ) , table.values( )[ 0 ].value( ) );
}
void ObjectTableTest::testUpdateMove( )
{
T_ObjectTable< uint32_t , T_Test_ > table( KeyGetter_ );
table.add( T_Test_( 123 , 456 ) );
T_Test_ test( 123 );
bool ok( table.update( std::move( test ) ) );
CPPUNIT_ASSERT( ok );
CPPUNIT_ASSERT_EQUAL( uint32_t( 456 ) , test.value( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , table.size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , table.keys( ).size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , table.values( ).size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 123 ) , table.keys( )[ 0 ] );
CPPUNIT_ASSERT_EQUAL( uint32_t( 246 ) , table.values( )[ 0 ].value( ) );
}
void ObjectTableTest::testUpdateMissing( )
{
T_ObjectTable< uint32_t , T_Test_ > table( KeyGetter_ );
bool ok( table.update( T_Test_( 123 ) ) );
CPPUNIT_ASSERT( !ok );
CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , table.size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , table.keys( ).size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , table.values( ).size( ) );
}
void ObjectTableTest::testSetNew( )
{
T_ObjectTable< uint32_t , T_Test_ > table( KeyGetter_ );
T_Test_ test( 123 );
table.set( test );
CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , table.size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , table.keys( ).size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , table.values( ).size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 123 ) , table.keys( )[ 0 ] );
CPPUNIT_ASSERT_EQUAL( uint32_t( 246 ) , table.values( )[ 0 ].value( ) );
}
void ObjectTableTest::testSetMove( )
{
T_ObjectTable< uint32_t , T_Test_ > table( KeyGetter_ );
T_Test_ test( 123 );
table.set( std::move( test ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , test.key( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , table.size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , table.keys( ).size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , table.values( ).size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 123 ) , table.keys( )[ 0 ] );
CPPUNIT_ASSERT_EQUAL( uint32_t( 246 ) , table.values( )[ 0 ].value( ) );
}
void ObjectTableTest::testSetExisting( )
{
T_ObjectTable< uint32_t , T_Test_ > table( KeyGetter_ );
table.add( T_Test_( 123 , 456 ) );
table.set( T_Test_( 123 ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , table.size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , table.keys( ).size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , table.values( ).size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 123 ) , table.keys( )[ 0 ] );
CPPUNIT_ASSERT_EQUAL( uint32_t( 246 ) , table.values( )[ 0 ].value( ) );
}
/*----------------------------------------------------------------------------*/
void ObjectTableTest::testRemove( )
{
T_ObjectTable< uint32_t , T_Test_ > table( KeyGetter_ );
table.set( T_Test_( 123 ) );
table.set( T_Test_( 456 ) );
bool ok( table.remove( 456 ) );
CPPUNIT_ASSERT( ok );
CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , table.size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , table.keys( ).size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , table.values( ).size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 123 ) , table.keys( )[ 0 ] );
CPPUNIT_ASSERT_EQUAL( uint32_t( 246 ) , table.values( )[ 0 ].value( ) );
}
void ObjectTableTest::testRemoveMissing( )
{
T_ObjectTable< uint32_t , T_Test_ > table( KeyGetter_ );
table.set( T_Test_( 123 ) );
bool ok( table.remove( 456 ) );
CPPUNIT_ASSERT( !ok );
CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , table.size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , table.keys( ).size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , table.values( ).size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 123 ) , table.keys( )[ 0 ] );
CPPUNIT_ASSERT_EQUAL( uint32_t( 246 ) , table.values( )[ 0 ].value( ) );
}
/*----------------------------------------------------------------------------*/
void ObjectTableTest::testContains( )
{
T_ObjectTable< uint32_t , T_Test_ > table( KeyGetter_ );
table.set( T_Test_( 123 ) );
CPPUNIT_ASSERT( table.contains( 123 ) );
}
void ObjectTableTest::testContainsMissing( )
{
T_ObjectTable< uint32_t , T_Test_ > table( KeyGetter_ );
table.set( T_Test_( 123 ) );
CPPUNIT_ASSERT( !table.contains( 456 ) );
}
void ObjectTableTest::testIndexOf( )
{
T_ObjectTable< uint32_t , T_Test_ > table( KeyGetter_ );
for ( uint32_t i = 0 ; i < 124 ; i += 2 ) {
table.set( T_Test_( i ) );
}
for ( uint32_t i = 1 ; i < 124 ; i += 2 ) {
table.set( T_Test_( i ) );
}
const uint32_t index( table.indexOf( 57 ) );
CPPUNIT_ASSERT( index != T_HashIndex::INVALID_INDEX );
CPPUNIT_ASSERT( index < table.size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 57 ) , table[ index ].key( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 114 ) , table[ index ].value( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 114 ) , table.values( )[ index ].value( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 57 ) , table.keys( )[ index ] );
}
void ObjectTableTest::testIndexOfMissing( )
{
T_ObjectTable< uint32_t , T_Test_ > table( KeyGetter_ );
const uint32_t index( table.indexOf( 57 ) );
CPPUNIT_ASSERT( index == T_HashIndex::INVALID_INDEX );
}
void ObjectTableTest::testGet( )
{
T_ObjectTable< uint32_t , T_Test_ > table( KeyGetter_ );
for ( uint32_t i = 0 ; i < 124 ; i += 2 ) {
table.set( T_Test_( i ) );
}
for ( uint32_t i = 1 ; i < 124 ; i += 2 ) {
table.set( T_Test_( i ) );
}
const T_Test_* ptr( table.get( 57 ) );
CPPUNIT_ASSERT( ptr != nullptr );
CPPUNIT_ASSERT_EQUAL( uint32_t( 57 ) , ptr->key( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 114 ) , ptr->value( ) );
}
void ObjectTableTest::testGetMissing( )
{
T_ObjectTable< uint32_t , T_Test_ > table( KeyGetter_ );
const T_Test_* ptr( table.get( 57 ) );
CPPUNIT_ASSERT( ptr == nullptr );
}
/*----------------------------------------------------------------------------*/
void ObjectTableTest::testCopyCons( )
{
T_ObjectTable< uint32_t , T_Test_ > table( KeyGetter_ );
for ( uint32_t i = 0 ; i < 124 ; i += 2 ) {
table.set( T_Test_( i ) );
}
for ( uint32_t i = 1 ; i < 124 ; i += 2 ) {
table.set( T_Test_( i ) );
}
const auto sz( table.size( ) );
T_ObjectTable< uint32_t , T_Test_ > copy( table );
CPPUNIT_ASSERT_EQUAL( sz , table.size( ) );
CPPUNIT_ASSERT_EQUAL( sz , copy.size( ) );
auto const& k( table.keys( ) );
for ( uint32_t i = 0 ; i < sz ; i ++ ) {
CPPUNIT_ASSERT( copy.contains( k[ i ] ) );
T_Test_ const& oValue( table.values( )[ i ] );
T_Test_ const* const cPtr( copy.get( k[ i ] ) );
CPPUNIT_ASSERT( cPtr != nullptr );
CPPUNIT_ASSERT_EQUAL( oValue.key( ) , cPtr->key( ) );
CPPUNIT_ASSERT_EQUAL( oValue.value( ) , cPtr->value( ) );
}
}
void ObjectTableTest::testCopyAss( )
{
T_ObjectTable< uint32_t , T_Test_ > table( KeyGetter_ );
for ( uint32_t i = 0 ; i < 124 ; i += 2 ) {
table.set( T_Test_( i ) );
}
for ( uint32_t i = 1 ; i < 124 ; i += 2 ) {
table.set( T_Test_( i ) );
}
const auto sz( table.size( ) );
T_ObjectTable< uint32_t , T_Test_ > copy( []( T_Test_ const& v ) {
return v.value( );
} );
copy = table;
CPPUNIT_ASSERT_EQUAL( sz , table.size( ) );
CPPUNIT_ASSERT_EQUAL( sz , copy.size( ) );
auto const& k( table.keys( ) );
for ( uint32_t i = 0 ; i < sz ; i ++ ) {
CPPUNIT_ASSERT( copy.contains( k[ i ] ) );
T_Test_ const& oValue( table.values( )[ i ] );
T_Test_ const* const cPtr( copy.get( k[ i ] ) );
CPPUNIT_ASSERT( cPtr != nullptr );
CPPUNIT_ASSERT_EQUAL( oValue.key( ) , cPtr->key( ) );
CPPUNIT_ASSERT_EQUAL( oValue.value( ) , cPtr->value( ) );
}
T_Test_ v( 543 , 210 );
copy.set( v );
CPPUNIT_ASSERT( copy.contains( 543 ) );
CPPUNIT_ASSERT( !table.contains( 543 ) );
}
/*----------------------------------------------------------------------------*/
void ObjectTableTest::testMoveCons( )
{
T_ObjectTable< uint32_t , T_Test_ > table( KeyGetter_ );
for ( uint32_t i = 0 ; i < 124 ; i += 2 ) {
table.set( T_Test_( i ) );
}
for ( uint32_t i = 1 ; i < 124 ; i += 2 ) {
table.set( T_Test_( i ) );
}
const auto sz( table.size( ) );
T_Array< uint32_t > k( table.keys( ) );
T_ObjectTable< uint32_t , T_Test_ > copy( std::move( table ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , table.size( ) );
CPPUNIT_ASSERT_EQUAL( sz , copy.size( ) );
for ( uint32_t i = 0 ; i < sz ; i ++ ) {
CPPUNIT_ASSERT( copy.contains( k[ i ] ) );
CPPUNIT_ASSERT( !table.contains( k[ i ] ) );
T_Test_ const* const cPtr( copy.get( k[ i ] ) );
CPPUNIT_ASSERT( cPtr != nullptr );
CPPUNIT_ASSERT_EQUAL( k[ i ] , cPtr->key( ) );
CPPUNIT_ASSERT_EQUAL( k[ i ] * 2 , cPtr->value( ) );
}
}
void ObjectTableTest::testMoveAss( )
{
T_ObjectTable< uint32_t , T_Test_ > table( KeyGetter_ );
for ( uint32_t i = 0 ; i < 124 ; i += 2 ) {
table.set( T_Test_( i ) );
}
for ( uint32_t i = 1 ; i < 124 ; i += 2 ) {
table.set( T_Test_( i ) );
}
const auto sz( table.size( ) );
T_Array< uint32_t > k( table.keys( ) );
T_ObjectTable< uint32_t , T_Test_ > copy( []( T_Test_ const& v ) {
return v.value( );
} );
copy = std::move( table );
CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , table.size( ) );
CPPUNIT_ASSERT_EQUAL( sz , copy.size( ) );
for ( uint32_t i = 0 ; i < sz ; i ++ ) {
CPPUNIT_ASSERT( copy.contains( k[ i ] ) );
CPPUNIT_ASSERT( !table.contains( k[ i ] ) );
T_Test_ const* const cPtr( copy.get( k[ i ] ) );
CPPUNIT_ASSERT( cPtr != nullptr );
CPPUNIT_ASSERT_EQUAL( k[ i ] , cPtr->key( ) );
CPPUNIT_ASSERT_EQUAL( k[ i ] * 2 , cPtr->value( ) );
}
copy.add( T_Test_( 456 , 789 ) );
CPPUNIT_ASSERT( copy.contains( 456 ) );
}
/*----------------------------------------------------------------------------*/
void ObjectTableTest::testClear( )
{
T_ObjectTable< uint32_t , T_Test_ > table( KeyGetter_ );
for ( uint32_t i = 0 ; i < 124 ; i ++ ) {
table.set( T_Test_( i ) );
}
table.clear( );
CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , table.size( ) );
}
void ObjectTableTest::testFree( )
{
T_ObjectTable< uint32_t , T_Test_ > table( KeyGetter_ );
for ( uint32_t i = 0 ; i < 124 ; i ++ ) {
table.set( T_Test_( i ) );
}
table.free( );
CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , table.size( ) );
}
/*----------------------------------------------------------------------------*/
void ObjectTableTest::testSwap( )
{
T_ObjectTable< uint32_t , T_Test_ > table( KeyGetter_ );
T_ObjectTable< uint32_t , T_Test_ > table2( KeyGetter_ );
for ( uint32_t i = 0 ; i < 12 ; i ++ ) {
table.set( T_Test_( i , i * 2 ) );
table2.set( T_Test_( 20 + i , i ) );
}
table.set( T_Test_( 123 , 456 ) );
swap( table , table2 );
CPPUNIT_ASSERT_EQUAL( uint32_t( 12 ) , table.size( ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 13 ) , table2.size( ) );
for ( uint32_t i = 0 ; i < 12 ; i ++ ) {
CPPUNIT_ASSERT( !table.contains( i ) );
CPPUNIT_ASSERT( table.contains( 20 + i ) );
CPPUNIT_ASSERT_EQUAL( i , table.get( 20 + i )->value( ) );
CPPUNIT_ASSERT( !table2.contains( 20 + i ) );
CPPUNIT_ASSERT( table2.contains( i ) );
CPPUNIT_ASSERT_EQUAL( i * 2 , table2.get( i )->value( ) );
}
CPPUNIT_ASSERT( table2.contains( 123 ) );
CPPUNIT_ASSERT_EQUAL( uint32_t( 456 ) , table2.get( 123 )->value( ) );
}