1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * drawElements Quality Program Test Executor
3e5c31af7Sopenharmony_ci * ------------------------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright 2014 The Android Open Source Project
6e5c31af7Sopenharmony_ci *
7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
10e5c31af7Sopenharmony_ci *
11e5c31af7Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
12e5c31af7Sopenharmony_ci *
13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
17e5c31af7Sopenharmony_ci * limitations under the License.
18e5c31af7Sopenharmony_ci *
19e5c31af7Sopenharmony_ci *//*!
20e5c31af7Sopenharmony_ci * \file
21e5c31af7Sopenharmony_ci * \brief Test case.
22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
23e5c31af7Sopenharmony_ci
24e5c31af7Sopenharmony_ci#include "xeTestCase.hpp"
25e5c31af7Sopenharmony_ci
26e5c31af7Sopenharmony_ciusing std::vector;
27e5c31af7Sopenharmony_ci
28e5c31af7Sopenharmony_cinamespace xe
29e5c31af7Sopenharmony_ci{
30e5c31af7Sopenharmony_ci
31e5c31af7Sopenharmony_ciconst char* getTestCaseTypeName (TestCaseType caseType)
32e5c31af7Sopenharmony_ci{
33e5c31af7Sopenharmony_ci	switch (caseType)
34e5c31af7Sopenharmony_ci	{
35e5c31af7Sopenharmony_ci		case TESTCASETYPE_SELF_VALIDATE:	return "SelfValidate";
36e5c31af7Sopenharmony_ci		case TESTCASETYPE_CAPABILITY:		return "Capability";
37e5c31af7Sopenharmony_ci		case TESTCASETYPE_ACCURACY:			return "Accuracy";
38e5c31af7Sopenharmony_ci		case TESTCASETYPE_PERFORMANCE:		return "Performance";
39e5c31af7Sopenharmony_ci		default:
40e5c31af7Sopenharmony_ci			DE_ASSERT(false);
41e5c31af7Sopenharmony_ci			return DE_NULL;
42e5c31af7Sopenharmony_ci	}
43e5c31af7Sopenharmony_ci}
44e5c31af7Sopenharmony_ci
45e5c31af7Sopenharmony_cistatic inline int getFirstComponentLength (const char* path)
46e5c31af7Sopenharmony_ci{
47e5c31af7Sopenharmony_ci	int compLen = 0;
48e5c31af7Sopenharmony_ci	while (path[compLen] != 0 && path[compLen] != '.')
49e5c31af7Sopenharmony_ci		compLen++;
50e5c31af7Sopenharmony_ci	return compLen;
51e5c31af7Sopenharmony_ci}
52e5c31af7Sopenharmony_ci
53e5c31af7Sopenharmony_cistatic bool compareNameToPathComponent (const char* name, const char* path, int compLen)
54e5c31af7Sopenharmony_ci{
55e5c31af7Sopenharmony_ci	for (int pos = 0; pos < compLen; pos++)
56e5c31af7Sopenharmony_ci	{
57e5c31af7Sopenharmony_ci		if (name[pos] != path[pos])
58e5c31af7Sopenharmony_ci			return false;
59e5c31af7Sopenharmony_ci	}
60e5c31af7Sopenharmony_ci
61e5c31af7Sopenharmony_ci	if (name[compLen] != 0)
62e5c31af7Sopenharmony_ci		return false;
63e5c31af7Sopenharmony_ci
64e5c31af7Sopenharmony_ci	return true;
65e5c31af7Sopenharmony_ci}
66e5c31af7Sopenharmony_ci
67e5c31af7Sopenharmony_cistatic void splitPath (const char* path, std::vector<std::string>& components)
68e5c31af7Sopenharmony_ci{
69e5c31af7Sopenharmony_ci	std::string	pathStr		(path);
70e5c31af7Sopenharmony_ci	int			compStart	= 0;
71e5c31af7Sopenharmony_ci
72e5c31af7Sopenharmony_ci	for (int pos = 0; pos < (int)pathStr.length(); pos++)
73e5c31af7Sopenharmony_ci	{
74e5c31af7Sopenharmony_ci		if (pathStr[pos] == '.')
75e5c31af7Sopenharmony_ci		{
76e5c31af7Sopenharmony_ci			components.push_back(pathStr.substr(compStart, pos-compStart));
77e5c31af7Sopenharmony_ci			compStart = pos+1;
78e5c31af7Sopenharmony_ci		}
79e5c31af7Sopenharmony_ci	}
80e5c31af7Sopenharmony_ci
81e5c31af7Sopenharmony_ci	DE_ASSERT(compStart < (int)pathStr.length());
82e5c31af7Sopenharmony_ci	components.push_back(pathStr.substr(compStart));
83e5c31af7Sopenharmony_ci}
84e5c31af7Sopenharmony_ci
85e5c31af7Sopenharmony_ci// TestNode
86e5c31af7Sopenharmony_ci
87e5c31af7Sopenharmony_ciTestNode::TestNode (TestGroup* parent, TestNodeType nodeType, const char* name)
88e5c31af7Sopenharmony_ci	: m_parent		(parent)
89e5c31af7Sopenharmony_ci	, m_nodeType	(nodeType)
90e5c31af7Sopenharmony_ci	, m_name		(name)
91e5c31af7Sopenharmony_ci{
92e5c31af7Sopenharmony_ci	if (m_parent)
93e5c31af7Sopenharmony_ci	{
94e5c31af7Sopenharmony_ci		// Verify that the name is unique.
95e5c31af7Sopenharmony_ci		if (parent->m_childNames.find(name) != parent->m_childNames.end())
96e5c31af7Sopenharmony_ci			throw Error(std::string("Duplicate node '") + name + "' in '" + parent->getFullPath());
97e5c31af7Sopenharmony_ci
98e5c31af7Sopenharmony_ci		m_parent->m_children.push_back(this);
99e5c31af7Sopenharmony_ci		m_parent->m_childNames.insert(name);
100e5c31af7Sopenharmony_ci	}
101e5c31af7Sopenharmony_ci}
102e5c31af7Sopenharmony_ci
103e5c31af7Sopenharmony_civoid TestNode::getFullPath (std::string& dst) const
104e5c31af7Sopenharmony_ci{
105e5c31af7Sopenharmony_ci	dst.clear();
106e5c31af7Sopenharmony_ci
107e5c31af7Sopenharmony_ci	int				nameLen	= 0;
108e5c31af7Sopenharmony_ci	const TestNode*	curNode	= this;
109e5c31af7Sopenharmony_ci
110e5c31af7Sopenharmony_ci	for (;;)
111e5c31af7Sopenharmony_ci	{
112e5c31af7Sopenharmony_ci		nameLen += (int)curNode->m_name.length();
113e5c31af7Sopenharmony_ci
114e5c31af7Sopenharmony_ci		DE_ASSERT(curNode->m_parent);
115e5c31af7Sopenharmony_ci		if (curNode->m_parent->getNodeType() != TESTNODETYPE_ROOT)
116e5c31af7Sopenharmony_ci		{
117e5c31af7Sopenharmony_ci			nameLen += 1;
118e5c31af7Sopenharmony_ci			curNode  = curNode->m_parent;
119e5c31af7Sopenharmony_ci		}
120e5c31af7Sopenharmony_ci		else
121e5c31af7Sopenharmony_ci			break;
122e5c31af7Sopenharmony_ci	}
123e5c31af7Sopenharmony_ci
124e5c31af7Sopenharmony_ci	dst.resize(nameLen);
125e5c31af7Sopenharmony_ci
126e5c31af7Sopenharmony_ci	curNode = this;
127e5c31af7Sopenharmony_ci	int pos = nameLen;
128e5c31af7Sopenharmony_ci
129e5c31af7Sopenharmony_ci	for (;;)
130e5c31af7Sopenharmony_ci	{
131e5c31af7Sopenharmony_ci		std::copy(curNode->m_name.begin(), curNode->m_name.end(), dst.begin()+(pos-curNode->m_name.length()));
132e5c31af7Sopenharmony_ci		pos -= (int)curNode->m_name.length();
133e5c31af7Sopenharmony_ci
134e5c31af7Sopenharmony_ci		DE_ASSERT(curNode->m_parent);
135e5c31af7Sopenharmony_ci		if (curNode->m_parent->getNodeType() != TESTNODETYPE_ROOT)
136e5c31af7Sopenharmony_ci		{
137e5c31af7Sopenharmony_ci			dst[--pos] = '.';
138e5c31af7Sopenharmony_ci			curNode = curNode->m_parent;
139e5c31af7Sopenharmony_ci		}
140e5c31af7Sopenharmony_ci		else
141e5c31af7Sopenharmony_ci			break;
142e5c31af7Sopenharmony_ci	}
143e5c31af7Sopenharmony_ci}
144e5c31af7Sopenharmony_ci
145e5c31af7Sopenharmony_ciconst TestNode* TestNode::find (const char* path) const
146e5c31af7Sopenharmony_ci{
147e5c31af7Sopenharmony_ci	if (m_nodeType == TESTNODETYPE_ROOT)
148e5c31af7Sopenharmony_ci	{
149e5c31af7Sopenharmony_ci		// Don't need to consider current node.
150e5c31af7Sopenharmony_ci		return static_cast<const TestGroup*>(this)->findChildNode(path);
151e5c31af7Sopenharmony_ci	}
152e5c31af7Sopenharmony_ci	else
153e5c31af7Sopenharmony_ci	{
154e5c31af7Sopenharmony_ci		// Check if first component matches this node.
155e5c31af7Sopenharmony_ci		int compLen = getFirstComponentLength(path);
156e5c31af7Sopenharmony_ci		XE_CHECK(compLen > 0);
157e5c31af7Sopenharmony_ci
158e5c31af7Sopenharmony_ci		if (compareNameToPathComponent(getName(), path, compLen))
159e5c31af7Sopenharmony_ci		{
160e5c31af7Sopenharmony_ci			if (path[compLen] == 0)
161e5c31af7Sopenharmony_ci				return this;
162e5c31af7Sopenharmony_ci			else if (getNodeType() == TESTNODETYPE_GROUP)
163e5c31af7Sopenharmony_ci				return static_cast<const TestGroup*>(this)->findChildNode(path + compLen + 1);
164e5c31af7Sopenharmony_ci			else
165e5c31af7Sopenharmony_ci				return DE_NULL;
166e5c31af7Sopenharmony_ci		}
167e5c31af7Sopenharmony_ci		else
168e5c31af7Sopenharmony_ci			return DE_NULL;
169e5c31af7Sopenharmony_ci	}
170e5c31af7Sopenharmony_ci}
171e5c31af7Sopenharmony_ci
172e5c31af7Sopenharmony_ciTestNode* TestNode::find (const char* path)
173e5c31af7Sopenharmony_ci{
174e5c31af7Sopenharmony_ci	return const_cast<TestNode*>(const_cast<const TestNode*>(this)->find(path));
175e5c31af7Sopenharmony_ci}
176e5c31af7Sopenharmony_ci
177e5c31af7Sopenharmony_ci// TestGroup
178e5c31af7Sopenharmony_ci
179e5c31af7Sopenharmony_ciTestGroup::TestGroup (TestGroup* parent, TestNodeType nodeType, const char* name)
180e5c31af7Sopenharmony_ci	: TestNode(parent, nodeType, name)
181e5c31af7Sopenharmony_ci{
182e5c31af7Sopenharmony_ci	DE_ASSERT(nodeType == TESTNODETYPE_GROUP || nodeType == TESTNODETYPE_ROOT);
183e5c31af7Sopenharmony_ci	DE_ASSERT(!parent == (nodeType == TESTNODETYPE_ROOT));
184e5c31af7Sopenharmony_ci}
185e5c31af7Sopenharmony_ci
186e5c31af7Sopenharmony_ciTestGroup::~TestGroup (void)
187e5c31af7Sopenharmony_ci{
188e5c31af7Sopenharmony_ci	for (std::vector<TestNode*>::iterator i = m_children.begin(); i != m_children.end(); i++)
189e5c31af7Sopenharmony_ci		delete *i;
190e5c31af7Sopenharmony_ci}
191e5c31af7Sopenharmony_ci
192e5c31af7Sopenharmony_ciTestGroup* TestGroup::createGroup (const char* name)
193e5c31af7Sopenharmony_ci{
194e5c31af7Sopenharmony_ci	return new TestGroup(this, TESTNODETYPE_GROUP, name);
195e5c31af7Sopenharmony_ci}
196e5c31af7Sopenharmony_ci
197e5c31af7Sopenharmony_ciTestCase* TestGroup::createCase (TestCaseType caseType, const char* name)
198e5c31af7Sopenharmony_ci{
199e5c31af7Sopenharmony_ci	return TestCase::createAsChild(this, caseType, name);
200e5c31af7Sopenharmony_ci}
201e5c31af7Sopenharmony_ci
202e5c31af7Sopenharmony_ciconst TestNode* TestGroup::findChildNode (const char* path) const
203e5c31af7Sopenharmony_ci{
204e5c31af7Sopenharmony_ci	int compLen = getFirstComponentLength(path);
205e5c31af7Sopenharmony_ci	XE_CHECK(compLen > 0);
206e5c31af7Sopenharmony_ci
207e5c31af7Sopenharmony_ci	// Try to find matching children.
208e5c31af7Sopenharmony_ci	const TestNode* matchingNode = DE_NULL;
209e5c31af7Sopenharmony_ci	for (vector<TestNode*>::const_iterator iter = m_children.begin(); iter != m_children.end(); iter++)
210e5c31af7Sopenharmony_ci	{
211e5c31af7Sopenharmony_ci		if (compareNameToPathComponent((*iter)->getName(), path, compLen))
212e5c31af7Sopenharmony_ci		{
213e5c31af7Sopenharmony_ci			matchingNode = *iter;
214e5c31af7Sopenharmony_ci			break;
215e5c31af7Sopenharmony_ci		}
216e5c31af7Sopenharmony_ci	}
217e5c31af7Sopenharmony_ci
218e5c31af7Sopenharmony_ci	if (matchingNode)
219e5c31af7Sopenharmony_ci	{
220e5c31af7Sopenharmony_ci		if (path[compLen] == 0)
221e5c31af7Sopenharmony_ci			return matchingNode; // Last element in path, return matching node.
222e5c31af7Sopenharmony_ci		else if (matchingNode->getNodeType() == TESTNODETYPE_GROUP)
223e5c31af7Sopenharmony_ci			return static_cast<const TestGroup*>(matchingNode)->findChildNode(path + compLen + 1);
224e5c31af7Sopenharmony_ci		else
225e5c31af7Sopenharmony_ci			return DE_NULL;
226e5c31af7Sopenharmony_ci	}
227e5c31af7Sopenharmony_ci	else
228e5c31af7Sopenharmony_ci		return DE_NULL;
229e5c31af7Sopenharmony_ci}
230e5c31af7Sopenharmony_ci
231e5c31af7Sopenharmony_ci// TestRoot
232e5c31af7Sopenharmony_ci
233e5c31af7Sopenharmony_ciTestRoot::TestRoot (void)
234e5c31af7Sopenharmony_ci	: TestGroup(DE_NULL, TESTNODETYPE_ROOT, "")
235e5c31af7Sopenharmony_ci{
236e5c31af7Sopenharmony_ci}
237e5c31af7Sopenharmony_ci
238e5c31af7Sopenharmony_ci// TestCase
239e5c31af7Sopenharmony_ci
240e5c31af7Sopenharmony_ciTestCase* TestCase::createAsChild(TestGroup* parent, TestCaseType caseType, const char *name)
241e5c31af7Sopenharmony_ci{
242e5c31af7Sopenharmony_ci	return new TestCase(parent, caseType, name);
243e5c31af7Sopenharmony_ci}
244e5c31af7Sopenharmony_ci
245e5c31af7Sopenharmony_ciTestCase::TestCase (TestGroup* parent, TestCaseType caseType, const char* name)
246e5c31af7Sopenharmony_ci	: TestNode		(parent, TESTNODETYPE_TEST_CASE, name)
247e5c31af7Sopenharmony_ci	, m_caseType	(caseType)
248e5c31af7Sopenharmony_ci{
249e5c31af7Sopenharmony_ci}
250e5c31af7Sopenharmony_ci
251e5c31af7Sopenharmony_ciTestCase::~TestCase (void)
252e5c31af7Sopenharmony_ci{
253e5c31af7Sopenharmony_ci}
254e5c31af7Sopenharmony_ci
255e5c31af7Sopenharmony_ci// TestHierarchyBuilder helpers
256e5c31af7Sopenharmony_ci
257e5c31af7Sopenharmony_civoid addChildGroupsToMap (std::map<std::string, TestGroup*>& groupMap, TestGroup* group)
258e5c31af7Sopenharmony_ci{
259e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < group->getNumChildren(); ndx++)
260e5c31af7Sopenharmony_ci	{
261e5c31af7Sopenharmony_ci		TestNode* node = group->getChild(ndx);
262e5c31af7Sopenharmony_ci		if (node->getNodeType() == TESTNODETYPE_GROUP)
263e5c31af7Sopenharmony_ci		{
264e5c31af7Sopenharmony_ci			TestGroup*	childGroup	= static_cast<TestGroup*>(node);
265e5c31af7Sopenharmony_ci			std::string	fullPath;
266e5c31af7Sopenharmony_ci			childGroup->getFullPath(fullPath);
267e5c31af7Sopenharmony_ci
268e5c31af7Sopenharmony_ci			groupMap.insert(std::make_pair(fullPath, childGroup));
269e5c31af7Sopenharmony_ci			addChildGroupsToMap(groupMap, childGroup);
270e5c31af7Sopenharmony_ci		}
271e5c31af7Sopenharmony_ci	}
272e5c31af7Sopenharmony_ci}
273e5c31af7Sopenharmony_ci
274e5c31af7Sopenharmony_ci// TestHierarchyBuilder
275e5c31af7Sopenharmony_ci
276e5c31af7Sopenharmony_ciTestHierarchyBuilder::TestHierarchyBuilder (TestRoot* root)
277e5c31af7Sopenharmony_ci	: m_root(root)
278e5c31af7Sopenharmony_ci{
279e5c31af7Sopenharmony_ci	addChildGroupsToMap(m_groupMap, root);
280e5c31af7Sopenharmony_ci}
281e5c31af7Sopenharmony_ci
282e5c31af7Sopenharmony_ciTestHierarchyBuilder::~TestHierarchyBuilder (void)
283e5c31af7Sopenharmony_ci{
284e5c31af7Sopenharmony_ci}
285e5c31af7Sopenharmony_ci
286e5c31af7Sopenharmony_ciTestCase* TestHierarchyBuilder::createCase (const char* path, TestCaseType caseType)
287e5c31af7Sopenharmony_ci{
288e5c31af7Sopenharmony_ci	// \todo [2012-09-05 pyry] This can be done with less string manipulations.
289e5c31af7Sopenharmony_ci	std::vector<std::string> components;
290e5c31af7Sopenharmony_ci	splitPath(path, components);
291e5c31af7Sopenharmony_ci	DE_ASSERT(!components.empty());
292e5c31af7Sopenharmony_ci
293e5c31af7Sopenharmony_ci	// Create all parents if necessary.
294e5c31af7Sopenharmony_ci	TestGroup*	curGroup		= m_root;
295e5c31af7Sopenharmony_ci	std::string	curGroupPath;
296e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < (int)components.size()-1; ndx++)
297e5c31af7Sopenharmony_ci	{
298e5c31af7Sopenharmony_ci		if (!curGroupPath.empty())
299e5c31af7Sopenharmony_ci			curGroupPath += ".";
300e5c31af7Sopenharmony_ci		curGroupPath += components[ndx];
301e5c31af7Sopenharmony_ci
302e5c31af7Sopenharmony_ci		std::map<std::string, TestGroup*>::const_iterator groupPos = m_groupMap.find(curGroupPath);
303e5c31af7Sopenharmony_ci		if (groupPos == m_groupMap.end())
304e5c31af7Sopenharmony_ci		{
305e5c31af7Sopenharmony_ci			TestGroup* newGroup = curGroup->createGroup(components[ndx].c_str());
306e5c31af7Sopenharmony_ci			m_groupMap.insert(std::make_pair(curGroupPath, newGroup));
307e5c31af7Sopenharmony_ci			curGroup = newGroup;
308e5c31af7Sopenharmony_ci		}
309e5c31af7Sopenharmony_ci		else
310e5c31af7Sopenharmony_ci			curGroup = groupPos->second;
311e5c31af7Sopenharmony_ci	}
312e5c31af7Sopenharmony_ci
313e5c31af7Sopenharmony_ci	return curGroup->createCase(caseType, components.back().c_str());
314e5c31af7Sopenharmony_ci}
315e5c31af7Sopenharmony_ci
316e5c31af7Sopenharmony_ci// TestSet helpers
317e5c31af7Sopenharmony_ci
318e5c31af7Sopenharmony_cistatic void addNodeAndParents (std::set<const TestNode*>& nodeSet, const TestNode* node)
319e5c31af7Sopenharmony_ci{
320e5c31af7Sopenharmony_ci	while (node != DE_NULL)
321e5c31af7Sopenharmony_ci	{
322e5c31af7Sopenharmony_ci		nodeSet.insert(node);
323e5c31af7Sopenharmony_ci		node = node->getParent();
324e5c31af7Sopenharmony_ci	}
325e5c31af7Sopenharmony_ci}
326e5c31af7Sopenharmony_ci
327e5c31af7Sopenharmony_cistatic void addChildren (std::set<const TestNode*>& nodeSet, const TestGroup* group)
328e5c31af7Sopenharmony_ci{
329e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < group->getNumChildren(); ndx++)
330e5c31af7Sopenharmony_ci	{
331e5c31af7Sopenharmony_ci		const TestNode* child = group->getChild(ndx);
332e5c31af7Sopenharmony_ci		nodeSet.insert(child);
333e5c31af7Sopenharmony_ci
334e5c31af7Sopenharmony_ci		if (child->getNodeType() == TESTNODETYPE_GROUP)
335e5c31af7Sopenharmony_ci			addChildren(nodeSet, static_cast<const TestGroup*>(child));
336e5c31af7Sopenharmony_ci	}
337e5c31af7Sopenharmony_ci}
338e5c31af7Sopenharmony_ci
339e5c31af7Sopenharmony_cistatic void removeChildren (std::set<const TestNode*>& nodeSet, const TestGroup* group)
340e5c31af7Sopenharmony_ci{
341e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < group->getNumChildren(); ndx++)
342e5c31af7Sopenharmony_ci	{
343e5c31af7Sopenharmony_ci		const TestNode* child = group->getChild(ndx);
344e5c31af7Sopenharmony_ci		nodeSet.erase(child);
345e5c31af7Sopenharmony_ci
346e5c31af7Sopenharmony_ci		if (child->getNodeType() == TESTNODETYPE_GROUP)
347e5c31af7Sopenharmony_ci			removeChildren(nodeSet, static_cast<const TestGroup*>(child));
348e5c31af7Sopenharmony_ci	}
349e5c31af7Sopenharmony_ci}
350e5c31af7Sopenharmony_ci
351e5c31af7Sopenharmony_cistatic bool hasChildrenInSet (const std::set<const TestNode*>& nodeSet, const TestGroup* group)
352e5c31af7Sopenharmony_ci{
353e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < group->getNumChildren(); ndx++)
354e5c31af7Sopenharmony_ci	{
355e5c31af7Sopenharmony_ci		if (nodeSet.find(group->getChild(ndx)) != nodeSet.end())
356e5c31af7Sopenharmony_ci			return true;
357e5c31af7Sopenharmony_ci	}
358e5c31af7Sopenharmony_ci	return false;
359e5c31af7Sopenharmony_ci}
360e5c31af7Sopenharmony_ci
361e5c31af7Sopenharmony_cistatic void removeEmptyGroups (std::set<const TestNode*>& nodeSet, const TestGroup* group)
362e5c31af7Sopenharmony_ci{
363e5c31af7Sopenharmony_ci	if (!hasChildrenInSet(nodeSet, group))
364e5c31af7Sopenharmony_ci	{
365e5c31af7Sopenharmony_ci		nodeSet.erase(group);
366e5c31af7Sopenharmony_ci		if (group->getParent() != DE_NULL)
367e5c31af7Sopenharmony_ci			removeEmptyGroups(nodeSet, group->getParent());
368e5c31af7Sopenharmony_ci	}
369e5c31af7Sopenharmony_ci}
370e5c31af7Sopenharmony_ci
371e5c31af7Sopenharmony_ci// TestSet
372e5c31af7Sopenharmony_ci
373e5c31af7Sopenharmony_civoid TestSet::add (const TestNode* node)
374e5c31af7Sopenharmony_ci{
375e5c31af7Sopenharmony_ci	if (node->getNodeType() == TESTNODETYPE_TEST_CASE)
376e5c31af7Sopenharmony_ci		addCase(static_cast<const TestCase*>(node));
377e5c31af7Sopenharmony_ci	else
378e5c31af7Sopenharmony_ci	{
379e5c31af7Sopenharmony_ci		XE_CHECK(node->getNodeType() == TESTNODETYPE_GROUP ||
380e5c31af7Sopenharmony_ci				  node->getNodeType() == TESTNODETYPE_ROOT);
381e5c31af7Sopenharmony_ci		addGroup(static_cast<const TestGroup*>(node));
382e5c31af7Sopenharmony_ci	}
383e5c31af7Sopenharmony_ci}
384e5c31af7Sopenharmony_ci
385e5c31af7Sopenharmony_civoid TestSet::addCase (const TestCase* testCase)
386e5c31af7Sopenharmony_ci{
387e5c31af7Sopenharmony_ci	addNodeAndParents(m_set, testCase);
388e5c31af7Sopenharmony_ci}
389e5c31af7Sopenharmony_ci
390e5c31af7Sopenharmony_civoid TestSet::addGroup (const TestGroup* testGroup)
391e5c31af7Sopenharmony_ci{
392e5c31af7Sopenharmony_ci	addNodeAndParents(m_set, testGroup);
393e5c31af7Sopenharmony_ci	addChildren(m_set, testGroup);
394e5c31af7Sopenharmony_ci}
395e5c31af7Sopenharmony_ci
396e5c31af7Sopenharmony_civoid TestSet::remove (const TestNode* node)
397e5c31af7Sopenharmony_ci{
398e5c31af7Sopenharmony_ci	if (node->getNodeType() == TESTNODETYPE_TEST_CASE)
399e5c31af7Sopenharmony_ci		removeCase(static_cast<const TestCase*>(node));
400e5c31af7Sopenharmony_ci	else
401e5c31af7Sopenharmony_ci	{
402e5c31af7Sopenharmony_ci		XE_CHECK(node->getNodeType() == TESTNODETYPE_GROUP ||
403e5c31af7Sopenharmony_ci				  node->getNodeType() == TESTNODETYPE_ROOT);
404e5c31af7Sopenharmony_ci		removeGroup(static_cast<const TestGroup*>(node));
405e5c31af7Sopenharmony_ci	}
406e5c31af7Sopenharmony_ci}
407e5c31af7Sopenharmony_ci
408e5c31af7Sopenharmony_civoid TestSet::removeCase (const TestCase* testCase)
409e5c31af7Sopenharmony_ci{
410e5c31af7Sopenharmony_ci	if (m_set.find(testCase) != m_set.end())
411e5c31af7Sopenharmony_ci	{
412e5c31af7Sopenharmony_ci		m_set.erase(testCase);
413e5c31af7Sopenharmony_ci		removeEmptyGroups(m_set, testCase->getParent());
414e5c31af7Sopenharmony_ci	}
415e5c31af7Sopenharmony_ci}
416e5c31af7Sopenharmony_ci
417e5c31af7Sopenharmony_civoid TestSet::removeGroup (const TestGroup* testGroup)
418e5c31af7Sopenharmony_ci{
419e5c31af7Sopenharmony_ci	if (m_set.find(testGroup) != m_set.end())
420e5c31af7Sopenharmony_ci	{
421e5c31af7Sopenharmony_ci		m_set.erase(testGroup);
422e5c31af7Sopenharmony_ci		removeChildren(m_set, testGroup);
423e5c31af7Sopenharmony_ci		if (testGroup->getParent() != DE_NULL)
424e5c31af7Sopenharmony_ci			removeEmptyGroups(m_set, testGroup->getParent());
425e5c31af7Sopenharmony_ci	}
426e5c31af7Sopenharmony_ci}
427e5c31af7Sopenharmony_ci
428e5c31af7Sopenharmony_ci// ConstTestNodeIterator
429e5c31af7Sopenharmony_ci
430e5c31af7Sopenharmony_ciConstTestNodeIterator::ConstTestNodeIterator (const TestNode* root)
431e5c31af7Sopenharmony_ci	: m_root(root)
432e5c31af7Sopenharmony_ci{
433e5c31af7Sopenharmony_ci}
434e5c31af7Sopenharmony_ci
435e5c31af7Sopenharmony_ciConstTestNodeIterator ConstTestNodeIterator::begin (const TestNode* root)
436e5c31af7Sopenharmony_ci{
437e5c31af7Sopenharmony_ci	ConstTestNodeIterator iter(root);
438e5c31af7Sopenharmony_ci	iter.m_iterStack.push_back(GroupState(DE_NULL));
439e5c31af7Sopenharmony_ci	return iter;
440e5c31af7Sopenharmony_ci}
441e5c31af7Sopenharmony_ci
442e5c31af7Sopenharmony_ciConstTestNodeIterator ConstTestNodeIterator::end (const TestNode* root)
443e5c31af7Sopenharmony_ci{
444e5c31af7Sopenharmony_ci	DE_UNREF(root);
445e5c31af7Sopenharmony_ci	return ConstTestNodeIterator(root);
446e5c31af7Sopenharmony_ci}
447e5c31af7Sopenharmony_ci
448e5c31af7Sopenharmony_ciConstTestNodeIterator& ConstTestNodeIterator::operator++ (void)
449e5c31af7Sopenharmony_ci{
450e5c31af7Sopenharmony_ci	DE_ASSERT(!m_iterStack.empty());
451e5c31af7Sopenharmony_ci
452e5c31af7Sopenharmony_ci	const TestNode*	curNode			= **this;
453e5c31af7Sopenharmony_ci	TestNodeType	curNodeType		= curNode->getNodeType();
454e5c31af7Sopenharmony_ci
455e5c31af7Sopenharmony_ci	if ((curNodeType == TESTNODETYPE_GROUP || curNodeType == TESTNODETYPE_ROOT) &&
456e5c31af7Sopenharmony_ci		static_cast<const TestGroup*>(curNode)->getNumChildren() > 0)
457e5c31af7Sopenharmony_ci	{
458e5c31af7Sopenharmony_ci		m_iterStack.push_back(GroupState(static_cast<const TestGroup*>(curNode)));
459e5c31af7Sopenharmony_ci	}
460e5c31af7Sopenharmony_ci	else
461e5c31af7Sopenharmony_ci	{
462e5c31af7Sopenharmony_ci		for (;;)
463e5c31af7Sopenharmony_ci		{
464e5c31af7Sopenharmony_ci			const TestGroup*	group		= m_iterStack.back().group;
465e5c31af7Sopenharmony_ci			int&				childNdx	= m_iterStack.back().childNdx;
466e5c31af7Sopenharmony_ci			int					numChildren	= group ? group->getNumChildren() : 1;
467e5c31af7Sopenharmony_ci
468e5c31af7Sopenharmony_ci			childNdx += 1;
469e5c31af7Sopenharmony_ci			if (childNdx == numChildren)
470e5c31af7Sopenharmony_ci			{
471e5c31af7Sopenharmony_ci				m_iterStack.pop_back();
472e5c31af7Sopenharmony_ci				if (m_iterStack.empty())
473e5c31af7Sopenharmony_ci					break;
474e5c31af7Sopenharmony_ci			}
475e5c31af7Sopenharmony_ci			else
476e5c31af7Sopenharmony_ci				break;
477e5c31af7Sopenharmony_ci		}
478e5c31af7Sopenharmony_ci	}
479e5c31af7Sopenharmony_ci
480e5c31af7Sopenharmony_ci	return *this;
481e5c31af7Sopenharmony_ci}
482e5c31af7Sopenharmony_ci
483e5c31af7Sopenharmony_ciConstTestNodeIterator ConstTestNodeIterator::operator++ (int)
484e5c31af7Sopenharmony_ci{
485e5c31af7Sopenharmony_ci	ConstTestNodeIterator copy(*this);
486e5c31af7Sopenharmony_ci	++(*this);
487e5c31af7Sopenharmony_ci	return copy;
488e5c31af7Sopenharmony_ci}
489e5c31af7Sopenharmony_ci
490e5c31af7Sopenharmony_ciconst TestNode* ConstTestNodeIterator::operator* (void) const
491e5c31af7Sopenharmony_ci{
492e5c31af7Sopenharmony_ci	DE_ASSERT(!m_iterStack.empty());
493e5c31af7Sopenharmony_ci	if (m_iterStack.size() == 1)
494e5c31af7Sopenharmony_ci	{
495e5c31af7Sopenharmony_ci		DE_ASSERT(m_iterStack[0].group == DE_NULL && m_iterStack[0].childNdx == 0);
496e5c31af7Sopenharmony_ci		return m_root;
497e5c31af7Sopenharmony_ci	}
498e5c31af7Sopenharmony_ci	else
499e5c31af7Sopenharmony_ci		return m_iterStack.back().group->getChild(m_iterStack.back().childNdx);
500e5c31af7Sopenharmony_ci}
501e5c31af7Sopenharmony_ci
502e5c31af7Sopenharmony_cibool ConstTestNodeIterator::operator!= (const ConstTestNodeIterator& other) const
503e5c31af7Sopenharmony_ci{
504e5c31af7Sopenharmony_ci	return m_root != other.m_root || m_iterStack != other.m_iterStack;
505e5c31af7Sopenharmony_ci}
506e5c31af7Sopenharmony_ci
507e5c31af7Sopenharmony_ci} // xe
508