| /*------------------------------------------------------------------------- |
| * drawElements Quality Program Tester Core |
| * ---------------------------------------- |
| * |
| * Copyright 2014 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| *//*! |
| * \file |
| * \brief Test hierarchy utilities. |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "tcuTestHierarchyUtil.hpp" |
| #include "tcuStringTemplate.hpp" |
| #include "tcuCommandLine.hpp" |
| |
| #include "qpXmlWriter.h" |
| |
| #include <fstream> |
| |
| namespace tcu |
| { |
| |
| using std::string; |
| |
| static const char* getNodeTypeName (TestNodeType nodeType) |
| { |
| switch (nodeType) |
| { |
| case NODETYPE_SELF_VALIDATE: return "SelfValidate"; |
| case NODETYPE_CAPABILITY: return "Capability"; |
| case NODETYPE_ACCURACY: return "Accuracy"; |
| case NODETYPE_PERFORMANCE: return "Performance"; |
| case NODETYPE_GROUP: return "TestGroup"; |
| default: |
| DE_ASSERT(false); |
| return DE_NULL; |
| } |
| } |
| |
| // Utilities |
| |
| static std::string makePackageFilename (const std::string& pattern, const std::string& packageName, const std::string& typeExtension) |
| { |
| std::map<string, string> args; |
| args["packageName"] = packageName; |
| args["typeExtension"] = typeExtension; |
| return StringTemplate(pattern).specialize(args); |
| } |
| |
| static void writeXmlCaselist (TestHierarchyIterator& iter, qpXmlWriter* writer) |
| { |
| DE_ASSERT(iter.getState() == TestHierarchyIterator::STATE_ENTER_NODE && |
| iter.getNode()->getNodeType() == NODETYPE_PACKAGE); |
| |
| { |
| const TestNode* node = iter.getNode(); |
| qpXmlAttribute attribs[2]; |
| int numAttribs = 0; |
| attribs[numAttribs++] = qpSetStringAttrib("PackageName", node->getName()); |
| attribs[numAttribs++] = qpSetStringAttrib("Description", node->getDescription()); |
| DE_ASSERT(numAttribs <= DE_LENGTH_OF_ARRAY(attribs)); |
| |
| if (!qpXmlWriter_startDocument(writer) || |
| !qpXmlWriter_startElement(writer, "TestCaseList", numAttribs, attribs)) |
| throw Exception("Failed to start XML document"); |
| } |
| |
| iter.next(); |
| |
| while (iter.getNode()->getNodeType() != NODETYPE_PACKAGE) |
| { |
| const TestNode* const node = iter.getNode(); |
| const TestNodeType nodeType = node->getNodeType(); |
| const bool isEnter = iter.getState() == TestHierarchyIterator::STATE_ENTER_NODE; |
| |
| DE_ASSERT(iter.getState() == TestHierarchyIterator::STATE_ENTER_NODE || |
| iter.getState() == TestHierarchyIterator::STATE_LEAVE_NODE); |
| { |
| if (isEnter) |
| { |
| const string caseName = node->getName(); |
| const string description = node->getDescription(); |
| qpXmlAttribute attribs[3]; |
| int numAttribs = 0; |
| |
| attribs[numAttribs++] = qpSetStringAttrib("Name", caseName.c_str()); |
| attribs[numAttribs++] = qpSetStringAttrib("CaseType", getNodeTypeName(nodeType)); |
| attribs[numAttribs++] = qpSetStringAttrib("Description", description.c_str()); |
| DE_ASSERT(numAttribs <= DE_LENGTH_OF_ARRAY(attribs)); |
| |
| if (!qpXmlWriter_startElement(writer, "TestCase", numAttribs, attribs)) |
| throw Exception("Writing to case list file failed"); |
| } |
| else |
| { |
| if (!qpXmlWriter_endElement(writer, "TestCase")) |
| throw tcu::Exception("Writing to case list file failed"); |
| } |
| } |
| |
| iter.next(); |
| } |
| |
| // This could be done in catch, but the file is corrupt at that point anyways. |
| if (!qpXmlWriter_endElement(writer, "TestCaseList") || |
| !qpXmlWriter_endDocument(writer)) |
| throw Exception("Failed to terminate XML document"); |
| } |
| |
| /*--------------------------------------------------------------------*//*! |
| * \brief Export the test list of each package into a separate XML file. |
| *//*--------------------------------------------------------------------*/ |
| void writeXmlCaselistsToFiles (TestPackageRoot& root, TestContext& testCtx, const CommandLine& cmdLine) |
| { |
| DefaultHierarchyInflater inflater (testCtx); |
| de::MovePtr<const CaseListFilter> caseListFilter (testCtx.getCommandLine().createCaseListFilter(testCtx.getArchive())); |
| |
| TestHierarchyIterator iter (root, inflater, *caseListFilter); |
| const char* const filenamePattern = cmdLine.getCaseListExportFile(); |
| |
| while (iter.getState() != TestHierarchyIterator::STATE_FINISHED) |
| { |
| const TestNode* node = iter.getNode(); |
| const char* pkgName = node->getName(); |
| const string filename = makePackageFilename(filenamePattern, pkgName, "xml"); |
| |
| DE_ASSERT(iter.getState() == TestHierarchyIterator::STATE_ENTER_NODE && |
| node->getNodeType() == NODETYPE_PACKAGE); |
| |
| FILE* file = DE_NULL; |
| qpXmlWriter* writer = DE_NULL; |
| |
| try |
| { |
| file = fopen(filename.c_str(), "wb"); |
| if (!file) |
| throw Exception("Failed to open " + filename); |
| |
| writer = qpXmlWriter_createFileWriter(file, DE_FALSE, DE_FALSE); |
| if (!writer) |
| throw Exception("XML writer creation failed"); |
| |
| print("Writing test cases from '%s' to file '%s'..\n", pkgName, filename.c_str()); |
| |
| writeXmlCaselist(iter, writer); |
| |
| qpXmlWriter_destroy(writer); |
| writer = DE_NULL; |
| |
| fclose(file); |
| file = DE_NULL; |
| } |
| catch (...) |
| { |
| if (writer) |
| qpXmlWriter_destroy(writer); |
| if (file) |
| fclose(file); |
| throw; |
| } |
| |
| DE_ASSERT(iter.getState() == TestHierarchyIterator::STATE_LEAVE_NODE && |
| iter.getNode()->getNodeType() == NODETYPE_PACKAGE); |
| iter.next(); |
| } |
| } |
| |
| /*--------------------------------------------------------------------*//*! |
| * \brief Export the test list of each package into a separate ascii file. |
| *//*--------------------------------------------------------------------*/ |
| void writeTxtCaselistsToFiles (TestPackageRoot& root, TestContext& testCtx, const CommandLine& cmdLine) |
| { |
| DefaultHierarchyInflater inflater (testCtx); |
| de::MovePtr<const CaseListFilter> caseListFilter (testCtx.getCommandLine().createCaseListFilter(testCtx.getArchive())); |
| |
| TestHierarchyIterator iter (root, inflater, *caseListFilter); |
| const char* const filenamePattern = cmdLine.getCaseListExportFile(); |
| |
| while (iter.getState() != TestHierarchyIterator::STATE_FINISHED) |
| { |
| const TestNode* node = iter.getNode(); |
| const char* pkgName = node->getName(); |
| const string filename = makePackageFilename(filenamePattern, pkgName, "txt"); |
| |
| DE_ASSERT(iter.getState() == TestHierarchyIterator::STATE_ENTER_NODE && |
| node->getNodeType() == NODETYPE_PACKAGE); |
| |
| std::ofstream out(filename.c_str(), std::ios_base::binary); |
| if (!out.is_open() || !out.good()) |
| throw Exception("Failed to open " + filename); |
| |
| print("Writing test cases from '%s' to file '%s'..\n", pkgName, filename.c_str()); |
| |
| iter.next(); |
| |
| while (iter.getNode()->getNodeType() != NODETYPE_PACKAGE) |
| { |
| if (iter.getState() == TestHierarchyIterator::STATE_ENTER_NODE) |
| out << (isTestNodeTypeExecutable(iter.getNode()->getNodeType()) ? "TEST" : "GROUP") << ": " << iter.getNodePath() << "\n"; |
| iter.next(); |
| } |
| |
| DE_ASSERT(iter.getState() == TestHierarchyIterator::STATE_LEAVE_NODE && |
| iter.getNode()->getNodeType() == NODETYPE_PACKAGE); |
| iter.next(); |
| } |
| } |
| |
| } // tcu |