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


class ArraysAutoTest : public CppUnit::TestFixture
{
	CPPUNIT_TEST_SUITE( ArraysAutoTest );
		CPPUNIT_TEST( testEmpty );

		CPPUNIT_TEST( testStaticOps );
		CPPUNIT_TEST( testStaticToDynamic );
		CPPUNIT_TEST( testRemovalKeepsDynamic );
		CPPUNIT_TEST( testClearKeepsDynamic );
		CPPUNIT_TEST( testFreeClearsStatic );
		CPPUNIT_TEST( testFreeMakesStatic );

		CPPUNIT_TEST( testCopyCons );
		CPPUNIT_TEST( testCopyAss );

		CPPUNIT_TEST( testMoveCons );
		CPPUNIT_TEST( testMoveAss );

		CPPUNIT_TEST( testSwap );

		CPPUNIT_TEST( testRemoveEnd );
		CPPUNIT_TEST( testRemoveMiddle );
		CPPUNIT_TEST( testRemoveSwapEnd );
		CPPUNIT_TEST( testRemoveSwapMiddle );

		CPPUNIT_TEST( testInsertEmpty );
		CPPUNIT_TEST( testInsertAfter );
		CPPUNIT_TEST( testInsertBefore );

		CPPUNIT_TEST( testIndexOf );
		CPPUNIT_TEST( testIndexOfMissing );
		CPPUNIT_TEST( testContains );
		CPPUNIT_TEST( testContainsMissing );

		CPPUNIT_TEST( testIndexOfPred );
		CPPUNIT_TEST( testIndexOfPredMissing );
		CPPUNIT_TEST( testContainsPred );
		CPPUNIT_TEST( testContainsPredMissing );

		CPPUNIT_TEST( testSort );

		CPPUNIT_TEST( testAddAllSS2S );
		CPPUNIT_TEST( testAddAllSD2S );
		CPPUNIT_TEST( testAddAllSS2D );
		CPPUNIT_TEST( testAddAllSD2D );
		CPPUNIT_TEST( testAddAllDS2D );
		CPPUNIT_TEST( testAddAllDD2D );

		CPPUNIT_TEST( testAddAllMoveSS2S );
		CPPUNIT_TEST( testAddAllMoveSD2S );
		CPPUNIT_TEST( testAddAllMoveSS2D );
		CPPUNIT_TEST( testAddAllMoveSD2D );
		CPPUNIT_TEST( testAddAllMoveDS2D );
		CPPUNIT_TEST( testAddAllMoveDD2D );

		CPPUNIT_TEST( testCopyRangeS2S );
		CPPUNIT_TEST( testCopyRangeD2S );
		CPPUNIT_TEST( testCopyRangeD2D );

		CPPUNIT_TEST( testMoveRangeS2S );
		CPPUNIT_TEST( testMoveRangeD2S );
		CPPUNIT_TEST( testMoveRangeD2D );
	CPPUNIT_TEST_SUITE_END( );

    public:
	void testEmpty( );

	void testStaticOps( );
	void testStaticToDynamic( );
	void testRemovalKeepsDynamic( );
	void testClearKeepsDynamic( );
	void testFreeClearsStatic( );
	void testFreeMakesStatic( );

	void testCopyCons( );
	void testCopyAss( );

	void testMoveCons( );
	void testMoveAss( );

	void testSwap( );

	void testRemoveEnd( );
	void testRemoveMiddle( );
	void testRemoveSwapEnd( );
	void testRemoveSwapMiddle( );

	void testInsertEmpty( );
	void testInsertAfter( );
	void testInsertBefore( );

	void testIndexOf( );
	void testIndexOfMissing( );
	void testContains( );
	void testContainsMissing( );

	void testIndexOfPred( );
	void testIndexOfPredMissing( );
	void testContainsPred( );
	void testContainsPredMissing( );

	void testSort( );

	void testAddAllSS2S( );
	void testAddAllSD2S( );
	void testAddAllSS2D( );
	void testAddAllSD2D( );
	void testAddAllDS2D( );
	void testAddAllDD2D( );

	void testAddAllMoveSS2S( );
	void testAddAllMoveSD2S( );
	void testAddAllMoveSS2D( );
	void testAddAllMoveSD2D( );
	void testAddAllMoveDS2D( );
	void testAddAllMoveDD2D( );

	void testCopyRangeS2S( );
	void testCopyRangeD2S( );
	void testCopyRangeD2D( );

