//////////////////////////////////////////////////////////////////////////////
//
// Asura_UnitTest_ChunkSystem.cpp
//
// Copyright (c) 2006 Rebellion. All rights reserved.
//
// Description:
//
//     unit tests for Chunk System functions
//
//////////////////////////////////////////////////////////////////////////////

// I N C L U D E S ///////////////////////////////////////////////////////////

#include "Core/Asura.h"


#ifdef ASURA_SUPPORT_UNITTEST

#include "ChunkSystem/Asura_Chunk_Stream.h"
#include "ChunkSystem/Asura_SaveBlock.h"
#include "Core/Asura_Maths.h"
#include "Core/Asura_HalfFloat.h"
#include "FileAccess/Asura_FileAccess.h"
#include "LoadAndSave/Asura_LoadAndSave.h"
#include "Rendering/Asura_Colour.h"
#include "UnitTest/Asura_UnitTest.h"

#ifdef ASURA_TOOLS
#include "PC/FileSystem/Tools_FileSystem.h"
#endif 

// stream memory allocation size
const u_int uSTREAM_ALLOCATION_SIZE = 1024;

#ifdef ASURA_TOOLS
// Test file
static const char* g_szFilename = "FileStreamTestFile";
#endif 


//globals for Basic types
static const u_int g_uZero = 0;
static const u_int g_uMax  = UINT_MAX;
static const u_int g_uMagic = 0xabcdef25;

static const float g_fZero =  0.0f;
static const float g_fMax  =  Asura_Maths::LargeFloat;
static const float g_fMin  = -Asura_Maths::LargeFloat;

static const u_short g_usZero = 0;
static const u_short g_usMax  = USHRT_MAX;

static const char g_cA    = 'a';
static const char g_cB    = 'b';
static const char g_cC    = 'c';
static const char g_cW    = 'w';
static const char g_cX    = 'x';
static const char g_cZ    = 'z';
static const char g_cZero = '0';
static const char g_cCr   = '\r';
static const char g_cCrlf = '\n';
static const char g_cTab  = '\t';

static const u_char g_ucZero     = 0;
static const u_char g_ucCharMax  = UCHAR_MAX;

static const bool g_bTrue  = true;
static const bool g_bFalse = false;

static const int g_iZero = 0;
static const int g_iOne  = 1;
static const int g_iMinusOne = -1;
static const int g_iMax = INT_MAX;
static const int g_iMin = INT_MIN;

static const short g_sZero = 0;
static const short g_sOne = 1;
static const short g_sMinusOne = -1;
static const short g_sMax = SHRT_MAX;
static const short g_sMin = SHRT_MIN;

//globals for Asura types
static const Asura_HalfFloat g_xAhfZero      =  Asura_HalfFloat(0.0f);
static const Asura_HalfFloat g_xAhfMinusOne  =  Asura_HalfFloat(-1.0f);
static const Asura_HalfFloat g_xAhf    =  Asura_HalfFloat(990.0f);

static const Asura_Quat              g_xAq   = Asura_Quat(0.0f,0.0f,0.0f,1.0f);

// (MP - 22.08.2008) Initialised later to avoid problems on PS2.
static Asura_Comp_Quat g_xAcq;
static Asura_Comp_Quat_Fast g_xAcqf;

static const Asura_Euler_3 g_xAe3(0.0f,0.0f,1.0f);

static const Asura_RGBA g_xArgba(0.0f,0.0f,1.0f,1.0f);

static const Asura_String g_xAs("this is an Asura string\n");

static const Asura_Vector_2 g_xAv2(0.0f,0.0f);

static const Asura_Vector_3 g_xAv3(0.0f,1.0f,0.0f);

static const Asura_AVector3 g_xAav3(0.0f,1.0f,0.0f);

static const Asura_Matrix_3x3 g_xAm3x3 = Asura_Matrix_3x3(0.0f,1.0f,0.0f,
	                                                   1.0f,0.0f,1.0f,
													   1.0f,0.0f,1.0f);

static const Asura_AMatrix3x3 g_xAam3x3(0.0f,0.0f,0.0f,
	                                 1.0f,1.0f,1.0f,
									 0.0f,1.0f,1.0f);

static const Asura_Bounding_Box g_xAbb = { { { 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f } } };

static const Asura_String g_xWString("wxy");


static void InitialiseGlobals( void )
{
    static bool bGlobalsInitialised = false;
    if( bGlobalsInitialised )
    {
        return;
    }

    g_xAcq  = g_xAq;
    g_xAcqf = g_xAq;

    bGlobalsInitialised = true;
}

// note that because this function is called from a unit test context and performs tests itself
// that some members of the unit test context are needed to be passed in as arguments (xResult, m_xName)
static void DoStreamTestBasicTypesWrite(Asura_Chunk_Stream& xStream, Asura_UnitTest_TestResult& xResult, Asura_String& m_xName)
{
	xStream << g_uZero;
	xStream << g_uMax;

	xStream << g_fZero;
	xStream << g_fMax;
	xStream << g_fMin;
	
	xStream << g_usZero;
	xStream << g_usMax;

	xStream << g_cA;
	xStream << g_cB;
	xStream << g_cZero;
	xStream << g_cCr;
	xStream << g_cCrlf;
	xStream << g_cTab;
	
	xStream << g_ucZero;
	xStream << g_ucCharMax;

	xStream << g_bTrue;
	xStream << g_iZero;
	xStream << g_iOne;
	xStream << g_bFalse;
	xStream << g_iMinusOne;
	xStream << g_iMin;
	xStream << g_iMax;

	xStream << g_sMax;
	xStream << g_bTrue;
	xStream << g_sZero;
	xStream << g_iMinusOne;
	xStream << g_sMinusOne;
	xStream << g_bFalse;
	xStream << g_sMin;
	xStream << g_sOne;
}

