/*
	Test-ZIniReader.cpp
	Author: James Russell

	Purpose :	Unit tests for ZIniReader

	Changelog :
	12/18/2011 - Removed dependency on ZString (crertel)
	2/15/2011 - Created (jcrussell)
*/

#include "ZUnitTest.hpp"

#include <ZUtil/ZSmartPointer.hpp>
#include <ZUtil/ZIniReader.hpp>

static const char* test_LoadSuccess();
static const char* test_LoadFailure();
static const char* test_SectionNames();
static const char* test_SectionValues();
static const char* test_AsZRegistry();

//List of unit tests
ZUnitTest ZIniReaderUnitTests[] =
{
	{ "Successfully load good data",	test_LoadSuccess },
	{ "Fail load on invalid data",		test_LoadFailure },
	{ "Section names",					test_SectionNames },
	{ "Section values",					test_SectionValues },
	{ "CreateZRegistry()",				test_AsZRegistry }
};

DECLARE_ZTESTBLOCK(ZIniReader);

/*************************************************************************/

namespace ZIniReaderTestData
{
	const char testDataValid1[] = "[Header1]"			LINE_TERMINATOR
								 "Variable1=Value1"		LINE_TERMINATOR
								 "Variable2=Value2"		LINE_TERMINATOR
								 ""						LINE_TERMINATOR
								 "#Comment"				LINE_TERMINATOR
								 ""						LINE_TERMINATOR
								 "[Header2]"			LINE_TERMINATOR
								 "Variable1=Value3"		LINE_TERMINATOR
														LINE_TERMINATOR;
	
	const char testDataValid2[] = "[Header1]"			LINE_TERMINATOR
								 ";Comment here"		LINE_TERMINATOR
								 "Variable1= Value1"	LINE_TERMINATOR
								 "Variable2 =Value2"	LINE_TERMINATOR
								 "Variable3 = Value3"	LINE_TERMINATOR
								 ""						LINE_TERMINATOR
														LINE_TERMINATOR;

	const char testDataInvalid1[] =	"[Hea[der1]"		LINE_TERMINATOR
									"Variable1=Value1"	LINE_TERMINATOR
									"Variable2=Value2"	LINE_TERMINATOR
									""					LINE_TERMINATOR
									"# Comment"			LINE_TERMINATOR
									""					LINE_TERMINATOR
									"[Header2]"			LINE_TERMINATOR
									"Variable1=Value3"	LINE_TERMINATOR
														LINE_TERMINATOR;

	const char testDataInvalid2[] =	"[Header1]"			LINE_TERMINATOR
									"Variable1=Value1"	LINE_TERMINATOR
									"Variable2"			LINE_TERMINATOR
									""					LINE_TERMINATOR
									"# Comment"			LINE_TERMINATOR
									""					LINE_TERMINATOR
									"[Header2]"			LINE_TERMINATOR
									"Variable1=Value3"	LINE_TERMINATOR
														LINE_TERMINATOR;

	const char testDataInvalid3[] =	""					LINE_TERMINATOR;
	const char testDataInvalid4[] =	"[Header1]"			LINE_TERMINATOR
									"Val ue = failure"	LINE_TERMINATOR;
	const char testDataInvalid5[] =	"[Header1]"			LINE_TERMINATOR
									"Val!ue = failure"	LINE_TERMINATOR;
}

using namespace ZIniReaderTestData;

/*************************************************************************/

static const char* test_LoadSuccess()
{
	ZIniReader reader;

	TASSERT(reader.Read(testDataValid1, sizeof(testDataValid1)-1), "Failed to read valid data set #1");
	TASSERT(reader.GetErrorString().Empty(), "Error is not empty after reading #1 successful?");
	TASSERT(reader.Read(testDataValid2, sizeof(testDataValid2)-1), "Failed to read valid data set #2");
	TASSERT(reader.GetErrorString().Empty(), "Error is not empty after reading #2 successful?");
	return ZTEST_SUCCESS;
}

