Merge "x11: Fix deadlock" into nougat-cts-dev am: 34b869eeea
[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 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
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
120 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
135 TestNode* TestHierarchyIterator::getNode (void) const
136 {
137         DE_ASSERT(getState() != STATE_FINISHED);
138         return m_sessionStack.back().node;
139 }
140
141 const std::string& TestHierarchyIterator::getNodePath (void) const
142 {
143         DE_ASSERT(getState() != STATE_FINISHED);
144         return m_nodePath;
145 }
146
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
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