1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker * drawElements Quality Program Tester Core
3*35238bceSAndroid Build Coastguard Worker * ----------------------------------------
4*35238bceSAndroid Build Coastguard Worker *
5*35238bceSAndroid Build Coastguard Worker * Copyright 2014 The Android Open Source Project
6*35238bceSAndroid Build Coastguard Worker *
7*35238bceSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
8*35238bceSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
9*35238bceSAndroid Build Coastguard Worker * You may obtain a copy of the License at
10*35238bceSAndroid Build Coastguard Worker *
11*35238bceSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
12*35238bceSAndroid Build Coastguard Worker *
13*35238bceSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
14*35238bceSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
15*35238bceSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*35238bceSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
17*35238bceSAndroid Build Coastguard Worker * limitations under the License.
18*35238bceSAndroid Build Coastguard Worker *
19*35238bceSAndroid Build Coastguard Worker *//*!
20*35238bceSAndroid Build Coastguard Worker * \file
21*35238bceSAndroid Build Coastguard Worker * \brief Test hierarchy utilities.
22*35238bceSAndroid Build Coastguard Worker *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker
24*35238bceSAndroid Build Coastguard Worker #include "tcuTestHierarchyUtil.hpp"
25*35238bceSAndroid Build Coastguard Worker #include "tcuStringTemplate.hpp"
26*35238bceSAndroid Build Coastguard Worker #include "tcuCommandLine.hpp"
27*35238bceSAndroid Build Coastguard Worker
28*35238bceSAndroid Build Coastguard Worker #include "qpXmlWriter.h"
29*35238bceSAndroid Build Coastguard Worker
30*35238bceSAndroid Build Coastguard Worker #include <fstream>
31*35238bceSAndroid Build Coastguard Worker
32*35238bceSAndroid Build Coastguard Worker namespace tcu
33*35238bceSAndroid Build Coastguard Worker {
34*35238bceSAndroid Build Coastguard Worker
35*35238bceSAndroid Build Coastguard Worker using std::string;
36*35238bceSAndroid Build Coastguard Worker
getNodeTypeName(TestNodeType nodeType)37*35238bceSAndroid Build Coastguard Worker static const char *getNodeTypeName(TestNodeType nodeType)
38*35238bceSAndroid Build Coastguard Worker {
39*35238bceSAndroid Build Coastguard Worker switch (nodeType)
40*35238bceSAndroid Build Coastguard Worker {
41*35238bceSAndroid Build Coastguard Worker case NODETYPE_SELF_VALIDATE:
42*35238bceSAndroid Build Coastguard Worker return "SelfValidate";
43*35238bceSAndroid Build Coastguard Worker case NODETYPE_CAPABILITY:
44*35238bceSAndroid Build Coastguard Worker return "Capability";
45*35238bceSAndroid Build Coastguard Worker case NODETYPE_ACCURACY:
46*35238bceSAndroid Build Coastguard Worker return "Accuracy";
47*35238bceSAndroid Build Coastguard Worker case NODETYPE_PERFORMANCE:
48*35238bceSAndroid Build Coastguard Worker return "Performance";
49*35238bceSAndroid Build Coastguard Worker case NODETYPE_GROUP:
50*35238bceSAndroid Build Coastguard Worker return "TestGroup";
51*35238bceSAndroid Build Coastguard Worker default:
52*35238bceSAndroid Build Coastguard Worker DE_ASSERT(false);
53*35238bceSAndroid Build Coastguard Worker return DE_NULL;
54*35238bceSAndroid Build Coastguard Worker }
55*35238bceSAndroid Build Coastguard Worker }
56*35238bceSAndroid Build Coastguard Worker
57*35238bceSAndroid Build Coastguard Worker // Utilities
58*35238bceSAndroid Build Coastguard Worker
makePackageFilename(const std::string & pattern,const std::string & packageName,const std::string & typeExtension)59*35238bceSAndroid Build Coastguard Worker static std::string makePackageFilename(const std::string &pattern, const std::string &packageName,
60*35238bceSAndroid Build Coastguard Worker const std::string &typeExtension)
61*35238bceSAndroid Build Coastguard Worker {
62*35238bceSAndroid Build Coastguard Worker std::map<string, string> args;
63*35238bceSAndroid Build Coastguard Worker args["packageName"] = packageName;
64*35238bceSAndroid Build Coastguard Worker args["typeExtension"] = typeExtension;
65*35238bceSAndroid Build Coastguard Worker return StringTemplate(pattern).specialize(args);
66*35238bceSAndroid Build Coastguard Worker }
67*35238bceSAndroid Build Coastguard Worker
writeXmlCaselist(TestHierarchyIterator & iter,qpXmlWriter * writer)68*35238bceSAndroid Build Coastguard Worker static void writeXmlCaselist(TestHierarchyIterator &iter, qpXmlWriter *writer)
69*35238bceSAndroid Build Coastguard Worker {
70*35238bceSAndroid Build Coastguard Worker DE_ASSERT(iter.getState() == TestHierarchyIterator::STATE_ENTER_NODE &&
71*35238bceSAndroid Build Coastguard Worker iter.getNode()->getNodeType() == NODETYPE_PACKAGE);
72*35238bceSAndroid Build Coastguard Worker
73*35238bceSAndroid Build Coastguard Worker {
74*35238bceSAndroid Build Coastguard Worker const TestNode *node = iter.getNode();
75*35238bceSAndroid Build Coastguard Worker qpXmlAttribute attribs[1];
76*35238bceSAndroid Build Coastguard Worker int numAttribs = 0;
77*35238bceSAndroid Build Coastguard Worker attribs[numAttribs++] = qpSetStringAttrib("PackageName", node->getName());
78*35238bceSAndroid Build Coastguard Worker DE_ASSERT(numAttribs <= DE_LENGTH_OF_ARRAY(attribs));
79*35238bceSAndroid Build Coastguard Worker
80*35238bceSAndroid Build Coastguard Worker if (!qpXmlWriter_startDocument(writer, true) ||
81*35238bceSAndroid Build Coastguard Worker !qpXmlWriter_startElement(writer, "TestCaseList", numAttribs, attribs))
82*35238bceSAndroid Build Coastguard Worker throw Exception("Failed to start XML document");
83*35238bceSAndroid Build Coastguard Worker }
84*35238bceSAndroid Build Coastguard Worker
85*35238bceSAndroid Build Coastguard Worker iter.next();
86*35238bceSAndroid Build Coastguard Worker
87*35238bceSAndroid Build Coastguard Worker while (iter.getNode()->getNodeType() != NODETYPE_PACKAGE)
88*35238bceSAndroid Build Coastguard Worker {
89*35238bceSAndroid Build Coastguard Worker const TestNode *const node = iter.getNode();
90*35238bceSAndroid Build Coastguard Worker const TestNodeType nodeType = node->getNodeType();
91*35238bceSAndroid Build Coastguard Worker const bool isEnter = iter.getState() == TestHierarchyIterator::STATE_ENTER_NODE;
92*35238bceSAndroid Build Coastguard Worker
93*35238bceSAndroid Build Coastguard Worker DE_ASSERT(iter.getState() == TestHierarchyIterator::STATE_ENTER_NODE ||
94*35238bceSAndroid Build Coastguard Worker iter.getState() == TestHierarchyIterator::STATE_LEAVE_NODE);
95*35238bceSAndroid Build Coastguard Worker {
96*35238bceSAndroid Build Coastguard Worker if (isEnter)
97*35238bceSAndroid Build Coastguard Worker {
98*35238bceSAndroid Build Coastguard Worker const string caseName = node->getName();
99*35238bceSAndroid Build Coastguard Worker qpXmlAttribute attribs[2];
100*35238bceSAndroid Build Coastguard Worker int numAttribs = 0;
101*35238bceSAndroid Build Coastguard Worker
102*35238bceSAndroid Build Coastguard Worker attribs[numAttribs++] = qpSetStringAttrib("Name", caseName.c_str());
103*35238bceSAndroid Build Coastguard Worker attribs[numAttribs++] = qpSetStringAttrib("CaseType", getNodeTypeName(nodeType));
104*35238bceSAndroid Build Coastguard Worker DE_ASSERT(numAttribs <= DE_LENGTH_OF_ARRAY(attribs));
105*35238bceSAndroid Build Coastguard Worker
106*35238bceSAndroid Build Coastguard Worker if (!qpXmlWriter_startElement(writer, "TestCase", numAttribs, attribs))
107*35238bceSAndroid Build Coastguard Worker throw Exception("Writing to case list file failed");
108*35238bceSAndroid Build Coastguard Worker }
109*35238bceSAndroid Build Coastguard Worker else
110*35238bceSAndroid Build Coastguard Worker {
111*35238bceSAndroid Build Coastguard Worker if (!qpXmlWriter_endElement(writer, "TestCase"))
112*35238bceSAndroid Build Coastguard Worker throw tcu::Exception("Writing to case list file failed");
113*35238bceSAndroid Build Coastguard Worker }
114*35238bceSAndroid Build Coastguard Worker }
115*35238bceSAndroid Build Coastguard Worker
116*35238bceSAndroid Build Coastguard Worker iter.next();
117*35238bceSAndroid Build Coastguard Worker }
118*35238bceSAndroid Build Coastguard Worker
119*35238bceSAndroid Build Coastguard Worker // This could be done in catch, but the file is corrupt at that point anyways.
120*35238bceSAndroid Build Coastguard Worker if (!qpXmlWriter_endElement(writer, "TestCaseList") || !qpXmlWriter_endDocument(writer))
121*35238bceSAndroid Build Coastguard Worker throw Exception("Failed to terminate XML document");
122*35238bceSAndroid Build Coastguard Worker }
123*35238bceSAndroid Build Coastguard Worker
124*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
125*35238bceSAndroid Build Coastguard Worker * \brief Export the test list of each package into a separate XML file.
126*35238bceSAndroid Build Coastguard Worker *//*--------------------------------------------------------------------*/
writeXmlCaselistsToFiles(TestPackageRoot & root,TestContext & testCtx,const CommandLine & cmdLine)127*35238bceSAndroid Build Coastguard Worker void writeXmlCaselistsToFiles(TestPackageRoot &root, TestContext &testCtx, const CommandLine &cmdLine)
128*35238bceSAndroid Build Coastguard Worker {
129*35238bceSAndroid Build Coastguard Worker DefaultHierarchyInflater inflater(testCtx);
130*35238bceSAndroid Build Coastguard Worker de::MovePtr<const CaseListFilter> caseListFilter(
131*35238bceSAndroid Build Coastguard Worker testCtx.getCommandLine().createCaseListFilter(testCtx.getArchive()));
132*35238bceSAndroid Build Coastguard Worker
133*35238bceSAndroid Build Coastguard Worker TestHierarchyIterator iter(root, inflater, *caseListFilter);
134*35238bceSAndroid Build Coastguard Worker const char *const filenamePattern = cmdLine.getCaseListExportFile();
135*35238bceSAndroid Build Coastguard Worker
136*35238bceSAndroid Build Coastguard Worker while (iter.getState() != TestHierarchyIterator::STATE_FINISHED)
137*35238bceSAndroid Build Coastguard Worker {
138*35238bceSAndroid Build Coastguard Worker const TestNode *node = iter.getNode();
139*35238bceSAndroid Build Coastguard Worker const char *pkgName = node->getName();
140*35238bceSAndroid Build Coastguard Worker const string filename = makePackageFilename(filenamePattern, pkgName, "xml");
141*35238bceSAndroid Build Coastguard Worker
142*35238bceSAndroid Build Coastguard Worker DE_ASSERT(iter.getState() == TestHierarchyIterator::STATE_ENTER_NODE &&
143*35238bceSAndroid Build Coastguard Worker node->getNodeType() == NODETYPE_PACKAGE);
144*35238bceSAndroid Build Coastguard Worker
145*35238bceSAndroid Build Coastguard Worker FILE *file = DE_NULL;
146*35238bceSAndroid Build Coastguard Worker qpXmlWriter *writer = DE_NULL;
147*35238bceSAndroid Build Coastguard Worker
148*35238bceSAndroid Build Coastguard Worker try
149*35238bceSAndroid Build Coastguard Worker {
150*35238bceSAndroid Build Coastguard Worker file = fopen(filename.c_str(), "wb");
151*35238bceSAndroid Build Coastguard Worker if (!file)
152*35238bceSAndroid Build Coastguard Worker throw Exception("Failed to open " + filename);
153*35238bceSAndroid Build Coastguard Worker
154*35238bceSAndroid Build Coastguard Worker writer = qpXmlWriter_createFileWriter(file, false, false);
155*35238bceSAndroid Build Coastguard Worker if (!writer)
156*35238bceSAndroid Build Coastguard Worker throw Exception("XML writer creation failed");
157*35238bceSAndroid Build Coastguard Worker
158*35238bceSAndroid Build Coastguard Worker print("Writing test cases from '%s' to file '%s'..\n", pkgName, filename.c_str());
159*35238bceSAndroid Build Coastguard Worker
160*35238bceSAndroid Build Coastguard Worker writeXmlCaselist(iter, writer);
161*35238bceSAndroid Build Coastguard Worker
162*35238bceSAndroid Build Coastguard Worker qpXmlWriter_destroy(writer);
163*35238bceSAndroid Build Coastguard Worker writer = DE_NULL;
164*35238bceSAndroid Build Coastguard Worker
165*35238bceSAndroid Build Coastguard Worker fclose(file);
166*35238bceSAndroid Build Coastguard Worker file = DE_NULL;
167*35238bceSAndroid Build Coastguard Worker }
168*35238bceSAndroid Build Coastguard Worker catch (...)
169*35238bceSAndroid Build Coastguard Worker {
170*35238bceSAndroid Build Coastguard Worker if (writer)
171*35238bceSAndroid Build Coastguard Worker qpXmlWriter_destroy(writer);
172*35238bceSAndroid Build Coastguard Worker if (file)
173*35238bceSAndroid Build Coastguard Worker fclose(file);
174*35238bceSAndroid Build Coastguard Worker throw;
175*35238bceSAndroid Build Coastguard Worker }
176*35238bceSAndroid Build Coastguard Worker
177*35238bceSAndroid Build Coastguard Worker DE_ASSERT(iter.getState() == TestHierarchyIterator::STATE_LEAVE_NODE &&
178*35238bceSAndroid Build Coastguard Worker iter.getNode()->getNodeType() == NODETYPE_PACKAGE);
179*35238bceSAndroid Build Coastguard Worker iter.next();
180*35238bceSAndroid Build Coastguard Worker }
181*35238bceSAndroid Build Coastguard Worker }
182*35238bceSAndroid Build Coastguard Worker
183*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
184*35238bceSAndroid Build Coastguard Worker * \brief Export the test list of each package into a separate ascii file.
185*35238bceSAndroid Build Coastguard Worker *//*--------------------------------------------------------------------*/
writeTxtCaselistsToFiles(TestPackageRoot & root,TestContext & testCtx,const CommandLine & cmdLine)186*35238bceSAndroid Build Coastguard Worker void writeTxtCaselistsToFiles(TestPackageRoot &root, TestContext &testCtx, const CommandLine &cmdLine)
187*35238bceSAndroid Build Coastguard Worker {
188*35238bceSAndroid Build Coastguard Worker DefaultHierarchyInflater inflater(testCtx);
189*35238bceSAndroid Build Coastguard Worker de::MovePtr<const CaseListFilter> caseListFilter(
190*35238bceSAndroid Build Coastguard Worker testCtx.getCommandLine().createCaseListFilter(testCtx.getArchive()));
191*35238bceSAndroid Build Coastguard Worker
192*35238bceSAndroid Build Coastguard Worker TestHierarchyIterator iter(root, inflater, *caseListFilter);
193*35238bceSAndroid Build Coastguard Worker const char *const filenamePattern = cmdLine.getCaseListExportFile();
194*35238bceSAndroid Build Coastguard Worker
195*35238bceSAndroid Build Coastguard Worker while (iter.getState() != TestHierarchyIterator::STATE_FINISHED)
196*35238bceSAndroid Build Coastguard Worker {
197*35238bceSAndroid Build Coastguard Worker const TestNode *node = iter.getNode();
198*35238bceSAndroid Build Coastguard Worker const char *pkgName = node->getName();
199*35238bceSAndroid Build Coastguard Worker const string filename = makePackageFilename(filenamePattern, pkgName, "txt");
200*35238bceSAndroid Build Coastguard Worker
201*35238bceSAndroid Build Coastguard Worker DE_ASSERT(iter.getState() == TestHierarchyIterator::STATE_ENTER_NODE &&
202*35238bceSAndroid Build Coastguard Worker node->getNodeType() == NODETYPE_PACKAGE);
203*35238bceSAndroid Build Coastguard Worker
204*35238bceSAndroid Build Coastguard Worker std::ofstream out(filename.c_str(), std::ios_base::binary);
205*35238bceSAndroid Build Coastguard Worker if (!out.is_open() || !out.good())
206*35238bceSAndroid Build Coastguard Worker throw Exception("Failed to open " + filename);
207*35238bceSAndroid Build Coastguard Worker
208*35238bceSAndroid Build Coastguard Worker print("Writing test cases from '%s' to file '%s'..\n", pkgName, filename.c_str());
209*35238bceSAndroid Build Coastguard Worker
210*35238bceSAndroid Build Coastguard Worker try
211*35238bceSAndroid Build Coastguard Worker {
212*35238bceSAndroid Build Coastguard Worker iter.next();
213*35238bceSAndroid Build Coastguard Worker }
214*35238bceSAndroid Build Coastguard Worker catch (const tcu::NotSupportedError &)
215*35238bceSAndroid Build Coastguard Worker {
216*35238bceSAndroid Build Coastguard Worker return;
217*35238bceSAndroid Build Coastguard Worker }
218*35238bceSAndroid Build Coastguard Worker
219*35238bceSAndroid Build Coastguard Worker while (iter.getNode()->getNodeType() != NODETYPE_PACKAGE)
220*35238bceSAndroid Build Coastguard Worker {
221*35238bceSAndroid Build Coastguard Worker if (iter.getState() == TestHierarchyIterator::STATE_ENTER_NODE)
222*35238bceSAndroid Build Coastguard Worker out << (isTestNodeTypeExecutable(iter.getNode()->getNodeType()) ? "TEST" : "GROUP") << ": "
223*35238bceSAndroid Build Coastguard Worker << iter.getNodePath() << "\n";
224*35238bceSAndroid Build Coastguard Worker iter.next();
225*35238bceSAndroid Build Coastguard Worker }
226*35238bceSAndroid Build Coastguard Worker
227*35238bceSAndroid Build Coastguard Worker DE_ASSERT(iter.getState() == TestHierarchyIterator::STATE_LEAVE_NODE &&
228*35238bceSAndroid Build Coastguard Worker iter.getNode()->getNodeType() == NODETYPE_PACKAGE);
229*35238bceSAndroid Build Coastguard Worker iter.next();
230*35238bceSAndroid Build Coastguard Worker }
231*35238bceSAndroid Build Coastguard Worker }
232*35238bceSAndroid Build Coastguard Worker
233*35238bceSAndroid Build Coastguard Worker } // namespace tcu
234