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