#include #include using namespace lw; 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( ) ); }