Commit 139472c5 authored by Dave Moxey's avatar Dave Moxey

Changing namespace to Nektar and adding factory for metrics.

git-svn-id: https://gforge.sci.utah.edu/svn/nektar/branches/new-tests@4078 305cdda6-5ce1-45b3-a98d-dfc68c8b3305
parent 615a0992
...@@ -34,46 +34,58 @@ ...@@ -34,46 +34,58 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#include <Metric.h> #include <Metric.h>
#include <loki/Singleton.h>
/** namespace Nektar
* @brief Constructor.
*/
Metric::Metric(int id) : m_id(id)
{ {
MetricFactory& GetMetricFactory()
{
typedef Loki::SingletonHolder<MetricFactory,
Loki::CreateUsingNew,
Loki::NoDestroy > Type;
return Type::Instance();
}
/**
* @brief Constructor.
*/
Metric::Metric(int id) : m_id(id)
{
}
/**
* @brief Parse the contents of a metric tag. This function is implemented by
* subclasses.
*/
void Metric::Parse(TiXmlElement *metric)
{
v_Parse(metric);
}
} /**
* @brief Test a line of output from an executible.
/** */
* @brief Parse the contents of a metric tag. This function is implemented by bool Metric::TestLine(std::string line)
* subclasses. {
*/ return v_TestLine(line);
void Metric::Parse(TiXmlElement *metric) }
{
v_Parse(metric); /**
} * @brief Test which is run after the executible has finished.
*/
/** bool Metric::FinishTest()
* @brief Test a line of output from an executible. {
*/ return v_FinishTest();
bool Metric::TestLine(std::string line) }
{
return v_TestLine(line); bool Metric::v_TestLine(std::string line)
} {
return true;
/** }
* @brief Test which is run after the executible has finished.
*/ bool Metric::v_FinishTest()
bool Metric::FinishTest() {
{ return true;
return v_FinishTest(); }
}
bool Metric::v_TestLine(std::string line)
{
return true;
}
bool Metric::v_FinishTest()
{
return true;
} }
...@@ -39,22 +39,35 @@ ...@@ -39,22 +39,35 @@
#include <tinyxml/tinyxml.h> #include <tinyxml/tinyxml.h>
#include <string> #include <string>
class Metric #include <LibUtilities/BasicUtils/NekFactory.hpp>
namespace Nektar
{ {
public: class Metric
Metric(int id); {
public:
void Parse (TiXmlElement *metric); Metric(int id);
bool TestLine (std::string line);
bool FinishTest(); void Parse (TiXmlElement *metric);
bool TestLine (std::string line);
protected: bool FinishTest();
// Stores the ID of this metric.
int m_id; protected:
// Stores the ID of this metric.
int m_id;
virtual void v_Parse (TiXmlElement *metric) = 0;
virtual bool v_TestLine (std::string line);
virtual bool v_FinishTest();
};
/// A shared pointer to an EquationSystem object
typedef boost::shared_ptr<Metric> MetricSharedPtr;
virtual void v_Parse (TiXmlElement *metric) = 0; /// Datatype of the NekFactory used to instantiate classes derived from the
virtual bool v_TestLine (std::string line); /// Advection class.
virtual bool v_FinishTest(); typedef LibUtilities::NekFactory<std::string, Metric, int> MetricFactory;
}; MetricFactory& GetMetricFactory();
}
#endif #endif
...@@ -35,35 +35,42 @@ ...@@ -35,35 +35,42 @@
#include <MetricL2.h> #include <MetricL2.h>
MetricL2::MetricL2(int id) : MetricRegex(id) namespace Nektar
{ {
std::string MetricL2::type = GetMetricFactory().
RegisterCreatorFunction("l2", MetricL2::create);
} MetricL2::MetricL2(int id) : MetricRegex(id)
{
}
void MetricL2::v_Parse(TiXmlElement *metric) void MetricL2::v_Parse(TiXmlElement *metric)
{ {
// Set up the regular expression. This (optionally) matches a variable // Set up the regular expression. This (optionally) matches a variable
// name if it exists: first field is variable name, second field is L2 // name if it exists: first field is variable name, second field is L2
// error. // error.
m_regex = "^L 2 error\\s*(?:\\(variable (\\w+)\\))?\\s*:\\s*([+-]?\\d.+\\d).*"; m_regex =
"^L 2 error\\s*(?:\\(variable (\\w+)\\))?\\s*:\\s*([+-]?\\d.+\\d).*";
// Find the L2 error to match against. // Find the L2 error to match against.
TiXmlElement *value; TiXmlElement *value;
while (value = metric->FirstChildElement("value")) while (value = metric->FirstChildElement("value"))
{ {
// Find name of field. // Find name of field.
std::string variable = value->Attribute("variable"); std::string variable = value->Attribute("variable");
// Set up a match with two fields which correspond with the // Set up a match with two fields which correspond with the
// subexpression above. The first is the variable name, second is // subexpression above. The first is the variable name, second is
// the L2 error. // the L2 error.
std::vector<std::string> tmp(2); std::vector<std::string> tmp(2);
tmp[0] = variable; tmp[0] = variable;
tmp[1] = value->GetText(); tmp[1] = value->GetText();
m_matches.push_back(tmp); m_matches.push_back(tmp);
// Indicate that the L2 error needs tolerance testing. // Indicate that the L2 error needs tolerance testing.
m_tolerance.insert(1); m_tolerance.insert(1);
}
} }
} }
...@@ -38,13 +38,23 @@ ...@@ -38,13 +38,23 @@
#include <MetricRegex.h> #include <MetricRegex.h>
class MetricL2 : public MetricRegex namespace Nektar
{ {
public: class MetricL2 : public MetricRegex
MetricL2(int id); {
public:
protected: static MetricSharedPtr create(int id)
virtual void v_Parse(TiXmlElement *metric); {
}; return MetricSharedPtr(new MetricL2(id));
}
static std::string type;
protected:
MetricL2(int id);
virtual void v_Parse(TiXmlElement *metric);
};
}
#endif #endif
...@@ -37,60 +37,65 @@ ...@@ -37,60 +37,65 @@
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
/** namespace Nektar
* @brief Constructor.
*/
MetricRegex::MetricRegex(int id) : Metric(id)
{ {
std::string MetricRegex::type = GetMetricFactory().
RegisterCreatorFunction("regex", MetricRegex::create);
} /**
* @brief Constructor.
void MetricRegex::v_Parse(TiXmlElement *metric) */
{ MetricRegex::MetricRegex(int id) : Metric(id)
// Parse a regex <METRIC> tag. This would populate m_regex, m_matches {
// and m_tolerance below.
} }
bool MetricRegex::v_TestLine(std::string line) void MetricRegex::v_Parse(TiXmlElement *metric)
{
// If we have matched everything, nothing to do.
if (m_matches.size() == 0)
{ {
return true; // Parse a regex <METRIC> tag. This would populate m_regex, m_matches
// and m_tolerance below.
} }
boost::cmatch matches;
std::vector<std::string> &okValues = m_matches[0];
// Test to see if we have a match. bool MetricRegex::v_TestLine(std::string line)
if (boost::regex_match(line.c_str(), matches, m_regex))
{ {
for (int i = 0; i < matches.size(); ++i) // If we have matched everything, nothing to do.
if (m_matches.size() == 0)
{ {
std::string match(matches[i].first, matches[i].second); return true;
}
boost::cmatch matches;
std::vector<std::string> &okValues = m_matches[0];
if (m_tolerance.count(i) > 0) // Test to see if we have a match.
if (boost::regex_match(line.c_str(), matches, m_regex))
{
for (int i = 0; i < matches.size(); ++i)
{ {
// If the okValues are not within tolerance, failed the std::string match(matches[i].first, matches[i].second);
// test.
if (fabs(boost::lexical_cast<int>(okValues[i]) - if (m_tolerance.count(i) > 0)
boost::lexical_cast<int>(match)) > 1e-6)
{ {
return false; // If the okValues are not within tolerance, failed the
// test.
if (fabs(boost::lexical_cast<int>(okValues[i]) -
boost::lexical_cast<int>(match)) > 1e-6)
{
return false;
}
} }
} else
else
{
// Case insensitive match.
if (!boost::iequals(match, okValues[i]))
{ {
return false; // Case insensitive match.
if (!boost::iequals(match, okValues[i]))
{
return false;
}
} }
} }
}
// Remove this match from the list of matches. // Remove this match from the list of matches.
m_matches.erase(m_matches.begin()); m_matches.erase(m_matches.begin());
}
} }
} }
...@@ -40,21 +40,31 @@ ...@@ -40,21 +40,31 @@
#include <boost/regex.hpp> #include <boost/regex.hpp>
#include <vector> #include <vector>
class MetricRegex : public Metric namespace Nektar
{ {
public: class MetricRegex : public Metric
MetricRegex(int id); {
public:
static MetricSharedPtr create(int id)
{
return MetricSharedPtr(new MetricRegex(id));
}
static std::string type;
protected: protected:
// Storage for the boost regex. /// Storage for the boost regex.
boost::regex m_regex; boost::regex m_regex;
// Stores the multiple matches defined in each <MATCH> tag. /// Stores the multiple matches defined in each <MATCH> tag.
std::vector<std::vector<std::string> > m_matches; std::vector<std::vector<std::string> > m_matches;
// Indicates which fields of a match need to be tested for tolerance. /// Indicates which fields of a match need to be tested for tolerance.
std::set<int> m_tolerance; std::set<int> m_tolerance;
MetricRegex(int id);
virtual void v_Parse (TiXmlElement *metric); virtual void v_Parse (TiXmlElement *metric);
virtual bool v_TestLine(std::string line); virtual bool v_TestLine(std::string line);
}; };
}
#endif #endif
...@@ -37,18 +37,41 @@ ...@@ -37,18 +37,41 @@
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <vector> #include <vector>
#include <sys/stat.h>
#include <MetricL2.h> #include <MetricL2.h>
#include <MetricRegex.h> #include <MetricRegex.h>
#include <boost/filesystem.hpp>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <boost/version.hpp> #include <boost/version.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/program_options.hpp>
#ifdef _WINDOWS
#define COPY_COMMAND "copy "
#else
#define COPY_COMMAND "cp "
#endif
using namespace std; using namespace std;
using namespace Nektar;
namespace po = boost::program_options;
std::string PortablePath(const boost::filesystem::path& path)
{
boost::filesystem::path temp = path;
#if BOOST_VERSION > 104200
temp.make_preferred();
return temp.string();
#else
return temp.file_string();
#endif
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
// Open file. // Process test file format.
TiXmlDocument *file = new TiXmlDocument(argv[1]); TiXmlDocument *file = new TiXmlDocument(argv[1]);
bool loadOkay = file->LoadFile(); bool loadOkay = file->LoadFile();
...@@ -65,23 +88,21 @@ int main(int argc, char *argv[]) ...@@ -65,23 +88,21 @@ int main(int argc, char *argv[])
// Find description tag. // Find description tag.
TiXmlElement *descElement = handle.FirstChildElement("test"). TiXmlElement *descElement = handle.FirstChildElement("test").
FirstChildElement("description").Element(); FirstChildElement("description").Element();
string description(descElement->GetText()); string description(descElement->GetText());
cout << description << endl;
// Find solver tag. // Find solver tag.
TiXmlElement *solverElement = handle.FirstChildElement("test"). TiXmlElement *solverElement = handle.FirstChildElement("test").
FirstChildElement("executable").Element(); FirstChildElement("executable").Element();
string executable(solverElement->GetText()); string executable(solverElement->GetText());
cout << executable << endl;
// Find input tag. // Find input tag.
TiXmlElement *inputElement = handle.FirstChildElement("test"). TiXmlElement *inputElement = handle.FirstChildElement("test").
FirstChildElement("parameters").Element(); FirstChildElement("parameters").Element();
string input(inputElement->GetText()); string input(inputElement->GetText());
cout << input << endl;
// Iterate through metric tags. /*
* Process and set up metric tags.
*/
TiXmlElement *metrics = testElement->FirstChildElement("metrics"); TiXmlElement *metrics = testElement->FirstChildElement("metrics");
if (!metrics) if (!metrics)
...@@ -91,33 +112,70 @@ int main(int argc, char *argv[]) ...@@ -91,33 +112,70 @@ int main(int argc, char *argv[])
} }
// Construct vector of metrics. // Construct vector of metrics.
TiXmlElement *metric = metrics->FirstChildElement("metric"); TiXmlElement *metric = metrics->FirstChildElement("metric");
vector<Metric*> metricList; vector<MetricSharedPtr> metricList;
while (metric) while (metric)
{ {
string metricType = metric->Attribute("type"); string metricType = metric->Attribute("type");
int metricId = boost::lexical_cast<int>(metric->Attribute("id")); int metricId = boost::lexical_cast<int>(metric->Attribute("id"));
Metric *m;
boost::algorithm::to_lower(metricType);
MetricSharedPtr m = GetMetricFactory().CreateInstance(
metricType, metricId);
metricList.push_back(m);
cout << "Metric type: " << metricType << ", id = " << metricId << endl; cout << "Metric type: " << metricType << ", id = " << metricId << endl;
if (metricType == "L2") m->Parse(metric);
metric = metric->NextSiblingElement("metric");
}
/*
* Copy required files for this test.
*/
TiXmlElement *required = handle.FirstChildElement("test").
FirstChildElement("required").Element();
TiXmlElement *reqfile = required->FirstChildElement("file");
struct stat vFileInfo;
while (reqfile)
{
string fname = reqfile->GetText();
string source = PortablePath(std::string(TEST_PATH)) + fname;
string command = std::string(COPY_COMMAND) + source + " .";
int vNotPresent = stat(source.c_str(), &vFileInfo);
if (vNotPresent)
{ {
m = new MetricL2(metricId); cerr << "Required file " << fname << " not found." << endl;
return 1;
} }
else if (metricType == "Regex")
int status = system(command.c_str());
if (status)
{ {
m = new MetricRegex(metricId); cerr << "Unable to copy file:" << source
<< " to current location" << endl;
return 1;
} }
m->Parse(metric); reqfile = metric->NextSiblingElement("required");
metric = metric->NextSiblingElement("metric");
} }
/*
* Run executable and perform tests.
*/
string cmd = executable + " " + input;
/* /*
while (getline(fpstream, line)) ifstream file(filename);
while (getline(file, line))
{ {
for (int i = 0; i < metricList.size(); ++i) for (int i = 0; i < metricList.size(); ++i)
{ {
...@@ -127,7 +185,7 @@ int main(int argc, char *argv[]) ...@@ -127,7 +185,7 @@ int main(int argc, char *argv[])
} }
} }
} }
for (int i = 0; i < metricList.size(); ++i) for (int i = 0; i < metricList.size(); ++i)
{ {
if (!metricList[i]->FinishTest()) if (!metricList[i]->FinishTest())
...@@ -136,7 +194,6 @@ int main(int argc, char *argv[]) ...@@ -136,7 +194,6 @@ int main(int argc, char *argv[])
} }
} }
*/ */
return 0; return 0;
} }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment