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
27using std::string;
28using std::vector;
29using std::map;
30
31namespace xe
32{
33
34TestLogParser::TestLogParser (TestLogHandler* handler)
35	: m_handler		(handler)
36	, m_inSession	(false)
37{
38}
39
40TestLogParser::~TestLogParser (void)
41{
42}
43
44void TestLogParser::reset (void)
45{
46	m_containerParser.clear();
47	m_currentCaseData.clear();
48	m_sessionInfo	= SessionInfo();
49	m_inSession		= false;
50}
51
52void 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