// note that because this function is called from a unit test context and performs tests itself
// that some members of the unit test context are needed to be passed in as arguments (xResult, m_xName)
static void DoStreamTestBasicTypesRead(Asura_Chunk_Stream& xStreamReader, Asura_UnitTest_TestResult& xResult, Asura_String& m_xName)
{
	//Basic type variables to fill
	u_int  uZeroTest;
	u_int  uMaxTest;

	float  fZeroTest;
	float  fMaxTest;
	float  fMinTest;

	u_short  usZeroTest;
	u_short  usMaxTest;

    char  cATest;
	char  cBTest;
	char  cZeroTest;
	char  cCrTest;
	char  cCrlfTest;
	char  cTabTest;

	u_char  ucZeroTest;
	u_char  ucCharMaxTest;

	
	bool bTrueTest;
	bool bFalseTest;

	int iZeroTest;
	int iOneTest;
	int iMinusOneTest;
	int iMaxTest;
	int iMinTest;

	short sZeroTest;
	short sOneTest;
	short sMinusOneTest;
	short sMaxTest;
	short sMinTest;

	//Test reading the stream
	xStreamReader >> uZeroTest;
	ASURA_UNITTEST_CHECK( g_uZero == uZeroTest );
	xStreamReader >> uMaxTest;
	ASURA_UNITTEST_CHECK( g_uMax == uMaxTest );

	xStreamReader >> fZeroTest;
	ASURA_UNITTEST_CHECK( g_fZero == fZeroTest );
	xStreamReader >> fMaxTest;
	ASURA_UNITTEST_CHECK( g_fMax  == fMaxTest );
	xStreamReader >> fMinTest;
	ASURA_UNITTEST_CHECK( g_fMin  == fMinTest );

	xStreamReader >> usZeroTest;
	ASURA_UNITTEST_CHECK( g_usZero == usZeroTest );
	xStreamReader >> usMaxTest;
	ASURA_UNITTEST_CHECK( g_usMax  == usMaxTest );

	xStreamReader >> cATest;
	ASURA_UNITTEST_CHECK( g_cA    == cATest );
	xStreamReader >> cBTest;
	ASURA_UNITTEST_CHECK( g_cB    == cBTest );
	xStreamReader >> cZeroTest;
	ASURA_UNITTEST_CHECK( g_cZero == cZeroTest );
	xStreamReader >> cCrTest;
	ASURA_UNITTEST_CHECK( g_cCr   == cCrTest );
	xStreamReader >> cCrlfTest;
	ASURA_UNITTEST_CHECK( g_cCrlf == cCrlfTest );
	xStreamReader >> cTabTest;
	ASURA_UNITTEST_CHECK( g_cTab  == cTabTest );

	xStreamReader >> ucZeroTest;
	ASURA_UNITTEST_CHECK( g_ucZero    == ucZeroTest );
	xStreamReader >> ucCharMaxTest;
	ASURA_UNITTEST_CHECK( g_ucCharMax == ucCharMaxTest );


	xStreamReader >> bTrueTest;
	ASURA_UNITTEST_CHECK( g_bTrue  == bTrueTest );
	xStreamReader >> iZeroTest;
	ASURA_UNITTEST_CHECK( g_iZero  == iZeroTest );
	xStreamReader >> iOneTest;
	ASURA_UNITTEST_CHECK( g_iOne   == iOneTest );
	xStreamReader >> bFalseTest;
	ASURA_UNITTEST_CHECK( g_bFalse == bFalseTest );
	xStreamReader >> iMinusOneTest;
	ASURA_UNITTEST_CHECK( g_iMinusOne == iMinusOneTest );
	xStreamReader >> iMinTest;
	ASURA_UNITTEST_CHECK( g_iMin == iMinTest );
	xStreamReader >> iMaxTest;
	ASURA_UNITTEST_CHECK( g_iMax == iMaxTest );

	xStreamReader >> sMaxTest;
	ASURA_UNITTEST_CHECK( g_sMax == sMaxTest );
	xStreamReader >> bTrueTest;
	ASURA_UNITTEST_CHECK( g_bTrue == bTrueTest );
	xStreamReader >> sZeroTest;
	ASURA_UNITTEST_CHECK( g_sZero == sZeroTest );
	xStreamReader >> iMinusOneTest;
	ASURA_UNITTEST_CHECK( g_iMinusOne == iMinusOneTest );
	xStreamReader >> sMinusOneTest;
	ASURA_UNITTEST_CHECK( g_sMinusOne == sMinusOneTest );
	xStreamReader >> bFalseTest;
	ASURA_UNITTEST_CHECK( g_bFalse == bFalseTest );
	xStreamReader >> sMinTest;
	ASURA_UNITTEST_CHECK( g_sMin == sMinTest );
	xStreamReader >> sOneTest;
	ASURA_UNITTEST_CHECK( g_sOne == sOneTest );
}

// note that because this function is called from a unit test context and performs tests itself
// that some members of the unit test context are needed to be passed in as arguments (xResult, m_xName)
static void DoStreamTestAsuraTypesWrite(Asura_Chunk_Stream& xStream, Asura_UnitTest_TestResult& xResult, Asura_String& m_xName)
{
	xStream << g_xAhfZero;
	xStream << g_xAhfMinusOne;
	xStream << g_xAhf;

	xStream << g_xAq;
	xStream << g_xAcq;
	xStream << g_xAcqf;
	
	xStream << g_xAe3;
	xStream << g_xArgba;
	xStream << g_xAs;
	xStream << g_xAv2;
	xStream << g_xAv3;
	xStream << g_xAav3;
	
	xStream << g_xAm3x3;
	xStream << g_xAam3x3;

	xStream << g_xAbb;
}

