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
leaveTestPackage(TestPackage * testPackage)69 void DefaultHierarchyInflater::leaveTestPackage (TestPackage* testPackage)
70 {
71 m_testCtx.setCurrentArchive(m_testCtx.getRootArchive());
72 testPackage->deinit();
73 }
74
enterGroupNode(TestCaseGroup * testGroup,vector<TestNode * > & children)75 void DefaultHierarchyInflater::enterGroupNode (TestCaseGroup* testGroup, vector<TestNode*>& children)
76 {
77 testGroup->init();
78 testGroup->getChildren(children);
79 }
80
leaveGroupNode(TestCaseGroup * testGroup)81 void DefaultHierarchyInflater::leaveGroupNode (TestCaseGroup* testGroup)
82 {
83 testGroup->deinit();
84 }
85
86 // TestHierarchyIterator
87
TestHierarchyIterator(TestPackageRoot & rootNode,TestHierarchyInflater & inflater,const CommandLine & cmdLine)88 TestHierarchyIterator::TestHierarchyIterator (TestPackageRoot& rootNode,
89 TestHierarchyInflater& inflater,
90 const CommandLine& cmdLine)
91 : m_inflater (inflater)
92 , m_cmdLine (cmdLine)
93 {
94 // Init traverse state and "seek" to first reportable node.
95 NodeIter iter(&rootNode);
96 iter.setState(NodeIter::STATE_ENTER); // Root is never reported
97 m_sessionStack.push_back(iter);
98 next();
99 }
100
~TestHierarchyIterator(void)101 TestHierarchyIterator::~TestHierarchyIterator (void)
102 {
103 // Tear down inflated nodes in m_sessionStack
104 for (vector<NodeIter>::reverse_iterator iter = m_sessionStack.rbegin(); iter != m_sessionStack.rend(); ++iter)
105 {
106 TestNode* const node = iter->node;
107 const TestNodeType nodeType = node->getNodeType();
108
109 switch (nodeType)
110 {
111 case NODETYPE_ROOT: /* root is not de-initialized */ break;
112 case NODETYPE_PACKAGE: m_inflater.leaveTestPackage(static_cast<TestPackage*>(node)); break;
113 case NODETYPE_GROUP: m_inflater.leaveGroupNode(static_cast<TestCaseGroup*>(node)); break;
114 default:
115 break;
116 }
117 }
118 }
119
getState(void) const120 TestHierarchyIterator::State TestHierarchyIterator::getState (void) const
121 {
122 if (!m_sessionStack.empty())
123 {
124 const NodeIter& iter = m_sessionStack.back();
125
126 DE_ASSERT(iter.getState() == NodeIter::STATE_ENTER ||
127 iter.getState() == NodeIter::STATE_LEAVE);
128
129 return iter.getState() == NodeIter::STATE_ENTER ? STATE_ENTER_NODE : STATE_LEAVE_NODE;
130 }
131 else
132 return STATE_FINISHED;
133 }
134
getNode(void) const135 TestNode* TestHierarchyIterator::getNode (void) const
136 {
137 DE_ASSERT(getState() != STATE_FINISHED);
138 return m_sessionStack.back().node;
139 }
140
getNodePath(void) const141 const std::string& TestHierarchyIterator::getNodePath (void) const
142 {
143 DE_ASSERT(getState() != STATE_FINISHED);
144 return m_nodePath;
145 }
146
buildNodePath(const vector<NodeIter> & nodeStack)147 std::string TestHierarchyIterator::buildNodePath (const vector<NodeIter>& nodeStack)
148 {
149 string nodePath;
150 for (size_t ndx = 1; ndx < nodeStack.size(); ndx++)
151 {
152 const NodeIter& iter = nodeStack[ndx];
153 if (ndx > 1) // ignore root package
154 nodePath += ".";
155 nodePath += iter.node->getName();
156 }
157 return nodePath;
158 }
159
next(void)160 void TestHierarchyIterator::next (void)
161 {
162 while (!m_sessionStack.empty())
163 {
164 NodeIter& iter = m_sessionStack.back();
165 TestNode* const node = iter.node;
166 const bool isLeaf = isTestNodeTypeExecutable(node->getNodeType());
167
168 switch (iter.getState())
169 {
170 case NodeIter::STATE_INIT:
171 {
172 const std::string nodePath = buildNodePath(m_sessionStack);
173
174 // Return to parent if name doesn't match filter.
175 if (!(isLeaf ? m_cmdLine.checkTestCaseName(nodePath.c_str()) : m_cmdLine.checkTestGroupName(nodePath.c_str())))
176 {
177 m_sessionStack.pop_back();
178 break;
179 }
180
181 m_nodePath = nodePath;
182 iter.setState(NodeIter::STATE_ENTER);
183 return; // Yield enter event
184 }
185
186 case NodeIter::STATE_ENTER:
187 {
188 if (isLeaf)
189 {
190 iter.setState(NodeIter::STATE_LEAVE);
191 return; // Yield leave event
192 }
193 else
194 {
195 iter.setState(NodeIter::STATE_TRAVERSE_CHILDREN);
196 iter.children.clear();
197
198 switch (node->getNodeType())
199 {
200 case NODETYPE_ROOT: static_cast<TestPackageRoot*>(node)->getChildren(iter.children); break;
201 case NODETYPE_PACKAGE: m_inflater.enterTestPackage(static_cast<TestPackage*>(node), iter.children); break;
202 case NODETYPE_GROUP: m_inflater.enterGroupNode(static_cast<TestCaseGroup*>(node), iter.children); break;
203 default:
204 DE_ASSERT(false);
205 }
206 }
207
208 break;
209 }
210
211 case NodeIter::STATE_TRAVERSE_CHILDREN:
212 {
213 int numChildren = (int)iter.children.size();
214 if (++iter.curChildNdx < numChildren)
215 {
216 // Push child to stack.
217 TestNode* childNode = iter.children[iter.curChildNdx];
218 m_sessionStack.push_back(NodeIter(childNode));
219 }
220 else
221 {
222 iter.setState(NodeIter::STATE_LEAVE);
223 if (node->getNodeType() != NODETYPE_ROOT)
224 return; // Yield leave event
225 }
226
227 break;
228 }
229
230 case NodeIter::STATE_LEAVE:
231 {
232 // Leave node.
233 if (!isLeaf)
234 {
235 switch (node->getNodeType())
236 {
237 case NODETYPE_ROOT: /* root is not de-initialized */ break;
238 case NODETYPE_PACKAGE: m_inflater.leaveTestPackage(static_cast<TestPackage*>(node)); break;
239 case NODETYPE_GROUP: m_inflater.leaveGroupNode(static_cast<TestCaseGroup*>(node)); break;
240 default:
241 DE_ASSERT(false);
242 }
243 }
244
245 m_sessionStack.pop_back();
246 m_nodePath = buildNodePath(m_sessionStack);
247 break;
248 }
249
250 default:
251 DE_ASSERT(false);
252 return;
253 }
254 }
255
256 DE_ASSERT(m_sessionStack.empty() && getState() == STATE_FINISHED);
257 }
258
259 } // tcu
260