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