// note that because this function is called from a unit test context and performs tests itself
// that some members of the unit test context are needed to be passed in as arguments (xResult, m_xName)
static void DoStreamTestAsuraTypesRead(Asura_Chunk_Stream& xStreamReader, Asura_UnitTest_TestResult& xResult, Asura_String& m_xName)
{
	Asura_HalfFloat xAhfZeroTest;
	Asura_HalfFloat xAhfMinusOneTest;
	Asura_HalfFloat xAhfTest;

	Asura_Quat           xAqTest;
	Asura_Comp_Quat      xAcqTest;
	Asura_Comp_Quat_Fast xAcqfTest;

	Asura_Euler_3 xAe3Test;

	Asura_RGBA    xArgbaTest;

	Asura_String  xAsTest;

	Asura_Vector_2 xAv2Test;

	Asura_Vector_3 xAv3Test;

	Asura_AVector3 xAav3Test;

	Asura_Matrix_3x3   xAm3x3Test;

	Asura_AMatrix3x3   xAam3x3Test;

	Asura_Bounding_Box xAbbTest;

	//TEST
	xStreamReader >> xAhfZeroTest;
	ASURA_UNITTEST_CHECK( g_xAhfZero == xAhfZeroTest );
	xStreamReader >> xAhfMinusOneTest;
	ASURA_UNITTEST_CHECK( g_xAhfMinusOne == xAhfMinusOneTest );
	xStreamReader >> xAhfTest;
	ASURA_UNITTEST_CHECK( g_xAhf == xAhfTest );
	xStreamReader >> xAqTest;
	ASURA_UNITTEST_CHECK( g_xAq == xAqTest );
	xStreamReader >> xAcqTest;
	ASURA_UNITTEST_CHECK( g_xAcq.GetBits() == xAcqTest.GetBits() );
	xStreamReader >> xAcqfTest;
	ASURA_UNITTEST_CHECK( g_xAcqf.GetBits() == xAcqfTest.GetBits() );
	xStreamReader >> xAe3Test;
	ASURA_UNITTEST_CHECK((g_xAe3.x == xAe3Test.x) &&
		                 (g_xAe3.y == xAe3Test.y) &&
						 (g_xAe3.z == xAe3Test.z));
	xStreamReader >> xArgbaTest;
	ASURA_UNITTEST_CHECK( g_xArgba == xArgbaTest );
	xStreamReader >> xAsTest;
	ASURA_UNITTEST_CHECK( g_xAs     == xAsTest );
	xStreamReader >> xAv2Test;
	ASURA_UNITTEST_CHECK( g_xAv2    == xAv2Test );
	xStreamReader >> xAv3Test;
	ASURA_UNITTEST_CHECK( g_xAv3    == xAv3Test );
	xStreamReader >> xAav3Test;
	ASURA_UNITTEST_CHECK( g_xAav3   == xAav3Test );
	xStreamReader >> xAm3x3Test;
	ASURA_UNITTEST_CHECK( g_xAm3x3  == xAm3x3Test );
	xStreamReader >> xAam3x3Test;
	ASURA_UNITTEST_CHECK( g_xAam3x3 == xAam3x3Test );
	xStreamReader >> xAbbTest;
	ASURA_UNITTEST_CHECK( g_xAbb    == xAbbTest );
}

// note that because this function is called from a unit test context and performs tests itself
// that some members of the unit test context are needed to be passed in as arguments (xResult, m_xName)
static void DoStreamTestGetPosition(Asura_Chunk_Stream& xStream, Asura_UnitTest_TestResult& xResult, Asura_String& m_xName)
{
	//Offeset in case there is a header
	u_int uStartPosition = xStream.GetPosition();

    //Position now must be zero
	ASURA_UNITTEST_CHECK(0 + uStartPosition ==  xStream.GetPosition());

	//add some 1 byte data; position must be one
    xStream << g_cA;                                                         
    ASURA_UNITTEST_CHECK(1 + uStartPosition == xStream.GetPosition());
	//add some 2 byte data; position must be 3
    xStream << g_usZero; 
    ASURA_UNITTEST_CHECK(3 + uStartPosition == xStream.GetPosition());
	//add some 4 byte data; position must be 7
    xStream << g_uMax;  
    ASURA_UNITTEST_CHECK(7 + uStartPosition == xStream.GetPosition());
	//add another float 4 byte data; position must be 11
    xStream << g_fZero;
    ASURA_UNITTEST_CHECK(11 + uStartPosition == xStream.GetPosition());

	//add some Asura specific data types
    //add Asura_HalfFloat
	//data members are (2bytes)
	//position now must be 13
	xStream << g_xAhfZero;
    ASURA_UNITTEST_CHECK(13 + uStartPosition == xStream.GetPosition());


    //add Asura_Quat
	//data members are float (4bytes) * 4 = 16 Bytes
	//position now must be 29
    xStream << g_xAq;
    ASURA_UNITTEST_CHECK( xStream.GetPosition() == 29  + uStartPosition);

    //add Asura_Comp_Quat
	//data members are u_int (4bytes)
	//position now must be 33
    xStream << g_xAcq;
    ASURA_UNITTEST_CHECK(33 + uStartPosition == xStream.GetPosition());


    //add Asura_Comp_Quat_Fast
	//data members are u_int (4bytes)
	//position now must be 37
    xStream << g_xAcqf;
    ASURA_UNITTEST_CHECK(37 + uStartPosition == xStream.GetPosition());


    //add Asura_Euler_3
	//data members are float (4bytes) * 3 = 12
	//position now must be 49
    xStream << g_xAe3;
    ASURA_UNITTEST_CHECK(49 + uStartPosition == xStream.GetPosition());

    //add Asura_RGBA
	//data members are float (4bytes) * 4 = 16
	//position now must be 65
    xStream << g_xArgba;
    ASURA_UNITTEST_CHECK(65 + uStartPosition == xStream.GetPosition());

    //add Asura_Vector_2
	//data members are float (4bytes) * 2 = 8
	//position now must be 73
    xStream << g_xAv2;
    ASURA_UNITTEST_CHECK(73 + uStartPosition == xStream.GetPosition());

    //add Asura_Vector_3
	//data members are float (4bytes) * 3 = 12
	//position now must be 85
    xStream << g_xAv3;
    ASURA_UNITTEST_CHECK(85 + uStartPosition == xStream.GetPosition());


    //add Asura_AVector3
	//data members are float (4bytes) * 4 = 16
	//position now must be 97
    xStream << g_xAav3;
    ASURA_UNITTEST_CHECK(97 + uStartPosition == xStream.GetPosition());


    //add Asura_Matrix_3x3
	//data members are float (4bytes) * 9 = 36
	//position now must be 133
    //Asura_Matrix_3x3
	xStream << g_xAm3x3;
    ASURA_UNITTEST_CHECK(133 + uStartPosition == xStream.GetPosition());

	//add Asura_AMatrix3x3
	//data members are float (4bytes) * 9 = 36
	//position now must be 169
    //Asura_AMatrix3x3
	xStream << g_xAam3x3;
    ASURA_UNITTEST_CHECK(169 + uStartPosition == xStream.GetPosition());

	//add Asura_Bounding_Box
	//data members are float (4bytes) * 6 = 24
	//position now must be 193
    //Asura_AMatrix3x3
	xStream << g_xAbb;
    ASURA_UNITTEST_CHECK(193 + uStartPosition == xStream.GetPosition());
}

