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 27namespace tcu 28{ 29 30using std::string; 31using std::vector; 32 33// TestHierarchyInflater 34 35TestHierarchyInflater::TestHierarchyInflater (void) 36{ 37} 38 39TestHierarchyInflater::~TestHierarchyInflater (void) 40{ 41} 42 43// DefaultHierarchyInflater 44 45DefaultHierarchyInflater::DefaultHierarchyInflater (TestContext& testCtx) 46 : m_testCtx(testCtx) 47{ 48} 49 50DefaultHierarchyInflater::~DefaultHierarchyInflater (void) 51{ 52} 53 54void 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 69void DefaultHierarchyInflater::leaveTestPackage (TestPackage* testPackage) 70{ 71 m_testCtx.setCurrentArchive(m_testCtx.getRootArchive()); 72 testPackage->deinit(); 73} 74 75void DefaultHierarchyInflater::enterGroupNode (TestCaseGroup* testGroup, vector<TestNode*>& children) 76{ 77 testGroup->init(); 78 testGroup->getChildren(children); 79} 80 81void DefaultHierarchyInflater::leaveGroupNode (TestCaseGroup* testGroup) 82{ 83 testGroup->deinit(); 84} 85 86// TestHierarchyIterator 87 88TestHierarchyIterator::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 101TestHierarchyIterator::~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 120TestHierarchyIterator::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 135TestNode* TestHierarchyIterator::getNode (void) const 136{ 137 DE_ASSERT(getState() != STATE_FINISHED); 138 return m_sessionStack.back().node; 139} 140 141const std::string& TestHierarchyIterator::getNodePath (void) const 142{ 143 DE_ASSERT(getState() != STATE_FINISHED); 144 return m_nodePath; 145} 146 147std::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 160void 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