/*-------------------------------------------------------------------------
 * drawElements Quality Program Test Executor
 * ------------------------------------------
 *
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief Command line test executor.
 *//*--------------------------------------------------------------------*/

#include "xeBatchExecutor.hpp"
#include "xeLocalTcpIpLink.hpp"
#include "xeTcpIpLink.hpp"
#include "xeTestCaseListParser.hpp"
#include "xeTestLogWriter.hpp"
#include "xeTestResultParser.hpp"

#include "deCommandLine.hpp"
#include "deDirectoryIterator.hpp"
#include "deStringUtil.hpp"

#include "deString.h"

#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <memory>
#include <sstream>
#include <string>
#include <vector>

#if (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_WIN32)
#	include <signal.h>
#endif

using std::vector;
using std::string;

namespace
{

// Command line arguments.
namespace opt
{

DE_DECLARE_COMMAND_LINE_OPT(StartServer,	string);
DE_DECLARE_COMMAND_LINE_OPT(Host,			string);
DE_DECLARE_COMMAND_LINE_OPT(Port,			int);
DE_DECLARE_COMMAND_LINE_OPT(CaseListDir,	string);
DE_DECLARE_COMMAND_LINE_OPT(TestSet,		vector<string>);
DE_DECLARE_COMMAND_LINE_OPT(ExcludeSet,		vector<string>);
DE_DECLARE_COMMAND_LINE_OPT(ContinueFile,	string);
DE_DECLARE_COMMAND_LINE_OPT(TestLogFile,	string);
DE_DECLARE_COMMAND_LINE_OPT(InfoLogFile,	string);
DE_DECLARE_COMMAND_LINE_OPT(Summary,		bool);

// TargetConfiguration
DE_DECLARE_COMMAND_LINE_OPT(BinaryName,		string);
DE_DECLARE_COMMAND_LINE_OPT(WorkingDir,		string);
DE_DECLARE_COMMAND_LINE_OPT(CmdLineArgs,	string);

void parseCommaSeparatedList (const char* src, vector<string>* dst)
{
	std::istringstream	inStr	(src);
	string			comp;

	while (std::getline(inStr, comp, ','))
		dst->push_back(comp);
}

void registerOptions (de::cmdline::Parser& parser)
{
	using de::cmdline::Option;
	using de::cmdline::NamedValue;

	static const NamedValue<bool> s_yesNo[] =
	{
		{ "yes",	true	},
		{ "no",		false	}
	};

	parser << Option<StartServer>	("s",		"start-server",	"Start local execserver. Path to the execserver binary.")
		   << Option<Host>			("c",		"connect",		"Connect to host. Address of the execserver.")
		   << Option<Port>			("p",		"port",			"TCP port of the execserver.",											"50016")
		   << Option<CaseListDir>	("cd",		"caselistdir",	"Path to the directory containing test case XML files.",				".")
		   << Option<TestSet>		("t",		"testset",		"Comma-separated list of include filters.",								parseCommaSeparatedList)
		   << Option<ExcludeSet>	("e",		"exclude",		"Comma-separated list of exclude filters.",								parseCommaSeparatedList, "")
		   << Option<ContinueFile>	(DE_NULL,	"continue",		"Continue execution by initializing results from existing test log.")
		   << Option<TestLogFile>	("o",		"out",			"Output test log filename.",											"TestLog.qpa")
		   << Option<InfoLogFile>	("i",		"info",			"Output info log filename.",											"InfoLog.txt")
		   << Option<Summary>		(DE_NULL,	"summary",		"Print summary after running tests.",									s_yesNo, "yes")
		   << Option<BinaryName>	("b",		"binaryname",	"Test binary path. Relative to working directory.",						"<Unused>")
		   << Option<WorkingDir>	("wd",		"workdir",		"Working directory for the test execution.",							".")
		   << Option<CmdLineArgs>	(DE_NULL,	"cmdline",		"Additional command line arguments for the test binary.",				"");
}

} // opt

enum RunMode
{
	RUNMODE_CONNECT,
	RUNMODE_START_SERVER
};

struct CommandLine
{
	CommandLine (void)
		: port		(0)
		, summary	(false)
	{
	}

