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 hierarchy utilities. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "tcuTestHierarchyUtil.hpp" 25 #include "tcuStringTemplate.hpp" 26 #include "tcuCommandLine.hpp" 27 28 #include "qpXmlWriter.h" 29 30 #include <fstream> 31 32 namespace tcu 33 { 34 35 using std::string; 36 37 static const char* getNodeTypeName (TestNodeType nodeType) 38 { 39 switch (nodeType) 40 { 41 case NODETYPE_SELF_VALIDATE: return "SelfValidate"; 42 case NODETYPE_CAPABILITY: return "Capability"; 43 case NODETYPE_ACCURACY: return "Accuracy"; 44 case NODETYPE_PERFORMANCE: return "Performance"; 45 case NODETYPE_GROUP: return "TestGroup"; 46 default: 47 DE_ASSERT(false); 48 return DE_NULL; 49 } 50 } 51 52 // Utilities 53 54 static std::string makePackageFilename (const std::string& pattern, const std::string& packageName, const std::string& typeExtension) 55 { 56 std::map<string, string> args; 57 args["packageName"] = packageName; 58 args["typeExtension"] = typeExtension; 59 return StringTemplate(pattern).specialize(args); 60 } 61 62 static void writeXmlCaselist (TestHierarchyIterator& iter, qpXmlWriter* writer) 63 { 64 DE_ASSERT(iter.getState() == TestHierarchyIterator::STATE_ENTER_NODE && 65 iter.getNode()->getNodeType() == NODETYPE_PACKAGE); 66 67 { 68 const TestNode* node = iter.getNode(); 69 qpXmlAttribute attribs[2]; 70 int numAttribs = 0; 71 attribs[numAttribs++] = qpSetStringAttrib("PackageName", node->getName()); 72 attribs[numAttribs++] = qpSetStringAttrib("Description", node->getDescription()); 73 DE_ASSERT(numAttribs <= DE_LENGTH_OF_ARRAY(attribs)); 74 75 if (!qpXmlWriter_startDocument(writer) || 76 !qpXmlWriter_startElement(writer, "TestCaseList", numAttribs, attribs)) 77 throw Exception("Failed to start XML document"); 78 } 79 80 iter.next(); 81 82 while (iter.getNode()->getNodeType() != NODETYPE_PACKAGE) 83 { 84 const TestNode* const node = iter.getNode(); 85 const TestNodeType nodeType = node->getNodeType(); 86 const bool isEnter = iter.getState() == TestHierarchyIterator::STATE_ENTER_NODE; 87 88 DE_ASSERT(iter.getState() == TestHierarchyIterator::STATE_ENTER_NODE || 89 iter.getState() == TestHierarchyIterator::STATE_LEAVE_NODE); 90 { 91 if (isEnter) 92 { 93 const string caseName = node->getName(); 94 const string description = node->getDescription(); 95 qpXmlAttribute attribs[3]; 96 int numAttribs = 0; 97 98 attribs[numAttribs++] = qpSetStringAttrib("Name", caseName.c_str()); 99 attribs[numAttribs++] = qpSetStringAttrib("CaseType", getNodeTypeName(nodeType)); 100 attribs[numAttribs++] = qpSetStringAttrib("Description", description.c_str()); 101 DE_ASSERT(numAttribs <= DE_LENGTH_OF_ARRAY(attribs)); 102 103 if (!qpXmlWriter_startElement(writer, "TestCase", numAttribs, attribs)) 104 throw Exception("Writing to case list file failed"); 105 } 106 else 107 { 108 if (!qpXmlWriter_endElement(writer, "TestCase")) 109 throw tcu::Exception("Writing to case list file failed"); 110 } 111 } 112 113 iter.next(); 114 } 115 116 // This could be done in catch, but the file is corrupt at that point anyways. 117 if (!qpXmlWriter_endElement(writer, "TestCaseList") || 118 !qpXmlWriter_endDocument(writer)) 119 throw Exception("Failed to terminate XML document"); 120 } 121 122 /*--------------------------------------------------------------------*//*! 123 * \brief Export the test list of each package into a separate XML file. 124 *//*--------------------------------------------------------------------*/ 125 void writeXmlCaselistsToFiles (TestPackageRoot& root, TestContext& testCtx, const CommandLine& cmdLine) 126 { 127 DefaultHierarchyInflater inflater (testCtx); 128 TestHierarchyIterator iter (root, inflater, cmdLine); 129 const char* const filenamePattern = cmdLine.getCaseListExportFile(); 130 131 while (iter.getState() != TestHierarchyIterator::STATE_FINISHED) 132 { 133 const TestNode* node = iter.getNode(); 134 const char* pkgName = node->getName(); 135 const string filename = makePackageFilename(filenamePattern, pkgName, "xml"); 136 137 DE_ASSERT(iter.getState() == TestHierarchyIterator::STATE_ENTER_NODE && 138 node->getNodeType() == NODETYPE_PACKAGE); 139 140 FILE* file = DE_NULL; 141 qpXmlWriter* writer = DE_NULL; 142 143 try 144 { 145 file = fopen(filename.c_str(), "wb"); 146 if (!file) 147 throw Exception("Failed to open " + filename); 148 149 writer = qpXmlWriter_createFileWriter(file, DE_FALSE, DE_FALSE); 150 if (!writer) 151 throw Exception("XML writer creation failed"); 152 153 print("Writing test cases from '%s' to file '%s'..\n", pkgName, filename.c_str()); 154 155 writeXmlCaselist(iter, writer); 156 157 qpXmlWriter_destroy(writer); 158 writer = DE_NULL; 159 160 fclose(file); 161 file = DE_NULL; 162 } 163 catch (...) 164 { 165 if (writer) 166 qpXmlWriter_destroy(writer); 167 if (file) 168 fclose(file); 169 throw; 170 } 171 172 DE_ASSERT(iter.getState() == TestHierarchyIterator::STATE_LEAVE_NODE && 173 iter.getNode()->getNodeType() == NODETYPE_PACKAGE); 174 iter.next(); 175 } 176 } 177 178 /*--------------------------------------------------------------------*//*! 179 * \brief Export the test list of each package into a separate ascii file. 180 *//*--------------------------------------------------------------------*/ 181 void writeTxtCaselistsToFiles (TestPackageRoot& root, TestContext& testCtx, const CommandLine& cmdLine) 182 { 183 DefaultHierarchyInflater inflater (testCtx); 184 TestHierarchyIterator iter (root, inflater, cmdLine); 185 const char* const filenamePattern = cmdLine.getCaseListExportFile(); 186 187 while (iter.getState() != TestHierarchyIterator::STATE_FINISHED) 188 { 189 const TestNode* node = iter.getNode(); 190 const char* pkgName = node->getName(); 191 const string filename = makePackageFilename(filenamePattern, pkgName, "txt"); 192 193 DE_ASSERT(iter.getState() == TestHierarchyIterator::STATE_ENTER_NODE && 194 node->getNodeType() == NODETYPE_PACKAGE); 195 196 std::ofstream out(filename.c_str(), std::ios_base::binary); 197 if (!out.is_open() || !out.good()) 198 throw Exception("Failed to open " + filename); 199 200 print("Writing test cases from '%s' to file '%s'..\n", pkgName, filename.c_str()); 201 202 iter.next(); 203 204 while (iter.getNode()->getNodeType() != NODETYPE_PACKAGE) 205 { 206 if (iter.getState() == TestHierarchyIterator::STATE_ENTER_NODE) 207 out << (isTestNodeTypeExecutable(iter.getNode()->getNodeType()) ? "TEST" : "GROUP") << ": " << iter.getNodePath() << "\n"; 208 iter.next(); 209 } 210 211 DE_ASSERT(iter.getState() == TestHierarchyIterator::STATE_LEAVE_NODE && 212 iter.getNode()->getNodeType() == NODETYPE_PACKAGE); 213 iter.next(); 214 } 215 } 216 217 } // tcu 218