#include <ebcl/Arrays.hh>
#include <cppunit/extensions/HelperMacros.h>
using namespace ebcl;


class ArraysMultiTest : public CppUnit::TestFixture
{
	CPPUNIT_TEST_SUITE( ArraysMultiTest );
		CPPUNIT_TEST( testInitialSize );

		CPPUNIT_TEST( testNext );
		CPPUNIT_TEST( testNextMultiple );

		CPPUNIT_TEST( testAddToEmpty );
		CPPUNIT_TEST( testAdd );
		CPPUNIT_TEST( testAddNewToEmpty );
		CPPUNIT_TEST( testAddNew );
		CPPUNIT_TEST( testNextAfterAdd );

		CPPUNIT_TEST( testCopyFromToEmpty );
		CPPUNIT_TEST( testCopyFrom );
		CPPUNIT_TEST( testCopyFromEmpty );

		CPPUNIT_TEST( testGetRead );
		CPPUNIT_TEST( testGetWrite );
		CPPUNIT_TEST( testDirectRead );
		CPPUNIT_TEST( testDirectWrite );

		CPPUNIT_TEST( testContainsYes );
		CPPUNIT_TEST( testContainsNo );

		CPPUNIT_TEST( testCopyFromSelf );
		CPPUNIT_TEST( testCopyFromSelfEmptySrc );
		CPPUNIT_TEST( testCopyFromSelfEmptyDst );
		CPPUNIT_TEST( testCopyFromOther );
		CPPUNIT_TEST( testCopyFromOtherEmptySrc );
		CPPUNIT_TEST( testCopyFromOtherEmptyDst );

		CPPUNIT_TEST( testCopyUniqueFromSelfNoDups );
		CPPUNIT_TEST( testCopyUniqueFromSelfDupsInSource );
		CPPUNIT_TEST( testCopyUniqueFromSelfDups );
		CPPUNIT_TEST( testCopyUniqueFromSelfEmptySrc );
		CPPUNIT_TEST( testCopyUniqueFromSelfEmptyDst );

		CPPUNIT_TEST( testCopyUniqueFromOtherNoDups );
		CPPUNIT_TEST( testCopyUniqueFromOtherDupsInSource );
		CPPUNIT_TEST( testCopyUniqueFromOtherDups );
		CPPUNIT_TEST( testCopyUniqueFromOtherEmptySrc );
		CPPUNIT_TEST( testCopyUniqueFromOtherEmptyDst );

		CPPUNIT_TEST( testSort );

		CPPUNIT_TEST( testFree );
		CPPUNIT_TEST( testClear );

		CPPUNIT_TEST( testCopyCons );
		CPPUNIT_TEST( testCopyAss );
		CPPUNIT_TEST( testMoveCons );
		CPPUNIT_TEST( testMoveAss );
		CPPUNIT_TEST( testSwap );
	CPPUNIT_TEST_SUITE_END( );

public:
	void testInitialSize( );

	void testNext( );
	void testNextMultiple( );

	void testAddToEmpty( );
	void testAdd( );
	void testAddNewToEmpty( );
	void testAddNew( );
	void testNextAfterAdd( );

	void testCopyFromToEmpty( );
	void testCopyFrom( );
	void testCopyFromEmpty( );

	void testGetRead( );
	void testGetWrite( );
	void testDirectRead( );
	void testDirectWrite( );

	void testContainsYes( );
	void testContainsNo( );

	void testCopyFromSelf( );
	void testCopyFromSelfEmptySrc( );
	void testCopyFromSelfEmptyDst( );
	void testCopyFromOther( );
	void testCopyFromOtherEmptySrc( );
	void testCopyFromOtherEmptyDst( );

	void testCopyUniqueFromSelfNoDups( );
	void testCopyUniqueFromSelfDupsInSource( );
	void testCopyUniqueFromSelfDups( );
	void testCopyUniqueFromSelfEmptySrc( );
	void testCopyUniqueFromSelfEmptyDst( );

