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 34 namespace tcu 35 { 36 37 static void watchDogTimeoutFunc (qpWatchDog* watchDog, void* userPtr) 38 { 39 DE_UNREF(watchDog); 40 static_cast<App*>(userPtr)->onWatchdogTimeout(); 41 } 42 43 static 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 *//*--------------------------------------------------------------------*/ 58 App::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 97 App::~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 *//*--------------------------------------------------------------------*/ 115 bool 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 *//*--------------------------------------------------------------------*/ 164 const TestRunResult& App::getResult (void) const 165 { 166 return m_testExecutor->getResult(); 167 } 168 169 void 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 180 static void writeCrashToLog (void* userPtr, const char* infoString) 181 { 182 TestLog* log = static_cast<TestLog*>(userPtr); 183 *log << TestLog::Message << infoString << TestLog::EndMessage; 184 } 185 186 static void writeCrashToConsole (void* userPtr, const char* infoString) 187 { 188 DE_UNREF(userPtr); 189 print("%s", infoString); 190 } 191 192 void 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