static const char* test_SectionNames()
{
	ZIniReader reader;

	TASSERT(reader.Read(testDataValid1, sizeof(testDataValid1)-1), "Failed to read valid data set #1");
	TASSERT(reader.GetSectionCount() == 2, "Incorrect number of sections");

	for(size_t i=0; i<reader.GetSectionCount(); i++)
	{
		ZString header("Header");

		header += '1' + (char)i;

		TASSERT(reader.GetSectionName(i) == header, "Header name does not match");
		TASSERT(reader.GetSection(i) != NULL, "Unable to get header by ordinal");
		TASSERT(reader.GetSection(header) != NULL, "Unable to get header by name");

	}

	return ZTEST_SUCCESS;
}

static const char* test_SectionValues()
{
	ZIniReader reader;

	TASSERT(reader.Read(testDataValid1, sizeof(testDataValid1)-1), "Failed to read valid data set #1");

	TASSERT(reader.GetSection("Header1")->Get("Variable1") == "Value1", "[Header1]:Variable1 does not match!");
	TASSERT(reader.GetSection("Header1")->Get("Variable2") == "Value2", "[Header1]:Variable2 does not match!");
	TASSERT(reader.GetSection("Header2")->Get("Variable1") == "Value3", "[Header2]:Variable1 does not match!");

	//=======

	TASSERT(reader.Read(testDataValid2, sizeof(testDataValid2)-1), "Failed to read valid data set #2");

	TASSERT(reader.GetSection("Header1")->Get("Variable1") == "Value1", "[Header1]:Variable1 does not match!");
	TASSERT(reader.GetSection("Header1")->Get("Variable2") == "Value2", "[Header1]:Variable2 does not match!");
	TASSERT(reader.GetSection("Header1")->Get("Variable3") == "Value3", "[Header2]:Variable1 does not match!");

	return ZTEST_SUCCESS;
}

static const char* test_LoadFailure()
{
	ZIniReader reader;

	TASSERT(!reader.Read(testDataInvalid1, sizeof(testDataInvalid1)-1), "ZIniReader loaded invalid data set #1!");
	TASSERT(!reader.Read(testDataInvalid2, sizeof(testDataInvalid2)-1), "ZIniReader loaded invalid data set #2!");
	TASSERT(!reader.Read(testDataInvalid3, sizeof(testDataInvalid3)-1), "ZIniReader loaded invalid data set #3!");
	TASSERT(!reader.Read(testDataInvalid4, sizeof(testDataInvalid4)-1), "ZIniReader loaded invalid data set #4!");
	TASSERT(!reader.Read(testDataInvalid5, sizeof(testDataInvalid5)-1), "ZIniReader loaded invalid data set #5!");

	TASSERT(reader.GetSectionCount() == 0, "Shouldn't have any valid sections after this");
	TASSERT(reader.GetSection("Header1") == NULL, "Shouldn't have any valid name -> section mappings");

	return ZTEST_SUCCESS;
}


static const char* test_AsZRegistry()
{
	ZKVTree tree1;
	ZKVTree tree2;
	ZIniReader reader;

	reader.Read(testDataValid1, sizeof(testDataValid1)-1);

	reader.GetKVTree(tree1);
	
	TASSERT(tree1.Get("Header1.Variable1") == "Value1", "ZIniReader failed to store [Header1]:Variable1 correctly!");
	TASSERT(tree1.Get("Header1.Variable2") == "Value2", "ZIniReader failed to store [Header1]:Variable2 correctly!");
	TASSERT(tree1.Get("Header2.Variable1") == "Value3", "ZIniReader failed to store [Header2]:Variable1 correctly!");
	
	//============
	reader.Read(testDataValid2, sizeof(testDataValid2)-1);

	reader.GetKVTree(tree2);
	
	TASSERT(tree2.Get("Header1.Variable1") == "Value1", "ZIniReader failed to store [Header1]:Variable1 correctly!");
	TASSERT(tree2.Get("Header1.Variable2") == "Value2", "ZIniReader failed to store [Header1]:Variable2 correctly!");
	TASSERT(tree2.Get("Header1.Variable3") == "Value3", "ZIniReader failed to store [Header1]:Variable3 correctly!");

	return ZTEST_SUCCESS;
}