	xe::TargetConfiguration	targetCfg;
	RunMode					runMode;
	string					serverBinOrAddress;
	int						port;
	string					caseListDir;
	vector<string>			testset;
	vector<string>			exclude;
	string					inFile;
	string					outFile;
	string					infoFile;
	bool					summary;
};

bool parseCommandLine (CommandLine& cmdLine, int argc, const char* const* argv)
{
	de::cmdline::Parser			parser;
	de::cmdline::CommandLine	opts;

	XE_CHECK(argc >= 1);

	opt::registerOptions(parser);

	if (!parser.parse(argc-1, argv+1, &opts, std::cerr))
	{
		std::cout << argv[0] << " [options]\n";
		parser.help(std::cout);
		return false;
	}

	if (opts.hasOption<opt::StartServer>() && opts.hasOption<opt::Host>())
	{
		std::cout << "Invalid command line arguments. Both --start-server and --connect defined." << std::endl;
		return false;
	}
	else if (!opts.hasOption<opt::StartServer>() && !opts.hasOption<opt::Host>())
	{
		std::cout << "Invalid command line arguments. Must define either --start-server or --connect." << std::endl;
		return false;
	}

	if (!opts.hasOption<opt::TestSet>())
	{
		std::cout << "Invalid command line arguments. --testset not defined." << std::endl;
		return false;
	}

	if (opts.hasOption<opt::StartServer>())
	{
		cmdLine.runMode				= RUNMODE_START_SERVER;
		cmdLine.serverBinOrAddress	= opts.getOption<opt::StartServer>();
	}
	else
	{
		cmdLine.runMode				= RUNMODE_CONNECT;
		cmdLine.serverBinOrAddress	= opts.getOption<opt::Host>();
	}

	if (opts.hasOption<opt::ContinueFile>())
	{
		cmdLine.inFile = opts.getOption<opt::ContinueFile>();

		if (cmdLine.inFile.empty())
		{
			std::cout << "Invalid command line arguments. --continue argument is empty." << std::endl;
			return false;
		}
	}

	cmdLine.port					= opts.getOption<opt::Port>();
	cmdLine.caseListDir				= opts.getOption<opt::CaseListDir>();
	cmdLine.testset					= opts.getOption<opt::TestSet>();
	cmdLine.exclude					= opts.getOption<opt::ExcludeSet>();
	cmdLine.outFile					= opts.getOption<opt::TestLogFile>();
	cmdLine.infoFile				= opts.getOption<opt::InfoLogFile>();
	cmdLine.summary					= opts.getOption<opt::Summary>();
	cmdLine.targetCfg.binaryName	= opts.getOption<opt::BinaryName>();
	cmdLine.targetCfg.workingDir	= opts.getOption<opt::WorkingDir>();
	cmdLine.targetCfg.cmdLineArgs	= opts.getOption<opt::CmdLineArgs>();

	return true;
}

bool checkCasePathPatternMatch (const char* pattern, const char* casePath, bool isTestGroup)
{
	int ptrnPos = 0;
	int casePos = 0;

	for (;;)
	{
		char c = casePath[casePos];
		char p = pattern[ptrnPos];

		if (p == '*')
		{
			/* Recurse to rest of positions. */
			int next = casePos;
			for (;;)
			{
				if (checkCasePathPatternMatch(pattern+ptrnPos+1, casePath+next, isTestGroup))
					return DE_TRUE;

				if (casePath[next] == 0)
					return DE_FALSE; /* No match found. */
				else
					next += 1;
			}
			DE_ASSERT(DE_FALSE);
		}
		else if (c == 0 && p == 0)
			return true;
		else if (c == 0)
		{
			/* Incomplete match is ok for test groups. */
			return isTestGroup;
		}
		else if (c != p)
			return false;

		casePos += 1;
		ptrnPos += 1;
	}

	DE_ASSERT(false);
	return false;
}

void readCaseList (xe::TestGroup* root, const char* filename)
{
	xe::TestCaseListParser	caseListParser;
	std::ifstream			in				(filename, std::ios_base::binary);
	deUint8					buf[1024];

	XE_CHECK(in.good());

	caseListParser.init(root);

	for (;;)
	{
		in.read((char*)&buf[0], sizeof(buf));
		int numRead = (int)in.gcount();

		if (numRead > 0)
			caseListParser.parse(&buf[0], numRead);

		if (numRead < (int)sizeof(buf))
			break; // EOF
	}
}

void readCaseLists (xe::TestRoot& root, const char* caseListDir)
{
	int						testCaseListCount	= 0;
	de::DirectoryIterator	iter				(caseListDir);

	for (; iter.hasItem(); iter.next())
	{
		de::FilePath item = iter.getItem();

		if (item.getType() == de::FilePath::TYPE_FILE)
		{
			string baseName = item.getBaseName();
			if (baseName.find("-cases.xml") == baseName.length()-10)
			{
				string		packageName	= baseName.substr(0, baseName.length()-10);
				xe::TestGroup*	package		= root.createGroup(packageName.c_str(), "");

				readCaseList(package, item.getPath());
				testCaseListCount++;
			}
		}
	}

	if (testCaseListCount == 0)
		throw xe::Error("Couldn't find test case lists from test case list directory: '" + string(caseListDir)  + "'");
}

void addMatchingCases (const xe::TestGroup& group, xe::TestSet& testSet, const char* filter)
{
	for (int childNdx = 0; childNdx < group.getNumChildren(); childNdx++)
	{
		const xe::TestNode* child		= group.getChild(childNdx);
		const bool			isGroup		= child->getNodeType() == xe::TESTNODETYPE_GROUP;
		const string	 	fullPath	= child->getFullPath();

		if (checkCasePathPatternMatch(filter, fullPath.c_str(), isGroup))
		{
			if (isGroup)
			{
				// Recurse into group.
				addMatchingCases(static_cast<const xe::TestGroup&>(*child), testSet, filter);
			}
			else
			{
				DE_ASSERT(child->getNodeType() == xe::TESTNODETYPE_TEST_CASE);
				testSet.add(child);
			}
		}
	}
}

void removeMatchingCases (const xe::TestGroup& group, xe::TestSet& testSet, const char* filter)
{
	for (int childNdx = 0; childNdx < group.getNumChildren(); childNdx++)
	{
		const xe::TestNode* child		= group.getChild(childNdx);
		const bool			isGroup		= child->getNodeType() == xe::TESTNODETYPE_GROUP;
		const string		fullPath	= child->getFullPath();

		if (checkCasePathPatternMatch(filter, fullPath.c_str(), isGroup))
		{
			if (isGroup)
			{
				// Recurse into group.
				removeMatchingCases(static_cast<const xe::TestGroup&>(*child), testSet, filter);
			}
			else
			{
				DE_ASSERT(child->getNodeType() == xe::TESTNODETYPE_TEST_CASE);
				testSet.remove(child);
			}
		}
	}
}

class BatchResultHandler : public xe::TestLogHandler
{
public:
	BatchResultHandler (xe::BatchResult* batchResult)
		: m_batchResult(batchResult)
	{
	}

