1/*-------------------------------------------------------------------------
2 * drawElements Quality Program Test Executor
3 * ------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Batch result to JUnit report conversion tool.
22 *//*--------------------------------------------------------------------*/
23
24#include "xeTestLogParser.hpp"
25#include "xeTestResultParser.hpp"
26#include "xeXMLWriter.hpp"
27#include "deFilePath.hpp"
28#include "deString.h"
29#include "deStringUtil.hpp"
30
31#include <vector>
32#include <string>
33#include <map>
34#include <cstdio>
35#include <fstream>
36
37using std::vector;
38using std::string;
39using std::map;
40
41struct CommandLine
42{
43	CommandLine (void)
44	{
45	}
46
47	std::string		batchResultFile;
48	std::string		outputFile;
49};
50
51static void printHelp (const char* binName)
52{
53	printf("%s: [testlog] [output file]\n", binName);
54}
55
56static void parseCommandLine (CommandLine& cmdLine, int argc, const char* const* argv)
57{
58	if (argc != 3)
59		throw xe::Error("Expected input and output paths");
60
61	cmdLine.batchResultFile	= argv[argc-2];
62	cmdLine.outputFile		= argv[argc-1];
63}
64
65static void parseBatchResult (xe::TestLogParser& parser, const char* filename)
66{
67	std::ifstream	in			(filename, std::ios_base::binary);
68	deUint8			buf[2048];
69
70	for (;;)
71	{
72		in.read((char*)&buf[0], sizeof(buf));
73		int numRead = (int)in.gcount();
74
75		if (numRead > 0)
76			parser.parse(&buf[0], numRead);
77
78		if (numRead < (int)sizeof(buf))
79			break;
80	}
81}
82
83class ResultToJUnitHandler : public xe::TestLogHandler
84{
85public:
86	ResultToJUnitHandler (xe::xml::Writer& writer)
87		: m_writer(writer)
88	{
89	}
90
91	void setSessionInfo (const xe::SessionInfo&)
92	{
93	}
94
95	xe::TestCaseResultPtr startTestCaseResult (const char* casePath)
96	{
97		return xe::TestCaseResultPtr(new xe::TestCaseResultData(casePath));
98	}
99
100	void testCaseResultUpdated (const xe::TestCaseResultPtr&)
101	{
102	}
103
104	void testCaseResultComplete (const xe::TestCaseResultPtr& resultData)
105	{
106		using xe::xml::Writer;
107
108		xe::TestCaseResult result;
109
110		xe::parseTestCaseResultFromData(&m_resultParser, &result, *resultData.get());
111
112		// Split group and case names.
113		size_t			sepPos		= result.casePath.find_last_of('.');
114		std::string		caseName	= result.casePath.substr(sepPos+1);
115		std::string		groupName	= result.casePath.substr(0, sepPos);
116
117		// Write result.
118		m_writer << Writer::BeginElement("testcase")
119				 << Writer::Attribute("name", caseName)
120				 << Writer::Attribute("classname", groupName);
121
122		if (result.statusCode != xe::TESTSTATUSCODE_PASS)
123			m_writer << Writer::BeginElement("failure")
124					 << Writer::Attribute("type", xe::getTestStatusCodeName(result.statusCode))
125					 << result.statusDetails
126					 << Writer::EndElement;
127
128		m_writer << Writer::EndElement;
129	}
130
131private:
132	xe::xml::Writer&		m_writer;
133	xe::TestResultParser	m_resultParser;
134};
135
136static void batchResultToJUnitReport (const char* batchResultFilename, const char* dstFileName)
137{
138	std::ofstream				out			(dstFileName, std::ios_base::binary);
139	xe::xml::Writer				writer		(out);
140	ResultToJUnitHandler		handler		(writer);
141	xe::TestLogParser			parser		(&handler);
142
143	XE_CHECK(out.good());
144
145	out << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
146
147	writer << xe::xml::Writer::BeginElement("testsuites")
148		   << xe::xml::Writer::BeginElement("testsuite");
149
150	// Parse and write individual cases
151	parseBatchResult(parser, batchResultFilename);
152
153	writer << xe::xml::Writer::EndElement << xe::xml::Writer::EndElement;
154}
155
156int main (int argc, const char* const* argv)
157{
158	CommandLine cmdLine;
159	try
160	{
161		parseCommandLine(cmdLine, argc, argv);
162	}
163	catch (const std::exception&)
164	{
165		printHelp(argv[0]);
166		return -1;
167	}
168
169	try
170	{
171		batchResultToJUnitReport(cmdLine.batchResultFile.c_str(), cmdLine.outputFile.c_str());
172	}
173	catch (const std::exception& e)
174	{
175		printf("%s\n", e.what());
176		return -1;
177	}
178
179	return 0;
180}
181