Nektar++
Public Member Functions | Static Public Member Functions | Static Public Attributes | Protected Member Functions | Protected Attributes | List of all members
Nektar::MetricRegex Class Reference

#include <MetricRegex.h>

Inheritance diagram for Nektar::MetricRegex:
[legend]

Public Member Functions

 ~MetricRegex () override
 
- Public Member Functions inherited from Nektar::Metric
 Metric (TiXmlElement *metric, bool generate)
 Constructor. More...
 
virtual ~Metric ()=default
 
bool Test (std::istream &pStdout, std::istream &pStderr)
 Calls a metric's v_Test function (or v_Generate if m_generate). More...
 
void Generate (std::istream &pStdout, std::istream &pStderr)
 
std::string GetType ()
 Return metric type. More...
 
int GetID ()
 Return metric ID. More...
 
bool SupportsAverage () const
 Return whether this metric supports averaging results from multiple runs. More...
 

Static Public Member Functions

static MetricSharedPtr create (TiXmlElement *metric, bool generate)
 

Static Public Attributes

static std::string type
 

Protected Member Functions

 MetricRegex (TiXmlElement *metric, bool generate)
 Constructor. More...
 
bool v_Test (std::istream &pStdout, std::istream &pStderr) override
 Test output against a regex expression and set of matches. More...
 
void v_Generate (std::istream &pStdout, std::istream &pStderr) override
 Test output against a regex expression and set of matches. More...
 
virtual bool v_Test (std::istream &pStdout, std::istream &pStderr)=0
 Virtual function to test the metric. Should be redefined in derived classes. More...
 
virtual void v_Generate (std::istream &pStdout, std::istream &pSrderr)=0
 Virtual function to generate the metric. Should be redefined in derived classes. More...
 

Protected Attributes

std::regex m_regex
 Storage for the boost regex. More...
 
std::vector< std::vector< MetricRegexFieldValue > > m_matches
 Stores the multiple matches defined in each <MATCH> tag. More...
 
bool m_unordered = false
 If true, regex matches may be in any order in output. More...
 
bool m_useStderr = false
 If true, use stderr for testing/generation instead of stdout. More...
 
- Protected Attributes inherited from Nektar::Metric
int m_id
 Stores the ID of this metric. More...
 
std::string m_type
 Stores the type of this metric (uppercase). More...
 
bool m_generate
 Determines whether to generate this metric or not. More...
 
bool m_average = false
 Indicates whether a metric supports averaging results from multiple runs. More...
 
TiXmlElement * m_metric
 Pointer to XML structure containing metric definition. More...
 

Detailed Description

Definition at line 66 of file MetricRegex.h.

Constructor & Destructor Documentation

◆ ~MetricRegex()

Nektar::MetricRegex::~MetricRegex ( )
inlineoverride

Definition at line 69 of file MetricRegex.h.

70 {
71 }

◆ MetricRegex()

Nektar::MetricRegex::MetricRegex ( TiXmlElement *  metric,
bool  generate 
)
protected

Constructor.

Definition at line 51 of file MetricRegex.cpp.