	void setSessionInfo (const xe::SessionInfo& sessionInfo)
	{
		m_batchResult->getSessionInfo() = sessionInfo;
	}

	xe::TestCaseResultPtr startTestCaseResult (const char* casePath)
	{
		// \todo [2012-11-01 pyry] What to do with duplicate results?
		if (m_batchResult->hasTestCaseResult(casePath))
			return m_batchResult->getTestCaseResult(casePath);
		else
			return m_batchResult->createTestCaseResult(casePath);
	}

	void testCaseResultUpdated (const xe::TestCaseResultPtr&)
	{
	}

	void testCaseResultComplete (const xe::TestCaseResultPtr&)
	{
	}

private:
	xe::BatchResult* m_batchResult;
};

void readLogFile (xe::BatchResult* batchResult, const char* filename)
{
	std::ifstream		in		(filename, std::ifstream::binary|std::ifstream::in);
	BatchResultHandler	handler	(batchResult);
	xe::TestLogParser	parser	(&handler);
	deUint8				buf		[1024];
	int					numRead	= 0;

	for (;;)
	{
		in.read((char*)&buf[0], DE_LENGTH_OF_ARRAY(buf));
		numRead = (int)in.gcount();

		if (numRead <= 0)
			break;

		parser.parse(&buf[0], numRead);
	}

	in.close();
}

void printBatchResultSummary (const xe::TestNode* root, const xe::TestSet& testSet, const xe::BatchResult& batchResult)
{
	int countByStatusCode[xe::TESTSTATUSCODE_LAST];
	std::fill(&countByStatusCode[0], &countByStatusCode[0]+DE_LENGTH_OF_ARRAY(countByStatusCode), 0);

	for (xe::ConstTestNodeIterator iter = xe::ConstTestNodeIterator::begin(root); iter != xe::ConstTestNodeIterator::end(root); ++iter)
	{
		const xe::TestNode* node = *iter;
		if (node->getNodeType() == xe::TESTNODETYPE_TEST_CASE && testSet.hasNode(node))
		{
			const xe::TestCase*				testCase		= static_cast<const xe::TestCase*>(node);
			string							fullPath;
			xe::TestStatusCode				statusCode		= xe::TESTSTATUSCODE_PENDING;
			testCase->getFullPath(fullPath);

			// Parse result data if such exists.
			if (batchResult.hasTestCaseResult(fullPath.c_str()))
			{
				xe::ConstTestCaseResultPtr	resultData	= batchResult.getTestCaseResult(fullPath.c_str());
				xe::TestCaseResult			result;
				xe::TestResultParser		parser;

				xe::parseTestCaseResultFromData(&parser, &result, *resultData.get());
				statusCode = result.statusCode;
			}

			countByStatusCode[statusCode] += 1;
		}
	}

	printf("\nTest run summary:\n");
	int totalCases = 0;
	for (int code = 0; code < xe::TESTSTATUSCODE_LAST; code++)
	{
		if (countByStatusCode[code] > 0)
			printf("  %20s: %5d\n", xe::getTestStatusCodeName((xe::TestStatusCode)code), countByStatusCode[code]);

		totalCases += countByStatusCode[code];
	}
	printf("  %20s: %5d\n", "Total", totalCases);
}

void writeInfoLog (const xe::InfoLog& log, const char* filename)
{
	std::ofstream out(filename, std::ios_base::binary);
	XE_CHECK(out.good());
	out.write((const char*)log.getBytes(), log.getSize());
	out.close();
}

xe::CommLink* createCommLink (const CommandLine& cmdLine)
{
	if (cmdLine.runMode == RUNMODE_START_SERVER)
	{
		xe::LocalTcpIpLink* link = new xe::LocalTcpIpLink();
		try
		{
			link->start(cmdLine.serverBinOrAddress.c_str(), DE_NULL, cmdLine.port);
			return link;
		}
		catch (...)
		{
			delete link;
			throw;
		}
	}
	else if (cmdLine.runMode == RUNMODE_CONNECT)
	{
		de::SocketAddress address;

		address.setFamily(DE_SOCKETFAMILY_INET4);
		address.setProtocol(DE_SOCKETPROTOCOL_TCP);
		address.setHost(cmdLine.serverBinOrAddress.c_str());
		address.setPort(cmdLine.port);

		xe::TcpIpLink* link = new xe::TcpIpLink();
		try
		{
			std::string error;

			link->connect(address);
			return link;
		}
		catch (const std::exception& error)
		{
			delete link;
			throw xe::Error("Failed to connect to ExecServer at: " + cmdLine.serverBinOrAddress + ":" + de::toString(cmdLine.port) + ", " + error.what());
		}
		catch (...)
		{
			delete link;
			throw;
		}
	}
	else
	{
		DE_ASSERT(false);
		return DE_NULL;
	}
}

#if (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_ANDROID)

static xe::BatchExecutor* s_executor = DE_NULL;

void signalHandler (int, siginfo_t*, void*)
{
	if (s_executor)
		s_executor->cancel();
}

void setupSignalHandler (xe::BatchExecutor* executor)
{
	s_executor = executor;
	struct sigaction sa;

	sa.sa_sigaction = signalHandler;
	sa.sa_flags = SA_SIGINFO | SA_RESTART;
	sigfillset(&sa.sa_mask);

	sigaction(SIGINT, &sa, DE_NULL);
}

void resetSignalHandler (void)
{
	struct sigaction sa;

	sa.sa_handler = SIG_DFL;
	sa.sa_flags = SA_RESTART;
	sigfillset(&sa.sa_mask);

	sigaction(SIGINT, &sa, DE_NULL);
	s_executor = DE_NULL;
}

#elif (DE_OS == DE_OS_WIN32)

static xe::BatchExecutor* s_executor = DE_NULL;

void signalHandler (int)
{
	if (s_executor)
		s_executor->cancel();
}

void setupSignalHandler (xe::BatchExecutor* executor)
{
	s_executor = executor;
	signal(SIGINT, signalHandler);
}

void resetSignalHandler (void)
{
	signal(SIGINT, SIG_DFL);
	s_executor = DE_NULL;
}

#else

void setupSignalHandler (xe::BatchExecutor*)
{
}

void resetSignalHandler (void)
{
}

#endif

void runExecutor (const CommandLine& cmdLine)
{
	xe::TestRoot root;

	// Read case list definitions.
	readCaseLists(root, cmdLine.caseListDir.c_str());

	// Build test set.
	xe::TestSet testSet;

	// Build test set.
	for (vector<string>::const_iterator filterIter = cmdLine.testset.begin(); filterIter != cmdLine.testset.end(); ++filterIter)
		addMatchingCases(root, testSet, filterIter->c_str());

	if (testSet.empty())
		throw xe::Error("None of the test case lists contains tests matching any of the test sets.");

	// Remove excluded cases.
	for (vector<string>::const_iterator filterIter = cmdLine.exclude.begin(); filterIter != cmdLine.exclude.end(); ++filterIter)
		removeMatchingCases(root, testSet, filterIter->c_str());

	// Initialize batch result.
	xe::BatchResult	batchResult;
	xe::InfoLog		infoLog;

	// Read existing results from input file (if supplied).
	if (!cmdLine.inFile.empty())
		readLogFile(&batchResult, cmdLine.inFile.c_str());

	// Initialize commLink.
	std::auto_ptr<xe::CommLink> commLink(createCommLink(cmdLine));

	xe::BatchExecutor executor(cmdLine.targetCfg, commLink.get(), &root, testSet, &batchResult, &infoLog);

	try
	{
		setupSignalHandler(&executor);
		executor.run();
		resetSignalHandler();
	}
	catch (...)
	{
		resetSignalHandler();

		if (!cmdLine.outFile.empty())
		{
			xe::writeBatchResultToFile(batchResult, cmdLine.outFile.c_str());
			printf("Test log written to %s\n", cmdLine.outFile.c_str());
		}

		if (!cmdLine.infoFile.empty())
		{
			writeInfoLog(infoLog, cmdLine.infoFile.c_str());
			printf("Info log written to %s\n", cmdLine.infoFile.c_str());
		}

		if (cmdLine.summary)
			printBatchResultSummary(&root, testSet, batchResult);

		throw;
	}

	if (!cmdLine.outFile.empty())
	{
		xe::writeBatchResultToFile(batchResult, cmdLine.outFile.c_str());
		printf("Test log written to %s\n", cmdLine.outFile.c_str());
	}

	if (!cmdLine.infoFile.empty())
	{
		writeInfoLog(infoLog, cmdLine.infoFile.c_str());
		printf("Info log written to %s\n", cmdLine.infoFile.c_str());
	}

	if (cmdLine.summary)
		printBatchResultSummary(&root, testSet, batchResult);

	{
		string err;

		if (commLink->getState(err) == xe::COMMLINKSTATE_ERROR)
			throw xe::Error(err);
	}
}

} // anonymous

int main (int argc, const char* const* argv)
{
	CommandLine cmdLine;

	if (!parseCommandLine(cmdLine, argc, argv))
		return -1;

	try
	{
		runExecutor(cmdLine);
	}
	catch (const std::exception& e)
	{
		printf("%s\n", e.what());
		return -1;
	}

	return 0;
}
