Add dual-source blending tests
[platform/upstream/VK-GL-CTS.git] / framework / common / tcuApp.cpp
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
32 #include "qpInfo.h"
33 #include "qpDebugOut.h"
34
35 #include "deMath.h"
36
37 #include <iostream>
38
39 namespace tcu
40 {
41
42 using std::string;
43
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)
51 {
52         DefaultHierarchyInflater                        inflater                (testCtx);
53         de::MovePtr<const CaseListFilter>       caseListFilter  (testCtx.getCommandLine().createCaseListFilter(testCtx.getArchive()));
54         TestHierarchyIterator                           iter                    (root, inflater, *caseListFilter);
55
56         while (iter.getState() != TestHierarchyIterator::STATE_FINISHED)
57         {
58                 iter.next();
59
60                 while (iter.getNode()->getNodeType() != NODETYPE_PACKAGE)
61                 {
62                         if (iter.getState() == TestHierarchyIterator::STATE_ENTER_NODE)
63                                 std::cout << (isTestNodeTypeExecutable(iter.getNode()->getNodeType()) ? "TEST" : "GROUP") << ": " << iter.getNodePath() << "\n";
64                         iter.next();
65                 }
66
67                 DE_ASSERT(iter.getState() == TestHierarchyIterator::STATE_LEAVE_NODE &&
68                                   iter.getNode()->getNodeType() == NODETYPE_PACKAGE);
69                 iter.next();
70         }
71 }
72
73 /*--------------------------------------------------------------------*//*!
74  * \brief Construct test application
75  *
76  * If a fatal error occurs during initialization constructor will call
77  * die() with debug information.
78  *
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)
85         , m_crashed                     (false)
86         , m_testCtx                     (DE_NULL)
87         , m_testRoot            (DE_NULL)
88         , m_testExecutor        (DE_NULL)
89 {
90         print("dEQP Core %s (0x%08x) starting..\n", qpGetReleaseName(), qpGetReleaseId());
91         print("  target implementation = '%s'\n", qpGetTargetName());
92
93         if (!deSetRoundingMode(DE_ROUNDINGMODE_TO_NEAREST_EVEN))
94                 qpPrintf("WARNING: Failed to set floating-point rounding mode!\n");
95
96         try
97         {
98                 const RunMode   runMode = cmdLine.getRunMode();
99
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));
103
104                 // Initialize crash handler.
105                 if (cmdLine.isCrashHandlingEnabled())
106                         TCU_CHECK_INTERNAL(m_crashHandler = qpCrashHandler_create(onCrash, this));
107
108                 // Create test context
109                 m_testCtx = new TestContext(m_platform, archive, log, cmdLine, m_watchDog);
110
111                 // Create root from registry
112                 m_testRoot = new TestPackageRoot(*m_testCtx, TestPackageRegistry::getSingleton());
113
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);
123                 else
124                         DE_ASSERT(false);
125         }
126         catch (const std::exception& e)
127         {
128                 cleanup();
129                 die("Failed to initialize dEQP: %s", e.what());
130         }
131 }
132
133 App::~App (void)
134 {
135         cleanup();
136 }
137
138 void App::cleanup (void)
139 {
140         delete m_testExecutor;
141         delete m_testRoot;
142         delete m_testCtx;
143
144         if (m_crashHandler)
145                 qpCrashHandler_destroy(m_crashHandler);
146
147         if (m_watchDog)
148                 qpWatchDog_destroy(m_watchDog);
149 }
150
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)
157 {
158         if (!m_testExecutor)
159         {
160                 DE_ASSERT(m_testCtx->getCommandLine().getRunMode() != RUNMODE_EXECUTE);
161                 return false;
162         }
163
164         // Poll platform events
165         const bool platformOk = m_platform.processEvents();
166
167         // Iterate a step.
168         bool testExecOk = false;
169         if (platformOk)
170         {
171                 try
172                 {
173                         testExecOk = m_testExecutor->iterate();
174                 }
175                 catch (const std::exception& e)
176                 {
177                         die("%s", e.what());
178                 }
179         }
180
181         if (!platformOk || !testExecOk)
182         {
183                 if (!platformOk)
184                         print("\nABORTED!\n");
185                 else
186                         print("\nDONE!\n");
187
188                 const RunMode runMode = m_testCtx->getCommandLine().getRunMode();
189                 if (runMode == RUNMODE_EXECUTE)
190                 {
191                         const TestRunStatus& result = m_testExecutor->getStatus();
192
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");
201                 }
202         }
203
204         return platformOk && testExecOk;
205 }
206
207 const TestRunStatus& App::getResult (void) const
208 {
209         return m_testExecutor->getStatus();
210 }
211
212 void App::onWatchdogTimeout (qpWatchDog* watchDog, void* userPtr, qpTimeoutReason reason)
213 {
214         DE_UNREF(watchDog);
215         static_cast<App*>(userPtr)->onWatchdogTimeout(reason);
216 }
217
218 void App::onCrash (qpCrashHandler* crashHandler, void* userPtr)
219 {
220         DE_UNREF(crashHandler);
221         static_cast<App*>(userPtr)->onCrash();
222 }
223
224 void App::onWatchdogTimeout (qpTimeoutReason reason)
225 {
226         if (!m_crashLock.tryLock() || m_crashed)
227                 return; // In crash handler already.
228
229         m_crashed = true;
230
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"));
233 }
234
235 static void writeCrashToLog (void* userPtr, const char* infoString)
236 {
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);
240 }
241
242 static void writeCrashToConsole (void* userPtr, const char* infoString)
243 {
244         // \note THIS IS CALLED BY SIGNAL HANDLER! CALLING MALLOC/FREE IS NOT ALLOWED!
245         DE_UNREF(userPtr);
246         qpPrint(infoString);
247 }
248
249 void App::onCrash (void)
250 {
251         // \note THIS IS CALLED BY SIGNAL HANDLER! CALLING MALLOC/FREE IS NOT ALLOWED!
252
253         if (!m_crashLock.tryLock() || m_crashed)
254                 return; // In crash handler already.
255
256         m_crashed = true;
257
258         bool isInCase = m_testExecutor ? m_testExecutor->isInTestCase() : false;
259
260         if (isInCase)
261         {
262                 qpCrashHandler_writeCrashInfo(m_crashHandler, writeCrashToLog, &m_testCtx->getLog());
263                 m_testCtx->getLog().terminateCase(QP_TEST_RESULT_CRASH);
264         }
265         else
266                 qpCrashHandler_writeCrashInfo(m_crashHandler, writeCrashToConsole, DE_NULL);
267
268         die("Test program crashed");
269 }
270
271 } // tcu