	void testCopyUniqueFromOtherNoDups( );
	void testCopyUniqueFromOtherDupsInSource( );
	void testCopyUniqueFromOtherDups( );
	void testCopyUniqueFromOtherEmptySrc( );
	void testCopyUniqueFromOtherEmptyDst( );

	void testSort( );

	void testFree( );
	void testClear( );

	void testCopyCons( );
	void testCopyAss( );
	void testMoveCons( );
	void testMoveAss( );
	void testSwap( );
};
CPPUNIT_TEST_SUITE_REGISTRATION( ArraysMultiTest );

/*----------------------------------------------------------------------------*/

namespace {

struct T_Obj
{
	uint32_t x;
	uint32_t y;

	T_Obj( ) = delete;
	T_Obj( uint32_t x , uint32_t y ) : x(x) , y(y) {}
	T_Obj( T_Obj const& ) = delete;
	T_Obj( T_Obj&& ) = default;
};

using T_Test = T_MultiArray< uint32_t >;
using T_ObjTest = T_MultiArray< T_Obj >;

};

/*----------------------------------------------------------------------------*/

void ArraysMultiTest::testInitialSize( )
{
	T_Test empty;
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , empty.size( ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , empty.values( ) );
}

/*----------------------------------------------------------------------------*/

void ArraysMultiTest::testNext( )
{
	T_Test test;
	test.next( );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , test.size( ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , test.sizeOf( 0 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , test.firstOf( 0 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , test.values( ) );
}

void ArraysMultiTest::testNextMultiple( )
{
	T_Test test;
	test.next( );
	test.next( );
	CPPUNIT_ASSERT_EQUAL( 2u , test.size( ) );
	CPPUNIT_ASSERT_EQUAL( 0u , test.sizeOf( 0 ) );
	CPPUNIT_ASSERT_EQUAL( 0u , test.firstOf( 0 ) );
	CPPUNIT_ASSERT_EQUAL( 0u , test.sizeOf( 1 ) );
	CPPUNIT_ASSERT_EQUAL( 0u , test.firstOf( 1 ) );
	CPPUNIT_ASSERT_EQUAL( 0u , test.values( ) );
}

/*----------------------------------------------------------------------------*/

void ArraysMultiTest::testAddToEmpty( )
{
	T_Test test;
	test.next( );
	test.add( 0 );
	CPPUNIT_ASSERT_EQUAL( 1u , test.size( ) );
	CPPUNIT_ASSERT_EQUAL( 1u , test.sizeOf( 0 ) );
	CPPUNIT_ASSERT_EQUAL( 0u , test.firstOf( 0 ) );
	CPPUNIT_ASSERT_EQUAL( 1u , test.values( ) );
}

void ArraysMultiTest::testAdd( )
{
	T_Test test;
	test.next( );
	test.add( 0 );
	test.add( 0 );
	CPPUNIT_ASSERT_EQUAL( 1u , test.size( ) );
	CPPUNIT_ASSERT_EQUAL( 2u , test.sizeOf( 0 ) );
	CPPUNIT_ASSERT_EQUAL( 0u , test.firstOf( 0 ) );
	CPPUNIT_ASSERT_EQUAL( 2u , test.values( ) );
}

void ArraysMultiTest::testAddNewToEmpty( )
{
	T_ObjTest test;
	test.next( );
	test.addNew( 1 , 2 );
	CPPUNIT_ASSERT_EQUAL( 1u , test.size( ) );
	CPPUNIT_ASSERT_EQUAL( 1u , test.sizeOf( 0 ) );
	CPPUNIT_ASSERT_EQUAL( 0u , test.firstOf( 0 ) );
	CPPUNIT_ASSERT_EQUAL( 1u , test.values( ) );
}

void ArraysMultiTest::testAddNew( )
{
	T_ObjTest test;
	test.next( );
	test.addNew( 1 , 2 );
	test.addNew( 3 , 4 );
	CPPUNIT_ASSERT_EQUAL( 1u , test.size( ) );
	CPPUNIT_ASSERT_EQUAL( 2u , test.sizeOf( 0 ) );
	CPPUNIT_ASSERT_EQUAL( 0u , test.firstOf( 0 ) );
	CPPUNIT_ASSERT_EQUAL( 2u , test.values( ) );
}

void ArraysMultiTest::testNextAfterAdd( )
{
	T_Test test;
	test.next( );
	test.add( 0 );
	test.next( );
	test.add( 0 );
	test.add( 0 );
	test.next( );
	test.add( 0 );
	CPPUNIT_ASSERT_EQUAL( 3u , test.size( ) );
	CPPUNIT_ASSERT_EQUAL( 1u , test.sizeOf( 0 ) );
	CPPUNIT_ASSERT_EQUAL( 0u , test.firstOf( 0 ) );
	CPPUNIT_ASSERT_EQUAL( 2u , test.sizeOf( 1 ) );
	CPPUNIT_ASSERT_EQUAL( 1u , test.firstOf( 1 ) );
	CPPUNIT_ASSERT_EQUAL( 1u , test.sizeOf( 2 ) );
	CPPUNIT_ASSERT_EQUAL( 3u , test.firstOf( 2 ) );
	CPPUNIT_ASSERT_EQUAL( 4u , test.values( ) );
}

/*----------------------------------------------------------------------------*/

void ArraysMultiTest::testCopyFromToEmpty( )
{
	T_Test::T_Data values;
	values << 1 << 2 << 3;

	T_Test test;
	test.next( );
	test.copyFrom( values );

	CPPUNIT_ASSERT_EQUAL( 1u , test.size( ) );
	CPPUNIT_ASSERT_EQUAL( 3u , test.sizeOf( 0 ) );
	CPPUNIT_ASSERT_EQUAL( 0u , test.firstOf( 0 ) );
	CPPUNIT_ASSERT_EQUAL( 3u , test.values( ) );
}

void ArraysMultiTest::testCopyFrom( )
{
	T_Test::T_Data values;
	values << 1 << 2 << 3;

	T_Test test;
	test.next( );
	test.add( 0 );
	test.copyFrom( values );

	CPPUNIT_ASSERT_EQUAL( 1u , test.size( ) );
	CPPUNIT_ASSERT_EQUAL( 4u , test.sizeOf( 0 ) );
	CPPUNIT_ASSERT_EQUAL( 0u , test.firstOf( 0 ) );
	CPPUNIT_ASSERT_EQUAL( 4u , test.values( ) );
}

void ArraysMultiTest::testCopyFromEmpty( )
{
	T_Test::T_Data values;
	T_Test test;
	test.next( );
	test.copyFrom( values );

	CPPUNIT_ASSERT_EQUAL( 1u , test.size( ) );
	CPPUNIT_ASSERT_EQUAL( 0u , test.sizeOf( 0 ) );
	CPPUNIT_ASSERT_EQUAL( 0u , test.firstOf( 0 ) );
	CPPUNIT_ASSERT_EQUAL( 0u , test.values( ) );
}

/*----------------------------------------------------------------------------*/

void ArraysMultiTest::testGetRead( )
{
	T_Test test;
	test.next( );
	test.add( 0 );
	test.next( );
	test.add( 1 );
	test.add( 2 );
	test.next( );
	test.add( 3 );
	CPPUNIT_ASSERT_EQUAL( 0u , test.get( 0 , 0 ) );
	CPPUNIT_ASSERT_EQUAL( 1u , test.get( 1 , 0 ) );
	CPPUNIT_ASSERT_EQUAL( 2u , test.get( 1 , 1 ) );
	CPPUNIT_ASSERT_EQUAL( 3u , test.get( 2 , 0 ) );
	CPPUNIT_ASSERT_EQUAL( 4u , test.values( ) );
}

void ArraysMultiTest::testGetWrite( )
{
	T_Test test;
	test.next( );
	test.add( 0 );
	test.next( );
	test.add( 1 );
	test.add( 2 );
	test.next( );
	test.add( 3 );
	test.get( 1 , 0 ) = 12;
	CPPUNIT_ASSERT_EQUAL( 0u , test.get( 0 , 0 ) );
	CPPUNIT_ASSERT_EQUAL( 12u , test.get( 1 , 0 ) );
	CPPUNIT_ASSERT_EQUAL( 2u , test.get( 1 , 1 ) );
	CPPUNIT_ASSERT_EQUAL( 3u , test.get( 2 , 0 ) );
}

void ArraysMultiTest::testDirectRead( )
{
	T_Test test;
	test.next( );
	test.add( 0 );
	test.next( );
	test.add( 1 );
	test.add( 2 );
	test.next( );
	test.add( 3 );

	for ( uint32_t i = 0 ; i < test.sizeOf( 1 ) ; i ++ ) {
		CPPUNIT_ASSERT_EQUAL( test.get( 1 , i ) , test[ test.firstOf( 1 ) + i ] );
	}
}

void ArraysMultiTest::testDirectWrite( )
{
	T_Test test;
	test.next( );
	test.add( 0 );
	test.next( );
	test.add( 1 );
	test.add( 2 );
	test.next( );
	test.add( 3 );
	test[ 1 ] = 12;

	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , test.get( 0 , 0 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 12 ) , test.get( 1 , 0 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , test.get( 1 , 1 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 3 ) , test.get( 2 , 0 ) );
}

/*----------------------------------------------------------------------------*/

void ArraysMultiTest::testContainsYes( )
{
	T_Test test;
	test.next( );
	test.add( 0 );
	test.next( );
	test.add( 1 );
	test.add( 2 );
	test.next( );
	test.add( 3 );
	CPPUNIT_ASSERT( test.contains( 1 , 1 ) );
	CPPUNIT_ASSERT( test.contains( 1 , 2 ) );
}

void ArraysMultiTest::testContainsNo( )
{
	T_Test test;
	test.next( );
	test.add( 0 );
	test.next( );
	test.add( 1 );
	test.add( 2 );
	test.next( );
	test.add( 3 );
	CPPUNIT_ASSERT( !test.contains( 1 , 0 ) );
	CPPUNIT_ASSERT( !test.contains( 1 , 3 ) );
}

/*----------------------------------------------------------------------------*/

void ArraysMultiTest::testCopyFromSelf( )
{
	T_Test test;
	test.next( );
	test.add( 0 );
	test.next( );
	test.add( 1 );
	test.add( 2 );
	test.next( );
	test.add( 3 );

	test.copyFrom( 1 );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 3 ) , test.sizeOf( 2 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 3 ) , test.get( 2 , 0 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , test.get( 2 , 1 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , test.get( 2 , 2 ) );
}

void ArraysMultiTest::testCopyFromSelfEmptySrc( )
{
	T_Test test;
	test.next( );
	test.next( );
	test.add( 3 );

	test.copyFrom( 0 );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , test.sizeOf( 1 ) );
}

void ArraysMultiTest::testCopyFromSelfEmptyDst( )
{
	T_Test test;
	test.next( );
	test.add( 0 );
	test.next( );
	test.add( 1 );
	test.add( 2 );
	test.next( );

	test.copyFrom( 1 );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , test.sizeOf( 2 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , test.get( 2 , 0 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , test.get( 2 , 1 ) );
}

void ArraysMultiTest::testCopyFromOther( )
{
	T_Test src;
	src.next( );
	src.add( 0 );
	src.next( );
	src.add( 1 );
	src.add( 2 );
	src.next( );
	src.add( 3 );

	T_Test test;
	test.next( );
	test.add( 4 );

	test.copyFrom( src , 1 );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 3 ) , test.sizeOf( 0 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 4 ) , test.get( 0 , 0 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , test.get( 0 , 1 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , test.get( 0 , 2 ) );
}

void ArraysMultiTest::testCopyFromOtherEmptySrc( )
{
	T_Test src;
	src.next( );
	src.next( );
	src.add( 1 );

	T_Test test;
	test.next( );
	test.add( 4 );

	test.copyFrom( src , 0 );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , test.sizeOf( 0 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 4 ) , test.get( 0 , 0 ) );
}

void ArraysMultiTest::testCopyFromOtherEmptyDst( )
{
	T_Test src;
	src.next( );
	src.add( 0 );
	src.next( );
	src.add( 1 );
	src.add( 2 );
	src.next( );
	src.add( 3 );

	T_Test test;
	test.next( );

	test.copyFrom( src , 1 );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , test.sizeOf( 0 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , test.get( 0 , 0 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , test.get( 0 , 1 ) );
}

/*----------------------------------------------------------------------------*/

void ArraysMultiTest::testCopyUniqueFromSelfNoDups( )
{
	T_Test test;
	test.next( );
	test.add( 0 );
	test.next( );
	test.add( 1 );
	test.add( 2 );
	test.next( );
	test.add( 3 );

	test.copyUnique( 1 );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 3 ) , test.sizeOf( 2 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 3 ) , test.get( 2 , 0 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , test.get( 2 , 1 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , test.get( 2 , 2 ) );
}

void ArraysMultiTest::testCopyUniqueFromSelfDupsInSource( )
{
	T_Test test;
	test.next( );
	test.add( 0 );
	test.next( );
	test.add( 1 );
	test.add( 2 );
	test.add( 2 );
	test.next( );
	test.add( 3 );

	test.copyUnique( 1 );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 4 ) , test.sizeOf( 2 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 3 ) , test.get( 2 , 0 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , test.get( 2 , 1 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , test.get( 2 , 2 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , test.get( 2 , 3 ) );
}

void ArraysMultiTest::testCopyUniqueFromSelfDups( )
{
	T_Test test;
	test.next( );
	test.add( 0 );
	test.next( );
	test.add( 1 );
	test.add( 2 );
	test.add( 2 );
	test.next( );
	test.add( 2 );

	test.copyUnique( 1 );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , test.sizeOf( 2 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , test.get( 2 , 0 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , test.get( 2 , 1 ) );
}

void ArraysMultiTest::testCopyUniqueFromSelfEmptySrc( )
{
	T_Test test;
	test.next( );
	test.add( 0 );
	test.next( );
	test.next( );
	test.add( 2 );

	test.copyUnique( 1 );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , test.sizeOf( 2 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , test.get( 2 , 0 ) );
}

void ArraysMultiTest::testCopyUniqueFromSelfEmptyDst( )
{
	T_Test test;
	test.next( );
	test.add( 0 );
	test.next( );
	test.add( 1 );
	test.next( );

	test.copyUnique( 1 );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , test.sizeOf( 2 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , test.get( 2 , 0 ) );
}

/*----------------------------------------------------------------------------*/

void ArraysMultiTest::testCopyUniqueFromOtherNoDups( )
{
	T_Test src;
	src.next( );
	src.add( 0 );
	src.next( );
	src.add( 1 );
	src.add( 2 );
	src.next( );
	src.add( 3 );

	T_Test test;
	test.next( );
	test.add( 0 );

	test.copyUnique( src , 1 );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 3 ) , test.sizeOf( 0 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , test.get( 0 , 0 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , test.get( 0 , 1 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , test.get( 0 , 2 ) );
}

void ArraysMultiTest::testCopyUniqueFromOtherDupsInSource( )
{
	T_Test src;
	src.next( );
	src.add( 0 );
	src.next( );
	src.add( 2 );
	src.add( 2 );
	src.next( );
	src.add( 3 );

	T_Test test;
	test.next( );
	test.add( 0 );

	test.copyUnique( src , 1 );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 3 ) , test.sizeOf( 0 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , test.get( 0 , 0 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , test.get( 0 , 1 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , test.get( 0 , 2 ) );
}

void ArraysMultiTest::testCopyUniqueFromOtherDups( )
{
	T_Test src;
	src.next( );
	src.add( 0 );
	src.next( );
	src.add( 1 );
	src.add( 2 );
	src.next( );
	src.add( 3 );

	T_Test test;
	test.next( );
	test.add( 1 );

	test.copyUnique( src , 1 );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , test.sizeOf( 0 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , test.get( 0 , 0 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , test.get( 0 , 1 ) );
}

void ArraysMultiTest::testCopyUniqueFromOtherEmptySrc( )
{
	T_Test src;
	src.next( );
	src.add( 0 );
	src.next( );
	src.next( );
	src.add( 3 );

	T_Test test;
	test.next( );
	test.add( 1 );

	test.copyUnique( src , 1 );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , test.sizeOf( 0 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , test.get( 0 , 0 ) );
}

void ArraysMultiTest::testCopyUniqueFromOtherEmptyDst( )
{
	T_Test src;
	src.next( );
	src.add( 0 );
	src.next( );
	src.add( 1 );
	src.add( 2 );
	src.next( );
	src.add( 3 );

	T_Test test;
	test.next( );

	test.copyUnique( src , 1 );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , test.sizeOf( 0 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , test.get( 0 , 0 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , test.get( 0 , 1 ) );
}

/*----------------------------------------------------------------------------*/

void ArraysMultiTest::testSort( )
{
	T_Test main;
	T_Test::T_Data values[ 3 ];
	for ( uint32_t j = 0 ; j < 3 ; j ++ ) {
		main.next( );
		for ( uint32_t i = 0 ; i < 5000 ; i ++ ) {
			const uint32_t v( std::rand( ) );
			values[ j ] << v;
			main.add( v );
		}
	}
	main.sort( 1 );

	for ( uint32_t j = 0 ; j < 2 ; j ++ ) {
		for ( uint32_t i = 0 ; i < 5000 ; i ++ ) {
			CPPUNIT_ASSERT_EQUAL( values[ j * 2 ][ i ] , main.get( j * 2 , i ) );
		}
	}
	for ( uint32_t i = 1 ; i < 5000 ; i ++ ) {
		CPPUNIT_ASSERT( main.get( 1 , i ) >= main.get( 1 , i - 1 ) );
	}
}

/*----------------------------------------------------------------------------*/

void ArraysMultiTest::testFree( )
{
	T_Test test;
	test.next( );
	test.add( 0 );
	test.next( );
	test.add( 1 );
	test.add( 2 );
	test.next( );
	test.add( 3 );
	test.free( );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , test.size( ) );
}

void ArraysMultiTest::testClear( )
{
	T_Test test;
	test.next( );
	test.add( 0 );
	test.next( );
	test.add( 1 );
	test.add( 2 );
	test.next( );
	test.add( 3 );
	test.clear( );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , test.size( ) );
}

/*----------------------------------------------------------------------------*/

void ArraysMultiTest::testCopyCons( )
{
	T_Test src;
	for ( uint32_t j = 0 ; j < 8 ; j ++ ) {
		src.next( );
		const uint32_t n( std::rand( ) % 64 + 1 );
		for ( uint32_t i = 0 ; i < n ; i ++ ) {
			src.add( std::rand( ) );
		}
	}

	T_Test test( src );
	const uint32_t msz( src.size( ) );
	CPPUNIT_ASSERT_EQUAL( msz , test.size( ) );
	for ( uint32_t j = 0 ; j < msz ; j ++ ) {
		CPPUNIT_ASSERT_EQUAL( src.sizeOf( j ) , test.sizeOf( j ) );
		CPPUNIT_ASSERT_EQUAL( src.firstOf( j ) , test.firstOf( j ) );
		const uint32_t sz( test.sizeOf( j ) );
		for ( uint32_t i = 0 ; i < sz ; i ++ ) {
			CPPUNIT_ASSERT_EQUAL( src.get( j , i ) , test.get( j , i ) );
		}
	}
	src.clear( );
	CPPUNIT_ASSERT_EQUAL( msz , test.size( ) );
}

void ArraysMultiTest::testCopyAss( )
{
	T_Test src;
	for ( uint32_t j = 0 ; j < 8 ; j ++ ) {
		src.next( );
		const uint32_t n( std::rand( ) % 64 + 1 );
		for ( uint32_t i = 0 ; i < n ; i ++ ) {
			src.add( std::rand( ) );
		}
	}

	T_Test test;
	test = src;
	const uint32_t msz( src.size( ) );
	CPPUNIT_ASSERT_EQUAL( msz , test.size( ) );
	for ( uint32_t j = 0 ; j < msz ; j ++ ) {
		CPPUNIT_ASSERT_EQUAL( src.sizeOf( j ) , test.sizeOf( j ) );
		CPPUNIT_ASSERT_EQUAL( src.firstOf( j ) , test.firstOf( j ) );
		const uint32_t sz( test.sizeOf( j ) );
		for ( uint32_t i = 0 ; i < sz ; i ++ ) {
			CPPUNIT_ASSERT_EQUAL( src.get( j , i ) , test.get( j , i ) );
		}
	}
	src.clear( );
	CPPUNIT_ASSERT_EQUAL( msz , test.size( ) );
}

void ArraysMultiTest::testMoveCons( )
{
	T_Array< uint32_t > sizes;
	T_Test::T_Data data;
	T_Test src;
	for ( uint32_t j = 0 ; j < 8 ; j ++ ) {
		src.next( );
		const uint32_t n( std::rand( ) % 64 + 1 );
		sizes << n;
		for ( uint32_t i = 0 ; i < n ; i ++ ) {
			const uint32_t v( std::rand( ) );
			src.add( v );
			data.add( v );
		}
	}

	const uint32_t msz( src.size( ) );
	T_Test test( std::move( src ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , src.size( ) );
	CPPUNIT_ASSERT_EQUAL( msz , test.size( ) );
	for ( uint32_t j = 0 , idx = 0 ; j < msz ; j ++ ) {
		CPPUNIT_ASSERT_EQUAL( sizes[ j ] , test.sizeOf( j ) );
		CPPUNIT_ASSERT_EQUAL( idx , test.firstOf( j ) );
		const uint32_t sz( test.sizeOf( j ) );
		for ( uint32_t i = 0 ; i < sz ; i ++ , idx ++ ) {
			CPPUNIT_ASSERT_EQUAL( data[ idx ] , test.get( j , i ) );
		}
	}
}

void ArraysMultiTest::testMoveAss( )
{
	T_Array< uint32_t > sizes;
	T_Test::T_Data data;
	T_Test src;
	for ( uint32_t j = 0 ; j < 8 ; j ++ ) {
		src.next( );
		const uint32_t n( std::rand( ) % 64 + 1 );
		sizes << n;
		for ( uint32_t i = 0 ; i < n ; i ++ ) {
			const uint32_t v( std::rand( ) );
			src.add( v );
			data.add( v );
		}
	}

	const uint32_t msz( src.size( ) );
	T_Test test;
	test = std::move( src );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , src.size( ) );
	CPPUNIT_ASSERT_EQUAL( msz , test.size( ) );
	for ( uint32_t j = 0 , idx = 0 ; j < msz ; j ++ ) {
		CPPUNIT_ASSERT_EQUAL( sizes[ j ] , test.sizeOf( j ) );
		CPPUNIT_ASSERT_EQUAL( idx , test.firstOf( j ) );
		const uint32_t sz( test.sizeOf( j ) );
		for ( uint32_t i = 0 ; i < sz ; i ++ , idx ++ ) {
			CPPUNIT_ASSERT_EQUAL( data[ idx ] , test.get( j , i ) );
		}
	}
}

void ArraysMultiTest::testSwap( )
{
	T_Test test1 , test2;
	test1.next( );
	test1.add( 1 );
	test1.add( 2 );
	test1.next( );
	test1.add( 3 );

	test2.next( );
	test2.add( 4 );

	swap( test1 , test2 );

	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , test1.size( ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , test1.sizeOf( 0 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 4 ) , test1.get( 0 , 0 ) );

	CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , test2.size( ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , test2.sizeOf( 0 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , test2.get( 0 , 0 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 2 ) , test2.get( 0 , 1 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 1 ) , test2.sizeOf( 1 ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 3 ) , test2.get( 1 , 0 ) );
}