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