Commit ad6ccfb8 authored by David Moxey's avatar David Moxey

Potentially fix CWIPI tester by adding multiple commands.

parent 97dcbfc6
......@@ -43,7 +43,7 @@ using namespace std;
namespace Nektar
{
TestData::TestData(const fs::path& pFilename, po::variables_map& pVm)
: m_cmdoptions(pVm), m_pythonTest(false)
: m_cmdoptions(pVm)
{
// Process test file format.
m_doc = new TiXmlDocument(pFilename.string().c_str());
......@@ -67,29 +67,16 @@ namespace Nektar
return m_description;
}
const fs::path& TestData::GetExecutable() const
const Command& TestData::GetCommand(unsigned int pId) const
{
return m_executable;
ASSERTL0(pId < m_commands.size(),
"Command ID '" + std::to_string(pId) + "' not found");
return m_commands[pId];
}
const std::string& TestData::GetParameters() const
unsigned int TestData::GetNumCommands() const
{
return m_parameters;
}
const std::string& TestData::GetCommand() const
{
return m_command;
}
const unsigned int& TestData::GetNProcesses() const
{
return m_processes;
}
bool TestData::IsPythonTest() const
{
return m_pythonTest;
return m_commands.size();
}
std::string TestData::GetMetricType(unsigned int pId) const
......@@ -121,7 +108,7 @@ namespace Nektar
ASSERTL0(id, "No ID found for metric!");
return boost::lexical_cast<unsigned int>(id);
}
DependentFile TestData::GetDependentFile(unsigned int pId) const
{
ASSERTL0(pId < m_files.size(), "File index out of range.");
......@@ -133,71 +120,92 @@ namespace Nektar
return m_files.size();
}
void TestData::Parse(TiXmlDocument* pDoc)
Command TestData::ParseCommand(TiXmlElement *elmt) const
{
TiXmlHandle handle(m_doc);
TiXmlElement *testElement, *tmp, *metrics, *files;
testElement = handle.FirstChildElement("test").Element();
ASSERTL0(testElement, "Cannot find 'test' root element.");
Command cmd;
TiXmlElement *tmp;
// Find description tag.
tmp = testElement->FirstChildElement("description");
ASSERTL0(tmp, "Cannot find 'description' for test.");
m_description = string(tmp->GetText());
cmd.m_pythonTest = false;
// Find executable.
if (m_cmdoptions.count("executable"))
{
m_executable = fs::path(
m_cmdoptions["executable"].as<std::string>());
}
else
// Parse executable tag. Do not enforce a check because this might be
// overridden on the command line.
if (elmt->FirstChildElement("executable"))
{
tmp = testElement->FirstChildElement("executable");
ASSERTL0(tmp, "Cannot find 'executable' for test.");
m_executable = fs::path(tmp->GetText());
tmp = elmt->FirstChildElement("executable");
cmd.m_executable = fs::path(tmp->GetText());
// Test to see if this test requires Python
std::string needsPython;
tmp->QueryStringAttribute("python", &needsPython);
m_pythonTest = needsPython == "true";
cmd.m_pythonTest = needsPython == "true";
#if defined(RELWITHDEBINFO)
m_executable += m_pythonTest ? "" : "-rg";
cmd.m_executable += cmd.m_pythonTest ? "" : "-rg";
#elif !defined(NDEBUG)
m_executable += m_pythonTest ? "" : "-g";
cmd.m_executable += cmd.m_pythonTest ? "" : "-g";
#endif
}
// Find parameters tag.
tmp = testElement->FirstChildElement("parameters");
// Find associated parameters.
tmp = elmt->FirstChildElement("parameters");
ASSERTL0(tmp, "Cannot find 'parameters' for test.");
if (tmp->GetText())
{
m_parameters = string(tmp->GetText());
cmd.m_parameters = string(tmp->GetText());
}
tmp = testElement->FirstChildElement("command");
// Find parallel processes tah.
tmp = elmt->FirstChildElement("processes");
if (tmp)
{
m_command = string(tmp->GetText());
cmd.m_processes = atoi(tmp->GetText());
}
else
{
m_command = "";
cmd.m_processes = 1;
}
// Find parallel processes tah.
tmp = testElement->FirstChildElement("processes");
if (tmp)
return cmd;
}
void TestData::Parse(TiXmlDocument* pDoc)
{
TiXmlHandle handle(m_doc);
TiXmlElement *testElement, *tmp, *metrics, *files;
testElement = handle.FirstChildElement("test").Element();
ASSERTL0(testElement, "Cannot find 'test' root element.");
// Find description tag.
tmp = testElement->FirstChildElement("description");
ASSERTL0(tmp, "Cannot find 'description' for test.");
m_description = string(tmp->GetText());
// Find command(s) to run.
if ((tmp = testElement->FirstChildElement("executable")))
{
m_processes = atoi(tmp->GetText());
m_commands.push_back(ParseCommand(testElement));
}
else
else if (m_cmdoptions.count("executable"))
{
m_commands.push_back(ParseCommand(testElement));
m_commands.back().m_executable = fs::path(
m_cmdoptions["executable"].as<std::string>());
}
else if ((tmp = testElement->FirstChildElement("segment")))
{
m_processes = 1;
ASSERTL0(m_cmdoptions.count("executable") == 0,
"Test files defining more than one command in segment "
"blocks cannot use --executable.");
while (tmp)
{
m_commands.push_back(ParseCommand(tmp));
tmp = tmp->NextSiblingElement("segment");
}
}
ASSERTL0(m_commands.size() > 0, "lol");
// Extract metric tags
metrics = testElement->FirstChildElement("metrics");
ASSERTL0(metrics, "No metrics defined for test.");
......@@ -227,7 +235,7 @@ namespace Nektar
}
}
}
void TestData::SaveFile()
{
m_doc->SaveFile();
......
......@@ -54,6 +54,14 @@ namespace Nektar
std::string m_filename;
};
struct Command
{
fs::path m_executable;
std::string m_parameters;
unsigned int m_processes;
bool m_pythonTest;
};
class TestData
{
public:
......@@ -61,11 +69,8 @@ namespace Nektar
TestData(const TestData& pSrc);
const std::string& GetDescription() const;
const fs::path& GetExecutable() const;
const std::string& GetParameters() const;
const std::string& GetCommand() const;
const unsigned int& GetNProcesses() const;
bool IsPythonTest() const;
const Command &GetCommand(unsigned int pId) const;
unsigned int GetNumCommands() const;
std::string GetMetricType(unsigned int pId) const;
unsigned int GetNumMetrics() const;
......@@ -80,16 +85,13 @@ namespace Nektar
private:
po::variables_map m_cmdoptions;
std::string m_description;
fs::path m_executable;
std::string m_parameters;
std::string m_command;
unsigned int m_processes;
std::vector<Command> m_commands;
TiXmlDocument* m_doc;
std::vector<TiXmlElement*> m_metrics;
std::vector<DependentFile> m_files;
bool m_pythonTest;
void Parse(TiXmlDocument* pDoc);
Command ParseCommand(TiXmlElement *pElmt) const;
};
}
......
......@@ -245,51 +245,84 @@ int main(int argc, char *argv[])
// If we're Python, copy script too.
// Construct test command to run. If in debug mode, append "-g"
// Output from stdout and stderr are directed to the files output.out
// and output.err, respectively.
// Construct test command to run. Output from stdout and stderr are
// directed to the files output.out and output.err, respectively.
if (file.IsPythonTest())
bool pythonAdded = false, mpiAdded = false;
for (unsigned int i = 0; i < file.GetNumCommands(); ++i)
{
command += "PYTHONPATH=\"@CMAKE_BINARY_DIR@\" ";
}
Command cmd = file.GetCommand(i);
if (cmd.m_pythonTest && !pythonAdded)
{
// Prepend Python to very start of command.
command = "PYTHONPATH=\"@CMAKE_BINARY_DIR@\" " + command;
pythonAdded = true;
}
#ifdef NEKTAR_TEST_FORCEMPIEXEC
#else
if (file.GetNProcesses() > 1)
if (cmd.m_processes > 1 || file.GetNumCommands() > 1)
#endif
{
command += "@MPIEXEC@ @MPIEXEC_NUMPROC_FLAG@ "
+ boost::lexical_cast<string>(file.GetNProcesses())
+ " ";
if (std::string("@NEKTAR_TEST_USE_HOSTFILE@") == "ON")
{
command += " -hostfile hostfile ";
system("echo 'localhost slots=12' > hostfile");
if (mpiAdded)
{
continue;
}
command += "@MPIEXEC@ ";
if (std::string("@NEKTAR_TEST_USE_HOSTFILE@") == "ON")
{
command += "-hostfile hostfile ";
system("echo 'localhost slots=12' > hostfile");
}
if (file.GetNumCommands() > 1)
{
command += "--tag-output ";
}
mpiAdded = true;
}
}
fs::path execPath = startDir / file.GetExecutable();
if (!fs::exists(execPath))
// Parse commands.
for (unsigned int i = 0; i < file.GetNumCommands(); ++i)
{
ASSERTL0(!file.IsPythonTest(), "Python script not found.");
execPath = file.GetExecutable();
}
Command cmd = file.GetCommand(i);
if (file.IsPythonTest())
{
command += "@PYTHON_EXECUTABLE@ ";
}
// If running with multiple commands simultaneously, separate with
// colon.
if (i > 0)
{
command += " : ";
}
command += PortablePath(execPath);
command += " ";
command += file.GetParameters();
command += " 1>output.out 2>output.err";
// Add -n where appropriate.
if (file.GetNumCommands() > 1 || cmd.m_processes > 1)
{
command += "@MPIEXEC_NUMPROC_FLAG@ ";
command += std::to_string(cmd.m_processes) + " ";
}
// override command if specified
if (file.GetCommand() != "")
{
command = file.GetCommand();
// Look for executable or Python script.
fs::path execPath = startDir / cmd.m_executable;
if (!fs::exists(execPath))
{
ASSERTL0(!cmd.m_pythonTest, "Python script not found.");
execPath = cmd.m_executable;
}
// Prepend script name with Python executable path if this is a
// Python test.
if (cmd.m_pythonTest)
{
command += "@PYTHON_EXECUTABLE@ ";
}
command += PortablePath(execPath);
command += " ";
command += cmd.m_parameters;
command += " 1>output.out 2>output.err";
}
status = 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