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 Test log parser.
22 *//*--------------------------------------------------------------------*/
23
24 #include "xeTestLogParser.hpp"
25 #include "deString.h"
26
27 using std::map;
28 using std::string;
29 using std::vector;
30
31 namespace xe
32 {
33
TestLogParser(TestLogHandler * handler)34 TestLogParser::TestLogParser(TestLogHandler *handler) : m_handler(handler), m_inSession(false)
35 {
36 }
37
~TestLogParser(void)38 TestLogParser::~TestLogParser(void)
39 {
40 }
41
reset(void)42 void TestLogParser::reset(void)
43 {
44 m_containerParser.clear();
45 m_currentCaseData.clear();
46 m_sessionInfo = SessionInfo();
47 m_inSession = false;
48 }
49
parse(const uint8_t * bytes,size_t numBytes)50 void TestLogParser::parse(const uint8_t *bytes, size_t numBytes)
51 {
52 m_containerParser.feed(bytes, numBytes);
53
54 for (;;)
55 {
56 ContainerElement element = m_containerParser.getElement();
57
58 if (element == CONTAINERELEMENT_INCOMPLETE)
59 break;
60
61 switch (element)
62 {
63 case CONTAINERELEMENT_BEGIN_SESSION:
64 {
65 if (m_inSession)
66 throw Error("Unexpected #beginSession");
67
68 m_handler->setSessionInfo(m_sessionInfo);
69 m_inSession = true;
70 break;
71 }
72
73 case CONTAINERELEMENT_END_SESSION:
74 {
75 if (!m_inSession)
76 throw Error("Unexpected #endSession");
77
78 m_inSession = false;
79 break;
80 }
81
82 case CONTAINERELEMENT_SESSION_INFO:
83 {
84 if (m_inSession)
85 throw Error("Unexpected #sessionInfo");
86
87 const char *attribute = m_containerParser.getSessionInfoAttribute();
88 const char *value = m_containerParser.getSessionInfoValue();
89
90 if (deStringEqual(attribute, "releaseName"))
91 m_sessionInfo.releaseName = value;
92 else if (deStringEqual(attribute, "releaseId"))
93 m_sessionInfo.releaseId = value;
94 else if (deStringEqual(attribute, "targetName"))
95 m_sessionInfo.targetName = value;
96 else if (deStringEqual(attribute, "candyTargetName"))
97 m_sessionInfo.candyTargetName = value;
98 else if (deStringEqual(attribute, "configName"))
99 m_sessionInfo.configName = value;
100 else if (deStringEqual(attribute, "resultName"))
101 m_sessionInfo.resultName = value;
102 else if (deStringEqual(attribute, "timestamp"))
103 m_sessionInfo.timestamp = value;
104 else if (deStringEqual(attribute, "commandLineParameters"))
105 m_sessionInfo.qpaCommandLineParameters = value;
106
107 // \todo [2012-06-09 pyry] What to do with unknown/duplicate attributes? Currently just ignored.
108 break;
109 }
110
111 case CONTAINERELEMENT_BEGIN_TEST_CASE_RESULT:
112 {
113 if (!m_inSession)
114 throw Error("Unexpected #beginTestCaseResult");
115
116 const char *casePath = m_containerParser.getTestCasePath();
117 m_currentCaseData = m_handler->startTestCaseResult(casePath);
118
119 // Clear and set to running state.
120 m_currentCaseData->setDataSize(0);
121 m_currentCaseData->setTestResult(TESTSTATUSCODE_RUNNING, "Running");
122
123 m_handler->testCaseResultUpdated(m_currentCaseData);
124 break;
125 }
126
127 case CONTAINERELEMENT_END_TEST_CASE_RESULT:
128 if (m_currentCaseData)
129 {
130 // \todo [2012-06-16 pyry] Parse status code already here?
131 m_currentCaseData->setTestResult(TESTSTATUSCODE_LAST, "");
132 m_handler->testCaseResultComplete(m_currentCaseData);
133 }
134 m_currentCaseData.clear();
135 break;
136
137 case CONTAINERELEMENT_TERMINATE_TEST_CASE_RESULT:
138 if (m_currentCaseData)
139 {
140 TestStatusCode statusCode = TESTSTATUSCODE_CRASH;
141 const char *reason = m_containerParser.getTerminateReason();
142 try
143 {
144 statusCode = getTestStatusCode(reason);
145 }
146 catch (const xe::ParseError &)
147 {
148 // Could not map status code.
149 }
150 m_currentCaseData->setTestResult(statusCode, reason);
151 m_handler->testCaseResultComplete(m_currentCaseData);
152 }
153 m_currentCaseData.clear();
154 break;
155
156 case CONTAINERELEMENT_END_OF_STRING:
157 if (m_currentCaseData)
158 {
159 // Terminate current case.
160 m_currentCaseData->setTestResult(TESTSTATUSCODE_TERMINATED, "Unexpected end of string");
161 m_handler->testCaseResultComplete(m_currentCaseData);
162 }
163 m_currentCaseData.clear();
164 break;
165
166 case CONTAINERELEMENT_TEST_LOG_DATA:
167 if (m_currentCaseData)
168 {
169 int offset = m_currentCaseData->getDataSize();
170 int numDataBytes = m_containerParser.getDataSize();
171
172 m_currentCaseData->setDataSize(offset + numDataBytes);
173 m_containerParser.getData(m_currentCaseData->getData() + offset, numDataBytes, 0);
174
175 m_handler->testCaseResultUpdated(m_currentCaseData);
176 }
177 break;
178
179 default:
180 throw ContainerParseError("Unknown container element");
181 }
182
183 m_containerParser.advance();
184 }
185 }
186
187 } // namespace xe
188