You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
259 lines
6.6 KiB
259 lines
6.6 KiB
/*------------------------------------------------------------------------- |
|
* drawElements Quality Program Tester Core |
|
* ---------------------------------------- |
|
* |
|
* Copyright 2014 The Android Open Source Project |
|
* |
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
* you may not use this file except in compliance with the License. |
|
* You may obtain a copy of the License at |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
* |
|
*//*! |
|
* \file |
|
* \brief Test case hierarchy iterator. |
|
*//*--------------------------------------------------------------------*/ |
|
|
|
#include "tcuTestHierarchyIterator.hpp" |
|
#include "tcuCommandLine.hpp" |
|
|
|
namespace tcu |
|
{ |
|
|
|
using std::string; |
|
using std::vector; |
|
|
|
// TestHierarchyInflater |
|
|
|
TestHierarchyInflater::TestHierarchyInflater (void) |
|
{ |
|
} |
|
|
|
TestHierarchyInflater::~TestHierarchyInflater (void) |
|
{ |
|
} |
|
|
|
// DefaultHierarchyInflater |
|
|
|
DefaultHierarchyInflater::DefaultHierarchyInflater (TestContext& testCtx) |
|
: m_testCtx(testCtx) |
|
{ |
|
} |
|
|
|
DefaultHierarchyInflater::~DefaultHierarchyInflater (void) |
|
{ |
|
} |
|
|
|
void DefaultHierarchyInflater::enterTestPackage (TestPackage* testPackage, vector<TestNode*>& children) |
|
{ |
|
{ |
|
Archive* const pkgArchive = testPackage->getArchive(); |
|
|
|
if (pkgArchive) |
|
m_testCtx.setCurrentArchive(*pkgArchive); |
|
else |
|
m_testCtx.setCurrentArchive(m_testCtx.getRootArchive()); |
|
} |
|
|
|
testPackage->init(); |
|
testPackage->getChildren(children); |
|
} |
|
|
|
void DefaultHierarchyInflater::leaveTestPackage (TestPackage* testPackage) |
|
{ |
|
m_testCtx.setCurrentArchive(m_testCtx.getRootArchive()); |
|
testPackage->deinit(); |
|
} |
|
|
|
void DefaultHierarchyInflater::enterGroupNode (TestCaseGroup* testGroup, vector<TestNode*>& children) |
|
{ |
|
testGroup->init(); |
|
testGroup->getChildren(children); |
|
} |
|
|
|
void DefaultHierarchyInflater::leaveGroupNode (TestCaseGroup* testGroup) |
|
{ |
|
testGroup->deinit(); |
|
} |
|
|
|
// TestHierarchyIterator |
|
|
|
TestHierarchyIterator::TestHierarchyIterator (TestPackageRoot& rootNode, |
|
TestHierarchyInflater& inflater, |
|
const CommandLine& cmdLine) |
|
: m_inflater (inflater) |
|
, m_cmdLine (cmdLine) |
|
{ |
|
// Init traverse state and "seek" to first reportable node. |
|
NodeIter iter(&rootNode); |
|
iter.setState(NodeIter::STATE_ENTER); // Root is never reported |
|
m_sessionStack.push_back(iter); |
|
next(); |
|
} |
|
|
|
TestHierarchyIterator::~TestHierarchyIterator (void) |
|
{ |
|
// Tear down inflated nodes in m_sessionStack |
|
for (vector<NodeIter>::reverse_iterator iter = m_sessionStack.rbegin(); iter != m_sessionStack.rend(); ++iter) |
|
{ |
|
TestNode* const node = iter->node; |
|
const TestNodeType nodeType = node->getNodeType(); |
|
|
|
switch (nodeType) |
|
{ |
|
case NODETYPE_ROOT: /* root is not de-initialized */ break; |
|
case NODETYPE_PACKAGE: m_inflater.leaveTestPackage(static_cast<TestPackage*>(node)); break; |
|
case NODETYPE_GROUP: m_inflater.leaveGroupNode(static_cast<TestCaseGroup*>(node)); break; |
|
default: |
|
break; |
|
} |
|
} |
|
} |
|
|
|
TestHierarchyIterator::State TestHierarchyIterator::getState (void) const |
|
{ |
|
if (!m_sessionStack.empty()) |
|
{ |
|
const NodeIter& iter = m_sessionStack.back(); |
|
|
|
DE_ASSERT(iter.getState() == NodeIter::STATE_ENTER || |
|
iter.getState() == NodeIter::STATE_LEAVE); |
|
|
|
return iter.getState() == NodeIter::STATE_ENTER ? STATE_ENTER_NODE : STATE_LEAVE_NODE; |
|
} |
|
else |
|
return STATE_FINISHED; |
|
} |
|
|
|
TestNode* TestHierarchyIterator::getNode (void) const |
|
{ |
|
DE_ASSERT(getState() != STATE_FINISHED); |
|
return m_sessionStack.back().node; |
|
} |
|
|
|
const std::string& TestHierarchyIterator::getNodePath (void) const |
|
{ |
|
DE_ASSERT(getState() != STATE_FINISHED); |
|
return m_nodePath; |
|
} |
|
|
|
std::string TestHierarchyIterator::buildNodePath (const vector<NodeIter>& nodeStack) |
|
{ |
|
string nodePath; |
|
for (size_t ndx = 1; ndx < nodeStack.size(); ndx++) |
|
{ |
|
const NodeIter& iter = nodeStack[ndx]; |
|
if (ndx > 1) // ignore root package |
|
nodePath += "."; |
|
nodePath += iter.node->getName(); |
|
} |
|
return nodePath; |
|
} |
|
|
|
void TestHierarchyIterator::next (void) |
|
{ |
|
while (!m_sessionStack.empty()) |
|
{ |
|
NodeIter& iter = m_sessionStack.back(); |
|
TestNode* const node = iter.node; |
|
const bool isLeaf = isTestNodeTypeExecutable(node->getNodeType()); |
|
|
|
switch (iter.getState()) |
|
{ |
|
case NodeIter::STATE_INIT: |
|
{ |
|
const std::string nodePath = buildNodePath(m_sessionStack); |
|
|
|
// Return to parent if name doesn't match filter. |
|
if (!(isLeaf ? m_cmdLine.checkTestCaseName(nodePath.c_str()) : m_cmdLine.checkTestGroupName(nodePath.c_str()))) |
|
{ |
|
m_sessionStack.pop_back(); |
|
break; |
|
} |
|
|
|
m_nodePath = nodePath; |
|
iter.setState(NodeIter::STATE_ENTER); |
|
return; // Yield enter event |
|
} |
|
|
|
case NodeIter::STATE_ENTER: |
|
{ |
|
if (isLeaf) |
|
{ |
|
iter.setState(NodeIter::STATE_LEAVE); |
|
return; // Yield leave event |
|
} |
|
else |
|
{ |
|
iter.setState(NodeIter::STATE_TRAVERSE_CHILDREN); |
|
iter.children.clear(); |
|
|
|
switch (node->getNodeType()) |
|
{ |
|
case NODETYPE_ROOT: static_cast<TestPackageRoot*>(node)->getChildren(iter.children); break; |
|
case NODETYPE_PACKAGE: m_inflater.enterTestPackage(static_cast<TestPackage*>(node), iter.children); break; |
|
case NODETYPE_GROUP: m_inflater.enterGroupNode(static_cast<TestCaseGroup*>(node), iter.children); break; |
|
default: |
|
DE_ASSERT(false); |
|
} |
|
} |
|
|
|
break; |
|
} |
|
|
|
case NodeIter::STATE_TRAVERSE_CHILDREN: |
|
{ |
|
int numChildren = (int)iter.children.size(); |
|
if (++iter.curChildNdx < numChildren) |
|
{ |
|
// Push child to stack. |
|
TestNode* childNode = iter.children[iter.curChildNdx]; |
|
m_sessionStack.push_back(NodeIter(childNode)); |
|
} |
|
else |
|
{ |
|
iter.setState(NodeIter::STATE_LEAVE); |
|
if (node->getNodeType() != NODETYPE_ROOT) |
|
return; // Yield leave event |
|
} |
|
|
|
break; |
|
} |
|
|
|
case NodeIter::STATE_LEAVE: |
|
{ |
|
// Leave node. |
|
if (!isLeaf) |
|
{ |
|
switch (node->getNodeType()) |
|
{ |
|
case NODETYPE_ROOT: /* root is not de-initialized */ break; |
|
case NODETYPE_PACKAGE: m_inflater.leaveTestPackage(static_cast<TestPackage*>(node)); break; |
|
case NODETYPE_GROUP: m_inflater.leaveGroupNode(static_cast<TestCaseGroup*>(node)); break; |
|
default: |
|
DE_ASSERT(false); |
|
} |
|
} |
|
|
|
m_sessionStack.pop_back(); |
|
m_nodePath = buildNodePath(m_sessionStack); |
|
break; |
|
} |
|
|
|
default: |
|
DE_ASSERT(false); |
|
return; |
|
} |
|
} |
|
|
|
DE_ASSERT(m_sessionStack.empty() && getState() == STATE_FINISHED); |
|
} |
|
|
|
} // tcu
|
|
|