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