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