// note that because this function is called from a unit test context and performs tests itself
// that some members of the unit test context are needed to be passed in as arguments (xResult, m_xName)
static void DoStreamTestOtherWrite(Asura_Chunk_Stream& xStream, Asura_UnitTest_TestResult& xResult, Asura_String& m_xName)
{
    //Offeset in case there is a header
	u_int uStartPosition = xStream.GetPosition();
    //fill with a character
    xStream << g_cA;
	//pad to position 9
    xStream.WritePadding(8,g_cA);
	//Check for position must be 9
    ASURA_UNITTEST_CHECK(9  + uStartPosition == xStream.GetPosition());
	xStream << g_cB;
	xStream << g_cC;
	//Check for position must be 11
    ASURA_UNITTEST_CHECK(11  + uStartPosition == xStream.GetPosition());
	//Test the Write2BytePadding
	xStream.Write2BytePadding();
	//Check for position must be 12
    ASURA_UNITTEST_CHECK(12  + uStartPosition == xStream.GetPosition());
    xStream << g_cW;
	//Test the Write4BytePadding
	xStream.Write4BytePadding();
	//Check for position must be 16
    ASURA_UNITTEST_CHECK(16  + uStartPosition == xStream.GetPosition());
	//Test the Write2BytePadding(const u_char ucPad)
	xStream << g_cW;
	xStream.Write2BytePadding(g_cZ);
	//Check for position must be 18
    ASURA_UNITTEST_CHECK(18  + uStartPosition == xStream.GetPosition());
	//Test the Write4BytePadding(const u_char ucPad)
	xStream.Write4BytePadding(g_cX);
	//Check for position must be 20
    ASURA_UNITTEST_CHECK(20  + uStartPosition == xStream.GetPosition());
    //Add 16 more bytes to test skip functions
    xStream << 1.0f << 1.0f << 1.0f;
    //Add a u_int to test peek function
    xStream << g_uMagic;
	//Add an int to test the skip string function
    xStream << g_uMax;
    //Add string to test skip string function
    xStream << g_xWString;
}

