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
33namespace tcu
34{
35
36class 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 *//*--------------------------------------------------------------------*/
44class TestHierarchyInflater
45{
46public:
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
55protected:
56									~TestHierarchyInflater	(void);
57};
58
59// \todo [2015-02-26 pyry] Hierarchy traversal should not depend on TestContext
60class DefaultHierarchyInflater : public TestHierarchyInflater
61{
62public:
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
72protected:
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 *//*--------------------------------------------------------------------*/
107class TestHierarchyIterator
108{
109public:
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
129private:
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
142		NodeIter (void)
143			: node			(DE_NULL)
144			, curChildNdx	(-1)
145			, m_state		(STATE_LAST)
146		{
147		}
148
149		NodeIter (TestNode* node_)
150			: node			(node_)
151			, curChildNdx	(-1)
152			, m_state		(STATE_INIT)
153		{
154		}
155
156		State getState (void) const
157		{
158			return m_state;
159		}
160
161		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