52 : Metric(metric, generate)
53{
54 // If we are a derived class, do nothing
55 if (m_type != "REGEX")
56 {
57 return;
58 }
59
60 // Parse Regex expression
61 TiXmlElement *regex = metric->FirstChildElement("regex");
62 ASSERTL0(regex, "No Regex defined.");
63 ASSERTL0(regex->GetText(), "Failed to get text");
64 m_regex = std::regex(regex->GetText(), std::regex::ECMAScript);
65
66 // Parse matching values if not generating.
67 if (m_generate)
68 {
69 return;
70 }
71
72 TiXmlElement *matches = metric->FirstChildElement("matches");
73 ASSERTL0(matches, "No matches defined.");
74 TiXmlElement *match = matches->FirstChildElement("match");
75 while (match)
76 {
77 std::vector<MetricRegexFieldValue> tmp;
78 TiXmlElement *field = match->FirstChildElement("field");
79 while (field)
80 {
81 MetricRegexFieldValue v;
82 v.m_value = field->GetText();
83 v.m_useTolerance = false;
84 v.m_useIntTolerance = false;
85
86 const char *tol = field->Attribute("tolerance");
87 if (tol)
88 {
89 v.m_useTolerance = true;
90 v.m_tolerance = atof(tol);
91 }
92
93 const char *intTol = field->Attribute("inttolerance");
94 if (intTol)
95 {
96 v.m_useIntTolerance = true;
97 v.m_intTolerance = atoi(intTol);
98 }
99
100 ASSERTL0(!(intTol && tol),
101 "Cannot use both integer and double tolerances.");
102
103 tmp.push_back(v);
104 field = field->NextSiblingElement("field");
105 }
106 m_matches.push_back(tmp);
107
108 match = match->NextSiblingElement("match");
109 }
110}
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:208
Metric(TiXmlElement *metric, bool generate)
Constructor.
Definition: Metric.cpp:51
std::string m_type
Stores the type of this metric (uppercase).
Definition: Metric.h:94
bool m_generate
Determines whether to generate this metric or not.
Definition: Metric.h:96
std::vector< std::vector< MetricRegexFieldValue > > m_matches
Stores the multiple matches defined in each <MATCH> tag.
Definition: MetricRegex.h:84
std::regex m_regex
Storage for the boost regex.
Definition: MetricRegex.h:82

References ASSERTL0, Nektar::Metric::m_generate, Nektar::MetricRegexFieldValue::m_intTolerance, m_matches, m_regex, Nektar::MetricRegexFieldValue::m_tolerance, Nektar::Metric::m_type, Nektar::MetricRegexFieldValue::m_useIntTolerance, Nektar::MetricRegexFieldValue::m_useTolerance, and Nektar::MetricRegexFieldValue::m_value.

Referenced by create().

Member Function Documentation

◆ create()

static MetricSharedPtr Nektar::MetricRegex::create ( TiXmlElement *  metric,
bool  generate 
)
inlinestatic

Definition at line 73 of file MetricRegex.h.

74 {
75 return MetricSharedPtr(new MetricRegex(metric, generate));
76 }
MetricRegex(TiXmlElement *metric, bool generate)
Constructor.
Definition: MetricRegex.cpp:51
std::shared_ptr< Metric > MetricSharedPtr
A shared pointer to an EquationSystem object.
Definition: Metric.h:124

References MetricRegex().

◆ v_Generate()

void Nektar::MetricRegex::v_Generate ( std::istream &  pStdout,
std::istream &  pStderr 
)
overrideprotectedvirtual

Test output against a regex expression and set of matches.

Implements Nektar::Metric.

Definition at line 268 of file MetricRegex.cpp.

269{
270 boost::ignore_unused(pStderr);
271
272 // Select istream to use.
273 std::istream &is = m_useStderr ? pStderr : pStdout;
274
275 std::smatch matches;
276
277 // Process output file line by line searching for regex matches
278 std::string line;
279 while (getline(is, line))
280 {
281 // Test to see if we have a match on this line.
282 if (std::regex_match(line, matches, m_regex))
283 {
284 // Error if no fields in regex then throw an error.
285 ASSERTL0(matches.size() != 1, "No test sections in regex!");
286
287 vector<MetricRegexFieldValue> okValues;
288
289 for (int i = 1; i < matches.size(); ++i)
290 {
291 // Create new field.
292 MetricRegexFieldValue okValue;
293 okValue.m_useTolerance = false;
294 okValue.m_value =
295 std::string(matches[i].first, matches[i].second);
296 okValues.push_back(okValue);
297 }
298
299 m_matches.push_back(okValues);
300 }
301 }
302
303 // If we are not a derived class then create a new structure.
304 if (m_type == "REGEX")
305 {
306 // Remove matches if they already exist.
307 TiXmlElement *matches = m_metric->FirstChildElement("matches");
308 if (matches)
309 {
310 ASSERTL0(m_metric->RemoveChild(matches),
311 "Couldn't remove matches from metric!");
312 }
313
314 // Create new matches element.
315 matches = new TiXmlElement("matches");
316 m_metric->LinkEndChild(matches);
317
318 for (int i = 0; i < m_matches.size(); ++i)
319 {
320 TiXmlElement *match = new TiXmlElement("match");
321 matches->LinkEndChild(match);
322
323 for (int j = 0; j < m_matches[i].size(); ++j)
324 {
325 TiXmlElement *field = new TiXmlElement("field");
326 match->LinkEndChild(field);
327
328 field->SetAttribute("id", boost::lexical_cast<std::string>(j));
329
330 if (m_matches[i][j].m_useTolerance)
331 {
332 field->SetAttribute("tolerance",
333 boost::lexical_cast<std::string>(
334 m_matches[i][j].m_tolerance));
335 }
336
337 field->LinkEndChild(new TiXmlText(m_matches[i][j].m_value));
338 }
339 }
340 }
341}
TiXmlElement * m_metric
Pointer to XML structure containing metric definition.
Definition: Metric.h:101
bool m_useStderr
If true, use stderr for testing/generation instead of stdout.
Definition: MetricRegex.h:88

References ASSERTL0, m_matches, Nektar::Metric::m_metric, m_regex, Nektar::Metric::m_type, m_useStderr, Nektar::MetricRegexFieldValue::m_useTolerance, and Nektar::MetricRegexFieldValue::m_value.

Referenced by Nektar::MetricEigenvalue::v_Generate(), Nektar::MetricL2::v_Generate(), Nektar::MetricLInf::v_Generate(), Nektar::MetricPrecon::v_Generate(), and Nektar::MetricPyUnitTest::v_Generate().

◆ v_Test()

bool Nektar::MetricRegex::v_Test ( std::istream &  pStdout,
std::istream &  pStderr 
)
overrideprotectedvirtual

Test output against a regex expression and set of matches.

Implements Nektar::Metric.

Definition at line 115 of file MetricRegex.cpp.