void DoStreamTestOtherRead(Asura_Chunk_Stream& xStreamReader, Asura_UnitTest_TestResult& xResult, Asura_String& m_xName, bool bTestPeek)
{
	//Offeset in case there is a header
	u_int uStartPosition = xStreamReader.GetPosition();
	char cTest;
	xStreamReader >> cTest;
	ASURA_UNITTEST_CHECK( cTest == g_cA);
	xStreamReader >> cTest;
	ASURA_UNITTEST_CHECK( cTest == g_cA);
	xStreamReader >> cTest;
	ASURA_UNITTEST_CHECK( cTest == g_cA);
	xStreamReader >> cTest;
	ASURA_UNITTEST_CHECK( cTest == g_cA);
	xStreamReader >> cTest;
	ASURA_UNITTEST_CHECK( cTest == g_cA);
	xStreamReader >> cTest;
	ASURA_UNITTEST_CHECK( cTest == g_cA);
	//Check for position must be 6
    ASURA_UNITTEST_CHECK( 6  + uStartPosition == xStreamReader.GetPosition());

	//Test the skip function
    xStreamReader.SkipPadding(6);
    //read the char(must be w there)
    xStreamReader >> cTest;
    ASURA_UNITTEST_CHECK( cTest== g_cW);
	//go to pos 17
    xStreamReader.SkipPadding(4);
	//read the char(must be z there pos 18)
    xStreamReader >> cTest;
    ASURA_UNITTEST_CHECK( cTest== g_cZ);
    xStreamReader >> cTest;
    ASURA_UNITTEST_CHECK( cTest== g_cX);
    xStreamReader >> cTest;
    ASURA_UNITTEST_CHECK( cTest== g_cX);
	//Check for position must be 20
    ASURA_UNITTEST_CHECK( xStreamReader.GetPosition() == 20  + uStartPosition);


	//Skip 12 positions (bytes)
	xStreamReader.SkipPadding(12);
	//Check for position must be 32
    ASURA_UNITTEST_CHECK(32  + uStartPosition == xStreamReader.GetPosition());
	//Skip 2 bytes
	xStreamReader.Skip2BytePadding();
	//Check for position must be 32
    ASURA_UNITTEST_CHECK(32  + uStartPosition == xStreamReader.GetPosition());
	//Skip 4 bytes
	xStreamReader.Skip4BytePadding();
	//Check for position must be 32
    ASURA_UNITTEST_CHECK(32  + uStartPosition == xStreamReader.GetPosition());
    
	if(bTestPeek)
	{
		//Test the Peek() function
		//Read an int 4Bytes
		int iTest = xStreamReader.PeekInt();
		//Test for position; must be 32
		ASURA_UNITTEST_CHECK(32  + uStartPosition == xStreamReader.GetPosition());

		//Read a u_int 4Bytes
		u_int uTest = xStreamReader.PeekUInt();
		//Test for position; must be 32
		ASURA_UNITTEST_CHECK(32  + uStartPosition == xStreamReader.GetPosition());

		ASURA_UNITTEST_CHECK( uTest == g_uMagic );
		ASURA_UNITTEST_CHECK( iTest == static_cast<int>(uTest) );
	}
	//Test reading after a peek
	u_int uTest;
	xStreamReader >> uTest;
	ASURA_UNITTEST_CHECK( g_uMagic == uTest );

	int iTest;
	//Read the int
	xStreamReader >> iTest;
	ASURA_UNITTEST_CHECK( static_cast<u_int>(iTest) == g_uMax);
	//call SkipString must reach 44
	xStreamReader.SkipString();
	//Test for postion; must be 44
	ASURA_UNITTEST_CHECK(44 + uStartPosition == xStreamReader.GetPosition());
}

//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//                         MEMORY STREAM TEST                               //
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
//                    MEMORY STREAM TEST (Basic types)                                
//////////////////////////////////////////////////////////////////////////////
ASURA_UNITTEST(MemoryStreamBasicTypes, Asura_Chunk_Stream)
{
    InitialiseGlobals();

	const u_int uSize = uSTREAM_ALLOCATION_SIZE;
	void* const pMem         = Asura_Allocate(uSize);

	//Create the write stream
	Asura_Chunk_Memory_Stream xStreamWriter(uSize, pMem);
	//Read stream
	Asura_Chunk_Memory_Stream xStreamReader(uSize, pMem);
#ifdef ASURA_TOOLS
	xStreamWriter.SetSwapEndian(false);
#endif

	DoStreamTestBasicTypesWrite(xStreamWriter, xResult, m_xName);
	DoStreamTestBasicTypesRead(xStreamReader, xResult, m_xName);
	Asura_Deallocate(pMem);
}

//////////////////////////////////////////////////////////////////////////////
//                   MEMORY STREAM TEST (ASURA types)                                
//////////////////////////////////////////////////////////////////////////////
ASURA_UNITTEST(MemoryStreamAsuraTypes, Asura_Chunk_Stream)
{
    InitialiseGlobals();

	const u_int uSize = uSTREAM_ALLOCATION_SIZE;
	void* const pMem = Asura_Allocate(uSize);

	//Create the stream
	Asura_Chunk_Memory_Stream xStreamWriter(uSize, pMem);
	//Read stream
	Asura_Chunk_Memory_Stream xStreamReader(uSize, pMem);

#ifdef ASURA_TOOLS
	xStreamWriter.SetSwapEndian(false);
#endif
	DoStreamTestAsuraTypesWrite(xStreamWriter, xResult, m_xName);
	DoStreamTestAsuraTypesRead(xStreamReader, xResult, m_xName);

	Asura_Deallocate(pMem);
}


//////////////////////////////////////////////////////////////////////////////
//                  MEMORY STREAM TEST (GetPosition)                                
//////////////////////////////////////////////////////////////////////////////
ASURA_UNITTEST(MemoryStreamGetPosition, Asura_Chunk_Stream)
{
    InitialiseGlobals();

	const u_int uSize = uSTREAM_ALLOCATION_SIZE;
	void* const pMem = Asura_Allocate(uSize);

	//Create the stream
	Asura_Chunk_Memory_Stream xStream(uSize, pMem);

#ifdef ASURA_TOOLS
	xStream.SetSwapEndian(false);
#endif
	DoStreamTestGetPosition(xStream, xResult, m_xName);

	Asura_Deallocate(pMem);
}
//////////////////////////////////////////////////////////////////////////////
//                      MEMORY STREAM TEST (other)                                
//////////////////////////////////////////////////////////////////////////////
ASURA_UNITTEST(MemoryStreamOther, Asura_Chunk_Stream)
{
    InitialiseGlobals();

	const u_int uSize = uSTREAM_ALLOCATION_SIZE;
	void* const pMem = Asura_Allocate(uSize);

	//Create the stream
	Asura_Chunk_Memory_Stream xStreamWriter(uSize, pMem);
	//Read stream
	Asura_Chunk_Memory_Stream xStreamReader(uSize, pMem);

#ifdef ASURA_TOOLS
	xStreamWriter.SetSwapEndian(false);
#endif
	DoStreamTestOtherWrite(xStreamWriter, xResult, m_xName);
	DoStreamTestOtherRead(xStreamReader, xResult, m_xName, true);

	Asura_Deallocate(pMem);
}


