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 Test case hierarchy iterator.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "tcuTestHierarchyIterator.hpp"
     25 #include "tcuCommandLine.hpp"
     26 
     27 namespace tcu
     28 {
     29 
     30 using std::string;
     31 using std::vector;
     32 
     33 // TestHierarchyInflater
     34 
     35 TestHierarchyInflater::TestHierarchyInflater (void)
     36 {
     37 }
     38 
     39 TestHierarchyInflater::~TestHierarchyInflater (void)
     40 {
     41 }
     42 
     43 // DefaultHierarchyInflater
     44 
     45 DefaultHierarchyInflater::DefaultHierarchyInflater (TestContext& testCtx)
     46 	: m_testCtx(testCtx)
     47 {
     48 }
     49 
     50 DefaultHierarchyInflater::~DefaultHierarchyInflater (void)
     51 {
     52 }
     53 
     54 void DefaultHierarchyInflater::enterTestPackage (TestPackage* testPackage, vector<TestNode*>& children)
     55 {
     56 	{
     57 		Archive* const	pkgArchive	= testPackage->getArchive();
     58 
     59 		if (pkgArchive)
     60 			m_testCtx.setCurrentArchive(*pkgArchive);
     61 		else
     62 			m_testCtx.setCurrentArchive(m_testCtx.getRootArchive());
     63 	}
     64 
     65 	testPackage->init();
     66 	testPackage->getChildren(children);
     67 }
     68 
     69 void DefaultHierarchyInflater::leaveTestPackage (TestPackage* testPackage)
     70 {
     71 	m_testCtx.setCurrentArchive(m_testCtx.getRootArchive());
     72 	testPackage->deinit();
     73 }
     74 
     75 void DefaultHierarchyInflater::enterGroupNode (TestCaseGroup* testGroup, vector<TestNode*>& children)
     76 {
     77 	testGroup->init();
     78 	testGroup->getChildren(children);
     79 }
     80 
     81 void DefaultHierarchyInflater::leaveGroupNode (TestCaseGroup* testGroup)
     82 {
     83 	testGroup->deinit();
     84 }
     85 
     86 // TestHierarchyIterator
     87 
     88 TestHierarchyIterator::TestHierarchyIterator (TestPackageRoot&			rootNode,
     89 											  TestHierarchyInflater&	inflater,
     90 											  const CommandLine&		cmdLine)
     91 	: m_inflater	(inflater)
     92 	, m_cmdLine		(cmdLine)
     93 {
     94 	// Init traverse state and "seek" to first reportable node.
     95 	NodeIter iter(&rootNode);
     96 	iter.setState(NodeIter::STATE_ENTER); // Root is never reported
     97 	m_sessionStack.push_back(iter);
     98 	next();
     99 }
    100 
    101 TestHierarchyIterator::~TestHierarchyIterator (void)
    102 {
    103 	// Tear down inflated nodes in m_sessionStack
    104 	for (vector<NodeIter>::reverse_iterator iter = m_sessionStack.rbegin(); iter != m_sessionStack.rend(); ++iter)
    105 	{
    106 		TestNode* const		node		= iter->node;
    107 		const TestNodeType	nodeType	= node->getNodeType();
    108 
    109 		switch (nodeType)
    110 		{
    111 			case NODETYPE_ROOT:		/* root is not de-initialized */								break;
    112 			case NODETYPE_PACKAGE:	m_inflater.leaveTestPackage(static_cast<TestPackage*>(node));	break;
    113 			case NODETYPE_GROUP:	m_inflater.leaveGroupNode(static_cast<TestCaseGroup*>(node));	break;
    114 			default:
    115 				break;
    116 		}
    117 	}
    118 }
    119 
    120 TestHierarchyIterator::State TestHierarchyIterator::getState (void) const
    121 {
    122 	if (!m_sessionStack.empty())
    123 	{
    124 		const NodeIter&	iter	= m_sessionStack.back();
    125 
    126 		DE_ASSERT(iter.getState() == NodeIter::STATE_ENTER ||
    127 				  iter.getState() == NodeIter::STATE_LEAVE);
    128 
    129 		return iter.getState() == NodeIter::STATE_ENTER ? STATE_ENTER_NODE : STATE_LEAVE_NODE;
    130 	}
    131 	else
    132 		return STATE_FINISHED;
    133 }
    134 
    135 TestNode* TestHierarchyIterator::getNode (void) const
    136 {
    137 	DE_ASSERT(getState() != STATE_FINISHED);
    138 	return m_sessionStack.back().node;
    139 }
    140 
    141 const std::string& TestHierarchyIterator::getNodePath (void) const
    142 {
    143 	DE_ASSERT(getState() != STATE_FINISHED);
    144 	return m_nodePath;
    145 }
    146 
    147 std::string TestHierarchyIterator::buildNodePath (const vector<NodeIter>& nodeStack)
    148 {
    149 	string nodePath;
    150 	for (size_t ndx = 1; ndx < nodeStack.size(); ndx++)
    151 	{
    152 		const NodeIter& iter = nodeStack[ndx];
    153 		if (ndx > 1) // ignore root package
    154 			nodePath += ".";
    155 		nodePath += iter.node->getName();
    156 	}
    157 	return nodePath;
    158 }
    159 
    160 void TestHierarchyIterator::next (void)
    161 {
    162 	while (!m_sessionStack.empty())
    163 	{
    164 		NodeIter&			iter		= m_sessionStack.back();
    165 		TestNode* const		node		= iter.node;
    166 		const bool			isLeaf		= isTestNodeTypeExecutable(node->getNodeType());
    167 
    168 		switch (iter.getState())
    169 		{
    170 			case NodeIter::STATE_INIT:
    171 			{
    172 				const std::string nodePath = buildNodePath(m_sessionStack);
    173 
    174 				// Return to parent if name doesn't match filter.
    175 				if (!(isLeaf ? m_cmdLine.checkTestCaseName(nodePath.c_str()) : m_cmdLine.checkTestGroupName(nodePath.c_str())))
    176 				{
    177 					m_sessionStack.pop_back();
    178 					break;
    179 				}
    180 
    181 				m_nodePath = nodePath;
    182 				iter.setState(NodeIter::STATE_ENTER);
    183 				return; // Yield enter event
    184 			}
    185 
    186 			case NodeIter::STATE_ENTER:
    187 			{
    188 				if (isLeaf)
    189 				{
    190 					iter.setState(NodeIter::STATE_LEAVE);
    191 					return; // Yield leave event
    192 				}
    193 				else
    194 				{
    195 					iter.setState(NodeIter::STATE_TRAVERSE_CHILDREN);
    196 					iter.children.clear();
    197 
    198 					switch (node->getNodeType())
    199 					{
    200 						case NODETYPE_ROOT:		static_cast<TestPackageRoot*>(node)->getChildren(iter.children);				break;
    201 						case NODETYPE_PACKAGE:	m_inflater.enterTestPackage(static_cast<TestPackage*>(node), iter.children);	break;
    202 						case NODETYPE_GROUP:	m_inflater.enterGroupNode(static_cast<TestCaseGroup*>(node), iter.children);	break;
    203 						default:
    204 							DE_ASSERT(false);
    205 					}
    206 				}
    207 
    208 				break;
    209 			}
    210 
    211 			case NodeIter::STATE_TRAVERSE_CHILDREN:
    212 			{
    213 				int numChildren = (int)iter.children.size();
    214 				if (++iter.curChildNdx < numChildren)
    215 				{
    216 					// Push child to stack.
    217 					TestNode* childNode = iter.children[iter.curChildNdx];
    218 					m_sessionStack.push_back(NodeIter(childNode));
    219 				}
    220 				else
    221 				{
    222 					iter.setState(NodeIter::STATE_LEAVE);
    223 					if (node->getNodeType() != NODETYPE_ROOT)
    224 						return; // Yield leave event
    225 				}
    226 
    227 				break;
    228 			}
    229 
    230 			case NodeIter::STATE_LEAVE:
    231 			{
    232 				// Leave node.
    233 				if (!isLeaf)
    234 				{
    235 					switch (node->getNodeType())
    236 					{
    237 						case NODETYPE_ROOT:		/* root is not de-initialized */								break;
    238 						case NODETYPE_PACKAGE:	m_inflater.leaveTestPackage(static_cast<TestPackage*>(node));	break;
    239 						case NODETYPE_GROUP:	m_inflater.leaveGroupNode(static_cast<TestCaseGroup*>(node));	break;
    240 						default:
    241 							DE_ASSERT(false);
    242 					}
    243 				}
    244 
    245 				m_sessionStack.pop_back();
    246 				m_nodePath = buildNodePath(m_sessionStack);
    247 				break;
    248 			}
    249 
    250 			default:
    251 				DE_ASSERT(false);
    252 				return;
    253 		}
    254 	}
    255 
    256 	DE_ASSERT(m_sessionStack.empty() && getState() == STATE_FINISHED);
    257 }
    258 
    259 } // tcu
    260