|
|
|
@ -7,6 +7,8 @@
|
|
|
|
|
#include <iostream> |
|
|
|
|
#include <fstream> |
|
|
|
|
|
|
|
|
|
#include <sys/stat.h> |
|
|
|
|
|
|
|
|
|
using namespace std; |
|
|
|
|
using namespace ApplicationUtilities; |
|
|
|
|
|
|
|
|
@ -16,7 +18,7 @@ TestApplication *TestApplication::m_instance = nullptr;
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* \class TestApplication |
|
|
|
|
* \brief The TestApplication class simplifies writing test applications. |
|
|
|
|
* \brief The TestApplication class simplifies writing test applications that require opening test files. |
|
|
|
|
* \remarks Only one instance is allowed at a time (singletone class). |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
@ -26,12 +28,16 @@ TestApplication *TestApplication::m_instance = nullptr;
|
|
|
|
|
*/ |
|
|
|
|
TestApplication::TestApplication(int argc, char **argv) : |
|
|
|
|
m_helpArg(m_parser), |
|
|
|
|
m_testFilesPathArg("test-files-path", "p", "specifies the path of the directory with test files") |
|
|
|
|
m_testFilesPathArg("test-files-path", "p", "specifies the path of the directory with test files"), |
|
|
|
|
m_workingDirArg("working-dir", "w", "specifies the directory to store working copies of test files") |
|
|
|
|
{ |
|
|
|
|
// check whether there is already an instance
|
|
|
|
|
if(m_instance) { |
|
|
|
|
throw runtime_error("only one TestApplication instance allowed at a time"); |
|
|
|
|
} |
|
|
|
|
m_instance = this; |
|
|
|
|
|
|
|
|
|
// read TEST_FILE_PATH environment variable
|
|
|
|
|
if(const char *testFilesPathEnv = getenv("TEST_FILE_PATH")) { |
|
|
|
|
if(const auto len = strlen(testFilesPathEnv)) { |
|
|
|
|
m_testFilesPathEnvValue.reserve(len + 1); |
|
|
|
@ -39,13 +45,20 @@ TestApplication::TestApplication(int argc, char **argv) :
|
|
|
|
|
m_testFilesPathEnvValue += '/'; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// setup argument parser
|
|
|
|
|
m_testFilesPathArg.setRequiredValueCount(1); |
|
|
|
|
m_testFilesPathArg.setValueNames({"path"}); |
|
|
|
|
m_testFilesPathArg.setCombinable(true); |
|
|
|
|
m_parser.setMainArguments({&m_testFilesPathArg, &m_helpArg}); |
|
|
|
|
m_workingDirArg.setRequiredValueCount(1); |
|
|
|
|
m_workingDirArg.setValueNames({"path"}); |
|
|
|
|
m_workingDirArg.setCombinable(true); |
|
|
|
|
m_parser.setMainArguments({&m_testFilesPathArg, &m_workingDirArg, &m_helpArg}); |
|
|
|
|
|
|
|
|
|
// parse arguments
|
|
|
|
|
try { |
|
|
|
|
m_parser.parseArgs(argc, argv); |
|
|
|
|
cerr << "Directories used to search for testfiles: " << endl; |
|
|
|
|
cerr << "Directories used to search for testfiles:" << endl; |
|
|
|
|
if(m_testFilesPathArg.isPresent()) { |
|
|
|
|
if(!m_testFilesPathArg.values().front().empty()) { |
|
|
|
|
cerr << (m_testFilesPathArgValue = m_testFilesPathArg.values().front() + '/') << endl; |
|
|
|
@ -57,6 +70,30 @@ TestApplication::TestApplication(int argc, char **argv) :
|
|
|
|
|
cerr << m_testFilesPathEnvValue << endl; |
|
|
|
|
} |
|
|
|
|
cerr << "./testfiles/" << endl << endl; |
|
|
|
|
cerr << "Directory used to store working copies:" << endl; |
|
|
|
|
if(m_workingDirArg.isPresent()) { |
|
|
|
|
if(!m_workingDirArg.values().front().empty()) { |
|
|
|
|
m_workingDir = m_workingDirArg.values().front() + '/'; |
|
|
|
|
} else { |
|
|
|
|
m_workingDir = "./"; |
|
|
|
|
} |
|
|
|
|
} else if(const char *workingDirEnv = getenv("WORKING_DIR")) { |
|
|
|
|
if(const auto len = strlen(workingDirEnv)) { |
|
|
|
|
m_workingDir.reserve(len + 1); |
|
|
|
|
m_workingDir += workingDirEnv; |
|
|
|
|
m_workingDir += '/'; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
if(m_testFilesPathArg.isPresent()) { |
|
|
|
|
m_workingDir = m_testFilesPathArgValue + "workingdir/"; |
|
|
|
|
} else if(!m_testFilesPathEnvValue.empty()) { |
|
|
|
|
m_workingDir = m_testFilesPathEnvValue + "workingdir/"; |
|
|
|
|
} else { |
|
|
|
|
m_workingDir = "./testfiles/workingdir/"; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
cerr << m_workingDir << endl << endl; |
|
|
|
|
|
|
|
|
|
m_valid = true; |
|
|
|
|
cerr << "Executing test cases ..." << endl; |
|
|
|
|
} catch(const Failure &failure) { |
|
|
|
@ -74,18 +111,22 @@ TestApplication::~TestApplication()
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* \brief Returns the full path of tbe test file with the specified \a name. |
|
|
|
|
* \brief Returns the full path of the test file with the specified \a name. |
|
|
|
|
*/ |
|
|
|
|
string TestApplication::testFilePath(const string &name) const |
|
|
|
|
{ |
|
|
|
|
string path; |
|
|
|
|
fstream file; |
|
|
|
|
fstream file; // used to check whether the file is present
|
|
|
|
|
|
|
|
|
|
// check the path specified by command line argument
|
|
|
|
|
if(m_testFilesPathArg.isPresent()) { |
|
|
|
|
file.open(path = m_testFilesPathArgValue + name, ios_base::in); |
|
|
|
|
if(file.good()) { |
|
|
|
|
return path; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// check the path specified by environment variable
|
|
|
|
|
if(!m_testFilesPathEnvValue.empty()) { |
|
|
|
|
file.clear(); |
|
|
|
|
file.open(path = m_testFilesPathEnvValue + name, ios_base::in); |
|
|
|
@ -93,7 +134,41 @@ string TestApplication::testFilePath(const string &name) const
|
|
|
|
|
return path; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// file still not found -> return default path
|
|
|
|
|
return "./testfiles/" + name; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* \brief Returns the full path to a working copy of the test file with the specified \a name. |
|
|
|
|
*/ |
|
|
|
|
string TestApplication::workingCopyPath(const string &name) const |
|
|
|
|
{ |
|
|
|
|
// create file streams
|
|
|
|
|
fstream origFile, workingCopy; |
|
|
|
|
origFile.exceptions(ios_base::badbit | ios_base::failbit); |
|
|
|
|
workingCopy.exceptions(ios_base::badbit | ios_base::failbit); |
|
|
|
|
|
|
|
|
|
// ensure working directory is present
|
|
|
|
|
struct stat currentStat; |
|
|
|
|
if(stat(m_workingDir.c_str(), ¤tStat) || !S_ISDIR(currentStat.st_mode)) { |
|
|
|
|
if(mkdir(m_workingDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) { |
|
|
|
|
cerr << "Unable to create working copy for \"" << name << "\": can't create working directory." << endl; |
|
|
|
|
return string(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// copy file
|
|
|
|
|
try { |
|
|
|
|
origFile.open(testFilePath(name), ios_base::in | ios_base::binary); |
|
|
|
|
string path = m_workingDir + name; |
|
|
|
|
workingCopy.open(path, ios_base::out | ios_base::binary | ios_base::trunc); |
|
|
|
|
workingCopy << origFile.rdbuf(); |
|
|
|
|
return path; |
|
|
|
|
} catch(const ios_base::failure &) { |
|
|
|
|
cerr << "Unable to create working copy for \"" << name << "\": an IO error occured." << endl; |
|
|
|
|
} |
|
|
|
|
return string(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|