//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//                    CHUNK BUFFER STREAM TEST                              //
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
//                CHUNK BUFFER STREAM TEST (Basic types)                                
//////////////////////////////////////////////////////////////////////////////
ASURA_UNITTEST(ChunkBufferStreamBasicTypes, Asura_Chunk_Stream)
{
    InitialiseGlobals();

	char* pcBuffer1;
	char* pcBuffer2;

	void* const pMem = Asura_Allocate(uSTREAM_ALLOCATION_SIZE);
	pcBuffer1 = static_cast<char*>(pMem);

	//Create the stream
	Asura_Chunk_ChunkBuffer_Stream xStreamWriter(pcBuffer1);
	// read off the stream
	pcBuffer2 = static_cast<char*>(pMem);
	Asura_Chunk_ChunkBuffer_Stream xStreamReader(pcBuffer2);

#ifdef ASURA_TOOLS
	xStreamWriter.SetSwapEndian(false);
#endif

	DoStreamTestBasicTypesWrite(xStreamWriter, xResult, m_xName);
	DoStreamTestBasicTypesRead(xStreamReader, xResult, m_xName);

	Asura_Deallocate(pMem);
}

//////////////////////////////////////////////////////////////////////////////
//                 CHUNK BUFFER STREAM TEST (ASURA types)                                
//////////////////////////////////////////////////////////////////////////////
ASURA_UNITTEST(ChunkBufferStreamAsuraTypes, Asura_Chunk_Stream)
{
    InitialiseGlobals();

	char* pcBuffer1;
	char* pcBuffer2;

	void* const pMem = Asura_Allocate(uSTREAM_ALLOCATION_SIZE);
	pcBuffer1 = static_cast<char*>(pMem);

	//Create the stream
	Asura_Chunk_ChunkBuffer_Stream xStreamWriter(pcBuffer1);
	// read off the stream
	pcBuffer2 = static_cast<char*>(pMem);
	Asura_Chunk_ChunkBuffer_Stream xStreamReader(pcBuffer2);

#ifdef ASURA_TOOLS
	xStreamWriter.SetSwapEndian(false);
#endif

	DoStreamTestAsuraTypesWrite(xStreamWriter, xResult, m_xName);
	DoStreamTestAsuraTypesRead(xStreamReader, xResult, m_xName);

	Asura_Deallocate(pMem);
}

//////////////////////////////////////////////////////////////////////////////
//                CHUNK BUFFER STREAM TEST (GetPosition)                                
//////////////////////////////////////////////////////////////////////////////
ASURA_UNITTEST(ChunkBufferStreamGetPosition, Asura_Chunk_Stream)
{
    InitialiseGlobals();

	char* pcBuffer;
	void* const pMem = Asura_Allocate(uSTREAM_ALLOCATION_SIZE);
	pcBuffer = static_cast<char*>(pMem);

	Asura_Chunk_ChunkBuffer_Stream xStream(pcBuffer);

#ifdef ASURA_TOOLS
	xStream.SetSwapEndian(false);
#endif

	DoStreamTestGetPosition(xStream, xResult, m_xName);

	Asura_Deallocate(pMem);
}

//////////////////////////////////////////////////////////////////////////////
//                  CHUNK BUFFER STREAM TEST (other)                                
//////////////////////////////////////////////////////////////////////////////
ASURA_UNITTEST(ChunkBufferStreamOther, Asura_Chunk_Stream)
{
    InitialiseGlobals();

	char* pcBuffer1;
	char* pcBuffer2;

	void* const pMem = Asura_Allocate(uSTREAM_ALLOCATION_SIZE);
	pcBuffer1 = static_cast<char*>(pMem);
	Asura_Chunk_ChunkBuffer_Stream xStreamWriter(pcBuffer1);
	//read off the stream
	pcBuffer2 = static_cast<char*>(pMem);
	Asura_Chunk_ChunkBuffer_Stream xStreamReader(pcBuffer2);

#ifdef ASURA_TOOLS
	xStreamWriter.SetSwapEndian(false);
#endif

	DoStreamTestOtherWrite(xStreamWriter, xResult, m_xName);
	DoStreamTestOtherRead(xStreamReader, xResult, m_xName, true);

	Asura_Deallocate(pMem);
}


//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//                         SAVE BLOCK STREAM TEST                           //
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
//                    SAVE BLOCK STREAM TEST (Basic types)                                
//////////////////////////////////////////////////////////////////////////////
ASURA_UNITTEST(SaveBlockStreamBasicTypes, Asura_Chunk_Stream)
{
    InitialiseGlobals();

	Asura_SaveBlock xAsuraSaveBlock;
	Asura_Chunk_SaveBlock_Stream xStreamWriter(&xAsuraSaveBlock);

#ifdef ASURA_TOOLS
	xStreamWriter.SetSwapEndian(false);
#endif

	DoStreamTestBasicTypesWrite(xStreamWriter, xResult, m_xName);
	//Read off the stream
	Asura_Chunk_SaveBlockReader_Stream xStreamReader(&xAsuraSaveBlock);
	//Skip the header
	Asura_LoadAndSave::ProcessAsuraFileHeader(xStreamReader);

	DoStreamTestBasicTypesRead(xStreamReader, xResult, m_xName);
}

