Path: blob/main_old/src/tests/deqp_support/tcuRandomOrderExecutor.cpp
1693 views
/*-------------------------------------------------------------------------1* drawElements Quality Program Tester Core2* ----------------------------------------3*4* Copyright 2014 The Android Open Source Project5*6* Licensed under the Apache License, Version 2.0 (the "License");7* you may not use this file except in compliance with the License.8* You may obtain a copy of the License at9*10* http://www.apache.org/licenses/LICENSE-2.011*12* Unless required by applicable law or agreed to in writing, software13* distributed under the License is distributed on an "AS IS" BASIS,14* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.15* See the License for the specific language governing permissions and16* limitations under the License.17*18*//*!19* \file20* \brief Executor which can run randomly accessed tests.21*//*--------------------------------------------------------------------*/2223#include "tcuRandomOrderExecutor.h"2425#include "deClock.h"26#include "deStringUtil.hpp"27#include "tcuCommandLine.hpp"28#include "tcuTestLog.hpp"2930#include <algorithm>31#include <cstdio>32#include <fstream>3334using std::string;35using std::vector;3637namespace tcu38{3940RandomOrderExecutor::RandomOrderExecutor(TestPackageRoot &root,41TestContext &testCtx,42bool enableRenderDocCapture)43: m_testCtx(testCtx), m_inflater(testCtx)44{45m_nodeStack.push_back(NodeStackEntry(&root));46root.getChildren(m_nodeStack[0].children);4748if (enableRenderDocCapture)49{50mRenderDoc.attach();51}52}5354RandomOrderExecutor::~RandomOrderExecutor(void)55{56pruneStack(1);57}5859void RandomOrderExecutor::pruneStack(size_t newStackSize)60{61// \note Root is not managed by us62DE_ASSERT(de::inRange(newStackSize, size_t(1), m_nodeStack.size()));6364while (m_nodeStack.size() > newStackSize)65{66NodeStackEntry &curEntry = m_nodeStack.back();67const bool isPkg = curEntry.node->getNodeType() == NODETYPE_PACKAGE;6869DE_ASSERT((m_nodeStack.size() == 2) == isPkg);7071if (curEntry.node) // Just in case we are in72// cleanup path after partial73// prune74{75if (curEntry.node->getNodeType() == NODETYPE_GROUP)76m_inflater.leaveGroupNode(static_cast<TestCaseGroup *>(curEntry.node));77else if (curEntry.node->getNodeType() == NODETYPE_PACKAGE)78m_inflater.leaveTestPackage(static_cast<TestPackage *>(curEntry.node));79else80DE_ASSERT(curEntry.children.empty());8182curEntry.node = DE_NULL;83curEntry.children.clear();84}8586if (isPkg)87m_caseExecutor.clear();8889m_nodeStack.pop_back();90}91}9293static TestNode *findNodeByName(vector<TestNode *> &nodes, const std::string &name)94{95for (vector<TestNode *>::const_iterator node = nodes.begin(); node != nodes.end(); ++node)96{97if (name == (*node)->getName())98return *node;99}100101return DE_NULL;102}103104TestCase *RandomOrderExecutor::seekToCase(const string &path)105{106const vector<string> components = de::splitString(path, '.');107size_t compNdx;108109DE_ASSERT(!m_nodeStack.empty() && m_nodeStack.front().node->getNodeType() == NODETYPE_ROOT);110111for (compNdx = 0; compNdx < components.size(); compNdx++)112{113const size_t stackPos = compNdx + 1;114115if (stackPos >= m_nodeStack.size())116break; // Stack end117else if (components[compNdx] != m_nodeStack[stackPos].node->getName())118{119// Current stack doesn't match any more, prune.120pruneStack(stackPos);121break;122}123}124125DE_ASSERT(m_nodeStack.size() == compNdx + 1);126127for (; compNdx < components.size(); compNdx++)128{129const size_t parentStackPos = compNdx;130TestNode *const curNode =131findNodeByName(m_nodeStack[parentStackPos].children, components[compNdx]);132133if (!curNode)134throw Exception(string("Test hierarchy node not found: ") + path);135136m_nodeStack.push_back(NodeStackEntry(curNode));137138if (curNode->getNodeType() == NODETYPE_PACKAGE)139{140TestPackage *const testPackage = static_cast<TestPackage *>(curNode);141142m_inflater.enterTestPackage(testPackage, m_nodeStack.back().children);143DE_ASSERT(!m_caseExecutor);144m_caseExecutor = de::MovePtr<TestCaseExecutor>(testPackage->createExecutor());145}146else if (curNode->getNodeType() == NODETYPE_GROUP)147m_inflater.enterGroupNode(static_cast<TestCaseGroup *>(curNode),148m_nodeStack.back().children);149else if (compNdx + 1 != components.size())150throw Exception(string("Invalid test hierarchy path: ") + path);151}152153DE_ASSERT(m_nodeStack.size() == components.size() + 1);154155if (isTestNodeTypeExecutable(m_nodeStack.back().node->getNodeType()))156return dynamic_cast<TestCase *>(m_nodeStack.back().node);157else158throw Exception(string("Not a test case: ") + path);159}160161static qpTestCaseType nodeTypeToTestCaseType(TestNodeType nodeType)162{163switch (nodeType)164{165case NODETYPE_SELF_VALIDATE:166return QP_TEST_CASE_TYPE_SELF_VALIDATE;167case NODETYPE_PERFORMANCE:168return QP_TEST_CASE_TYPE_PERFORMANCE;169case NODETYPE_CAPABILITY:170return QP_TEST_CASE_TYPE_CAPABILITY;171case NODETYPE_ACCURACY:172return QP_TEST_CASE_TYPE_ACCURACY;173default:174DE_ASSERT(false);175return QP_TEST_CASE_TYPE_LAST;176}177}178179TestStatus RandomOrderExecutor::execute(const std::string &casePath)180{181TestCase *const testCase = seekToCase(casePath);182TestLog &log = m_testCtx.getLog();183const qpTestCaseType caseType = nodeTypeToTestCaseType(testCase->getNodeType());184185m_testCtx.setTerminateAfter(false);186log.startCase(casePath.c_str(), caseType);187188{189const TestStatus result = executeInner(testCase, casePath);190log.endCase(result.getCode(), result.getDescription().c_str());191return result;192}193}194195tcu::TestStatus RandomOrderExecutor::executeInner(TestCase *testCase, const std::string &casePath)196{197TestLog &log = m_testCtx.getLog();198const deUint64 testStartTime = deGetMicroseconds();199200m_testCtx.setTestResult(QP_TEST_RESULT_LAST, "");201202// Initialize, will return immediately if fails203try204{205mRenderDoc.startFrame();206m_caseExecutor->init(testCase, casePath);207}208catch (const std::bad_alloc &)209{210m_testCtx.setTerminateAfter(true);211return TestStatus(QP_TEST_RESULT_RESOURCE_ERROR,212"Failed to allocate memory in test case init");213}214catch (const TestException &e)215{216DE_ASSERT(e.getTestResult() != QP_TEST_RESULT_LAST);217m_testCtx.setTerminateAfter(e.isFatal());218log << e;219return TestStatus(e.getTestResult(), e.getMessage());220}221catch (const Exception &e)222{223log << e;224return TestStatus(QP_TEST_RESULT_FAIL, e.getMessage());225}226227bool isFirstFrameBeingCaptured = true;228229// Execute230for (;;)231{232TestCase::IterateResult iterateResult = TestCase::STOP;233234m_testCtx.touchWatchdog();235236try237{238// Make every iteration produce one renderdoc frame. Include the init code in the first239// frame, and the deinit code in the last frame.240if (!isFirstFrameBeingCaptured)241{242mRenderDoc.endFrame();243mRenderDoc.startFrame();244}245isFirstFrameBeingCaptured = false;246247iterateResult = m_caseExecutor->iterate(testCase);248}249catch (const std::bad_alloc &)250{251m_testCtx.setTestResult(QP_TEST_RESULT_RESOURCE_ERROR,252"Failed to allocate memory during test "253"execution");254}255catch (const TestException &e)256{257log << e;258m_testCtx.setTestResult(e.getTestResult(), e.getMessage());259m_testCtx.setTerminateAfter(e.isFatal());260}261catch (const Exception &e)262{263log << e;264m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, e.getMessage());265}266267if (iterateResult == TestCase::STOP)268break;269}270271DE_ASSERT(m_testCtx.getTestResult() != QP_TEST_RESULT_LAST);272273if (m_testCtx.getTestResult() == QP_TEST_RESULT_RESOURCE_ERROR)274m_testCtx.setTerminateAfter(true);275276// De-initialize277try278{279m_caseExecutor->deinit(testCase);280mRenderDoc.endFrame();281}282catch (const tcu::Exception &e)283{284log << e << TestLog::Message285<< "Error in test case deinit, test program "286"will terminate."287<< TestLog::EndMessage;288m_testCtx.setTerminateAfter(true);289}290291if (m_testCtx.getWatchDog())292qpWatchDog_reset(m_testCtx.getWatchDog());293294{295const TestStatus result =296TestStatus(m_testCtx.getTestResult(), m_testCtx.getTestResultDesc());297m_testCtx.setTestResult(QP_TEST_RESULT_LAST, "");298return result;299}300}301302} // namespace tcu303304305