	void testMoveRangeS2S( );
	void testMoveRangeD2S( );
	void testMoveRangeD2D( );
};
CPPUNIT_TEST_SUITE_REGISTRATION( ArraysAutoTest );

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

namespace {

static constexpr uint32_t StaticSize = 4;
static constexpr uint32_t DynamicGrowth = 8;

using T_Test_ = T_AutoArray< uint32_t , StaticSize , DynamicGrowth >;
using T_Check_ = T_StaticArray< uint32_t , DynamicGrowth >;

void GenerateTest_(
		const bool dynamic ,
		T_Test_& test ,
		T_Check_& check )
{
	for ( auto i = 1u ; i < ( dynamic ? DynamicGrowth : StaticSize ) ; i ++ ) {
		const uint32_t v( std::rand( ) );
		test.add( v );
		check.add( v );
	}
}

void CheckResult_(
		const bool dynamic ,
		T_Test_ const& test ,
		T_Check_ const& check )
{
	CPPUNIT_ASSERT_EQUAL( !dynamic , test.isStatic( ) );
	CPPUNIT_ASSERT_EQUAL( check.size( ) , test.size( ) );
	for ( auto i = 0u ; i < test.size( ) ; i ++ ) {
		CPPUNIT_ASSERT_EQUAL( check[ i ] , test[ i ] );
	}
}

} // namespace

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

void ArraysAutoTest::testEmpty( )
{
	T_Test_ test;
	CPPUNIT_ASSERT_EQUAL( 0u , test.size( ) );
	CPPUNIT_ASSERT_EQUAL( StaticSize , test.capacity( ) );
	CPPUNIT_ASSERT_EQUAL( DynamicGrowth , test.growth( ) );
	CPPUNIT_ASSERT( test.isStatic( ) );
}

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

void ArraysAutoTest::testStaticOps( )
{
	T_Test_ test;

	test << 1 << 2 << 3;
	CPPUNIT_ASSERT( test.isStatic( ) );
	CPPUNIT_ASSERT_EQUAL( 3u , test.size( ) );
	CPPUNIT_ASSERT_EQUAL( 1u , test[ 0 ] );
	CPPUNIT_ASSERT_EQUAL( 2u , test[ 1 ] );
	CPPUNIT_ASSERT_EQUAL( 3u , test[ 2 ] );

	test.insert( 0 , 0 );
	CPPUNIT_ASSERT( test.isStatic( ) );
	CPPUNIT_ASSERT_EQUAL( 4u , test.size( ) );
	CPPUNIT_ASSERT_EQUAL( 0u , test[ 0 ] );

	test.remove( 3 );
	CPPUNIT_ASSERT( test.isStatic( ) );
	CPPUNIT_ASSERT_EQUAL( 3u , test.size( ) );
}

void ArraysAutoTest::testStaticToDynamic( )
{
	T_Test_ test;
	for ( auto i = 0u ; i <= StaticSize ; i ++ ) {
		CPPUNIT_ASSERT_EQUAL( i , test.add( i ) );
	}
	CPPUNIT_ASSERT( !test.isStatic( ) );
	CPPUNIT_ASSERT_EQUAL( DynamicGrowth , test.capacity( ) );
	CPPUNIT_ASSERT_EQUAL( StaticSize + 1 , test.size( ) );
	for ( auto i = 0u ; i <= StaticSize ; i ++ ) {
		CPPUNIT_ASSERT_EQUAL( i , test[ i ] );
	}
}

void ArraysAutoTest::testRemovalKeepsDynamic( )
{
	T_Test_ test;
	for ( auto i = 0u ; i <= StaticSize ; i ++ ) {
		CPPUNIT_ASSERT_EQUAL( i , test.add( i ) );
	}
	test.remove( StaticSize );
	CPPUNIT_ASSERT( !test.isStatic( ) );
	CPPUNIT_ASSERT_EQUAL( DynamicGrowth , test.capacity( ) );
	CPPUNIT_ASSERT_EQUAL( StaticSize , test.size( ) );
}

void ArraysAutoTest::testClearKeepsDynamic( )
{
	T_Test_ test;
	for ( auto i = 0u ; i <= StaticSize ; i ++ ) {
		CPPUNIT_ASSERT_EQUAL( i , test.add( i ) );
	}
	test.clear( );
	CPPUNIT_ASSERT( !test.isStatic( ) );
	CPPUNIT_ASSERT_EQUAL( DynamicGrowth , test.capacity( ) );
	CPPUNIT_ASSERT_EQUAL( 0u , test.size( ) );
}

