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