#include "ZUnitTest.hpp"

#include <ZUtil/ZXMLReader.hpp>

static const char* test_LoadSuccess();
static const char* test_LoadFailed();

ZUnitTest ZXMLReaderUnitTests[] =
{
	{ "ZXMLReader: Successful Load",	test_LoadSuccess },
	{ "ZXMLReader: Failed Load",		test_LoadFailed }
};

//Now declare the ZUnitTestBlock associated with this.
DECLARE_ZTESTBLOCK(ZXMLReader);

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

namespace ZXMLReaderTestData
{
	const char* testDataValid1 = "<?xml version=\"1.0\"?>"						LINE_TERMINATOR
								 "<lvl1node>"									LINE_TERMINATOR
								 "  <lvl2node>"									LINE_TERMINATOR
								 "    <lvl3node x=\"0\" y=\"1\" z=\"2\" />"		LINE_TERMINATOR
								 "    Level 2 Node Has Some of the Datas."		LINE_TERMINATOR
								 "  </lvl2node>"								LINE_TERMINATOR
								 "  Level 1 Node Has All the Datas."			LINE_TERMINATOR
								 "</lvl1node>"									LINE_TERMINATOR
																				LINE_TERMINATOR;
	
	const char* testDataValid2 = "<?xml version=\"1.0\"?>"							LINE_TERMINATOR
								 "<lvl1node>"										LINE_TERMINATOR
								 "  <lvl2node>"										LINE_TERMINATOR
								 "    <lvl3node x=\"0\" y=\"1\" z=\"2\" />"			LINE_TERMINATOR
								 "    <lvl3node x=\"2\" y=\"1\" z=\"0\" />"			LINE_TERMINATOR
								 "    Level 2 Node Has Some of the Datas."			LINE_TERMINATOR
								 "  </lvl2node>"									LINE_TERMINATOR
								 "  <tinylvl2node size=\"tiny\" />"					LINE_TERMINATOR
								 "  <largelvl2node size=\"large\" />"				LINE_TERMINATOR
								 "  Level 1 Node Has All the Datas."				LINE_TERMINATOR
								 "</lvl1node>"										LINE_TERMINATOR
								 "<secondrootnode>"									LINE_TERMINATOR
								 "  This is a second root node.  Use it wisely."	LINE_TERMINATOR
								 "</secondrootnode>"								LINE_TERMINATOR
																					LINE_TERMINATOR;

	// the 'invalid' tests are mostly designed to test custom error handling in the reader, not
	// stability of rapidxml
	const char* testDataInvalid1 =	"<lvl1node>"					LINE_TERMINATOR
									"  <lvl2node>"					LINE_TERMINATOR
									"  </lvl1node>"					LINE_TERMINATOR
									"</lvl2node>"					LINE_TERMINATOR
									"</lvl3node>"					LINE_TERMINATOR
																	LINE_TERMINATOR;

	const char* testDataInvalid2 =	"<lvl1node>><>"					LINE_TERMINATOR
									"</lvl1node>"					LINE_TERMINATOR
																	LINE_TERMINATOR;

	const char* testDataInvalid3 =	"<!-- This is a bad comment. ->"	LINE_TERMINATOR
									"<lvl1node>"						LINE_TERMINATOR
									"  Bad Comment.  Bad."				LINE_TERMINATOR
									"</lvl1node>"						LINE_TERMINATOR
																		LINE_TERMINATOR;
}

using namespace ZXMLReaderTestData;

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

