1 #ifndef _TCUTESTHIERARCHYITERATOR_HPP
2 #define _TCUTESTHIERARCHYITERATOR_HPP
3 /*-------------------------------------------------------------------------
4  * drawElements Quality Program Tester Core
5  * ----------------------------------------
6  *
7  * Copyright 2014 The Android Open Source Project
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Test case hierarchy iterator.
24  *//*--------------------------------------------------------------------*/
25 
26 #include "tcuDefs.hpp"
27 #include "tcuTestContext.hpp"
28 #include "tcuTestCase.hpp"
29 #include "tcuTestPackage.hpp"
30 
31 #include <vector>
32 
33 namespace tcu
34 {
35 
36 class CommandLine;
37 
38 /*--------------------------------------------------------------------*//*!
39  * \brief Test hierarchy inflater
40  *
41  * This interface is used by TestHierarchyIterator to materialize, and clean
42  * up, test hierarchy on-demand while walking through it.
43  *//*--------------------------------------------------------------------*/
44 class TestHierarchyInflater
45 {
46 public:
47 									TestHierarchyInflater	(void);
48 
49 	virtual void					enterTestPackage		(TestPackage* testPackage, std::vector<TestNode*>& children) = 0;
50 	virtual void					leaveTestPackage		(TestPackage* testPackage) = 0;
51 
52 	virtual void					enterGroupNode			(TestCaseGroup* testGroup, std::vector<TestNode*>& children) = 0;
53 	virtual void					leaveGroupNode			(TestCaseGroup* testGroup) = 0;
54 
55 protected:
56 									~TestHierarchyInflater	(void);
57 };
58 
59 // \todo [2015-02-26 pyry] Hierarchy traversal should not depend on TestContext
60 class DefaultHierarchyInflater : public TestHierarchyInflater
61 {
62 public:
63 									DefaultHierarchyInflater	(TestContext& testCtx);
64 									~DefaultHierarchyInflater	(void);
65 
66 	virtual void					enterTestPackage			(TestPackage* testPackage, std::vector<TestNode*>& children);
67 	virtual void					leaveTestPackage			(TestPackage* testPackage);
68 
69 	virtual void					enterGroupNode				(TestCaseGroup* testGroup, std::vector<TestNode*>& children);
70 	virtual void					leaveGroupNode				(TestCaseGroup* testGroup);
71 
72 protected:
73 	TestContext&					m_testCtx;
74 };
75 
76 /*--------------------------------------------------------------------*//*!
77  * \brief Test hierarchy iterator
78  *
79  * Test hierarchy iterator allows walking test case hierarchy in depth-first
80  * order. The walked sub-tree is limited by command line parameters.
81  *
82  * Iterator signals current state with getState(), which initally, and after
83  * each increment (next()) may report one of the following:
84  *
85  * STATE_ENTER_NODE: A test node has been entered to for the first time.
86  *   Node can be queried with getNode() and its full path with getNodePath().
87  *   For group nodes the iterator will next enter first matching child node.
88  *   For executable (test case) nodes STATE_LEAVE_NODE will always be reported
89  *   immediately after entering that node.
90  *
91  * STATE_LEAVE_NODE: Iterator is leaving a node. In case of group nodes this
92  *   means that all child nodes and their children have been processed. For
93  *   executable nodes the iterator will either move on to the next sibling,
94  *   or leave the parent group if the reported node was last child of that
95  *   group.
96  *
97  * Root node is never reported, but instead iteration will start on first
98  * matching test package node, if there is any.
99  *
100  * Test hierarchy is created on demand with help of TestHierarchyInflater.
101  * Upon entering a group node, after STATE_ENTER_NODE has been signaled,
102  * inflater is called to construct the list of child nodes for that group.
103  * Upon exiting a group node, before STATE_LEAVE_NODE is called, inflater
104  * is asked to clean up any resources by calling leaveGroupNode() or
105  * leaveTestPackage() depending on the type of the node.
106  *//*--------------------------------------------------------------------*/
107 class TestHierarchyIterator
108 {
109 public:
110 							TestHierarchyIterator	(TestPackageRoot& rootNode, TestHierarchyInflater& inflater, const CommandLine& cmdLine);
111 							~TestHierarchyIterator	(void);
112 
113 	enum State
114 	{
115 		STATE_ENTER_NODE = 0,
116 		STATE_LEAVE_NODE,
117 		STATE_FINISHED,
118 
119 		STATE_LAST
120 	};
121 
122 	State					getState				(void) const;
123 
124 	TestNode*				getNode					(void) const;
125 	const std::string&		getNodePath				(void) const;
126 
127 	void					next					(void);
128 
129 private:
130 	struct NodeIter
131 	{
132 		enum State
133 		{
134 			STATE_INIT = 0,
135 			STATE_ENTER,
136 			STATE_TRAVERSE_CHILDREN,
137 			STATE_LEAVE,
138 
139 			STATE_LAST
140 		};
141 
NodeItertcu::TestHierarchyIterator::NodeIter142 		NodeIter (void)
143 			: node			(DE_NULL)
144 			, curChildNdx	(-1)
145 			, m_state		(STATE_LAST)
146 		{
147 		}
148 
NodeItertcu::TestHierarchyIterator::NodeIter149 		NodeIter (TestNode* node_)
150 			: node			(node_)
151 			, curChildNdx	(-1)
152 			, m_state		(STATE_INIT)
153 		{
154 		}
155 
getStatetcu::TestHierarchyIterator::NodeIter156 		State getState (void) const
157 		{
158 			return m_state;
159 		}
160 
setStatetcu::TestHierarchyIterator::NodeIter161 		void setState (State newState)
162 		{
163 			switch (newState)
164 			{
165 				case STATE_TRAVERSE_CHILDREN:
166 					curChildNdx = -1;
167 					break;
168 
169 				default:
170 					break;
171 			}
172 
173 			m_state = newState;
174 		}
175 
176 		TestNode*				node;
177 		std::vector<TestNode*>	children;
178 		int						curChildNdx;
179 
180 	private:
181 		State					m_state;
182 	};
183 
184 							TestHierarchyIterator	(const TestHierarchyIterator&);		// not allowed!
185 	TestHierarchyIterator&	operator=				(const TestHierarchyIterator&);		// not allowed!
186 
187 	bool					matchFolderName			(const std::string& folderName) const;
188 	bool					matchCaseName			(const std::string& caseName) const;
189 
190 	static std::string		buildNodePath			(const std::vector<NodeIter>& nodeStack);
191 
192 	TestHierarchyInflater&	m_inflater;
193 	const CommandLine&		m_cmdLine;
194 
195 	// Current session state.
196 	std::vector<NodeIter>	m_sessionStack;
197 	std::string				m_nodePath;
198 };
199 
200 } // tcu
201 
202 #endif // _TCUTESTHIERARCHYITERATOR_HPP
203