#ifndef _TCUTESTHIERARCHYITERATOR_HPP #define _TCUTESTHIERARCHYITERATOR_HPP /*------------------------------------------------------------------------- * 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 "tcuDefs.hpp" #include "tcuTestContext.hpp" #include "tcuTestCase.hpp" #include "tcuTestPackage.hpp" #include <vector> namespace tcu { class CommandLine; /*--------------------------------------------------------------------*//*! * \brief Test hierarchy inflater * * This interface is used by TestHierarchyIterator to materialize, and clean * up, test hierarchy on-demand while walking through it. *//*--------------------------------------------------------------------*/ class TestHierarchyInflater { public: TestHierarchyInflater (void); virtual void enterTestPackage (TestPackage* testPackage, std::vector<TestNode*>& children) = 0; virtual void leaveTestPackage (TestPackage* testPackage) = 0; virtual void enterGroupNode (TestCaseGroup* testGroup, std::vector<TestNode*>& children) = 0; virtual void leaveGroupNode (TestCaseGroup* testGroup) = 0; protected: ~TestHierarchyInflater (void); }; // \todo [2015-02-26 pyry] Hierarchy traversal should not depend on TestContext class DefaultHierarchyInflater : public TestHierarchyInflater { public: DefaultHierarchyInflater (TestContext& testCtx); ~DefaultHierarchyInflater (void); virtual void enterTestPackage (TestPackage* testPackage, std::vector<TestNode*>& children); virtual void leaveTestPackage (TestPackage* testPackage); virtual void enterGroupNode (TestCaseGroup* testGroup, std::vector<TestNode*>& children); virtual void leaveGroupNode (TestCaseGroup* testGroup); protected: TestContext& m_testCtx; }; /*--------------------------------------------------------------------*//*! * \brief Test hierarchy iterator * * Test hierarchy iterator allows walking test case hierarchy in depth-first * order. The walked sub-tree is limited by command line parameters. * * Iterator signals current state with getState(), which initally, and after * each increment (next()) may report one of the following: * * STATE_ENTER_NODE: A test node has been entered to for the first time. * Node can be queried with getNode() and its full path with getNodePath(). * For group nodes the iterator will next enter first matching child node. * For executable (test case) nodes STATE_LEAVE_NODE will always be reported * immediately after entering that node. * * STATE_LEAVE_NODE: Iterator is leaving a node. In case of group nodes this * means that all child nodes and their children have been processed. For * executable nodes the iterator will either move on to the next sibling, * or leave the parent group if the reported node was last child of that * group. * * Root node is never reported, but instead iteration will start on first * matching test package node, if there is any. * * Test hierarchy is created on demand with help of TestHierarchyInflater. * Upon entering a group node, after STATE_ENTER_NODE has been signaled, * inflater is called to construct the list of child nodes for that group. * Upon exiting a group node, before STATE_LEAVE_NODE is called, inflater * is asked to clean up any resources by calling leaveGroupNode() or * leaveTestPackage() depending on the type of the node. *//*--------------------------------------------------------------------*/ class TestHierarchyIterator { public: TestHierarchyIterator (TestPackageRoot& rootNode, TestHierarchyInflater& inflater, const CommandLine& cmdLine); ~TestHierarchyIterator (void); enum State { STATE_ENTER_NODE = 0, STATE_LEAVE_NODE, STATE_FINISHED, STATE_LAST }; State getState (void) const; TestNode* getNode (void) const; const std::string& getNodePath (void) const; void next (void); private: struct NodeIter { enum State { STATE_INIT = 0, STATE_ENTER, STATE_TRAVERSE_CHILDREN, STATE_LEAVE, STATE_LAST }; NodeIter (void) : node (DE_NULL) , curChildNdx (-1) , m_state (STATE_LAST) { } NodeIter (TestNode* node_) : node (node_) , curChildNdx (-1) , m_state (STATE_INIT) { } State getState (void) const { return m_state; } void setState (State newState) { switch (newState) { case STATE_TRAVERSE_CHILDREN: curChildNdx = -1; break; default: break; } m_state = newState; } TestNode* node; std::vector<TestNode*> children; int curChildNdx; private: State m_state; }; TestHierarchyIterator (const TestHierarchyIterator&); // not allowed! TestHierarchyIterator& operator= (const TestHierarchyIterator&); // not allowed! bool matchFolderName (const std::string& folderName) const; bool matchCaseName (const std::string& caseName) const; static std::string buildNodePath (const std::vector<NodeIter>& nodeStack); TestHierarchyInflater& m_inflater; const CommandLine& m_cmdLine; // Current session state. std::vector<NodeIter> m_sessionStack; std::string m_nodePath; }; } // tcu #endif // _TCUTESTHIERARCHYITERATOR_HPP