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
37 using std::map;
38 using std::string;
39 using std::vector;
40
41 struct CommandLine
42 {
CommandLineCommandLine43 CommandLine(void)
44 {
45 }
46
47 std::string batchResultFile;
48 std::string outputFile;
49 };
50
printHelp(const char * binName)51 static void printHelp(const char *binName)
52 {
53 printf("%s: [testlog] [output file]\n", binName);
54 }
55
parseCommandLine(CommandLine & cmdLine,int argc,const char * const * argv)56 static 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
parseBatchResult(xe::TestLogParser & parser,const char * filename)65 static void parseBatchResult(xe::TestLogParser &parser, const char *filename)
66 {
67 std::ifstream in(filename, std::ios_base::binary);
68 uint8_t 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
83 class ResultToJUnitHandler : public xe::TestLogHandler
84 {
85 public:
ResultToJUnitHandler(xe::xml::Writer & writer)86 ResultToJUnitHandler(xe::xml::Writer &writer) : m_writer(writer)
87 {
88 }
89
setSessionInfo(const xe::SessionInfo &)90 void setSessionInfo(const xe::SessionInfo &)
91 {
92 }
93
startTestCaseResult(const char * casePath)94 xe::TestCaseResultPtr startTestCaseResult(const char *casePath)
95 {
96 return xe::TestCaseResultPtr(new xe::TestCaseResultData(casePath));
97 }
98
testCaseResultUpdated(const xe::TestCaseResultPtr &)99 void testCaseResultUpdated(const xe::TestCaseResultPtr &)
100 {
101 }
102
testCaseResultComplete(const xe::TestCaseResultPtr & resultData)103 void testCaseResultComplete(const xe::TestCaseResultPtr &resultData)
104 {
105 using xe::xml::Writer;
106
107 xe::TestCaseResult result;
108
109 xe::parseTestCaseResultFromData(&m_resultParser, &result, *resultData.get());
110
111 // Split group and case names.
112 size_t sepPos = result.casePath.find_last_of('.');
113 std::string caseName = result.casePath.substr(sepPos + 1);
114 std::string groupName = result.casePath.substr(0, sepPos);
115
116 // Write result.
117 m_writer << Writer::BeginElement("testcase") << Writer::Attribute("name", caseName)
118 << Writer::Attribute("classname", groupName);
119
120 if (result.statusCode != xe::TESTSTATUSCODE_PASS)
121 m_writer << Writer::BeginElement("failure")
122 << Writer::Attribute("type", xe::getTestStatusCodeName(result.statusCode)) << result.statusDetails
123 << Writer::EndElement;
124
125 m_writer << Writer::EndElement;
126 }
127
128 private:
129 xe::xml::Writer &m_writer;
130 xe::TestResultParser m_resultParser;
131 };
132
batchResultToJUnitReport(const char * batchResultFilename,const char * dstFileName)133 static void batchResultToJUnitReport(const char *batchResultFilename, const char *dstFileName)
134 {
135 std::ofstream out(dstFileName, std::ios_base::binary);
136 xe::xml::Writer writer(out);
137 ResultToJUnitHandler handler(writer);
138 xe::TestLogParser parser(&handler);
139
140 XE_CHECK(out.good());
141
142 out << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
143
144 writer << xe::xml::Writer::BeginElement("testsuites") << xe::xml::Writer::BeginElement("testsuite");
145
146 // Parse and write individual cases
147 parseBatchResult(parser, batchResultFilename);
148
149 writer << xe::xml::Writer::EndElement << xe::xml::Writer::EndElement;
150 }
151
main(int argc,const char * const * argv)152 int main(int argc, const char *const *argv)
153 {
154 CommandLine cmdLine;
155 try
156 {
157 parseCommandLine(cmdLine, argc, argv);
158 }
159 catch (const std::exception &)
160 {
161 printHelp(argv[0]);
162 return -1;
163 }
164
165 try
166 {
167 batchResultToJUnitReport(cmdLine.batchResultFile.c_str(), cmdLine.outputFile.c_str());
168 }
169 catch (const std::exception &e)
170 {
171 printf("%s\n", e.what());
172 return -1;
173 }
174
175 return 0;
176 }
177