116{
117 boost::ignore_unused(pStdout, pStderr);
118
119 ASSERTL0(m_matches.size(), "No test conditions defined for Regex.");
120
121 // Select istream to use.
122 std::istream &is = m_useStderr ? pStderr : pStdout;
123
124 std::vector<MetricRegexFieldValue> &okValues = m_matches[0];
125 int nMatch = m_matches.size();
126 bool success = true;
127 bool matchedTol = false;
128 std::smatch matches;
129
130 // Process output file line by line searching for regex matches
131 std::string line;
132 while (getline(is, line) && m_matches.size() > 0)
133 {
134 matchedTol = true;
135
136 // Test to see if we have a match on this line.
137 if (std::regex_match(line, matches, m_regex))
138 {
139 // Error if no fields in regex then throw an error.
140 if (matches.size() == 1)
141 {
142 cerr << "No test sections in regex!" << endl;
143 return false;
144 }
145
146 // Check each regex capture group in turn
147 for (int i = 1; i < matches.size(); ++i)
148 {
149 // extract the captured string
150 std::string match(matches[i].first, matches[i].second);
151
152 if (okValues[i - 1].m_useTolerance)
153 {
154 double val;
155 try
156 {
157 val = fabs(fabs(boost::lexical_cast<double>(
158 okValues[i - 1].m_value)) -
159 fabs(boost::lexical_cast<double>(match)));
160 }
161 catch (boost::bad_lexical_cast &e)
162 {
163 cerr << "Could not convert one of " << match
164 << " (match) or " << okValues[i - 1].m_value
165 << " (comparison value) to double" << endl;
166 success = false;
167 continue;
168 }
169
170 // If the okValues are not within tolerance, failed the
171 // test.
172 if (val > okValues[i - 1].m_tolerance)
173 {
174 if (m_unordered)
175 {
176 matchedTol = false;
177 }
178 else
179 {
180 cerr << "Failed tolerance match." << endl;
181 cerr << " Expected: " << okValues[i - 1].m_value
182 << " +/- " << okValues[i - 1].m_tolerance
183 << endl;
184 cerr << " Result: " << match << endl;
185 success = false;
186 }
187 }
188 }
189 else if (okValues[i - 1].m_useIntTolerance)
190 {
191 int val;
192 try
193 {
194 val = abs(
195 boost::lexical_cast<int>(okValues[i - 1].m_value) -
196 boost::lexical_cast<int>(match));
197 }
198 catch (boost::bad_lexical_cast &e)
199 {
200 cerr << "Could not convert one of " << match
201 << " (match) or " << okValues[i - 1].m_value
202 << " (comparison value) to an integer" << endl;
203 success = false;
204 continue;
205 }
206
207 // If the okValues are not within tolerance, failed the
208 // test.
209 if (val > okValues[i - 1].m_intTolerance)
210 {
211 if (m_unordered)
212 {
213 matchedTol = false;
214 }
215 else
216 {
217 cerr << "Failed tolerance match." << endl;
218 cerr << " Expected: " << okValues[i - 1].m_value
219 << " +/- " << okValues[i - 1].m_intTolerance
220 << endl;
221 cerr << " Result: " << match << endl;
222 success = false;
223 }
224 }
225 }
226 else
227 {
228 // Case insensitive match.
229 if (!boost::iequals(match, okValues[i - 1].m_value))
230 {
231 if (m_unordered)
232 {
233 matchedTol = false;
234 }
235 else
236 {
237 cerr << "Failed case-insensitive match." << endl;
238 cerr << " Expected: " << okValues[i - 1].m_value
239 << endl;
240 cerr << " Result: " << match << endl;
241 success = false;
242 }
243 }
244 }
245 }
246
247 // Remove this match from the list of matches.
248 if (matchedTol)
249 {
250 m_matches.erase(m_matches.begin());
251 }
252 }
253 }
254
255 if (m_matches.size() != 0)
256 {
257 cerr << "Expected " << nMatch << " matches but only found "
258 << (nMatch - m_matches.size()) << "!" << endl;
259 success = false;
260 }
261
262 return success;
263}
bool m_unordered
If true, regex matches may be in any order in output.
Definition: MetricRegex.h:86
scalarT< T > abs(scalarT< T > in)
Definition: scalar.hpp:298

References tinysimd::abs(), ASSERTL0, m_matches, m_regex, m_unordered, and m_useStderr.

Member Data Documentation

◆ m_matches

std::vector<std::vector<MetricRegexFieldValue> > Nektar::MetricRegex::m_matches
protected

◆ m_regex

std::regex Nektar::MetricRegex::m_regex
protected

◆ m_unordered

bool Nektar::MetricRegex::m_unordered = false
protected

If true, regex matches may be in any order in output.

Definition at line 86 of file MetricRegex.h.

Referenced by Nektar::MetricEigenvalue::MetricEigenvalue(), and v_Test().

◆ m_useStderr

bool Nektar::MetricRegex::m_useStderr = false
protected

If true, use stderr for testing/generation instead of stdout.

Definition at line 88 of file MetricRegex.h.

Referenced by Nektar::MetricPyUnitTest::MetricPyUnitTest(), v_Generate(), and v_Test().

◆ type

std::string Nektar::MetricRegex::type
static
Initial value:
=
std::string RegisterCreatorFunction(std::string key, CreatorFunction func)
Definition: Metric.h:133
static MetricSharedPtr create(TiXmlElement *metric, bool generate)
Definition: MetricRegex.h:73
MetricFactory & GetMetricFactory()
Definition: Metric.cpp:42

Definition at line 78 of file MetricRegex.h.