229 lines
7.3 KiB
C++
229 lines
7.3 KiB
C++
/*-------------------------------------------------------------------------
|
|
* 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());
|
|
|
|
try
|
|
{
|
|
iter.next();
|
|
}
|
|
catch (const tcu::NotSupportedError&)
|
|
{
|
|
return;
|
|
}
|
|
|
|
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
|