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