void ArraysAutoTest::testFreeClearsStatic( )
{
	T_Test_ test;
	for ( auto i = 0u ; i < StaticSize ; i ++ ) {
		CPPUNIT_ASSERT_EQUAL( i , test.add( i ) );
	}
	test.free( );
	CPPUNIT_ASSERT( test.isStatic( ) );
	CPPUNIT_ASSERT_EQUAL( StaticSize , test.capacity( ) );
	CPPUNIT_ASSERT_EQUAL( 0u , test.size( ) );
}

void ArraysAutoTest::testFreeMakesStatic( )
{
	T_Test_ test;
	for ( auto i = 0u ; i <= StaticSize ; i ++ ) {
		CPPUNIT_ASSERT_EQUAL( i , test.add( i ) );
	}
	test.free( );
	CPPUNIT_ASSERT( test.isStatic( ) );
	CPPUNIT_ASSERT_EQUAL( StaticSize , test.capacity( ) );
	CPPUNIT_ASSERT_EQUAL( 0u , test.size( ) );
}

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

void ArraysAutoTest::testCopyCons( )
{
	{
		T_Test_ init;
		T_Check_ check;
		GenerateTest_( false , init , check );
		T_Test_ test( init );
		CheckResult_( false , init , check );
		CheckResult_( false , test , check );
	}
	{
		T_Test_ init;
		T_Check_ check;
		GenerateTest_( true , init , check );
		T_Test_ test( init );
		CheckResult_( true , init , check );
		CheckResult_( true , test , check );
	}
}

void ArraysAutoTest::testCopyAss( )
{
	{
		T_Test_ init , test;
		T_Check_ check;
		GenerateTest_( false , init , check );
		test = init;
		CheckResult_( false , init , check );
		CheckResult_( false , test , check );
	}
	{
		T_Test_ init , test;
		T_Check_ check;
		GenerateTest_( true , init , check );
		test = init;
		CheckResult_( true , init , check );
		CheckResult_( true , test , check );
	}
}

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

void ArraysAutoTest::testMoveCons( )
{
	{
		T_Test_ init;
		T_Check_ check;
		GenerateTest_( false , init , check );
		T_Test_ test( std::move( init ) );
		CPPUNIT_ASSERT( init.isStatic( ) );
		CPPUNIT_ASSERT_EQUAL( 0u , init.size( ) );
		CheckResult_( false , test , check );
	}
	{
		T_Test_ init;
		T_Check_ check;
		GenerateTest_( true , init , check );
		T_Test_ test( std::move( init ) );
		CPPUNIT_ASSERT( !init.isStatic( ) );
		CPPUNIT_ASSERT_EQUAL( 0u , init.size( ) );
		CheckResult_( true , test , check );
	}
}

void ArraysAutoTest::testMoveAss( )
{
	{
		T_Test_ init , test;
		T_Check_ check;
		GenerateTest_( false , init , check );
		test = std::move( init );
		CPPUNIT_ASSERT( init.isStatic( ) );
		CPPUNIT_ASSERT_EQUAL( 0u , init.size( ) );
		CheckResult_( false , test , check );
	}
	{
		T_Test_ init , test;
		T_Check_ check;
		GenerateTest_( true , init , check );
		test = std::move( init );
		CPPUNIT_ASSERT( !init.isStatic( ) );
		CPPUNIT_ASSERT_EQUAL( 0u , init.size( ) );
		CheckResult_( true , test , check );
	}
}

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

void ArraysAutoTest::testSwap( )
{
	{
		T_Test_ test , other;
		T_Check_ check;
		GenerateTest_( false , other , check );
		test << 1 << 2;
		swap( test , other );
		CPPUNIT_ASSERT_EQUAL( 2u , other.size( ) );
		CheckResult_( false , test , check );
	}
	{
		T_Test_ test , other;
		T_Check_ check;
		GenerateTest_( true , other , check );
		test << 1 << 2;
		swap( test , other );
		CPPUNIT_ASSERT_EQUAL( 2u , other.size( ) );
		CheckResult_( true , test , check );
	}
}

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

void ArraysAutoTest::testRemoveEnd( )
{
	{
		T_Test_ test;
		T_Check_ check;
		GenerateTest_( false , test , check );
		test.remove( test.size( ) - 1 );
		check.remove( check.size( ) - 1 );
		CheckResult_( false , test , check );
	}
	{
		T_Test_ test;
		T_Check_ check;
		GenerateTest_( true , test , check );
		test.remove( test.size( ) - 1 );
		check.remove( check.size( ) - 1 );
		CheckResult_( true , test , check );
	}
}

