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