13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program Test Executor
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * ------------------------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Batch result to XML export.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "xeTestLogParser.hpp"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "xeTestResultParser.hpp"
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "xeXMLWriter.hpp"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "xeTestLogWriter.hpp"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deFilePath.hpp"
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deString.h"
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deStringUtil.hpp"
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deCommandLine.hpp"
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <vector>
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <string>
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <map>
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <cstdio>
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <fstream>
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <iostream>
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::vector;
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::string;
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::map;
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const char*	CASELIST_STYLESHEET		= "caselist.xsl";
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const char*	TESTCASE_STYLESHEET		= "testlog.xsl";
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum OutputMode
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	OUTPUTMODE_SEPARATE = 0,	//!< Separate
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	OUTPUTMODE_SINGLE,
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	OUTPUTMODE_LAST
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace opt
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
583c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDE_DECLARE_COMMAND_LINE_OPT(OutMode, OutputMode);
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid registerOptions (de::cmdline::Parser& parser)
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using de::cmdline::Option;
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using de::cmdline::NamedValue;
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const NamedValue<OutputMode> s_modes[] =
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "single",		OUTPUTMODE_SINGLE	},
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "separate",	OUTPUTMODE_SEPARATE	}
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	parser << Option<OutMode>("m", "mode", "Output mode", s_modes, "single");
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // opt
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct CommandLine
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	CommandLine (void)
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: outputMode(OUTPUTMODE_SINGLE)
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string		batchResultFile;
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string		outputPath;
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	OutputMode		outputMode;
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool parseCommandLine (CommandLine& cmdLine, int argc, const char* const* argv)
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::cmdline::Parser			parser;
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::cmdline::CommandLine	opts;
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	opt::registerOptions(parser);
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!parser.parse(argc-1, argv+1, &opts, std::cerr) ||
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		opts.getArgs().size() != 2)
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		printf("%s: [options] [testlog] [destination path]\n", argv[0]);
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		parser.help(std::cout);
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	cmdLine.outputMode		= opts.getOption<opt::OutMode>();
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	cmdLine.batchResultFile	= opts.getArgs()[0];
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	cmdLine.outputPath		= opts.getArgs()[1];
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return true;
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void parseBatchResult (xe::TestLogParser& parser, const char* filename)
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ifstream	in			(filename, std::ios_base::binary);
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint8			buf[2048];
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (;;)
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		in.read((char*)&buf[0], sizeof(buf));
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int numRead = (int)in.gcount();
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (numRead > 0)
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			parser.parse(&buf[0], numRead);
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (numRead < (int)sizeof(buf))
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Export to single file
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct BatchResultTotals
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BatchResultTotals (void)
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0;i < xe::TESTSTATUSCODE_LAST; i++)
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			countByCode[i] = 0;
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int countByCode[xe::TESTSTATUSCODE_LAST];
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ResultToSingleXmlLogHandler : public xe::TestLogHandler
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ResultToSingleXmlLogHandler (xe::xml::Writer& writer, BatchResultTotals& totals)
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: m_writer	(writer)
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_totals	(totals)
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void setSessionInfo (const xe::SessionInfo&)
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	xe::TestCaseResultPtr startTestCaseResult (const char* casePath)
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return xe::TestCaseResultPtr(new xe::TestCaseResultData(casePath));
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void testCaseResultUpdated (const xe::TestCaseResultPtr&)
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void testCaseResultComplete (const xe::TestCaseResultPtr& resultData)
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		xe::TestCaseResult result;
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		xe::parseTestCaseResultFromData(&m_resultParser, &result, *resultData.get());
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Write result.
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		xe::writeTestResult(result, m_writer);
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Record total
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		XE_CHECK(de::inBounds<int>(result.statusCode, 0, xe::TESTSTATUSCODE_LAST));
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_totals.countByCode[result.statusCode] += 1;
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	xe::xml::Writer&		m_writer;
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BatchResultTotals&		m_totals;
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	xe::TestResultParser	m_resultParser;
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void writeTotals (xe::xml::Writer& writer, const BatchResultTotals& totals)
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using xe::xml::Writer;
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int totalCases = 0;
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	writer << Writer::BeginElement("ResultTotals");
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int code = 0; code < xe::TESTSTATUSCODE_LAST; code++)
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		writer << Writer::Attribute(xe::getTestStatusCodeName((xe::TestStatusCode)code), de::toString(totals.countByCode[code]).c_str());
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		totalCases += totals.countByCode[code];
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	writer << Writer::Attribute("All", de::toString(totalCases).c_str())
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   << Writer::EndElement;
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void batchResultToSingleXmlFile (const char* batchResultFilename, const char* dstFileName)
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::ofstream				out			(dstFileName, std::ios_base::binary);
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	xe::xml::Writer				writer		(out);
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	BatchResultTotals			totals;
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ResultToSingleXmlLogHandler	handler		(writer, totals);
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	xe::TestLogParser			parser		(&handler);
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	XE_CHECK(out.good());
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	out << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< "<?xml-stylesheet href=\"" << TESTCASE_STYLESHEET << "\" type=\"text/xsl\"?>\n";
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	writer << xe::xml::Writer::BeginElement("BatchResult")
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   << xe::xml::Writer::Attribute("FileName", de::FilePath(batchResultFilename).getBaseName());
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Parse and write individual cases
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	parseBatchResult(parser, batchResultFilename);
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Write ResultTotals
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	writeTotals(writer, totals);
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	writer << xe::xml::Writer::EndElement;
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	out << "\n";
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Export to separate files
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ResultToXmlFilesLogHandler : public xe::TestLogHandler
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ResultToXmlFilesLogHandler (vector<xe::TestCaseResultHeader>& resultHeaders, const char* dstPath)
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: m_resultHeaders	(resultHeaders)
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_dstPath			(dstPath)
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void setSessionInfo (const xe::SessionInfo&)
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	xe::TestCaseResultPtr startTestCaseResult (const char* casePath)
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return xe::TestCaseResultPtr(new xe::TestCaseResultData(casePath));
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void testCaseResultUpdated (const xe::TestCaseResultPtr&)
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void testCaseResultComplete (const xe::TestCaseResultPtr& resultData)
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		xe::TestCaseResult result;
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		xe::parseTestCaseResultFromData(&m_resultParser, &result, *resultData.get());
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Write result.
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			de::FilePath	casePath	= de::FilePath::join(m_dstPath, (result.casePath + ".xml").c_str());
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			std::ofstream	out			(casePath.getPath(), std::ofstream::binary|std::ofstream::trunc);
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			xe::xml::Writer	xmlWriter	(out);
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!out.good())
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				throw xe::Error(string("Failed to open ") + casePath.getPath());
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			out << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< "<?xml-stylesheet href=\"" << TESTCASE_STYLESHEET << "\" type=\"text/xsl\"?>\n";
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			xe::writeTestResult(result, xmlWriter);
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			out << "\n";
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_resultHeaders.push_back(xe::TestCaseResultHeader(result));
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<xe::TestCaseResultHeader>&	m_resultHeaders;
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string							m_dstPath;
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	xe::TestResultParser				m_resultParser;
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytypedef std::map<const xe::TestCase*, const xe::TestCaseResultHeader*> ShortTestResultMap;
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void writeTestCaseListNode (const xe::TestNode* testNode, const ShortTestResultMap& resultMap, xe::xml::Writer& dst)
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using xe::xml::Writer;
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool	isGroup		= testNode->getNodeType() == xe::TESTNODETYPE_GROUP;
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	string	fullPath;
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	testNode->getFullPath(fullPath);
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isGroup)
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const xe::TestGroup* group = static_cast<const xe::TestGroup*>(testNode);
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		dst << Writer::BeginElement("TestGroup")
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< Writer::Attribute("Name", testNode->getName());
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int childNdx = 0; childNdx < group->getNumChildren(); childNdx++)
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			writeTestCaseListNode(group->getChild(childNdx), resultMap, dst);
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		dst << Writer::EndElement;
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(testNode->getNodeType() == xe::TESTNODETYPE_TEST_CASE);
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const xe::TestCase*					testCase	= static_cast<const xe::TestCase*>(testNode);
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ShortTestResultMap::const_iterator	resultPos	= resultMap.find(testCase);
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const xe::TestCaseResultHeader*		result		= resultPos != resultMap.end() ? resultPos->second : DE_NULL;
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(result);
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		dst << Writer::BeginElement("TestCase")
3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< Writer::Attribute("Name", testNode->getName())
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< Writer::Attribute("Type", xe::getTestCaseTypeName(result->caseType))
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< Writer::Attribute("StatusCode", xe::getTestStatusCodeName(result->statusCode))
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< Writer::Attribute("StatusDetails", result->statusDetails.c_str())
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< Writer::EndElement;
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void writeTestCaseList (const xe::TestRoot& root, const ShortTestResultMap& resultMap, xe::xml::Writer& dst)
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using xe::xml::Writer;
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst << Writer::BeginElement("TestRoot");
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int childNdx = 0; childNdx < root.getNumChildren(); childNdx++)
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		writeTestCaseListNode(root.getChild(childNdx), resultMap, dst);
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst << Writer::EndElement;
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void batchResultToSeparateXmlFiles (const char* batchResultFilename, const char* dstPath)
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	xe::TestRoot						testRoot;
3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<xe::TestCaseResultHeader>	shortResults;
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ShortTestResultMap					resultMap;
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Initialize destination directory.
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!de::FilePath(dstPath).exists())
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::createDirectoryAndParents(dstPath);
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		XE_CHECK_MSG(de::FilePath(dstPath).getType() == de::FilePath::TYPE_DIRECTORY, "Destination is not directory");
3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Parse batch result and write out test cases.
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ResultToXmlFilesLogHandler	handler		(shortResults, dstPath);
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		xe::TestLogParser			parser		(&handler);
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		parseBatchResult(parser, batchResultFilename);
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Build case hierarchy & short result map.
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		xe::TestHierarchyBuilder hierarchyBuilder(&testRoot);
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (vector<xe::TestCaseResultHeader>::const_iterator result = shortResults.begin(); result != shortResults.end(); result++)
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			xe::TestCase* testCase = hierarchyBuilder.createCase(result->casePath.c_str(), result->caseType);
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			resultMap.insert(std::make_pair(testCase, &(*result)));
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Create caselist.
3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		de::FilePath	indexPath	= de::FilePath::join(dstPath, "caselist.xml");
3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		std::ofstream	out			(indexPath.getPath(), std::ofstream::binary|std::ofstream::trunc);
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		xe::xml::Writer	xmlWriter	(out);
3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		XE_CHECK_MSG(out.good(), "Failed to open caselist.xml");
3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		out << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< "<?xml-stylesheet href=\"" << CASELIST_STYLESHEET << "\" type=\"text/xsl\"?>\n";
3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		writeTestCaseList(testRoot, resultMap, xmlWriter);
3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		out << "\n";
3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint main (int argc, const char* const* argv)
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	try
3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		CommandLine cmdLine;
3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!parseCommandLine(cmdLine, argc, argv))
3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return -1;
3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (cmdLine.outputMode == OUTPUTMODE_SINGLE)
3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			batchResultToSingleXmlFile(cmdLine.batchResultFile.c_str(), cmdLine.outputPath.c_str());
3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			batchResultToSeparateXmlFiles(cmdLine.batchResultFile.c_str(), cmdLine.outputPath.c_str());
3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	catch (const std::exception& e)
3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		printf("%s\n", e.what());
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return -1;
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return 0;
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
401