static const char* test_LoadSuccess()
{
	ZString val;
	ZKVTree tree;

	ZXMLReader reader1;

	TASSERT(reader1.Read(testDataValid1, strlen(testDataValid1)), "ZXMLReader::Read returned 'false' on valid data set #1!");
	TASSERT(reader1.GetErrorString().Empty(), "ZXMLReader failed to load valid data set #1!");

	reader1.GetKVTree(tree);

	TASSERT(tree.Get("lvl1node") == "Level 1 Node Has All the Datas.", "ZXMLReader failed to store lvl1node correctly!");

	TASSERT(tree.Get("lvl1node.lvl2node") == "Level 2 Node Has Some of the Datas.", "ZXMLReader failed to store lvl2node correctly!");
	
	TASSERT(tree.Get("lvl1node.lvl2node.lvl3node") == "", "ZXMLReader failed to store lvl3node correctly!");
	TASSERT(tree.Get("lvl1node.lvl2node.lvl3node.x") == "0", "ZXMLReader failed to store lvl3node.x correctly!");
	TASSERT(tree.Get("lvl1node.lvl2node.lvl3node.y") == "1", "ZXMLReader failed to store lvl3node.y correctly!");
	TASSERT(tree.Get("lvl1node.lvl2node.lvl3node.z") == "2", "ZXMLReader failed to store lvl3node.z correctly!");

	ZXMLReader reader2;

	TASSERT(reader2.Read(testDataValid2, strlen(testDataValid2)), "ZXMLReader::Read returned 'false' on valid data set #2!");
	TASSERT(reader2.GetErrorString().Empty(), "ZXMLReader failed to load valid data set #2!");

	tree.Clear();
	reader2.GetKVTree(tree);
	
	TASSERT(tree.Get("lvl1node") == "Level 1 Node Has All the Datas.", "ZXMLReader failed to store lvl1node correctly!");

	TASSERT(tree.Get("lvl1node.lvl2node") == "Level 2 Node Has Some of the Datas.", "ZXMLReader failed to store lvl2node correctly!");
	
	TASSERT(tree.Get("lvl1node.lvl2node.lvl3node") == "", "ZXMLReader failed to store lvl3node correctly!");
	TASSERT(tree.Get("lvl1node.lvl2node.lvl3node.x") == "0", "ZXMLReader failed to store lvl3node.x correctly!");
	TASSERT(tree.Get("lvl1node.lvl2node.lvl3node.y") == "1", "ZXMLReader failed to store lvl3node.y correctly!");
	TASSERT(tree.Get("lvl1node.lvl2node.lvl3node.z") == "2", "ZXMLReader failed to store lvl3node.z correctly!");
	
	TASSERT(tree.Get("lvl1node.lvl2node.lvl3node[1]") == "", "ZXMLReader failed to store lvl3node[1] correctly!");
	TASSERT(tree.Get("lvl1node.lvl2node.lvl3node[1].x") == "2", "ZXMLReader failed to store lvl3node[1].x correctly!");
	TASSERT(tree.Get("lvl1node.lvl2node.lvl3node[1].y") == "1", "ZXMLReader failed to store lvl3node[1].y correctly!");
	TASSERT(tree.Get("lvl1node.lvl2node.lvl3node[1].z") == "0", "ZXMLReader failed to store lvl3node[1].z correctly!");

	TASSERT(tree.Get("lvl1node.tinylvl2node") == "", "ZXMLReader failed to store tinylvl2node correctly!");
	TASSERT(tree.Get("lvl1node.tinylvl2node.size") == "tiny", "ZXMLReader failed to store tinylvl2node.size correctly!");

	TASSERT(tree.Get("lvl1node.largelvl2node") == "", "ZXMLReader failed to store largelvl2node correctly!");
	TASSERT(tree.Get("lvl1node.largelvl2node.size") == "large", "ZXMLReader failed to store largelvl2node.size correctly!");

	TASSERT(tree.Get("secondrootnode") == "This is a second root node.  Use it wisely.", "ZXMLReader failed to store secondrootnode correctly!");

	return ZTEST_SUCCESS;
}

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

static const char* test_LoadFailed()
{
	ZXMLReader reader1;
	ZXMLReader reader2;
	ZXMLReader reader3;

	TASSERT(!reader1.Read(testDataValid1, strlen(testDataInvalid1)), "ZXMLReader returned 'true' on invalid data set #1!");
	TASSERT(!reader2.Read(testDataInvalid2, strlen(testDataInvalid2)), "ZXMLReader returned 'true' on invalid data set #2!");
	TASSERT(!reader3.Read(testDataInvalid3, strlen(testDataInvalid3)), "ZXMLReader returned 'true' on invalid data set #2!");

	TASSERT(!reader1.GetErrorString().Empty(), "ZXMLReader did not report error message for invalid data set #1!");
	TASSERT(!reader2.GetErrorString().Empty(), "ZXMLReader did not report error message for invalid data set #2!");
	TASSERT(!reader3.GetErrorString().Empty(), "ZXMLReader did not report error message for invalid data set #3!");

	return ZTEST_SUCCESS;
}