Home | History | Annotate | Download | only in common
      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