//////////////////////////////////////////////////////////////////////////////
//                 SAVE BLOCK STREAM TEST (ASURA types)                                
//////////////////////////////////////////////////////////////////////////////
ASURA_UNITTEST(SaveBlockStreamAsuraTypes, Asura_Chunk_Stream)
{
    InitialiseGlobals();

	Asura_SaveBlock xAsuraSaveBlock;
	Asura_Chunk_SaveBlock_Stream xStreamWriter(&xAsuraSaveBlock);

#ifdef ASURA_TOOLS
	xStreamWriter.SetSwapEndian(false);
#endif

	DoStreamTestAsuraTypesWrite(xStreamWriter, xResult, m_xName);
	//Read off the stream
	Asura_Chunk_SaveBlockReader_Stream xStreamReader(&xAsuraSaveBlock);
	//Skip the header
	Asura_LoadAndSave::ProcessAsuraFileHeader(xStreamReader);
	DoStreamTestAsuraTypesRead(xStreamReader, xResult, m_xName);
}

//////////////////////////////////////////////////////////////////////////////
//                 SAVE BLOCK STREAM TEST (GetPosition)                                
//////////////////////////////////////////////////////////////////////////////
ASURA_UNITTEST(SaveBlockStreamGetPosition, Asura_Chunk_Stream)
{
    InitialiseGlobals();

	Asura_SaveBlock xAsuraSaveBlock;
	Asura_Chunk_SaveBlock_Stream xStream(&xAsuraSaveBlock);

#ifdef ASURA_TOOLS
	xStream.SetSwapEndian(false);
#endif

	DoStreamTestGetPosition(xStream, xResult, m_xName);
}

//////////////////////////////////////////////////////////////////////////////
//                  SAVE BLOCK STREAM TEST (other)                                
//////////////////////////////////////////////////////////////////////////////
ASURA_UNITTEST(SaveBlockStreamOther, Asura_Chunk_Stream)
{
    InitialiseGlobals();

	Asura_SaveBlock xAsuraSaveBlock;
	Asura_Chunk_SaveBlock_Stream xStreamWriter(&xAsuraSaveBlock);


#ifdef ASURA_TOOLS
	xStreamWriter.SetSwapEndian(false);
#endif

	DoStreamTestOtherWrite(xStreamWriter, xResult, m_xName);
	//Read off the stream
	Asura_Chunk_SaveBlockReader_Stream xStreamReader(&xAsuraSaveBlock);
	//Skip the header
	Asura_LoadAndSave::ProcessAsuraFileHeader(xStreamReader);

	DoStreamTestOtherRead(xStreamReader, xResult, m_xName, true);
}

#ifdef ASURA_TOOLS
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//                         FILE STREAM STREAM TEST                          //
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
//					  FILE STREAM TEST (Basic types)                                
//////////////////////////////////////////////////////////////////////////////
ASURA_UNITTEST(FileStreamBasicTypes, Asura_Chunk_Stream)
{
    InitialiseGlobals();

	//Class for reading only
	//Create a save block
	Asura_SaveBlock xAsuraSaveBlock;
	Asura_Chunk_SaveBlock_Stream xStreamWriter(&xAsuraSaveBlock);

	#ifdef ASURA_TOOLS
		xStreamWriter.SetSwapEndian(false);
	#endif
    DoStreamTestBasicTypesWrite(xStreamWriter, xResult, m_xName);

    //SAVE THE FILE TO BE OPENED BY THE FILE STREAM CLASS
	xAsuraSaveBlock.SaveFile(g_szFilename,false);

	//OPEN IT WITH FILE STREAM
	Asura_Handle iFileHandle = Asura_FileAccess::Open(g_szFilename);
	ASURA_UNITTEST_CHECK(iFileHandle != ASURA_INVALID_HANDLE);

	if (iFileHandle != ASURA_INVALID_HANDLE)
	{
		Asura_Chunk_File_Stream xStreamReader(iFileHandle);
		Asura_LoadAndSave::ProcessAsuraFileHeader(xStreamReader);

		DoStreamTestBasicTypesRead(xStreamReader, xResult, m_xName);

		//Close opened files
		Asura_FileAccess::Close(iFileHandle);
		//Delete file
		if(! Tools_FileSystem::DeleteFileByName(g_szFilename))
		{
			Asura_Assertf(false, ("Could not delete file (%s) in Asura_UnitTest_ChunkSystem", g_szFilename));
		}
	}
}