void ArraysAutoTest::testRemoveMiddle( )
{
	{
		T_Test_ test;
		T_Check_ check;
		GenerateTest_( false , test , check );
		test.remove( 1 );
		check.remove( 1 );
		CheckResult_( false , test , check );
	}
	{
		T_Test_ test;
		T_Check_ check;
		GenerateTest_( true , test , check );
		test.remove( 1 );
		check.remove( 1 );
		CheckResult_( true , test , check );
	}
}

void ArraysAutoTest::testRemoveSwapEnd( )
{
	{
		T_Test_ test;
		T_Check_ check;
		GenerateTest_( false , test , check );
		test.removeSwap( test.size( ) - 1 );
		check.removeSwap( check.size( ) - 1 );
		CheckResult_( false , test , check );
	}
	{
		T_Test_ test;
		T_Check_ check;
		GenerateTest_( true , test , check );
		test.removeSwap( test.size( ) - 1 );
		check.removeSwap( check.size( ) - 1 );
		CheckResult_( true , test , check );
	}
}

void ArraysAutoTest::testRemoveSwapMiddle( )
{
	{
		T_Test_ test;
		T_Check_ check;
		GenerateTest_( false , test , check );
		test.removeSwap( 1 );
		check.removeSwap( 1 );
		CheckResult_( false , test , check );
	}
	{
		T_Test_ test;
		T_Check_ check;
		GenerateTest_( true , test , check );
		test.removeSwap( 1 );
		check.removeSwap( 1 );
		CheckResult_( true , test , check );
	}
}

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

void ArraysAutoTest::testInsertEmpty( )
{
	{
		T_Test_ test;
		T_Check_ check;
		test.insert( 0 , 0 );
		check.insert( 0 , 0 );
		GenerateTest_( false , test , check );
		CheckResult_( false , test , check );
	}
	{
		T_Test_ test;
		T_Check_ check;
		test.insert( 0 , 0 );
		check.insert( 0 , 0 );
		GenerateTest_( true , test , check );
		CheckResult_( true , test , check );
	}
}

void ArraysAutoTest::testInsertAfter( )
{
	{
		T_Test_ test;
		T_Check_ check;
		GenerateTest_( false , test , check );
		test.insert( test.size( ) , 0 );
		check.insert( check.size( ) , 0 );
		CheckResult_( false , test , check );
	}
	{
		T_Test_ test;
		T_Check_ check;
		GenerateTest_( true , test , check );
		test.insert( test.size( ) , 0 );
		check.insert( check.size( ) , 0 );
		CheckResult_( true , test , check );
	}
}

void ArraysAutoTest::testInsertBefore( )
{
	{
		T_Test_ test;
		T_Check_ check;
		GenerateTest_( false , test , check );
		test.insert( 0 , 0 );
		check.insert( 0 , 0 );
		CheckResult_( false , test , check );
	}
	{
		T_Test_ test;
		T_Check_ check;
		GenerateTest_( true , test , check );
		test.insert( 0 , 0 );
		check.insert( 0 , 0 );
		CheckResult_( true , test , check );
	}
}

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

void ArraysAutoTest::testIndexOf( )
{
	{
		T_Test_ test;
		for ( auto i = 0u ; i < StaticSize ; i ++ ) {
			test.add( i * 2 + 1 );
		}
		for ( auto i = 0u ; i < StaticSize ; i ++ ) {
			CPPUNIT_ASSERT_EQUAL( int32_t( i ) , test.indexOf( i * 2 + 1 ) );
		}
	}
	{
		T_Test_ test;
		for ( auto i = 0u ; i < DynamicGrowth ; i ++ ) {
			test.add( i * 2 + 1 );
		}
		for ( auto i = 0u ; i < DynamicGrowth ; i ++ ) {
			CPPUNIT_ASSERT_EQUAL( int32_t( i ) , test.indexOf( i * 2 + 1 ) );
		}
	}
}

void ArraysAutoTest::testIndexOfMissing( )
{
	{
		T_Test_ test;
		for ( auto i = 0u ; i < StaticSize ; i ++ ) {
			test.add( i * 2 + 1 );
		}
		CPPUNIT_ASSERT_EQUAL( -1 , test.indexOf( 2 ) );
	}
	{
		T_Test_ test;
		for ( auto i = 0u ; i < DynamicGrowth ; i ++ ) {
			test.add( i * 2 + 1 );
		}
		CPPUNIT_ASSERT_EQUAL( -1 , test.indexOf( 2 ) );
	}
}

