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
watchDogTimeoutFunc(qpWatchDog * watchDog,void * userPtr)37 static void watchDogTimeoutFunc (qpWatchDog* watchDog, void* userPtr)
38 {
39 DE_UNREF(watchDog);
40 static_cast<App*>(userPtr)->onWatchdogTimeout();
41 }
42
crashHandlerFunc(qpCrashHandler * crashHandler,void * userPtr)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 *//*--------------------------------------------------------------------*/
App(Platform & platform,Archive & archive,TestLog & log,const CommandLine & cmdLine)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 (!deSetRoundingMode(DE_ROUNDINGMODE_TO_NEAREST))
70 qpPrintf("WARNING: Failed to set floating-point rounding mode!\n");
71
72 try
73 {
74 // Initialize watchdog
75 if (cmdLine.isWatchDogEnabled())
76 TCU_CHECK(m_watchDog = qpWatchDog_create(watchDogTimeoutFunc, this, 300, 30));
77
78 // Initialize crash handler.
79 if (cmdLine.isCrashHandlingEnabled())
80 TCU_CHECK(m_crashHandler = qpCrashHandler_create(crashHandlerFunc, this));
81
82 // Create test context
83 m_testCtx = new TestContext(m_platform, archive, log, cmdLine, m_watchDog);
84
85 // Create test executor
86 m_testExecutor = new TestExecutor(*m_testCtx, cmdLine);
87 }
88 catch (const std::exception& e)
89 {
90 die("Failed to initialize dEQP: %s", e.what());
91 }
92 }
93
~App(void)94 App::~App (void)
95 {
96 delete m_testExecutor;
97 delete m_testCtx;
98
99 if (m_crashHandler)
100 qpCrashHandler_destroy(m_crashHandler);
101
102 if (m_watchDog)
103 qpWatchDog_destroy(m_watchDog);
104 }
105
106
107 /*--------------------------------------------------------------------*//*!
108 * \brief Step forward test execution
109 * \return true if application should call iterate() again and false
110 * if test execution session is complete.
111 *//*--------------------------------------------------------------------*/
iterate(void)112 bool App::iterate (void)
113 {
114 // Poll platform events
115 bool platformOk = m_platform.processEvents();
116
117 // Iterate a step.
118 bool testExecOk = false;
119 if (platformOk)
120 {
121 try
122 {
123 testExecOk = m_testExecutor->iterate();
124 }
125 catch (const std::exception& e)
126 {
127 die("%s", e.what());
128 }
129 }
130
131 if (!platformOk || !testExecOk)
132 {
133 if (!platformOk)
134 print("\nABORTED!\n");
135 else
136 print("\nDONE!\n");
137
138 const RunMode runMode = m_testCtx->getCommandLine().getRunMode();
139 if (runMode == RUNMODE_EXECUTE)
140 {
141 const TestRunResult& result = m_testExecutor->getResult();
142
143 // Report statistics.
144 print("\nTest run totals:\n");
145 print(" Passed: %d/%d (%.1f%%)\n", result.numPassed, result.numExecuted, (result.numExecuted > 0 ? (100.0f * result.numPassed / result.numExecuted) : 0.0f));
146 print(" Failed: %d/%d (%.1f%%)\n", result.numFailed, result.numExecuted, (result.numExecuted > 0 ? (100.0f * result.numFailed / result.numExecuted) : 0.0f));
147 print(" Not supported: %d/%d (%.1f%%)\n", result.numNotSupported, result.numExecuted, (result.numExecuted > 0 ? (100.0f * result.numNotSupported / result.numExecuted) : 0.0f));
148 print(" Warnings: %d/%d (%.1f%%)\n", result.numWarnings, result.numExecuted, (result.numExecuted > 0 ? (100.0f * result.numWarnings / result.numExecuted) : 0.0f));
149 if (!result.isComplete)
150 print("Test run was ABORTED!\n");
151 }
152 }
153
154 return platformOk && testExecOk;
155 }
156
157 /*--------------------------------------------------------------------*//*!
158 * \brief Get test run result
159 * \return Current test run result.
160 *//*--------------------------------------------------------------------*/
getResult(void) const161 const TestRunResult& App::getResult (void) const
162 {
163 return m_testExecutor->getResult();
164 }
165
onWatchdogTimeout(void)166 void App::onWatchdogTimeout (void)
167 {
168 if (!m_crashLock.tryLock() || m_crashed)
169 return; // In crash handler already.
170
171 m_crashed = true;
172
173 m_testCtx->getLog().terminateCase(QP_TEST_RESULT_TIMEOUT);
174 die("Watchdog timer timeout");
175 }
176
writeCrashToLog(void * userPtr,const char * infoString)177 static void writeCrashToLog (void* userPtr, const char* infoString)
178 {
179 TestLog* log = static_cast<TestLog*>(userPtr);
180 *log << TestLog::Message << infoString << TestLog::EndMessage;
181 }
182
writeCrashToConsole(void * userPtr,const char * infoString)183 static void writeCrashToConsole (void* userPtr, const char* infoString)
184 {
185 DE_UNREF(userPtr);
186 print("%s", infoString);
187 }
188
onCrash(void)189 void App::onCrash (void)
190 {
191 if (!m_crashLock.tryLock() || m_crashed)
192 return; // In crash handler already.
193
194 m_crashed = true;
195
196 bool isInCase = m_testExecutor ? m_testExecutor->isInTestCase() : false;
197
198 if (isInCase)
199 {
200 qpCrashHandler_writeCrashInfo(m_crashHandler, writeCrashToLog, &m_testCtx->getLog());
201 m_testCtx->getLog().terminateCase(QP_TEST_RESULT_CRASH);
202 }
203 else
204 qpCrashHandler_writeCrashInfo(m_crashHandler, writeCrashToConsole, DE_NULL);
205
206 die("Test program crashed");
207 }
208
209 } // tcu
210