• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
TestHierarchyInflater(void)35 TestHierarchyInflater::TestHierarchyInflater (void)
36 {
37 }
38 
~TestHierarchyInflater(void)39 TestHierarchyInflater::~TestHierarchyInflater (void)
40 {
41 }
42 
43 // DefaultHierarchyInflater
44 
DefaultHierarchyInflater(TestContext & testCtx)45 DefaultHierarchyInflater::DefaultHierarchyInflater (TestContext& testCtx)
46 	: m_testCtx(testCtx)
47 {
48 }
49 
~DefaultHierarchyInflater(void)50 DefaultHierarchyInflater::~DefaultHierarchyInflater (void)
51 {
52 }
53 
enterTestPackage(TestPackage * testPackage,vector<TestNode * > & children)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 	// write default session info if it was not done by package
69 	m_testCtx.writeSessionInfo();
70 }
71 
leaveTestPackage(TestPackage * testPackage)72 void DefaultHierarchyInflater::leaveTestPackage (TestPackage* testPackage)
73 {
74 	m_testCtx.setCurrentArchive(m_testCtx.getRootArchive());
75 	testPackage->deinit();
76 }
77 
enterGroupNode(TestCaseGroup * testGroup,vector<TestNode * > & children)78 void DefaultHierarchyInflater::enterGroupNode (TestCaseGroup* testGroup, vector<TestNode*>& children)
79 {
80 	testGroup->init();
81 	testGroup->getChildren(children);
82 }
83 
leaveGroupNode(TestCaseGroup * testGroup)84 void DefaultHierarchyInflater::leaveGroupNode (TestCaseGroup* testGroup)
85 {
86 	testGroup->deinit();
87 }
88 
89 // TestHierarchyIterator
90 
TestHierarchyIterator(TestPackageRoot & rootNode,TestHierarchyInflater & inflater,const CaseListFilter & caseListFilter)91 TestHierarchyIterator::TestHierarchyIterator (TestPackageRoot&			rootNode,
92 											  TestHierarchyInflater&	inflater,
93 											  const CaseListFilter&		caseListFilter)
94 	: m_inflater		(inflater)
95 	, m_caseListFilter	(caseListFilter)
96 	, m_groupNumber		(0)
97 {
98 	// Init traverse state and "seek" to first reportable node.
99 	NodeIter iter(&rootNode);
100 	iter.setState(NodeIter::NISTATE_ENTER); // Root is never reported
101 	m_sessionStack.push_back(iter);
102 	next();
103 }
104 
~TestHierarchyIterator(void)105 TestHierarchyIterator::~TestHierarchyIterator (void)
106 {
107 	// Tear down inflated nodes in m_sessionStack
108 	for (vector<NodeIter>::reverse_iterator iter = m_sessionStack.rbegin(); iter != m_sessionStack.rend(); ++iter)
109 	{
110 		TestNode* const		node		= iter->node;
111 		const TestNodeType	nodeType	= node->getNodeType();
112 
113 		switch (nodeType)
114 		{
115 			case NODETYPE_ROOT:		/* root is not de-initialized */								break;
116 			case NODETYPE_PACKAGE:	m_inflater.leaveTestPackage(static_cast<TestPackage*>(node));	break;
117 			case NODETYPE_GROUP:	m_inflater.leaveGroupNode(static_cast<TestCaseGroup*>(node));	break;
118 			default:
119 				break;
120 		}
121 	}
122 }
123 
getState(void) const124 TestHierarchyIterator::State TestHierarchyIterator::getState (void) const
125 {
126 	if (!m_sessionStack.empty())
127 	{
128 		const NodeIter&	iter	= m_sessionStack.back();
129 
130 		DE_ASSERT(iter.getState() == NodeIter::NISTATE_ENTER ||
131 				  iter.getState() == NodeIter::NISTATE_LEAVE);
132 
133 		return iter.getState() == NodeIter::NISTATE_ENTER ? STATE_ENTER_NODE : STATE_LEAVE_NODE;
134 	}
135 	else
136 		return STATE_FINISHED;
137 }
138 
getNode(void) const139 TestNode* TestHierarchyIterator::getNode (void) const
140 {
141 	DE_ASSERT(getState() != STATE_FINISHED);
142 	return m_sessionStack.back().node;
143 }
144 
getNodePath(void) const145 const std::string& TestHierarchyIterator::getNodePath (void) const
146 {
147 	DE_ASSERT(getState() != STATE_FINISHED);
148 	return m_nodePath;
149 }
150 
buildNodePath(const vector<NodeIter> & nodeStack)151 std::string TestHierarchyIterator::buildNodePath (const vector<NodeIter>& nodeStack)
152 {
153 	string nodePath;
154 	for (size_t ndx = 1; ndx < nodeStack.size(); ndx++)
155 	{
156 		const NodeIter& iter = nodeStack[ndx];
157 		if (ndx > 1) // ignore root package
158 			nodePath += ".";
159 		nodePath += iter.node->getName();
160 	}
161 	return nodePath;
162 }
163 
next(void)164 void TestHierarchyIterator::next (void)
165 {
166 	while (!m_sessionStack.empty())
167 	{
168 		NodeIter&			iter		= m_sessionStack.back();
169 		TestNode* const		node		= iter.node;
170 		const bool			isLeaf		= isTestNodeTypeExecutable(node->getNodeType());
171 
172 		switch (iter.getState())
173 		{
174 			case NodeIter::NISTATE_INIT:
175 			{
176 				const std::string nodePath = buildNodePath(m_sessionStack);
177 
178 				// Return to parent if name or runner type doesn't match filter.
179 				if (!(isLeaf ? (m_caseListFilter.checkRunnerType(node->getRunnerType()) && m_caseListFilter.checkTestCaseName(nodePath.c_str()))
180 							 : m_caseListFilter.checkTestGroupName(nodePath.c_str())))
181 				{
182 					m_sessionStack.pop_back();
183 					break;
184 				}
185 
186 				m_nodePath = nodePath;
187 				iter.setState(NodeIter::NISTATE_ENTER);
188 				return; // Yield enter event
189 			}
190 
191 			case NodeIter::NISTATE_ENTER:
192 			{
193 				if (isLeaf)
194 				{
195 					iter.setState(NodeIter::NISTATE_LEAVE);
196 					return; // Yield leave event
197 				}
198 				else
199 				{
200 					iter.setState(NodeIter::NISTATE_TRAVERSE_CHILDREN);
201 					iter.children.clear();
202 
203 					switch (node->getNodeType())
204 					{
205 						case NODETYPE_ROOT:		static_cast<TestPackageRoot*>(node)->getChildren(iter.children);				break;
206 						case NODETYPE_PACKAGE:	m_inflater.enterTestPackage(static_cast<TestPackage*>(node), iter.children);	break;
207 						case NODETYPE_GROUP:	m_inflater.enterGroupNode(static_cast<TestCaseGroup*>(node), iter.children);	break;
208 						default:
209 							DE_ASSERT(false);
210 					}
211 				}
212 
213 				break;
214 			}
215 
216 			case NodeIter::NISTATE_TRAVERSE_CHILDREN:
217 			{
218 				int numChildren = (int)iter.children.size();
219 				if (++iter.curChildNdx < numChildren)
220 				{
221 					// Push child to stack.
222 					TestNode* childNode = iter.children[iter.curChildNdx];
223 
224 					// Check whether this is a bottom-level group (child is executable)
225 					// and whether that group should be filtered out.
226 					if ( isTestNodeTypeExecutable(childNode->getNodeType()) )
227 					{
228 						const std::string testName = m_nodePath + "." + childNode->getName();
229 						if(!m_caseListFilter.checkCaseFraction(m_groupNumber, testName))
230 							break;
231 					}
232 					m_sessionStack.push_back(NodeIter(childNode));
233 				}
234 				else
235 				{
236 					iter.setState(NodeIter::NISTATE_LEAVE);
237 					if (node->getNodeType() != NODETYPE_ROOT)
238 						return; // Yield leave event
239 				}
240 
241 				break;
242 			}
243 
244 			case NodeIter::NISTATE_LEAVE:
245 			{
246 				// Leave node.
247 				if (!isLeaf)
248 				{
249 					switch (node->getNodeType())
250 					{
251 						case NODETYPE_ROOT:		/* root is not de-initialized */								break;
252 						case NODETYPE_PACKAGE:	m_inflater.leaveTestPackage(static_cast<TestPackage*>(node));	break;
253 						case NODETYPE_GROUP:	m_inflater.leaveGroupNode(static_cast<TestCaseGroup*>(node));	break;
254 						default:
255 							DE_ASSERT(false);
256 					}
257 					m_groupNumber++;
258 				}
259 
260 				m_sessionStack.pop_back();
261 				m_nodePath = buildNodePath(m_sessionStack);
262 				break;
263 			}
264 
265 			default:
266 				DE_ASSERT(false);
267 				return;
268 		}
269 	}
270 
271 	DE_ASSERT(m_sessionStack.empty() && getState() == STATE_FINISHED);
272 }
273 
274 } // tcu
275