void ArraysAutoTest::testContains( )
{
	{
		T_Test_ test;
		for ( auto i = 0u ; i < StaticSize ; i ++ ) {
			test.add( i * 2 + 1 );
		}
		for ( auto i = 0u ; i < StaticSize ; i ++ ) {
			CPPUNIT_ASSERT( test.contains( i * 2 + 1 ) );
		}
	}
	{
		T_Test_ test;
		for ( auto i = 0u ; i < DynamicGrowth ; i ++ ) {
			test.add( i * 2 + 1 );
		}
		for ( auto i = 0u ; i < DynamicGrowth ; i ++ ) {
			CPPUNIT_ASSERT( test.contains( i * 2 + 1 ) );
		}
	}
}

void ArraysAutoTest::testContainsMissing( )
{
	{
		T_Test_ test;
		for ( auto i = 0u ; i < StaticSize ; i ++ ) {
			test.add( i * 2 + 1 );
		}
		CPPUNIT_ASSERT( !test.contains( 2 ) );
	}
	{
		T_Test_ test;
		for ( auto i = 0u ; i < DynamicGrowth ; i ++ ) {
			test.add( i * 2 + 1 );
		}
		CPPUNIT_ASSERT( !test.contains( 2 ) );
	}
}

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

void ArraysAutoTest::testIndexOfPred( )
{
	{
		T_Test_ test;
		for ( auto i = 0u ; i < StaticSize ; i ++ ) {
			test.add( i * 2 + 1 );
		}
		for ( auto i = 0u ; i < StaticSize ; i ++ ) {
			CPPUNIT_ASSERT_EQUAL( int32_t( i ) ,
					test.indexOf( [=]( auto v ) {
						return v == i * 2 + 1;
					} ) );
		}
	}
	{
		T_Test_ test;
		for ( auto i = 0u ; i < DynamicGrowth ; i ++ ) {
			test.add( i * 2 + 1 );
		}
		for ( auto i = 0u ; i < DynamicGrowth ; i ++ ) {
			CPPUNIT_ASSERT_EQUAL( int32_t( i ) ,
					test.indexOf( [=]( auto v ) {
						return v == i * 2 + 1;
					} ) );
		}
	}
}

void ArraysAutoTest::testIndexOfPredMissing( )
{
	{
		T_Test_ test;
		for ( auto i = 0u ; i < StaticSize ; i ++ ) {
			test.add( i * 2 + 1 );
		}
		CPPUNIT_ASSERT_EQUAL( -1 , test.indexOf( [](auto v){ return v % 2 == 0; } ) );
	}
	{
		T_Test_ test;
		for ( auto i = 0u ; i < DynamicGrowth ; i ++ ) {
			test.add( i * 2 + 1 );
		}
		CPPUNIT_ASSERT_EQUAL( -1 , test.indexOf( [](auto v){ return v % 2 == 0; } ) );
	}
}

void ArraysAutoTest::testContainsPred( )
{
	{
		T_Test_ test;
		for ( auto i = 0u ; i < StaticSize ; i ++ ) {
			test.add( i * 2 + 1 );
		}
		for ( auto i = 0u ; i < StaticSize ; i ++ ) {
			CPPUNIT_ASSERT( test.contains( [=]( auto v ) {
						return v == i * 2 + 1;
					} ) );
		}
	}
	{
		T_Test_ test;
		for ( auto i = 0u ; i < DynamicGrowth ; i ++ ) {
			test.add( i * 2 + 1 );
		}
		for ( auto i = 0u ; i < DynamicGrowth ; i ++ ) {
			CPPUNIT_ASSERT( test.contains( [=]( auto v ) {
						return v == i * 2 + 1;
					} ) );
		}
	}
}

void ArraysAutoTest::testContainsPredMissing( )
{
	{
		T_Test_ test;
		for ( auto i = 0u ; i < StaticSize ; i ++ ) {
			test.add( i * 2 + 1 );
		}
		CPPUNIT_ASSERT( !test.contains( [](auto v){ return v % 2 == 0; } ) );
	}
	{
		T_Test_ test;
		for ( auto i = 0u ; i < DynamicGrowth ; i ++ ) {
			test.add( i * 2 + 1 );
		}
		CPPUNIT_ASSERT( !test.contains( [](auto v){ return v % 2 == 0; } ) );
	}
}

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