//////////////////////////////////////////////////////////////////////////////
//                  FILE STREAM TEST (ASURA types)                                
//////////////////////////////////////////////////////////////////////////////
ASURA_UNITTEST(FileStreamAsuraTypes, Asura_Chunk_Stream)
{
    InitialiseGlobals();

	//Create a save block
	Asura_SaveBlock xAsuraSaveBlock;
	Asura_Chunk_SaveBlock_Stream xStreamWriter(&xAsuraSaveBlock);

	#ifdef ASURA_TOOLS
		xStreamWriter.SetSwapEndian(false);
	#endif

    DoStreamTestAsuraTypesWrite(xStreamWriter, xResult, m_xName);

    //SAVE THE FILE TO BE OPENED BY THE FILE STREAM CLASS
	xAsuraSaveBlock.SaveFile(g_szFilename,false);

	//OPEN IT WITH FILE STREAM
	Asura_Handle iFileHandle = Asura_FileAccess::Open(g_szFilename);
	ASURA_UNITTEST_CHECK(iFileHandle != ASURA_INVALID_HANDLE);

	if (iFileHandle != ASURA_INVALID_HANDLE)
	{
		Asura_Chunk_File_Stream xStreamReader(iFileHandle);
		Asura_LoadAndSave::ProcessAsuraFileHeader(xStreamReader);
	    
		DoStreamTestAsuraTypesRead(xStreamReader, xResult, m_xName);

		//Close opened files
		Asura_FileAccess::Close(iFileHandle);
		//Delete file
		if(! Tools_FileSystem::DeleteFileByName(g_szFilename))
		{
			Asura_Assertf(false, ("Could not delete file (%s) in Asura_UnitTest_ChunkSystem", g_szFilename));
		}
	}
}
//////////////////////////////////////////////////////////////////////////////
//						FILE STREAM TEST (other)                                
//////////////////////////////////////////////////////////////////////////////
ASURA_UNITTEST(FileStreamOther, Asura_Chunk_Stream)
{
    InitialiseGlobals();

	Asura_SaveBlock xAsuraSaveBlock;
	Asura_Chunk_SaveBlock_Stream xStreamWriter(&xAsuraSaveBlock);

	#ifdef ASURA_TOOLS
		xStreamWriter.SetSwapEndian(false);
	#endif

    DoStreamTestOtherWrite(xStreamWriter, xResult, m_xName);

    //SAVE THE FILE TO BE OPENED BY THE FILE STREAM CLASS
	xAsuraSaveBlock.SaveFile(g_szFilename,false);

	//OPEN IT WITH FILE STREAM
	Asura_Handle iFileHandle = Asura_FileAccess::Open(g_szFilename);
	ASURA_UNITTEST_CHECK(iFileHandle != ASURA_INVALID_HANDLE);
	if (iFileHandle != ASURA_INVALID_HANDLE)
	{
		Asura_Chunk_File_Stream xStreamReader(iFileHandle);
		Asura_LoadAndSave::ProcessAsuraFileHeader(xStreamReader);

		//Don't test peek functions (not supported by file stream)
		DoStreamTestOtherRead(xStreamReader, xResult, m_xName, false);

		//Close opened files
		Asura_FileAccess::Close(iFileHandle);
		//Delete file
		if(! Tools_FileSystem::DeleteFileByName(g_szFilename))
		{
			Asura_Assertf(false, ("Could not delete file (%s) in Asura_UnitTest_ChunkSystem", g_szFilename));
		}
	}
}
#endif // #ifdef ASURA_TOOLS

//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//               COMPRESSED SAVE BLOCK STREAM TEST                          //
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
//           COMPRESSED SAVE BLOCK STREAM TEST (Basic types)                                
//////////////////////////////////////////////////////////////////////////////
ASURA_UNITTEST(CompressedSaveBlockStreamBasicTypes, Asura_Chunk_Stream)
{
    InitialiseGlobals();

	Asura_CompressedSaveBlock xAsuraSaveBlock(uSTREAM_ALLOCATION_SIZE);
	Asura_Chunk_SaveBlock_Stream xStreamWriter(&xAsuraSaveBlock);

	#ifdef ASURA_TOOLS
		xStreamWriter.SetSwapEndian(false);
	#endif

    DoStreamTestBasicTypesWrite(xStreamWriter, xResult, m_xName);
	//Read off the stream
	xAsuraSaveBlock.Flush();
	Asura_Chunk_SaveBlockReader_Stream xStreamReader(&xAsuraSaveBlock);

    DoStreamTestBasicTypesRead(xStreamReader, xResult, m_xName);
}

//////////////////////////////////////////////////////////////////////////////
//               COMPRESSED SAVE BLOCK STREAM TEST (ASURA types)                                
//////////////////////////////////////////////////////////////////////////////
ASURA_UNITTEST(CompressedSaveBlockStreamAsuraTypes, Asura_Chunk_Stream)
{
    InitialiseGlobals();

	Asura_CompressedSaveBlock xAsuraSaveBlock(uSTREAM_ALLOCATION_SIZE);
	Asura_Chunk_SaveBlock_Stream xStreamWriter(&xAsuraSaveBlock);

	#ifdef ASURA_TOOLS
		xStreamWriter.SetSwapEndian(false);
	#endif

	DoStreamTestAsuraTypesWrite(xStreamWriter, xResult, m_xName);
	//Read off the stream
	xAsuraSaveBlock.Flush();
	Asura_Chunk_SaveBlockReader_Stream xStreamReader(&xAsuraSaveBlock);

    DoStreamTestAsuraTypesRead(xStreamReader, xResult, m_xName);
}

//////////////////////////////////////////////////////////////////////////////
//               COMPRESSED SAVE BLOCK STREAM TEST (GetPosition)                                
//////////////////////////////////////////////////////////////////////////////
ASURA_UNITTEST(CompressedSaveBlockStreamGetPosition, Asura_Chunk_Stream)
{
    InitialiseGlobals();

	Asura_CompressedSaveBlock xAsuraSaveBlock(uSTREAM_ALLOCATION_SIZE);
	Asura_Chunk_SaveBlock_Stream xStream(&xAsuraSaveBlock);

	#ifdef ASURA_TOOLS
		xStream.SetSwapEndian(false);
	#endif

	DoStreamTestGetPosition(xStream, xResult, m_xName);
}

//////////////////////////////////////////////////////////////////////////////
//               COMPRESSED SAVE BLOCK STREAM TEST (other)                                
//////////////////////////////////////////////////////////////////////////////
ASURA_UNITTEST(CompressedSaveBlockStreamOther, Asura_Chunk_Stream)
{
    InitialiseGlobals();

    Asura_CompressedSaveBlock xAsuraSaveBlock(uSTREAM_ALLOCATION_SIZE);
	Asura_Chunk_SaveBlock_Stream xStreamWriter(&xAsuraSaveBlock);
    
	#ifdef ASURA_TOOLS
		xStreamWriter.SetSwapEndian(false);
	#endif
    
    DoStreamTestOtherWrite(xStreamWriter, xResult, m_xName);
	//Read off the stream
	xAsuraSaveBlock.Flush();
	Asura_Chunk_SaveBlockReader_Stream xStreamReader(&xAsuraSaveBlock);

    DoStreamTestOtherRead(xStreamReader, xResult, m_xName, true);
}

#endif // #ifdef ASURA_SUPPORT_UNITTEST
