tcuApp.cpp revision 3c827367444ee418f129b2c238299f49d3264554
1/*-------------------------------------------------------------------------
2 * drawElements Quality Program Tester Core
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 Render target info.
22 *//*--------------------------------------------------------------------*/
23
24#include "tcuApp.hpp"
25#include "tcuPlatform.hpp"
26#include "tcuTestContext.hpp"
27#include "tcuTestExecutor.hpp"
28#include "tcuCommandLine.hpp"
29#include "tcuTestLog.hpp"
30#include "qpInfo.h"
31#include "qpDebugOut.h"
32#include "deMath.h"
33
34namespace tcu
35{
36
37static void watchDogTimeoutFunc (qpWatchDog* watchDog, void* userPtr)
38{
39	DE_UNREF(watchDog);
40	static_cast<App*>(userPtr)->onWatchdogTimeout();
41}
42
43static void crashHandlerFunc (qpCrashHandler* crashHandler, void* userPtr)
44{
45	DE_UNREF(crashHandler);
46	static_cast<App*>(userPtr)->onCrash();
47}
48
49
50/*--------------------------------------------------------------------*//*!
51 * \brief Construct test application
52 *
53 * If a fatal error occurs during initialization constructor will call
54 * die() with debug information.
55 *
56 * \param platform Reference to platform implementation.
57 *//*--------------------------------------------------------------------*/
58App::App (Platform& platform, Archive& archive, TestLog& log, const CommandLine& cmdLine)
59	: m_platform		(platform)
60	, m_watchDog		(DE_NULL)
61	, m_crashHandler	(DE_NULL)
62	, m_crashed			(false)
63	, m_testCtx			(DE_NULL)
64	, m_testExecutor	(DE_NULL)
65{
66	print("dEQP Core %s (0x%08x) starting..\n", qpGetReleaseName(), qpGetReleaseId());
67	print("  target implementation = '%s'\n", qpGetTargetName());
68
69	if (!qpIsLicenseValid())
70		qpPrintf("WARNING: License has expired!\n");
71
72	if (!deSetRoundingMode(DE_ROUNDINGMODE_TO_NEAREST))
73		qpPrintf("WARNING: Failed to set floating-point rounding mode!\n");
74
75	try
76	{
77		// Initialize watchdog
78		if (cmdLine.isWatchDogEnabled())
79			TCU_CHECK(m_watchDog = qpWatchDog_create(watchDogTimeoutFunc, this, 300, 30));
80
81		// Initialize crash handler.
82		if (cmdLine.isCrashHandlingEnabled())
83			TCU_CHECK(m_crashHandler = qpCrashHandler_create(crashHandlerFunc, this));
84
85		// Create test context
86		m_testCtx = new TestContext(m_platform, archive, log, cmdLine, m_watchDog);
87
88		// Create test executor
89		m_testExecutor = new TestExecutor(*m_testCtx, cmdLine);
90	}
91	catch (const std::exception& e)
92	{
93		die("Failed to initialize dEQP: %s", e.what());
94	}
95}
96
97App::~App (void)
98{
99	delete m_testExecutor;
100	delete m_testCtx;
101
102	if (m_crashHandler)
103		qpCrashHandler_destroy(m_crashHandler);
104
105	if (m_watchDog)
106		qpWatchDog_destroy(m_watchDog);
107}
108
109
110/*--------------------------------------------------------------------*//*!
111 * \brief Step forward test execution
112 * \return true if application should call iterate() again and false
113 *         if test execution session is complete.
114 *//*--------------------------------------------------------------------*/
115bool App::iterate (void)
116{
117	// Poll platform events
118	bool platformOk = m_platform.processEvents();
119
120	// Iterate a step.
121	bool testExecOk = false;
122	if (platformOk)
123	{
124		try
125		{
126			testExecOk = m_testExecutor->iterate();
127		}
128		catch (const std::exception& e)
129		{
130			die("%s", e.what());
131		}
132	}
133
134	if (!platformOk || !testExecOk)
135	{
136		if (!platformOk)
137			print("\nABORTED!\n");
138		else
139			print("\nDONE!\n");
140
141		const RunMode runMode = m_testCtx->getCommandLine().getRunMode();
142		if (runMode == RUNMODE_EXECUTE)
143		{
144			const TestRunResult& result = m_testExecutor->getResult();
145
146			// Report statistics.
147			print("\nTest run totals:\n");
148			print("  Passed:        %d/%d (%.1f%%)\n", result.numPassed,		result.numExecuted, (result.numExecuted > 0 ? (100.0f * result.numPassed		/ result.numExecuted) : 0.0f));
149			print("  Failed:        %d/%d (%.1f%%)\n", result.numFailed,		result.numExecuted, (result.numExecuted > 0 ? (100.0f * result.numFailed		/ result.numExecuted) : 0.0f));
150			print("  Not supported: %d/%d (%.1f%%)\n", result.numNotSupported,	result.numExecuted, (result.numExecuted > 0 ? (100.0f * result.numNotSupported	/ result.numExecuted) : 0.0f));
151			print("  Warnings:      %d/%d (%.1f%%)\n", result.numWarnings,		result.numExecuted, (result.numExecuted > 0 ? (100.0f * result.numWarnings		/ result.numExecuted) : 0.0f));
152			if (!result.isComplete)
153				print("Test run was ABORTED!\n");
154		}
155	}
156
157	return platformOk && testExecOk;
158}
159
160/*--------------------------------------------------------------------*//*!
161 * \brief Get test run result
162 * \return Current test run result.
163 *//*--------------------------------------------------------------------*/
164const TestRunResult& App::getResult (void) const
165{
166	return m_testExecutor->getResult();
167}
168
169void App::onWatchdogTimeout (void)
170{
171	if (!m_crashLock.tryLock() || m_crashed)
172		return; // In crash handler already.
173
174	m_crashed = true;
175
176	m_testCtx->getLog().terminateCase(QP_TEST_RESULT_TIMEOUT);
177	die("Watchdog timer timeout");
178}
179
180static void writeCrashToLog (void* userPtr, const char* infoString)
181{
182	TestLog* log = static_cast<TestLog*>(userPtr);
183	*log << TestLog::Message << infoString << TestLog::EndMessage;
184}
185
186static void writeCrashToConsole (void* userPtr, const char* infoString)
187{
188	DE_UNREF(userPtr);
189	print("%s", infoString);
190}
191
192void App::onCrash (void)
193{
194	if (!m_crashLock.tryLock() || m_crashed)
195		return; // In crash handler already.
196
197	m_crashed = true;
198
199	bool isInCase = m_testExecutor ? m_testExecutor->isInTestCase() : false;
200
201	if (isInCase)
202	{
203		qpCrashHandler_writeCrashInfo(m_crashHandler, writeCrashToLog, &m_testCtx->getLog());
204		m_testCtx->getLog().terminateCase(QP_TEST_RESULT_CRASH);
205	}
206	else
207		qpCrashHandler_writeCrashInfo(m_crashHandler, writeCrashToConsole, DE_NULL);
208
209	die("Test program crashed");
210}
211
212} // tcu
213