void ArraysAutoTest::testSort( )
{
	{
		T_Test_ test;
		T_Check_ check;
		GenerateTest_( false , test , check );
		test.sort( );
		check.sort( );
		CheckResult_( false , test , check );
	}
	{
		T_Test_ test;
		T_Check_ check;
		GenerateTest_( true , test , check );
		test.sort( );
		check.sort( );
		CheckResult_( true , test , check );
	}
}

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

void ArraysAutoTest::testAddAllSS2S( )
{
	T_Test_ t1 , t2;
	for ( auto i = 0u ; i < StaticSize / 2 ; i ++ ) {
		t1.add( i );
		t2.add( i + StaticSize / 2 );
	}
	t1.addAll( t2 );
	CPPUNIT_ASSERT( t1.isStatic( ) );
	CPPUNIT_ASSERT_EQUAL( StaticSize , t1.size( ) );
	for ( auto i = 0u ; i < StaticSize ; i ++ ) {
		CPPUNIT_ASSERT_EQUAL( i , t1[ i ] );
	}
}

void ArraysAutoTest::testAddAllSD2S( )
{
	T_Test_ t1 , t2;
	t2.ensureCapacity( DynamicGrowth * 2 );
	for ( auto i = 0u ; i < StaticSize / 2 ; i ++ ) {
		t1.add( i );
		t2.add( i + StaticSize / 2 );
	}

	t1.addAll( t2 );
	CPPUNIT_ASSERT( t1.isStatic( ) );
	CPPUNIT_ASSERT_EQUAL( StaticSize , t1.size( ) );
	for ( auto i = 0u ; i < StaticSize ; i ++ ) {
		CPPUNIT_ASSERT_EQUAL( i , t1[ i ] );
	}
}

void ArraysAutoTest::testAddAllSS2D( )
{
	T_Test_ t1 , t2;
	for ( auto i = 0u ; i < StaticSize ; i ++ ) {
		t1.add( i );
		t2.add( i + StaticSize );
	}
	t1.addAll( t2 );
	CPPUNIT_ASSERT( !t1.isStatic( ) );
	CPPUNIT_ASSERT_EQUAL( StaticSize * 2 , t1.size( ) );
	for ( auto i = 0u ; i < StaticSize * 2 ; i ++ ) {
		CPPUNIT_ASSERT_EQUAL( i , t1[ i ] );
	}
}

void ArraysAutoTest::testAddAllSD2D( )
{
	T_Test_ t1 , t2;
	t2.ensureCapacity( DynamicGrowth );
	for ( auto i = 0u ; i < StaticSize ; i ++ ) {
		t1.add( i );
		t2.add( i + StaticSize );
	}
	t1.addAll( t2 );
	CPPUNIT_ASSERT( !t1.isStatic( ) );
	CPPUNIT_ASSERT_EQUAL( StaticSize * 2 , t1.size( ) );
	for ( auto i = 0u ; i < StaticSize * 2 ; i ++ ) {
		CPPUNIT_ASSERT_EQUAL( i , t1[ i ] );
	}
}

void ArraysAutoTest::testAddAllDS2D( )
{
	T_Test_ t1 , t2;
	t1.ensureCapacity( DynamicGrowth );
	for ( auto i = 0u ; i < StaticSize / 2 ; i ++ ) {
		t1.add( i );
		t2.add( i + StaticSize / 2 );
	}
	t1.addAll( t2 );
	CPPUNIT_ASSERT( !t1.isStatic( ) );
	CPPUNIT_ASSERT_EQUAL( StaticSize , t1.size( ) );
	for ( auto i = 0u ; i < StaticSize ; i ++ ) {
		CPPUNIT_ASSERT_EQUAL( i , t1[ i ] );
	}
}

void ArraysAutoTest::testAddAllDD2D( )
{
	T_Test_ t1 , t2;
	t1.ensureCapacity( DynamicGrowth );
	t2.ensureCapacity( DynamicGrowth );
	for ( auto i = 0u ; i < DynamicGrowth ; i ++ ) {
		t1.add( i );
		t2.add( i + DynamicGrowth );
	}
	t1.addAll( t2 );
	CPPUNIT_ASSERT( !t1.isStatic( ) );
	CPPUNIT_ASSERT_EQUAL( DynamicGrowth * 2 , t1.size( ) );
	for ( auto i = 0u ; i < DynamicGrowth * 2 ; i ++ ) {
		CPPUNIT_ASSERT_EQUAL( i , t1[ i ] );
	}
}

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

