1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program Tester Core
3 * ----------------------------------------
5 * Copyright 2014 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief Render target info.
22 *//*--------------------------------------------------------------------*/
25 #include "tcuPlatform.hpp"
26 #include "tcuTestContext.hpp"
27 #include "tcuTestSessionExecutor.hpp"
28 #include "tcuTestHierarchyUtil.hpp"
29 #include "tcuCommandLine.hpp"
30 #include "tcuTestLog.hpp"
33 #include "qpDebugOut.h"
44 /*--------------------------------------------------------------------*//*!
45 * Writes all packages found stdout without any
46 * separations. Recommended to be used with a single package
47 * only. It's possible to use test selectors for limiting the export
48 * to one package in a multipackage binary.
49 *//*--------------------------------------------------------------------*/
50 static void writeCaselistsToStdout (TestPackageRoot& root, TestContext& testCtx)
52 DefaultHierarchyInflater inflater (testCtx);
53 de::MovePtr<const CaseListFilter> caseListFilter (testCtx.getCommandLine().createCaseListFilter(testCtx.getArchive()));
54 TestHierarchyIterator iter (root, inflater, *caseListFilter);
56 while (iter.getState() != TestHierarchyIterator::STATE_FINISHED)
60 while (iter.getNode()->getNodeType() != NODETYPE_PACKAGE)
62 if (iter.getState() == TestHierarchyIterator::STATE_ENTER_NODE)
63 std::cout << (isTestNodeTypeExecutable(iter.getNode()->getNodeType()) ? "TEST" : "GROUP") << ": " << iter.getNodePath() << "\n";
67 DE_ASSERT(iter.getState() == TestHierarchyIterator::STATE_LEAVE_NODE &&
68 iter.getNode()->getNodeType() == NODETYPE_PACKAGE);
73 /*--------------------------------------------------------------------*//*!
74 * \brief Construct test application
76 * If a fatal error occurs during initialization constructor will call
77 * die() with debug information.
79 * \param platform Reference to platform implementation.
80 *//*--------------------------------------------------------------------*/
81 App::App (Platform& platform, Archive& archive, TestLog& log, const CommandLine& cmdLine)
82 : m_platform (platform)
83 , m_watchDog (DE_NULL)
84 , m_crashHandler (DE_NULL)
87 , m_testRoot (DE_NULL)
88 , m_testExecutor (DE_NULL)
90 print("dEQP Core %s (0x%08x) starting..\n", qpGetReleaseName(), qpGetReleaseId());
91 print(" target implementation = '%s'\n", qpGetTargetName());
93 if (!deSetRoundingMode(DE_ROUNDINGMODE_TO_NEAREST_EVEN))
94 qpPrintf("WARNING: Failed to set floating-point rounding mode!\n");
98 const RunMode runMode = cmdLine.getRunMode();
100 // Initialize watchdog
101 if (cmdLine.isWatchDogEnabled())
102 TCU_CHECK_INTERNAL(m_watchDog = qpWatchDog_create(onWatchdogTimeout, this, WATCHDOG_TOTAL_TIME_LIMIT_SECS, WATCHDOG_INTERVAL_TIME_LIMIT_SECS));
104 // Initialize crash handler.
105 if (cmdLine.isCrashHandlingEnabled())
106 TCU_CHECK_INTERNAL(m_crashHandler = qpCrashHandler_create(onCrash, this));
108 // Create test context
109 m_testCtx = new TestContext(m_platform, archive, log, cmdLine, m_watchDog);
111 // Create root from registry
112 m_testRoot = new TestPackageRoot(*m_testCtx, TestPackageRegistry::getSingleton());
114 // \note No executor is created if runmode is not EXECUTE
115 if (runMode == RUNMODE_EXECUTE)
116 m_testExecutor = new TestSessionExecutor(*m_testRoot, *m_testCtx);
117 else if (runMode == RUNMODE_DUMP_STDOUT_CASELIST)
118 writeCaselistsToStdout(*m_testRoot, *m_testCtx);
119 else if (runMode == RUNMODE_DUMP_XML_CASELIST)
120 writeXmlCaselistsToFiles(*m_testRoot, *m_testCtx, cmdLine);
121 else if (runMode == RUNMODE_DUMP_TEXT_CASELIST)
122 writeTxtCaselistsToFiles(*m_testRoot, *m_testCtx, cmdLine);
126 catch (const std::exception& e)
129 die("Failed to initialize dEQP: %s", e.what());
138 void App::cleanup (void)
140 delete m_testExecutor;
145 qpCrashHandler_destroy(m_crashHandler);
148 qpWatchDog_destroy(m_watchDog);
151 /*--------------------------------------------------------------------*//*!
152 * \brief Step forward test execution
153 * \return true if application should call iterate() again and false
154 * if test execution session is complete.
155 *//*--------------------------------------------------------------------*/
156 bool App::iterate (void)
160 DE_ASSERT(m_testCtx->getCommandLine().getRunMode() != RUNMODE_EXECUTE);
164 // Poll platform events
165 const bool platformOk = m_platform.processEvents();
168 bool testExecOk = false;
173 testExecOk = m_testExecutor->iterate();
175 catch (const std::exception& e)
181 if (!platformOk || !testExecOk)
184 print("\nABORTED!\n");
188 const RunMode runMode = m_testCtx->getCommandLine().getRunMode();
189 if (runMode == RUNMODE_EXECUTE)
191 const TestRunStatus& result = m_testExecutor->getStatus();
193 // Report statistics.
194 print("\nTest run totals:\n");
195 print(" Passed: %d/%d (%.1f%%)\n", result.numPassed, result.numExecuted, (result.numExecuted > 0 ? (100.0f * (float)result.numPassed / (float)result.numExecuted) : 0.0f));
196 print(" Failed: %d/%d (%.1f%%)\n", result.numFailed, result.numExecuted, (result.numExecuted > 0 ? (100.0f * (float)result.numFailed / (float)result.numExecuted) : 0.0f));
197 print(" Not supported: %d/%d (%.1f%%)\n", result.numNotSupported, result.numExecuted, (result.numExecuted > 0 ? (100.0f * (float)result.numNotSupported / (float)result.numExecuted) : 0.0f));
198 print(" Warnings: %d/%d (%.1f%%)\n", result.numWarnings, result.numExecuted, (result.numExecuted > 0 ? (100.0f * (float)result.numWarnings / (float)result.numExecuted) : 0.0f));
199 if (!result.isComplete)
200 print("Test run was ABORTED!\n");
204 return platformOk && testExecOk;
207 const TestRunStatus& App::getResult (void) const
209 return m_testExecutor->getStatus();
212 void App::onWatchdogTimeout (qpWatchDog* watchDog, void* userPtr, qpTimeoutReason reason)
215 static_cast<App*>(userPtr)->onWatchdogTimeout(reason);
218 void App::onCrash (qpCrashHandler* crashHandler, void* userPtr)
220 DE_UNREF(crashHandler);
221 static_cast<App*>(userPtr)->onCrash();
224 void App::onWatchdogTimeout (qpTimeoutReason reason)
226 if (!m_crashLock.tryLock() || m_crashed)
227 return; // In crash handler already.
231 m_testCtx->getLog().terminateCase(QP_TEST_RESULT_TIMEOUT);
232 die("Watchdog timer timeout for %s", (reason == QP_TIMEOUT_REASON_INTERVAL_LIMIT ? "touch interval" : "total time"));
235 static void writeCrashToLog (void* userPtr, const char* infoString)
237 // \note THIS IS CALLED BY SIGNAL HANDLER! CALLING MALLOC/FREE IS NOT ALLOWED!
238 TestLog* log = static_cast<TestLog*>(userPtr);
239 log->writeMessage(infoString);
242 static void writeCrashToConsole (void* userPtr, const char* infoString)
244 // \note THIS IS CALLED BY SIGNAL HANDLER! CALLING MALLOC/FREE IS NOT ALLOWED!
249 void App::onCrash (void)
251 // \note THIS IS CALLED BY SIGNAL HANDLER! CALLING MALLOC/FREE IS NOT ALLOWED!
253 if (!m_crashLock.tryLock() || m_crashed)
254 return; // In crash handler already.
258 bool isInCase = m_testExecutor ? m_testExecutor->isInTestCase() : false;
262 qpCrashHandler_writeCrashInfo(m_crashHandler, writeCrashToLog, &m_testCtx->getLog());
263 m_testCtx->getLog().terminateCase(QP_TEST_RESULT_CRASH);
266 qpCrashHandler_writeCrashInfo(m_crashHandler, writeCrashToConsole, DE_NULL);
268 die("Test program crashed");