xref: /aosp_15_r20/external/deqp/executor/tools/xeBatchResultToXml.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker  * drawElements Quality Program Test Executor
3*35238bceSAndroid Build Coastguard Worker  * ------------------------------------------
4*35238bceSAndroid Build Coastguard Worker  *
5*35238bceSAndroid Build Coastguard Worker  * Copyright 2014 The Android Open Source Project
6*35238bceSAndroid Build Coastguard Worker  *
7*35238bceSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
8*35238bceSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
9*35238bceSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
10*35238bceSAndroid Build Coastguard Worker  *
11*35238bceSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
12*35238bceSAndroid Build Coastguard Worker  *
13*35238bceSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
14*35238bceSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
15*35238bceSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*35238bceSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
17*35238bceSAndroid Build Coastguard Worker  * limitations under the License.
18*35238bceSAndroid Build Coastguard Worker  *
19*35238bceSAndroid Build Coastguard Worker  *//*!
20*35238bceSAndroid Build Coastguard Worker  * \file
21*35238bceSAndroid Build Coastguard Worker  * \brief Batch result to XML export.
22*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker 
24*35238bceSAndroid Build Coastguard Worker #include "xeTestLogParser.hpp"
25*35238bceSAndroid Build Coastguard Worker #include "xeTestResultParser.hpp"
26*35238bceSAndroid Build Coastguard Worker #include "xeXMLWriter.hpp"
27*35238bceSAndroid Build Coastguard Worker #include "xeTestLogWriter.hpp"
28*35238bceSAndroid Build Coastguard Worker #include "deFilePath.hpp"
29*35238bceSAndroid Build Coastguard Worker #include "deString.h"
30*35238bceSAndroid Build Coastguard Worker #include "deStringUtil.hpp"
31*35238bceSAndroid Build Coastguard Worker #include "deCommandLine.hpp"
32*35238bceSAndroid Build Coastguard Worker 
33*35238bceSAndroid Build Coastguard Worker #include <vector>
34*35238bceSAndroid Build Coastguard Worker #include <string>
35*35238bceSAndroid Build Coastguard Worker #include <map>
36*35238bceSAndroid Build Coastguard Worker #include <cstdio>
37*35238bceSAndroid Build Coastguard Worker #include <fstream>
38*35238bceSAndroid Build Coastguard Worker #include <iostream>
39*35238bceSAndroid Build Coastguard Worker 
40*35238bceSAndroid Build Coastguard Worker using std::map;
41*35238bceSAndroid Build Coastguard Worker using std::string;
42*35238bceSAndroid Build Coastguard Worker using std::vector;
43*35238bceSAndroid Build Coastguard Worker 
44*35238bceSAndroid Build Coastguard Worker static const char *CASELIST_STYLESHEET = "caselist.xsl";
45*35238bceSAndroid Build Coastguard Worker static const char *TESTCASE_STYLESHEET = "testlog.xsl";
46*35238bceSAndroid Build Coastguard Worker 
47*35238bceSAndroid Build Coastguard Worker enum OutputMode
48*35238bceSAndroid Build Coastguard Worker {
49*35238bceSAndroid Build Coastguard Worker     OUTPUTMODE_SEPARATE = 0, //!< Separate
50*35238bceSAndroid Build Coastguard Worker     OUTPUTMODE_SINGLE,
51*35238bceSAndroid Build Coastguard Worker 
52*35238bceSAndroid Build Coastguard Worker     OUTPUTMODE_LAST
53*35238bceSAndroid Build Coastguard Worker };
54*35238bceSAndroid Build Coastguard Worker 
55*35238bceSAndroid Build Coastguard Worker namespace opt
56*35238bceSAndroid Build Coastguard Worker {
57*35238bceSAndroid Build Coastguard Worker 
58*35238bceSAndroid Build Coastguard Worker DE_DECLARE_COMMAND_LINE_OPT(OutMode, OutputMode);
59*35238bceSAndroid Build Coastguard Worker 
registerOptions(de::cmdline::Parser & parser)60*35238bceSAndroid Build Coastguard Worker void registerOptions(de::cmdline::Parser &parser)
61*35238bceSAndroid Build Coastguard Worker {
62*35238bceSAndroid Build Coastguard Worker     using de::cmdline::NamedValue;
63*35238bceSAndroid Build Coastguard Worker     using de::cmdline::Option;
64*35238bceSAndroid Build Coastguard Worker 
65*35238bceSAndroid Build Coastguard Worker     static const NamedValue<OutputMode> s_modes[] = {{"single", OUTPUTMODE_SINGLE}, {"separate", OUTPUTMODE_SEPARATE}};
66*35238bceSAndroid Build Coastguard Worker 
67*35238bceSAndroid Build Coastguard Worker     parser << Option<OutMode>("m", "mode", "Output mode", s_modes, "single");
68*35238bceSAndroid Build Coastguard Worker }
69*35238bceSAndroid Build Coastguard Worker 
70*35238bceSAndroid Build Coastguard Worker } // namespace opt
71*35238bceSAndroid Build Coastguard Worker 
72*35238bceSAndroid Build Coastguard Worker struct CommandLine
73*35238bceSAndroid Build Coastguard Worker {
CommandLineCommandLine74*35238bceSAndroid Build Coastguard Worker     CommandLine(void) : outputMode(OUTPUTMODE_SINGLE)
75*35238bceSAndroid Build Coastguard Worker     {
76*35238bceSAndroid Build Coastguard Worker     }
77*35238bceSAndroid Build Coastguard Worker 
78*35238bceSAndroid Build Coastguard Worker     std::string batchResultFile;
79*35238bceSAndroid Build Coastguard Worker     std::string outputPath;
80*35238bceSAndroid Build Coastguard Worker     OutputMode outputMode;
81*35238bceSAndroid Build Coastguard Worker };
82*35238bceSAndroid Build Coastguard Worker 
parseCommandLine(CommandLine & cmdLine,int argc,const char * const * argv)83*35238bceSAndroid Build Coastguard Worker static bool parseCommandLine(CommandLine &cmdLine, int argc, const char *const *argv)
84*35238bceSAndroid Build Coastguard Worker {
85*35238bceSAndroid Build Coastguard Worker     de::cmdline::Parser parser;
86*35238bceSAndroid Build Coastguard Worker     de::cmdline::CommandLine opts;
87*35238bceSAndroid Build Coastguard Worker 
88*35238bceSAndroid Build Coastguard Worker     opt::registerOptions(parser);
89*35238bceSAndroid Build Coastguard Worker 
90*35238bceSAndroid Build Coastguard Worker     if (!parser.parse(argc - 1, argv + 1, &opts, std::cerr) || opts.getArgs().size() != 2)
91*35238bceSAndroid Build Coastguard Worker     {
92*35238bceSAndroid Build Coastguard Worker         printf("%s: [options] [testlog] [destination path]\n", argv[0]);
93*35238bceSAndroid Build Coastguard Worker         parser.help(std::cout);
94*35238bceSAndroid Build Coastguard Worker         return false;
95*35238bceSAndroid Build Coastguard Worker     }
96*35238bceSAndroid Build Coastguard Worker 
97*35238bceSAndroid Build Coastguard Worker     cmdLine.outputMode      = opts.getOption<opt::OutMode>();
98*35238bceSAndroid Build Coastguard Worker     cmdLine.batchResultFile = opts.getArgs()[0];
99*35238bceSAndroid Build Coastguard Worker     cmdLine.outputPath      = opts.getArgs()[1];
100*35238bceSAndroid Build Coastguard Worker 
101*35238bceSAndroid Build Coastguard Worker     return true;
102*35238bceSAndroid Build Coastguard Worker }
103*35238bceSAndroid Build Coastguard Worker 
parseBatchResult(xe::TestLogParser & parser,const char * filename)104*35238bceSAndroid Build Coastguard Worker static void parseBatchResult(xe::TestLogParser &parser, const char *filename)
105*35238bceSAndroid Build Coastguard Worker {
106*35238bceSAndroid Build Coastguard Worker     std::ifstream in(filename, std::ios_base::binary);
107*35238bceSAndroid Build Coastguard Worker     uint8_t buf[2048];
108*35238bceSAndroid Build Coastguard Worker 
109*35238bceSAndroid Build Coastguard Worker     for (;;)
110*35238bceSAndroid Build Coastguard Worker     {
111*35238bceSAndroid Build Coastguard Worker         in.read((char *)&buf[0], sizeof(buf));
112*35238bceSAndroid Build Coastguard Worker         int numRead = (int)in.gcount();
113*35238bceSAndroid Build Coastguard Worker 
114*35238bceSAndroid Build Coastguard Worker         if (numRead > 0)
115*35238bceSAndroid Build Coastguard Worker             parser.parse(&buf[0], numRead);
116*35238bceSAndroid Build Coastguard Worker 
117*35238bceSAndroid Build Coastguard Worker         if (numRead < (int)sizeof(buf))
118*35238bceSAndroid Build Coastguard Worker             break;
119*35238bceSAndroid Build Coastguard Worker     }
120*35238bceSAndroid Build Coastguard Worker }
121*35238bceSAndroid Build Coastguard Worker 
122*35238bceSAndroid Build Coastguard Worker // Export to single file
123*35238bceSAndroid Build Coastguard Worker 
124*35238bceSAndroid Build Coastguard Worker struct BatchResultTotals
125*35238bceSAndroid Build Coastguard Worker {
BatchResultTotalsBatchResultTotals126*35238bceSAndroid Build Coastguard Worker     BatchResultTotals(void)
127*35238bceSAndroid Build Coastguard Worker     {
128*35238bceSAndroid Build Coastguard Worker         for (int i = 0; i < xe::TESTSTATUSCODE_LAST; i++)
129*35238bceSAndroid Build Coastguard Worker             countByCode[i] = 0;
130*35238bceSAndroid Build Coastguard Worker     }
131*35238bceSAndroid Build Coastguard Worker 
132*35238bceSAndroid Build Coastguard Worker     int countByCode[xe::TESTSTATUSCODE_LAST];
133*35238bceSAndroid Build Coastguard Worker };
134*35238bceSAndroid Build Coastguard Worker 
135*35238bceSAndroid Build Coastguard Worker class ResultToSingleXmlLogHandler : public xe::TestLogHandler
136*35238bceSAndroid Build Coastguard Worker {
137*35238bceSAndroid Build Coastguard Worker public:
ResultToSingleXmlLogHandler(xe::xml::Writer & writer,BatchResultTotals & totals)138*35238bceSAndroid Build Coastguard Worker     ResultToSingleXmlLogHandler(xe::xml::Writer &writer, BatchResultTotals &totals) : m_writer(writer), m_totals(totals)
139*35238bceSAndroid Build Coastguard Worker     {
140*35238bceSAndroid Build Coastguard Worker     }
141*35238bceSAndroid Build Coastguard Worker 
setSessionInfo(const xe::SessionInfo &)142*35238bceSAndroid Build Coastguard Worker     void setSessionInfo(const xe::SessionInfo &)
143*35238bceSAndroid Build Coastguard Worker     {
144*35238bceSAndroid Build Coastguard Worker     }
145*35238bceSAndroid Build Coastguard Worker 
startTestCaseResult(const char * casePath)146*35238bceSAndroid Build Coastguard Worker     xe::TestCaseResultPtr startTestCaseResult(const char *casePath)
147*35238bceSAndroid Build Coastguard Worker     {
148*35238bceSAndroid Build Coastguard Worker         return xe::TestCaseResultPtr(new xe::TestCaseResultData(casePath));
149*35238bceSAndroid Build Coastguard Worker     }
150*35238bceSAndroid Build Coastguard Worker 
testCaseResultUpdated(const xe::TestCaseResultPtr &)151*35238bceSAndroid Build Coastguard Worker     void testCaseResultUpdated(const xe::TestCaseResultPtr &)
152*35238bceSAndroid Build Coastguard Worker     {
153*35238bceSAndroid Build Coastguard Worker     }
154*35238bceSAndroid Build Coastguard Worker 
testCaseResultComplete(const xe::TestCaseResultPtr & resultData)155*35238bceSAndroid Build Coastguard Worker     void testCaseResultComplete(const xe::TestCaseResultPtr &resultData)
156*35238bceSAndroid Build Coastguard Worker     {
157*35238bceSAndroid Build Coastguard Worker         xe::TestCaseResult result;
158*35238bceSAndroid Build Coastguard Worker 
159*35238bceSAndroid Build Coastguard Worker         xe::parseTestCaseResultFromData(&m_resultParser, &result, *resultData.get());
160*35238bceSAndroid Build Coastguard Worker 
161*35238bceSAndroid Build Coastguard Worker         // Write result.
162*35238bceSAndroid Build Coastguard Worker         xe::writeTestResult(result, m_writer);
163*35238bceSAndroid Build Coastguard Worker 
164*35238bceSAndroid Build Coastguard Worker         // Record total
165*35238bceSAndroid Build Coastguard Worker         XE_CHECK(de::inBounds<int>(result.statusCode, 0, xe::TESTSTATUSCODE_LAST));
166*35238bceSAndroid Build Coastguard Worker         m_totals.countByCode[result.statusCode] += 1;
167*35238bceSAndroid Build Coastguard Worker     }
168*35238bceSAndroid Build Coastguard Worker 
169*35238bceSAndroid Build Coastguard Worker private:
170*35238bceSAndroid Build Coastguard Worker     xe::xml::Writer &m_writer;
171*35238bceSAndroid Build Coastguard Worker     BatchResultTotals &m_totals;
172*35238bceSAndroid Build Coastguard Worker     xe::TestResultParser m_resultParser;
173*35238bceSAndroid Build Coastguard Worker };
174*35238bceSAndroid Build Coastguard Worker 
writeTotals(xe::xml::Writer & writer,const BatchResultTotals & totals)175*35238bceSAndroid Build Coastguard Worker static void writeTotals(xe::xml::Writer &writer, const BatchResultTotals &totals)
176*35238bceSAndroid Build Coastguard Worker {
177*35238bceSAndroid Build Coastguard Worker     using xe::xml::Writer;
178*35238bceSAndroid Build Coastguard Worker 
179*35238bceSAndroid Build Coastguard Worker     int totalCases = 0;
180*35238bceSAndroid Build Coastguard Worker 
181*35238bceSAndroid Build Coastguard Worker     writer << Writer::BeginElement("ResultTotals");
182*35238bceSAndroid Build Coastguard Worker 
183*35238bceSAndroid Build Coastguard Worker     for (int code = 0; code < xe::TESTSTATUSCODE_LAST; code++)
184*35238bceSAndroid Build Coastguard Worker     {
185*35238bceSAndroid Build Coastguard Worker         writer << Writer::Attribute(xe::getTestStatusCodeName((xe::TestStatusCode)code),
186*35238bceSAndroid Build Coastguard Worker                                     de::toString(totals.countByCode[code]).c_str());
187*35238bceSAndroid Build Coastguard Worker         totalCases += totals.countByCode[code];
188*35238bceSAndroid Build Coastguard Worker     }
189*35238bceSAndroid Build Coastguard Worker 
190*35238bceSAndroid Build Coastguard Worker     writer << Writer::Attribute("All", de::toString(totalCases).c_str()) << Writer::EndElement;
191*35238bceSAndroid Build Coastguard Worker }
192*35238bceSAndroid Build Coastguard Worker 
batchResultToSingleXmlFile(const char * batchResultFilename,const char * dstFileName)193*35238bceSAndroid Build Coastguard Worker static void batchResultToSingleXmlFile(const char *batchResultFilename, const char *dstFileName)
194*35238bceSAndroid Build Coastguard Worker {
195*35238bceSAndroid Build Coastguard Worker     std::ofstream out(dstFileName, std::ios_base::binary);
196*35238bceSAndroid Build Coastguard Worker     xe::xml::Writer writer(out);
197*35238bceSAndroid Build Coastguard Worker     BatchResultTotals totals;
198*35238bceSAndroid Build Coastguard Worker     ResultToSingleXmlLogHandler handler(writer, totals);
199*35238bceSAndroid Build Coastguard Worker     xe::TestLogParser parser(&handler);
200*35238bceSAndroid Build Coastguard Worker 
201*35238bceSAndroid Build Coastguard Worker     XE_CHECK(out.good());
202*35238bceSAndroid Build Coastguard Worker 
203*35238bceSAndroid Build Coastguard Worker     out << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
204*35238bceSAndroid Build Coastguard Worker         << "<?xml-stylesheet href=\"" << TESTCASE_STYLESHEET << "\" type=\"text/xsl\"?>\n";
205*35238bceSAndroid Build Coastguard Worker 
206*35238bceSAndroid Build Coastguard Worker     writer << xe::xml::Writer::BeginElement("BatchResult")
207*35238bceSAndroid Build Coastguard Worker            << xe::xml::Writer::Attribute("FileName", de::FilePath(batchResultFilename).getBaseName());
208*35238bceSAndroid Build Coastguard Worker 
209*35238bceSAndroid Build Coastguard Worker     // Parse and write individual cases
210*35238bceSAndroid Build Coastguard Worker     parseBatchResult(parser, batchResultFilename);
211*35238bceSAndroid Build Coastguard Worker 
212*35238bceSAndroid Build Coastguard Worker     // Write ResultTotals
213*35238bceSAndroid Build Coastguard Worker     writeTotals(writer, totals);
214*35238bceSAndroid Build Coastguard Worker 
215*35238bceSAndroid Build Coastguard Worker     writer << xe::xml::Writer::EndElement;
216*35238bceSAndroid Build Coastguard Worker     out << "\n";
217*35238bceSAndroid Build Coastguard Worker }
218*35238bceSAndroid Build Coastguard Worker 
219*35238bceSAndroid Build Coastguard Worker // Export to separate files
220*35238bceSAndroid Build Coastguard Worker 
221*35238bceSAndroid Build Coastguard Worker class ResultToXmlFilesLogHandler : public xe::TestLogHandler
222*35238bceSAndroid Build Coastguard Worker {
223*35238bceSAndroid Build Coastguard Worker public:
ResultToXmlFilesLogHandler(vector<xe::TestCaseResultHeader> & resultHeaders,const char * dstPath)224*35238bceSAndroid Build Coastguard Worker     ResultToXmlFilesLogHandler(vector<xe::TestCaseResultHeader> &resultHeaders, const char *dstPath)
225*35238bceSAndroid Build Coastguard Worker         : m_resultHeaders(resultHeaders)
226*35238bceSAndroid Build Coastguard Worker         , m_dstPath(dstPath)
227*35238bceSAndroid Build Coastguard Worker     {
228*35238bceSAndroid Build Coastguard Worker     }
229*35238bceSAndroid Build Coastguard Worker 
setSessionInfo(const xe::SessionInfo &)230*35238bceSAndroid Build Coastguard Worker     void setSessionInfo(const xe::SessionInfo &)
231*35238bceSAndroid Build Coastguard Worker     {
232*35238bceSAndroid Build Coastguard Worker     }
233*35238bceSAndroid Build Coastguard Worker 
startTestCaseResult(const char * casePath)234*35238bceSAndroid Build Coastguard Worker     xe::TestCaseResultPtr startTestCaseResult(const char *casePath)
235*35238bceSAndroid Build Coastguard Worker     {
236*35238bceSAndroid Build Coastguard Worker         return xe::TestCaseResultPtr(new xe::TestCaseResultData(casePath));
237*35238bceSAndroid Build Coastguard Worker     }
238*35238bceSAndroid Build Coastguard Worker 
testCaseResultUpdated(const xe::TestCaseResultPtr &)239*35238bceSAndroid Build Coastguard Worker     void testCaseResultUpdated(const xe::TestCaseResultPtr &)
240*35238bceSAndroid Build Coastguard Worker     {
241*35238bceSAndroid Build Coastguard Worker     }
242*35238bceSAndroid Build Coastguard Worker 
testCaseResultComplete(const xe::TestCaseResultPtr & resultData)243*35238bceSAndroid Build Coastguard Worker     void testCaseResultComplete(const xe::TestCaseResultPtr &resultData)
244*35238bceSAndroid Build Coastguard Worker     {
245*35238bceSAndroid Build Coastguard Worker         xe::TestCaseResult result;
246*35238bceSAndroid Build Coastguard Worker 
247*35238bceSAndroid Build Coastguard Worker         xe::parseTestCaseResultFromData(&m_resultParser, &result, *resultData.get());
248*35238bceSAndroid Build Coastguard Worker 
249*35238bceSAndroid Build Coastguard Worker         // Write result.
250*35238bceSAndroid Build Coastguard Worker         {
251*35238bceSAndroid Build Coastguard Worker             de::FilePath casePath = de::FilePath::join(m_dstPath, (result.casePath + ".xml").c_str());
252*35238bceSAndroid Build Coastguard Worker             std::ofstream out(casePath.getPath(), std::ofstream::binary | std::ofstream::trunc);
253*35238bceSAndroid Build Coastguard Worker             xe::xml::Writer xmlWriter(out);
254*35238bceSAndroid Build Coastguard Worker 
255*35238bceSAndroid Build Coastguard Worker             if (!out.good())
256*35238bceSAndroid Build Coastguard Worker                 throw xe::Error(string("Failed to open ") + casePath.getPath());
257*35238bceSAndroid Build Coastguard Worker 
258*35238bceSAndroid Build Coastguard Worker             out << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
259*35238bceSAndroid Build Coastguard Worker                 << "<?xml-stylesheet href=\"" << TESTCASE_STYLESHEET << "\" type=\"text/xsl\"?>\n";
260*35238bceSAndroid Build Coastguard Worker             xe::writeTestResult(result, xmlWriter);
261*35238bceSAndroid Build Coastguard Worker             out << "\n";
262*35238bceSAndroid Build Coastguard Worker         }
263*35238bceSAndroid Build Coastguard Worker 
264*35238bceSAndroid Build Coastguard Worker         m_resultHeaders.push_back(xe::TestCaseResultHeader(result));
265*35238bceSAndroid Build Coastguard Worker     }
266*35238bceSAndroid Build Coastguard Worker 
267*35238bceSAndroid Build Coastguard Worker private:
268*35238bceSAndroid Build Coastguard Worker     vector<xe::TestCaseResultHeader> &m_resultHeaders;
269*35238bceSAndroid Build Coastguard Worker     std::string m_dstPath;
270*35238bceSAndroid Build Coastguard Worker     xe::TestResultParser m_resultParser;
271*35238bceSAndroid Build Coastguard Worker };
272*35238bceSAndroid Build Coastguard Worker 
273*35238bceSAndroid Build Coastguard Worker typedef std::map<const xe::TestCase *, const xe::TestCaseResultHeader *> ShortTestResultMap;
274*35238bceSAndroid Build Coastguard Worker 
writeTestCaseListNode(const xe::TestNode * testNode,const ShortTestResultMap & resultMap,xe::xml::Writer & dst)275*35238bceSAndroid Build Coastguard Worker static void writeTestCaseListNode(const xe::TestNode *testNode, const ShortTestResultMap &resultMap,
276*35238bceSAndroid Build Coastguard Worker                                   xe::xml::Writer &dst)
277*35238bceSAndroid Build Coastguard Worker {
278*35238bceSAndroid Build Coastguard Worker     using xe::xml::Writer;
279*35238bceSAndroid Build Coastguard Worker 
280*35238bceSAndroid Build Coastguard Worker     bool isGroup = testNode->getNodeType() == xe::TESTNODETYPE_GROUP;
281*35238bceSAndroid Build Coastguard Worker     string fullPath;
282*35238bceSAndroid Build Coastguard Worker     testNode->getFullPath(fullPath);
283*35238bceSAndroid Build Coastguard Worker 
284*35238bceSAndroid Build Coastguard Worker     if (isGroup)
285*35238bceSAndroid Build Coastguard Worker     {
286*35238bceSAndroid Build Coastguard Worker         const xe::TestGroup *group = static_cast<const xe::TestGroup *>(testNode);
287*35238bceSAndroid Build Coastguard Worker 
288*35238bceSAndroid Build Coastguard Worker         dst << Writer::BeginElement("TestGroup") << Writer::Attribute("Name", testNode->getName());
289*35238bceSAndroid Build Coastguard Worker 
290*35238bceSAndroid Build Coastguard Worker         for (int childNdx = 0; childNdx < group->getNumChildren(); childNdx++)
291*35238bceSAndroid Build Coastguard Worker             writeTestCaseListNode(group->getChild(childNdx), resultMap, dst);
292*35238bceSAndroid Build Coastguard Worker 
293*35238bceSAndroid Build Coastguard Worker         dst << Writer::EndElement;
294*35238bceSAndroid Build Coastguard Worker     }
295*35238bceSAndroid Build Coastguard Worker     else
296*35238bceSAndroid Build Coastguard Worker     {
297*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(testNode->getNodeType() == xe::TESTNODETYPE_TEST_CASE);
298*35238bceSAndroid Build Coastguard Worker 
299*35238bceSAndroid Build Coastguard Worker         const xe::TestCase *testCase                 = static_cast<const xe::TestCase *>(testNode);
300*35238bceSAndroid Build Coastguard Worker         ShortTestResultMap::const_iterator resultPos = resultMap.find(testCase);
301*35238bceSAndroid Build Coastguard Worker         const xe::TestCaseResultHeader *result       = resultPos != resultMap.end() ? resultPos->second : DE_NULL;
302*35238bceSAndroid Build Coastguard Worker 
303*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(result);
304*35238bceSAndroid Build Coastguard Worker 
305*35238bceSAndroid Build Coastguard Worker         dst << Writer::BeginElement("TestCase") << Writer::Attribute("Name", testNode->getName())
306*35238bceSAndroid Build Coastguard Worker             << Writer::Attribute("Type", xe::getTestCaseTypeName(result->caseType))
307*35238bceSAndroid Build Coastguard Worker             << Writer::Attribute("StatusCode", xe::getTestStatusCodeName(result->statusCode))
308*35238bceSAndroid Build Coastguard Worker             << Writer::Attribute("StatusDetails", result->statusDetails.c_str()) << Writer::EndElement;
309*35238bceSAndroid Build Coastguard Worker     }
310*35238bceSAndroid Build Coastguard Worker }
311*35238bceSAndroid Build Coastguard Worker 
writeTestCaseList(const xe::TestRoot & root,const ShortTestResultMap & resultMap,xe::xml::Writer & dst)312*35238bceSAndroid Build Coastguard Worker static void writeTestCaseList(const xe::TestRoot &root, const ShortTestResultMap &resultMap, xe::xml::Writer &dst)
313*35238bceSAndroid Build Coastguard Worker {
314*35238bceSAndroid Build Coastguard Worker     using xe::xml::Writer;
315*35238bceSAndroid Build Coastguard Worker 
316*35238bceSAndroid Build Coastguard Worker     dst << Writer::BeginElement("TestRoot");
317*35238bceSAndroid Build Coastguard Worker 
318*35238bceSAndroid Build Coastguard Worker     for (int childNdx = 0; childNdx < root.getNumChildren(); childNdx++)
319*35238bceSAndroid Build Coastguard Worker         writeTestCaseListNode(root.getChild(childNdx), resultMap, dst);
320*35238bceSAndroid Build Coastguard Worker 
321*35238bceSAndroid Build Coastguard Worker     dst << Writer::EndElement;
322*35238bceSAndroid Build Coastguard Worker }
323*35238bceSAndroid Build Coastguard Worker 
batchResultToSeparateXmlFiles(const char * batchResultFilename,const char * dstPath)324*35238bceSAndroid Build Coastguard Worker static void batchResultToSeparateXmlFiles(const char *batchResultFilename, const char *dstPath)
325*35238bceSAndroid Build Coastguard Worker {
326*35238bceSAndroid Build Coastguard Worker     xe::TestRoot testRoot;
327*35238bceSAndroid Build Coastguard Worker     vector<xe::TestCaseResultHeader> shortResults;
328*35238bceSAndroid Build Coastguard Worker     ShortTestResultMap resultMap;
329*35238bceSAndroid Build Coastguard Worker 
330*35238bceSAndroid Build Coastguard Worker     // Initialize destination directory.
331*35238bceSAndroid Build Coastguard Worker     if (!de::FilePath(dstPath).exists())
332*35238bceSAndroid Build Coastguard Worker         de::createDirectoryAndParents(dstPath);
333*35238bceSAndroid Build Coastguard Worker     else
334*35238bceSAndroid Build Coastguard Worker         XE_CHECK_MSG(de::FilePath(dstPath).getType() == de::FilePath::TYPE_DIRECTORY, "Destination is not directory");
335*35238bceSAndroid Build Coastguard Worker 
336*35238bceSAndroid Build Coastguard Worker     // Parse batch result and write out test cases.
337*35238bceSAndroid Build Coastguard Worker     {
338*35238bceSAndroid Build Coastguard Worker         ResultToXmlFilesLogHandler handler(shortResults, dstPath);
339*35238bceSAndroid Build Coastguard Worker         xe::TestLogParser parser(&handler);
340*35238bceSAndroid Build Coastguard Worker 
341*35238bceSAndroid Build Coastguard Worker         parseBatchResult(parser, batchResultFilename);
342*35238bceSAndroid Build Coastguard Worker     }
343*35238bceSAndroid Build Coastguard Worker 
344*35238bceSAndroid Build Coastguard Worker     // Build case hierarchy & short result map.
345*35238bceSAndroid Build Coastguard Worker     {
346*35238bceSAndroid Build Coastguard Worker         xe::TestHierarchyBuilder hierarchyBuilder(&testRoot);
347*35238bceSAndroid Build Coastguard Worker 
348*35238bceSAndroid Build Coastguard Worker         for (vector<xe::TestCaseResultHeader>::const_iterator result = shortResults.begin();
349*35238bceSAndroid Build Coastguard Worker              result != shortResults.end(); result++)
350*35238bceSAndroid Build Coastguard Worker         {
351*35238bceSAndroid Build Coastguard Worker             xe::TestCase *testCase = hierarchyBuilder.createCase(result->casePath.c_str(), result->caseType);
352*35238bceSAndroid Build Coastguard Worker             resultMap.insert(std::make_pair(testCase, &(*result)));
353*35238bceSAndroid Build Coastguard Worker         }
354*35238bceSAndroid Build Coastguard Worker     }
355*35238bceSAndroid Build Coastguard Worker 
356*35238bceSAndroid Build Coastguard Worker     // Create caselist.
357*35238bceSAndroid Build Coastguard Worker     {
358*35238bceSAndroid Build Coastguard Worker         de::FilePath indexPath = de::FilePath::join(dstPath, "caselist.xml");
359*35238bceSAndroid Build Coastguard Worker         std::ofstream out(indexPath.getPath(), std::ofstream::binary | std::ofstream::trunc);
360*35238bceSAndroid Build Coastguard Worker         xe::xml::Writer xmlWriter(out);
361*35238bceSAndroid Build Coastguard Worker 
362*35238bceSAndroid Build Coastguard Worker         XE_CHECK_MSG(out.good(), "Failed to open caselist.xml");
363*35238bceSAndroid Build Coastguard Worker 
364*35238bceSAndroid Build Coastguard Worker         out << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
365*35238bceSAndroid Build Coastguard Worker             << "<?xml-stylesheet href=\"" << CASELIST_STYLESHEET << "\" type=\"text/xsl\"?>\n";
366*35238bceSAndroid Build Coastguard Worker         writeTestCaseList(testRoot, resultMap, xmlWriter);
367*35238bceSAndroid Build Coastguard Worker         out << "\n";
368*35238bceSAndroid Build Coastguard Worker     }
369*35238bceSAndroid Build Coastguard Worker }
370*35238bceSAndroid Build Coastguard Worker 
main(int argc,const char * const * argv)371*35238bceSAndroid Build Coastguard Worker int main(int argc, const char *const *argv)
372*35238bceSAndroid Build Coastguard Worker {
373*35238bceSAndroid Build Coastguard Worker     try
374*35238bceSAndroid Build Coastguard Worker     {
375*35238bceSAndroid Build Coastguard Worker         CommandLine cmdLine;
376*35238bceSAndroid Build Coastguard Worker         if (!parseCommandLine(cmdLine, argc, argv))
377*35238bceSAndroid Build Coastguard Worker             return -1;
378*35238bceSAndroid Build Coastguard Worker 
379*35238bceSAndroid Build Coastguard Worker         if (cmdLine.outputMode == OUTPUTMODE_SINGLE)
380*35238bceSAndroid Build Coastguard Worker             batchResultToSingleXmlFile(cmdLine.batchResultFile.c_str(), cmdLine.outputPath.c_str());
381*35238bceSAndroid Build Coastguard Worker         else
382*35238bceSAndroid Build Coastguard Worker             batchResultToSeparateXmlFiles(cmdLine.batchResultFile.c_str(), cmdLine.outputPath.c_str());
383*35238bceSAndroid Build Coastguard Worker     }
384*35238bceSAndroid Build Coastguard Worker     catch (const std::exception &e)
385*35238bceSAndroid Build Coastguard Worker     {
386*35238bceSAndroid Build Coastguard Worker         printf("%s\n", e.what());
387*35238bceSAndroid Build Coastguard Worker         return -1;
388*35238bceSAndroid Build Coastguard Worker     }
389*35238bceSAndroid Build Coastguard Worker 
390*35238bceSAndroid Build Coastguard Worker     return 0;
391*35238bceSAndroid Build Coastguard Worker }
392