void ArraysAutoTest::testAddAllMoveSS2S( )
{
	T_Test_ t1 , t2;
	for ( auto i = 0u ; i < StaticSize / 2 ; i ++ ) {
		t1.add( i );
		t2.add( i + StaticSize / 2 );
	}
	t1.addAll( std::move( t2 ) );
	CPPUNIT_ASSERT( t1.isStatic( ) );
	CPPUNIT_ASSERT_EQUAL( StaticSize , t1.size( ) );
	for ( auto i = 0u ; i < StaticSize ; i ++ ) {
		CPPUNIT_ASSERT_EQUAL( i , t1[ i ] );
	}
	CPPUNIT_ASSERT( t2.size( ) == 0 );
	CPPUNIT_ASSERT( t2.isStatic( ) );
}

void ArraysAutoTest::testAddAllMoveSD2S( )
{
	T_Test_ t1 , t2;
	t2.ensureCapacity( DynamicGrowth * 2 );
	for ( auto i = 0u ; i < StaticSize / 2 ; i ++ ) {
		t1.add( i );
		t2.add( i + StaticSize / 2 );
	}

	t1.addAll( std::move( t2 ) );
	CPPUNIT_ASSERT( t1.isStatic( ) );
	CPPUNIT_ASSERT_EQUAL( StaticSize , t1.size( ) );
	for ( auto i = 0u ; i < StaticSize ; i ++ ) {
		CPPUNIT_ASSERT_EQUAL( i , t1[ i ] );
	}
	CPPUNIT_ASSERT( t2.size( ) == 0 );
	CPPUNIT_ASSERT( t2.isStatic( ) );
}

void ArraysAutoTest::testAddAllMoveSS2D( )
{
	T_Test_ t1 , t2;
	for ( auto i = 0u ; i < StaticSize ; i ++ ) {
		t1.add( i );
		t2.add( i + StaticSize );
	}
	t1.addAll( std::move( t2 ) );
	CPPUNIT_ASSERT( !t1.isStatic( ) );
	CPPUNIT_ASSERT_EQUAL( StaticSize * 2 , t1.size( ) );
	for ( auto i = 0u ; i < StaticSize * 2 ; i ++ ) {
		CPPUNIT_ASSERT_EQUAL( i , t1[ i ] );
	}
	CPPUNIT_ASSERT( t2.size( ) == 0 );
	CPPUNIT_ASSERT( t2.isStatic( ) );
}

void ArraysAutoTest::testAddAllMoveSD2D( )
{
	T_Test_ t1 , t2;
	t2.ensureCapacity( DynamicGrowth );
	for ( auto i = 0u ; i < StaticSize ; i ++ ) {
		t1.add( i );
		t2.add( i + StaticSize );
	}
	t1.addAll( std::move( t2 ) );
	CPPUNIT_ASSERT( !t1.isStatic( ) );
	CPPUNIT_ASSERT_EQUAL( StaticSize * 2 , t1.size( ) );
	for ( auto i = 0u ; i < StaticSize * 2 ; i ++ ) {
		CPPUNIT_ASSERT_EQUAL( i , t1[ i ] );
	}
	CPPUNIT_ASSERT( t2.size( ) == 0 );
	CPPUNIT_ASSERT( t2.isStatic( ) );
}

void ArraysAutoTest::testAddAllMoveDS2D( )
{
	T_Test_ t1 , t2;
	t1.ensureCapacity( DynamicGrowth );
	for ( auto i = 0u ; i < StaticSize / 2 ; i ++ ) {
		t1.add( i );
		t2.add( i + StaticSize / 2 );
	}
	t1.addAll( std::move( t2 ) );
	CPPUNIT_ASSERT( !t1.isStatic( ) );
	CPPUNIT_ASSERT_EQUAL( StaticSize , t1.size( ) );
	for ( auto i = 0u ; i < StaticSize ; i ++ ) {
		CPPUNIT_ASSERT_EQUAL( i , t1[ i ] );
	}
	CPPUNIT_ASSERT( t2.size( ) == 0 );
	CPPUNIT_ASSERT( t2.isStatic( ) );
}

void ArraysAutoTest::testAddAllMoveDD2D( )
{
	T_Test_ t1 , t2;
	t1.ensureCapacity( DynamicGrowth );
	t2.ensureCapacity( DynamicGrowth );
	for ( auto i = 0u ; i < DynamicGrowth ; i ++ ) {
		t1.add( i );
		t2.add( i + DynamicGrowth );
	}
	t1.addAll( std::move( t2 ) );
	CPPUNIT_ASSERT( !t1.isStatic( ) );
	CPPUNIT_ASSERT_EQUAL( DynamicGrowth * 2 , t1.size( ) );
	for ( auto i = 0u ; i < DynamicGrowth * 2 ; i ++ ) {
		CPPUNIT_ASSERT_EQUAL( i , t1[ i ] );
	}
	CPPUNIT_ASSERT( t2.size( ) == 0 );
	CPPUNIT_ASSERT( !t2.isStatic( ) );
}

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

