• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
getNodeTypeName(TestNodeType nodeType)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 
makePackageFilename(const std::string & pattern,const std::string & packageName,const std::string & typeExtension)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 
writeXmlCaselist(TestHierarchyIterator & iter,qpXmlWriter * writer)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  *//*--------------------------------------------------------------------*/
writeXmlCaselistsToFiles(TestPackageRoot & root,TestContext & testCtx,const CommandLine & cmdLine)125 void writeXmlCaselistsToFiles (TestPackageRoot& root, TestContext& testCtx, const CommandLine& cmdLine)
126 {
127 	DefaultHierarchyInflater			inflater		(testCtx);
128 	de::MovePtr<const CaseListFilter>	caseListFilter	(testCtx.getCommandLine().createCaseListFilter(testCtx.getArchive()));
129 
130 	TestHierarchyIterator				iter			(root, inflater, *caseListFilter);
131 	const char* const					filenamePattern = cmdLine.getCaseListExportFile();
132 
133 	while (iter.getState() != TestHierarchyIterator::STATE_FINISHED)
134 	{
135 		const TestNode* node		= iter.getNode();
136 		const char*		pkgName		= node->getName();
137 		const string	filename	= makePackageFilename(filenamePattern, pkgName, "xml");
138 
139 		DE_ASSERT(iter.getState() == TestHierarchyIterator::STATE_ENTER_NODE &&
140 				  node->getNodeType() == NODETYPE_PACKAGE);
141 
142 		FILE*			file	= DE_NULL;
143 		qpXmlWriter*	writer	= DE_NULL;
144 
145 		try
146 		{
147 			file = fopen(filename.c_str(), "wb");
148 			if (!file)
149 				throw Exception("Failed to open " + filename);
150 
151 			writer = qpXmlWriter_createFileWriter(file, DE_FALSE, DE_FALSE);
152 			if (!writer)
153 				throw Exception("XML writer creation failed");
154 
155 			print("Writing test cases from '%s' to file '%s'..\n", pkgName, filename.c_str());
156 
157 			writeXmlCaselist(iter, writer);
158 
159 			qpXmlWriter_destroy(writer);
160 			writer = DE_NULL;
161 
162 			fclose(file);
163 			file = DE_NULL;
164 		}
165 		catch (...)
166 		{
167 			if (writer)
168 				qpXmlWriter_destroy(writer);
169 			if (file)
170 				fclose(file);
171 			throw;
172 		}
173 
174 		DE_ASSERT(iter.getState() == TestHierarchyIterator::STATE_LEAVE_NODE &&
175 				  iter.getNode()->getNodeType() == NODETYPE_PACKAGE);
176 		iter.next();
177 	}
178 }
179 
180 /*--------------------------------------------------------------------*//*!
181  * \brief Export the test list of each package into a separate ascii file.
182  *//*--------------------------------------------------------------------*/
writeTxtCaselistsToFiles(TestPackageRoot & root,TestContext & testCtx,const CommandLine & cmdLine)183 void writeTxtCaselistsToFiles (TestPackageRoot& root, TestContext& testCtx, const CommandLine& cmdLine)
184 {
185 	DefaultHierarchyInflater			inflater		(testCtx);
186 	de::MovePtr<const CaseListFilter>	caseListFilter	(testCtx.getCommandLine().createCaseListFilter(testCtx.getArchive()));
187 
188 	TestHierarchyIterator				iter			(root, inflater, *caseListFilter);
189 	const char* const					filenamePattern = cmdLine.getCaseListExportFile();
190 
191 	while (iter.getState() != TestHierarchyIterator::STATE_FINISHED)
192 	{
193 		const TestNode* node		= iter.getNode();
194 		const char*		pkgName		= node->getName();
195 		const string	filename	= makePackageFilename(filenamePattern, pkgName, "txt");
196 
197 		DE_ASSERT(iter.getState() == TestHierarchyIterator::STATE_ENTER_NODE &&
198 				  node->getNodeType() == NODETYPE_PACKAGE);
199 
200 		std::ofstream out(filename.c_str(), std::ios_base::binary);
201 		if (!out.is_open() || !out.good())
202 			throw Exception("Failed to open " + filename);
203 
204 		print("Writing test cases from '%s' to file '%s'..\n", pkgName, filename.c_str());
205 
206 		try
207 		{
208 			iter.next();
209 		}
210 		catch (const tcu::NotSupportedError&)
211 		{
212 			return;
213 		}
214 
215 		while (iter.getNode()->getNodeType() != NODETYPE_PACKAGE)
216 		{
217 			if (iter.getState() == TestHierarchyIterator::STATE_ENTER_NODE)
218 				out << (isTestNodeTypeExecutable(iter.getNode()->getNodeType()) ? "TEST" : "GROUP") << ": " << iter.getNodePath() << "\n";
219 			iter.next();
220 		}
221 
222 		DE_ASSERT(iter.getState() == TestHierarchyIterator::STATE_LEAVE_NODE &&
223 				  iter.getNode()->getNodeType() == NODETYPE_PACKAGE);
224 		iter.next();
225 	}
226 }
227 
228 } // tcu
229