Nektar++
TestData.cpp
Go to the documentation of this file.
1///////////////////////////////////////////////////////////////////////////////
2//
3// File: TestData.cpp
4//
5// For more information, please see: http://www.nektar.info
6//
7// The MIT License
8//
9// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10// Department of Aeronautics, Imperial College London (UK), and Scientific
11// Computing and Imaging Institute, University of Utah (USA).
12//
13// Permission is hereby granted, free of charge, to any person obtaining a
14// copy of this software and associated documentation files (the "Software"),
15// to deal in the Software without restriction, including without limitation
16// the rights to use, copy, modify, merge, publish, distribute, sublicense,
17// and/or sell copies of the Software, and to permit persons to whom the
18// Software is furnished to do so, subject to the following conditions:
19//
20// The above copyright notice and this permission notice shall be included
21// in all copies or substantial portions of the Software.
22//
23// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29// DEALINGS IN THE SOFTWARE.
30//
31// Description: Encapsulation of test XML file.
32//
33///////////////////////////////////////////////////////////////////////////////
34
35#include <boost/algorithm/string.hpp>
36#include <boost/core/ignore_unused.hpp>
37#include <boost/lexical_cast.hpp>
38
39#include <TestData.h>
40#include <TestException.hpp>
41
42using namespace std;
43
44namespace Nektar
45{
46
47/**
48 * @brief TestData constructor.
49 *
50 * The class is constructed with the path to the test XML file and a
51 * `po::variables_map` object containing the command-line options passed to the
52 * program.
53 *
54 * @param pFilename
55 * @param pVm
56 */
57
58TestData::TestData(const fs::path &pFilename, po::variables_map &pVm)
59 : m_cmdoptions(pVm)
60{
61 // Process test file format.
62 m_doc = new TiXmlDocument(pFilename.string().c_str());
63
64 bool loadOkay = m_doc->LoadFile();
65
66 ASSERTL0(loadOkay,
67 "Failed to load test definition file: " + pFilename.string() +
68 "\n" + string(m_doc->ErrorDesc()));
69
70 Parse(m_doc);
71}
72
74{
75 boost::ignore_unused(pSrc);
76}
77
78/// Returns the description of a test.
79const std::string &TestData::GetDescription() const
80{
81 return m_description;
82}
83
84const Command &TestData::GetCommand(unsigned int pId) const
85{
86 ASSERTL0(pId < m_commands.size(),
87 "Command ID '" + std::to_string(pId) + "' not found");
88 return m_commands[pId];
89}
90
91unsigned int TestData::GetNumCommands() const
92{
93 return m_commands.size();
94}
95
96/// Returns the type of metric to be collected for a given metric ID.
97std::string TestData::GetMetricType(unsigned int pId) const
98{
99 ASSERTL0(pId < m_metrics.size(), "Metric ID out of range.");
100
101 // read the property name
102 ASSERTL0(m_metrics[pId]->Attribute("type"),
103 "Missing 'type' attribute in metric " +
104 boost::lexical_cast<string>(pId) + ").");
105 return boost::to_upper_copy(string(m_metrics[pId]->Attribute("type")));
106}
107
108/// Returns the number of metrics to be collected for the test.
109unsigned int TestData::GetNumMetrics() const
110{
111 return m_metrics.size();
112}
113
114/// Returns a pointer to the `TiXmlElement` object representing the metric for a
115/// given metric ID.
116TiXmlElement *TestData::GetMetric(unsigned int pId)
117{
118 ASSERTL0(pId < m_metrics.size(), "Metric index out of range.");
119 return m_metrics[pId];
120}
121
122/// Returns the ID of the metric for a given metric ID.
123unsigned int TestData::GetMetricId(unsigned int pId)
124{
125 ASSERTL0(pId < m_metrics.size(), "Metric index out of range.");
126 const char *id = m_metrics[pId]->Attribute("id");
127 ASSERTL0(id, "No ID found for metric!");
128 return boost::lexical_cast<unsigned int>(id);
129}
130
132{
133 ASSERTL0(pId < m_files.size(), "File index out of range.");
134 return m_files[pId];
135}
136
137/// Returns the number of dependent files required for the test.
139{
140 return m_files.size();
141}
142
143/// Returns the number of runs to be performed for the test.
144unsigned int TestData::GetNumRuns() const
145{
146 return m_runs;
147}
148
149Command TestData::ParseCommand(TiXmlElement *elmt) const
150{
151 Command cmd;
152 TiXmlElement *tmp;
153
154 cmd.m_pythonTest = false;
155
156 // Parse executable tag. Do not enforce a check because this might be
157 // overridden on the command line.
158 if (elmt->FirstChildElement("executable"))
159 {
160 tmp = elmt->FirstChildElement("executable");
161 cmd.m_executable = fs::path(tmp->GetText());
162
163 // Test to see if this test requires Python
164 std::string needsPython;
165 tmp->QueryStringAttribute("python", &needsPython);
166 cmd.m_pythonTest = needsPython == "true";
167
168#if defined(RELWITHDEBINFO)
169 cmd.m_executable += cmd.m_pythonTest ? "" : "-rg";
170#elif !defined(NDEBUG)
171 cmd.m_executable += cmd.m_pythonTest ? "" : "-g";
172#endif
173 }
174
175 // Find associated parameters.
176 tmp = elmt->FirstChildElement("parameters");
177 ASSERTL0(tmp, "Cannot find 'parameters' for test.");
178 if (tmp->GetText())
179 {
180 cmd.m_parameters = string(tmp->GetText());
181 }
182
183 // Find parallel processes tah.
184 tmp = elmt->FirstChildElement("processes");
185 if (tmp)
186 {
187 cmd.m_processes = atoi(tmp->GetText());
188 }
189 else
190 {
191 cmd.m_processes = 1;
192 }
193
194 return cmd;
195}
196
197/// Parse the test file and populate member variables for the test.
198void TestData::Parse(TiXmlDocument *pDoc)
199{
200 TiXmlHandle handle(pDoc);
201 TiXmlElement *testElement, *tmp, *metrics, *files;
202 testElement = handle.FirstChildElement("test").Element();
203 ASSERTL0(testElement, "Cannot find 'test' root element.");
204
205 // Find the desired number of test runs
206 unsigned int runs = 1;
207 testElement->QueryUnsignedAttribute("runs", &runs);
208 ASSERTL0(runs > 0, "Number of runs must be greater than zero.");
209 m_runs = runs;
210
211 // Find description tag.
212 tmp = testElement->FirstChildElement("description");
213 ASSERTL0(tmp, "Cannot find 'description' for test.");
214 m_description = string(tmp->GetText());
215
216 // Find command(s) to run.
217 if (m_cmdoptions.count("executable"))
218 {
219 m_commands.push_back(ParseCommand(testElement));
220 m_commands.back().m_executable =
221 fs::path(m_cmdoptions["executable"].as<std::string>());
222 }
223 else if (testElement->FirstChildElement("executable"))
224 {
225 m_commands.push_back(ParseCommand(testElement));
226 }
227 else if ((tmp = testElement->FirstChildElement("segment")))
228 {
229 ASSERTL0(m_cmdoptions.count("executable") == 0,
230 "Test files defining more than one command in segment "
231 "blocks cannot use --executable.");
232
233 while (tmp)
234 {
235 m_commands.push_back(ParseCommand(tmp));
236 tmp = tmp->NextSiblingElement("segment");
237 }
238 }
239
240 ASSERTL0(m_commands.size() > 0,
241 "No executable / command segments specified for test.");
242
243 // Extract metric tags
244 metrics = testElement->FirstChildElement("metrics");
245 ASSERTL0(metrics, "No metrics defined for test.");
246
247 tmp = metrics->FirstChildElement("metric");
248 while (tmp)
249 {
250 m_metrics.push_back(tmp);
251 tmp = tmp->NextSiblingElement("metric");
252 }
253
254 // Extract list of dependent files
255 files = testElement->FirstChildElement("files");
256 if (files)
257 {
258 tmp = files->FirstChildElement("file");
259 while (tmp)
260 {
262 f.m_filename = string(tmp->GetText());
263 if (tmp->Attribute("description"))
264 {
265 f.m_description = string(tmp->Attribute("description"));
266 }
267 m_files.push_back(f);
268 tmp = tmp->NextSiblingElement("file");
269 }
270 }
271}
272
274{
275 m_doc->SaveFile();
276}
277} // namespace Nektar
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:208
The TestData class is responsible for parsing a test XML file and storing the data.
Definition: TestData.h:71
TestData(const fs::path &pFilename, po::variables_map &pVm)
TestData constructor.
Definition: TestData.cpp:58
std::vector< TiXmlElement * > m_metrics
Definition: TestData.h:97
DependentFile GetDependentFile(unsigned int pId) const
Definition: TestData.cpp:131
unsigned int GetMetricId(unsigned int pId)
Returns the ID of the metric for a given metric ID.
Definition: TestData.cpp:123
void Parse(TiXmlDocument *pDoc)
Parse the test file and populate member variables for the test.
Definition: TestData.cpp:198
std::vector< Command > m_commands
Definition: TestData.h:95
unsigned int GetNumDependentFiles() const
Returns the number of dependent files required for the test.
Definition: TestData.cpp:138
TiXmlDocument * m_doc
Definition: TestData.h:96
unsigned int GetNumMetrics() const
Returns the number of metrics to be collected for the test.
Definition: TestData.cpp:109
unsigned int m_runs
The number of times to run the test.
Definition: TestData.h:100
Command ParseCommand(TiXmlElement *pElmt) const
Definition: TestData.cpp:149
unsigned int GetNumRuns() const
Returns the number of runs to be performed for the test.
Definition: TestData.cpp:144
TiXmlElement * GetMetric(unsigned int pId)
Returns a pointer to the TiXmlElement object representing the metric for a given metric ID.
Definition: TestData.cpp:116
unsigned int GetNumCommands() const
Definition: TestData.cpp:91
const std::string & GetDescription() const
Returns the description of a test.
Definition: TestData.cpp:79
std::string GetMetricType(unsigned int pId) const
Returns the type of metric to be collected for a given metric ID.
Definition: TestData.cpp:97
po::variables_map m_cmdoptions
Definition: TestData.h:93
const Command & GetCommand(unsigned int pId) const
Definition: TestData.cpp:84
std::vector< DependentFile > m_files
Definition: TestData.h:98
std::string m_description
Definition: TestData.h:94
bool m_pythonTest
Definition: TestData.h:62
fs::path m_executable
Definition: TestData.h:59
std::string m_parameters
Definition: TestData.h:60
unsigned int m_processes
Definition: TestData.h:61
std::string m_filename
Definition: TestData.h:54
std::string m_description
Definition: TestData.h:53