void ArraysAutoTest::testCopyRangeS2S( )
{
	T_Test_ t1;
	for ( auto i = 0u ; i < StaticSize ; i ++ ) {
		t1.add( i );
	}

	T_Test_ t2( t1.copyRange( StaticSize / 4 , StaticSize / 4 + StaticSize / 2 - 1 ) );
	CPPUNIT_ASSERT( t2.isStatic( ) );
	CPPUNIT_ASSERT_EQUAL( StaticSize / 2 , t2.size( ) );
	for ( auto i = 0u ; i < StaticSize / 2 ; i ++ ) {
		CPPUNIT_ASSERT_EQUAL( t1[ i + StaticSize / 4 ] , t2[ i ] );
	}
}

void ArraysAutoTest::testCopyRangeD2S( )
{
	T_Test_ t1;
	t1.ensureCapacity( DynamicGrowth );
	for ( auto i = 0u ; i < DynamicGrowth ; i ++ ) {
		t1.add( i );
	}

	T_Test_ t2( t1.copyRange( 0 , StaticSize - 1 ) );
	CPPUNIT_ASSERT( t2.isStatic( ) );
	CPPUNIT_ASSERT_EQUAL( StaticSize , t2.size( ) );
	for ( auto i = 0u ; i < StaticSize ; i ++ ) {
		CPPUNIT_ASSERT_EQUAL( t1[ i ] , t2[ i ] );
	}
}

void ArraysAutoTest::testCopyRangeD2D( )
{
	T_Test_ t1;
	t1.ensureCapacity( DynamicGrowth );
	for ( auto i = 0u ; i < DynamicGrowth ; i ++ ) {
		t1.add( i );
	}

	T_Test_ t2( t1.copyRange( 0 , StaticSize ) );
	CPPUNIT_ASSERT( !t2.isStatic( ) );
	CPPUNIT_ASSERT_EQUAL( StaticSize + 1 , t2.size( ) );
	for ( auto i = 0u ; i < StaticSize + 1 ; i ++ ) {
		CPPUNIT_ASSERT_EQUAL( t1[ i ] , t2[ i ] );
	}
}

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

void ArraysAutoTest::testMoveRangeS2S( )
{
	T_Test_ t1;
	for ( auto i = 0u ; i < StaticSize ; i ++ ) {
		t1.add( i );
	}

	T_Test_ t2( t1.moveRange( StaticSize / 4 , StaticSize / 4 + StaticSize / 2 - 1 ) );
	CPPUNIT_ASSERT( t2.isStatic( ) );
	CPPUNIT_ASSERT_EQUAL( StaticSize / 2 , t2.size( ) );
	for ( auto i = 0u ; i < StaticSize / 2 ; i ++ ) {
		CPPUNIT_ASSERT_EQUAL( t1[ i + StaticSize / 4 ] , t2[ i ] );
	}
}

void ArraysAutoTest::testMoveRangeD2S( )
{
	T_Test_ t1;
	t1.ensureCapacity( DynamicGrowth );
	for ( auto i = 0u ; i < DynamicGrowth ; i ++ ) {
		t1.add( i );
	}

	T_Test_ t2( t1.moveRange( 0 , StaticSize - 1 ) );
	CPPUNIT_ASSERT( t2.isStatic( ) );
	CPPUNIT_ASSERT_EQUAL( StaticSize , t2.size( ) );
	for ( auto i = 0u ; i < StaticSize ; i ++ ) {
		CPPUNIT_ASSERT_EQUAL( t1[ i ] , t2[ i ] );
	}
}

void ArraysAutoTest::testMoveRangeD2D( )
{
	T_Test_ t1;
	t1.ensureCapacity( DynamicGrowth );
	for ( auto i = 0u ; i < DynamicGrowth ; i ++ ) {
		t1.add( i );
	}

	T_Test_ t2( t1.moveRange( 0 , StaticSize ) );
	CPPUNIT_ASSERT( !t2.isStatic( ) );
	CPPUNIT_ASSERT_EQUAL( StaticSize + 1 , t2.size( ) );
	for ( auto i = 0u ; i < StaticSize + 1 ; i ++ ) {
		CPPUNIT_ASSERT_EQUAL( t1[ i ] , t2[ i ] );
	}
}