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 Extract values by name from logs.
22 *//*--------------------------------------------------------------------*/
23
24 #include "xeTestLogParser.hpp"
25 #include "xeTestResultParser.hpp"
26 #include "deFilePath.hpp"
27 #include "deString.h"
28
29 #include <vector>
30 #include <string>
31 #include <cstdio>
32 #include <cstdlib>
33 #include <fstream>
34 #include <iostream>
35 #include <stdexcept>
36
37 using std::map;
38 using std::set;
39 using std::string;
40 using std::vector;
41
42 struct CommandLine
43 {
CommandLineCommandLine44 CommandLine(void) : statusCode(false)
45 {
46 }
47
48 string filename;
49 vector<string> tagNames;
50 bool statusCode;
51 };
52
53 typedef xe::ri::NumericValue Value;
54
55 struct CaseValues
56 {
57 string casePath;
58 xe::TestCaseType caseType;
59 xe::TestStatusCode statusCode;
60 string statusDetails;
61
62 vector<Value> values;
63 };
64
65 class BatchResultValues
66 {
67 public:
BatchResultValues(const vector<string> & tagNames)68 BatchResultValues(const vector<string> &tagNames) : m_tagNames(tagNames)
69 {
70 }
71
~BatchResultValues(void)72 ~BatchResultValues(void)
73 {
74 for (vector<CaseValues *>::iterator i = m_caseValues.begin(); i != m_caseValues.end(); ++i)
75 delete *i;
76 }
77
add(const CaseValues & result)78 void add(const CaseValues &result)
79 {
80 CaseValues *copy = new CaseValues(result);
81 try
82 {
83 m_caseValues.push_back(copy);
84 }
85 catch (...)
86 {
87 delete copy;
88 throw;
89 }
90 }
91
getTagNames(void) const92 const vector<string> &getTagNames(void) const
93 {
94 return m_tagNames;
95 }
96
size(void) const97 size_t size(void) const
98 {
99 return m_caseValues.size();
100 }
operator [](size_t ndx) const101 const CaseValues &operator[](size_t ndx) const
102 {
103 return *m_caseValues[ndx];
104 }
105
106 private:
107 vector<string> m_tagNames;
108 vector<CaseValues *> m_caseValues;
109 };
110
findValueByTag(const xe::ri::List & items,const string & tagName)111 static Value findValueByTag(const xe::ri::List &items, const string &tagName)
112 {
113 for (int ndx = 0; ndx < items.getNumItems(); ndx++)
114 {
115 const xe::ri::Item &item = items.getItem(ndx);
116
117 if (item.getType() == xe::ri::TYPE_SECTION)
118 {
119 const Value value = findValueByTag(static_cast<const xe::ri::Section &>(item).items, tagName);
120 if (value.getType() != Value::NUMVALTYPE_EMPTY)
121 return value;
122 }
123 else if (item.getType() == xe::ri::TYPE_NUMBER)
124 {
125 const xe::ri::Number &value = static_cast<const xe::ri::Number &>(item);
126 return value.value;
127 }
128 }
129
130 return Value();
131 }
132
133 class TagParser : public xe::TestLogHandler
134 {
135 public:
TagParser(BatchResultValues & result)136 TagParser(BatchResultValues &result) : m_result(result)
137 {
138 }
139
setSessionInfo(const xe::SessionInfo &)140 void setSessionInfo(const xe::SessionInfo &)
141 {
142 // Ignored.
143 }
144
startTestCaseResult(const char * casePath)145 xe::TestCaseResultPtr startTestCaseResult(const char *casePath)
146 {
147 return xe::TestCaseResultPtr(new xe::TestCaseResultData(casePath));
148 }
149
testCaseResultUpdated(const xe::TestCaseResultPtr &)150 void testCaseResultUpdated(const xe::TestCaseResultPtr &)
151 {
152 // Ignored.
153 }
154
testCaseResultComplete(const xe::TestCaseResultPtr & caseData)155 void testCaseResultComplete(const xe::TestCaseResultPtr &caseData)
156 {
157 const vector<string> &tagNames = m_result.getTagNames();
158 CaseValues tagResult;
159
160 tagResult.casePath = caseData->getTestCasePath();
161 tagResult.caseType = xe::TESTCASETYPE_SELF_VALIDATE;
162 tagResult.statusCode = caseData->getStatusCode();
163 tagResult.statusDetails = caseData->getStatusDetails();
164 tagResult.values.resize(tagNames.size());
165
166 if (caseData->getDataSize() > 0 && caseData->getStatusCode() == xe::TESTSTATUSCODE_LAST)
167 {
168 xe::TestCaseResult fullResult;
169 xe::TestResultParser::ParseResult parseResult;
170
171 m_testResultParser.init(&fullResult);
172 parseResult = m_testResultParser.parse(caseData->getData(), caseData->getDataSize());
173
174 if ((parseResult != xe::TestResultParser::PARSERESULT_ERROR &&
175 fullResult.statusCode != xe::TESTSTATUSCODE_LAST) ||
176 (tagResult.statusCode == xe::TESTSTATUSCODE_LAST && fullResult.statusCode != xe::TESTSTATUSCODE_LAST))
177 {
178 tagResult.statusCode = fullResult.statusCode;
179 tagResult.statusDetails = fullResult.statusDetails;
180 }
181 else if (tagResult.statusCode == xe::TESTSTATUSCODE_LAST)
182 {
183 DE_ASSERT(parseResult == xe::TestResultParser::PARSERESULT_ERROR);
184 tagResult.statusCode = xe::TESTSTATUSCODE_INTERNAL_ERROR;
185 tagResult.statusDetails = "Test case result parsing failed";
186 }
187
188 if (parseResult != xe::TestResultParser::PARSERESULT_ERROR)
189 {
190 for (int valNdx = 0; valNdx < (int)tagNames.size(); valNdx++)
191 tagResult.values[valNdx] = findValueByTag(fullResult.resultItems, tagNames[valNdx]);
192 }
193 }
194
195 m_result.add(tagResult);
196 }
197
198 private:
199 BatchResultValues &m_result;
200 xe::TestResultParser m_testResultParser;
201 };
202
readLogFile(BatchResultValues & batchResult,const char * filename)203 static void readLogFile(BatchResultValues &batchResult, const char *filename)
204 {
205 std::ifstream in(filename, std::ifstream::binary | std::ifstream::in);
206 TagParser resultHandler(batchResult);
207 xe::TestLogParser parser(&resultHandler);
208 uint8_t buf[1024];
209 int numRead = 0;
210
211 if (!in.good())
212 throw std::runtime_error(string("Failed to open '") + filename + "'");
213
214 for (;;)
215 {
216 in.read((char *)&buf[0], DE_LENGTH_OF_ARRAY(buf));
217 numRead = (int)in.gcount();
218
219 if (numRead <= 0)
220 break;
221
222 parser.parse(&buf[0], numRead);
223 }
224
225 in.close();
226 }
227
printTaggedValues(const CommandLine & cmdLine,std::ostream & dst)228 static void printTaggedValues(const CommandLine &cmdLine, std::ostream &dst)
229 {
230 BatchResultValues values(cmdLine.tagNames);
231
232 readLogFile(values, cmdLine.filename.c_str());
233
234 // Header
235 {
236 dst << "CasePath";
237 if (cmdLine.statusCode)
238 dst << ",StatusCode";
239
240 for (vector<string>::const_iterator tagName = values.getTagNames().begin();
241 tagName != values.getTagNames().end(); ++tagName)
242 dst << "," << *tagName;
243
244 dst << "\n";
245 }
246
247 for (int resultNdx = 0; resultNdx < (int)values.size(); resultNdx++)
248 {
249 const CaseValues &result = values[resultNdx];
250
251 dst << result.casePath;
252 if (cmdLine.statusCode)
253 dst << "," << xe::getTestStatusCodeName(result.statusCode);
254
255 for (vector<Value>::const_iterator value = result.values.begin(); value != result.values.end(); ++value)
256 dst << "," << *value;
257
258 dst << "\n";
259 }
260 }
261
printHelp(const char * binName)262 static void printHelp(const char *binName)
263 {
264 printf("%s: [filename] [name 1] [[name 2]...]\n", binName);
265 printf(" --statuscode Include status code as first entry.\n");
266 }
267
parseCommandLine(CommandLine & cmdLine,int argc,const char * const * argv)268 static bool parseCommandLine(CommandLine &cmdLine, int argc, const char *const *argv)
269 {
270 for (int argNdx = 1; argNdx < argc; argNdx++)
271 {
272 const char *arg = argv[argNdx];
273
274 if (deStringEqual(arg, "--statuscode"))
275 cmdLine.statusCode = true;
276 else if (!deStringBeginsWith(arg, "--"))
277 {
278 if (cmdLine.filename.empty())
279 cmdLine.filename = arg;
280 else
281 cmdLine.tagNames.push_back(arg);
282 }
283 else
284 return false;
285 }
286
287 if (cmdLine.filename.empty())
288 return false;
289
290 return true;
291 }
292
main(int argc,const char * const * argv)293 int main(int argc, const char *const *argv)
294 {
295 try
296 {
297 CommandLine cmdLine;
298
299 if (!parseCommandLine(cmdLine, argc, argv))
300 {
301 printHelp(argv[0]);
302 return -1;
303 }
304
305 printTaggedValues(cmdLine, std::cout);
306 }
307 catch (const std::exception &e)
308 {
309 printf("FATAL ERROR: %s\n", e.what());
310 return -1;
311 }
312
313 return 0;
314 }
315