From fde833c46bc027f13fc69ac4f954b3e60ee97b3f Mon Sep 17 00:00:00 2001 From: Justin Meimar Date: Mon, 3 Jun 2024 12:26:26 -0600 Subject: [PATCH] Make the TestHarness class depper --- include/analysis/Grader.h | 10 +- include/testharness/TestHarness.h | 40 ++++-- include/tests/TestFile.h | 12 +- include/tests/TestParser.h | 26 ++-- include/tests/Util.h | 22 ++-- src/analysis/Grader.cpp | 9 +- src/main.cpp | 12 -- src/testharness/TestHarness.cpp | 212 ++++++++++++++++++------------ src/tests/CMakeLists.txt | 1 - src/tests/TestFile.cpp | 10 +- src/tests/TestFinding.cpp | 105 --------------- src/tests/TestParser.cpp | 39 +++--- 12 files changed, 212 insertions(+), 286 deletions(-) delete mode 100644 src/tests/TestFinding.cpp diff --git a/include/analysis/Grader.h b/include/analysis/Grader.h index 3f28ea22..9ddfa859 100644 --- a/include/analysis/Grader.h +++ b/include/analysis/Grader.h @@ -4,6 +4,7 @@ #include "config/Config.h" #include "tests/Util.h" #include "json.hpp" +#include "testharness/TestHarness.h" #include #include @@ -14,13 +15,13 @@ using JSON = nlohmann::json; namespace tester { -class Grader { +class Grader : public TestHarness { public: // No default constructor. Grader() = delete; // Construct with output file path. - explicit Grader(const Config &cfg); + Grader(const Config &cfg) : TestHarness(cfg), cfg(cfg) { findTests(); buildResults(); } void dump(std::ostream &os) const { std::string jsonString = outputJson.dump(2); @@ -34,10 +35,7 @@ class Grader { private: // Our config. const Config &cfg; - - // Our tests. - TestModule tests; - + // The filtered (must have exe and tests) names of all solutions that will be tested. std::vector names; diff --git a/include/testharness/TestHarness.h b/include/testharness/TestHarness.h index 6bd4d6f0..f710e95b 100644 --- a/include/testharness/TestHarness.h +++ b/include/testharness/TestHarness.h @@ -2,10 +2,10 @@ #define TESTER_TEST_HARNESS_H #include "config/Config.h" -#include "tests/Util.h" #include "testharness/ResultManager.h" #include "toolchain/ToolChain.h" #include "Colors.h" +#include "tests/TestParser.h" #include #include @@ -16,6 +16,11 @@ namespace fs = std::filesystem; namespace tester { +// Test hierarchy types +typedef std::vector> SubPackage; +typedef std::map Package; +typedef std::map TestSet; + // Class that manages finding tests and running them. class TestHarness { public: @@ -23,9 +28,8 @@ class TestHarness { TestHarness() = delete; // Construct the Tester with a parsed JSON file. - TestHarness(const Config &cfg); + TestHarness(const Config &cfg) : cfg(cfg), results() { findTests(); } - // Run the found tests. // Returns true if any tests failed, false otherwise. bool runTests(); @@ -35,20 +39,34 @@ class TestHarness { // Get test summary. std::string getTestSummary() const; -private: - // Runs the accumulated tests against a specific exe and toolchain. - // Returns true if any tests failed, false otherwise. - bool runTestsForToolChain(std::string tcId, std::string exeName); +protected: + // where all the tests are held. + TestSet testSet; -private: + // A separate subpackage, just for invalid tests. + SubPackage invalidTests; + + // let derived classes find tests. + void findTests(); + +private: // Our input config. const Config &cfg; - + // The results of the tests. ResultManager results; - // module where all tests are contained - TestModule module; +private: + // test running + bool runTestsForToolChain(std::string tcId, std::string exeName); + + // test finding and filling methods + void addTestFileToSubPackage(SubPackage& subPackage, const fs::path& file); + + // utility for filling packages with tests + void fillSubpackage(SubPackage& subPackage, const fs::path& subPackPath); + void fillSubpackagesRecursive(Package& package, const fs::path& packPath, const std::string& parentKey); + void setupDebugModule(TestSet& testSet, const fs::path &debugPath); }; } // End namespace tester diff --git a/include/tests/TestFile.h b/include/tests/TestFile.h index 7c3a6fd4..000fa0ee 100644 --- a/include/tests/TestFile.h +++ b/include/tests/TestFile.h @@ -44,8 +44,9 @@ class TestFile { ParseError getErrorState() const { return errorState; } std::string getErrorMessage() const; double getElapsedTime() const { return elapsedTime; } - - // setters + bool didError() const { return errorState != ParseError::NoError; } + + // void setTestPath(fs::path path) { testPath = path; } void setInsPath(fs::path path) { insPath = path; } void setOutPath(fs::path path) { outPath = path; } @@ -54,8 +55,9 @@ class TestFile { void setElapsedTime(double elapsed) { elapsedTime = elapsed; } // if test has any input and if test uses input file specifically - bool usesInputStream, usesInputFile, usesOutStream, usesOutFile; + bool usesInputStream{false}, usesInputFile{false}, usesOutStream{false}, usesOutFile{false}; + // TODO: friend class TestParser; protected: @@ -66,11 +68,11 @@ class TestFile { fs::path testPath, insPath, outPath; // Test file breaks some convention or was unable to parse directives. - ParseError errorState; + ParseError errorState{ParseError::NoError}; std::string errorMsg; // elapsed time for final toolchain step - double elapsedTime; + double elapsedTime{0}; }; diff --git a/include/tests/TestParser.h b/include/tests/TestParser.h index 5fc55836..530f96e5 100644 --- a/include/tests/TestParser.h +++ b/include/tests/TestParser.h @@ -13,30 +13,25 @@ namespace tester { using PathOrError = std::variant; class TestParser { + public: - TestParser(TestFile &testfile) - : testfile(testfile), foundInput(false), foundInputFile(false), - foundCheck(false), foundCheckFile(false), inLineComment(false), - inBlockComment(false), inString(false), insByteCount(0), outByteCount(0) - { - parseTest(); - }; + TestParser(TestFile *testfile) : testfile(testfile) { parse(); } - int parseTest(); - void validate(); + // clear the parsing state for the next test. + void parse(); private: - // Testfile we parse on - TestFile &testfile; - + // testfile we are parsing + TestFile *testfile; + // track state of parse - bool foundInput, foundInputFile, foundCheck, foundCheckFile; + bool foundInput{false}, foundInputFile{false}, foundCheck{false}, foundCheckFile{false}; // track comment state - bool inLineComment, inBlockComment, inString; + bool inLineComment{false}, inBlockComment{false}, inString{false}; // current input stream size - uint32_t insByteCount, outByteCount; + uint32_t insByteCount{0}, outByteCount{0}; // determine if we are in a comment while parsing void trackCommentState(std::string &line); @@ -53,7 +48,6 @@ class TestParser { ParseError matchInputFileDirective(std::string &line); ParseError matchCheckFileDirective(std::string &line); ParseError matchDirectives(std::string &line); - }; }; // namespace tester diff --git a/include/tests/Util.h b/include/tests/Util.h index e43f5300..83a6e2a9 100644 --- a/include/tests/Util.h +++ b/include/tests/Util.h @@ -1,22 +1,22 @@ -#include -#include -#include -#include +// #include +// #include +// #include +// #include #include "config/Config.h" #include "TestFile.h" #include "TestResult.h" -#include "toolchain/ToolChain.h" -#include "Colors.h" +// #include "toolchain/ToolChain.h" +// #include "Colors.h" namespace tester { -typedef std::vector> SubPackage; -typedef std::map Package; -typedef std::map TestModule; +// typedef std::vector> SubPackage; +// typedef std::map Package; +// typedef std::map TestModule; -// test finding interface -void fillModule(const Config &cfg, TestModule& module); +// // test finding interface +// void fillModule(const Config &cfg, TestModule& module); TestResult runTest(TestFile *test, const ToolChain &toolChain, const Config &cfg); diff --git a/src/analysis/Grader.cpp b/src/analysis/Grader.cpp index 337bb77c..a3b7664f 100644 --- a/src/analysis/Grader.cpp +++ b/src/analysis/Grader.cpp @@ -8,11 +8,6 @@ namespace { namespace tester { -Grader::Grader(const Config &cfg) : cfg(cfg), tests(), outputJson(JSON::object()) { - fillModule(cfg, tests); - buildResults(); -} - void Grader::buildResults() { // outputJson["toolchainCount"] = cfg.getToolChains().size(); @@ -21,7 +16,7 @@ void Grader::buildResults() { // collect summary of grading JSON testSummary = JSON::array(); - for (const auto &testPackage : tests) { + for (const auto &testPackage : testSet) { // First check if the name exists in the executable lists. std::string name = testPackage.first; names.push_back(name); @@ -79,7 +74,7 @@ void Grader::buildResults() { // Iterate over subpackages and the contained tests from the attacker, tracking pass count. size_t passCount = 0, testCount = 0; - for (const auto &subpackages : tests[attacker]) { + for (const auto &subpackages : testSet[attacker]) { for (const std::unique_ptr &test : subpackages.second) { TestResult result = runTest(test.get(), tc, cfg); diff --git a/src/main.cpp b/src/main.cpp index 17e03dc2..11e8ae0d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -34,18 +34,6 @@ int main(int argc, char **argv) { // Run our tests. failed = t.runTests(); - - // Save or print the summary. - // std::string summary = t.getTestSummary(); - // if (cfg.hasSummaryPath()) { - // std::ofstream sumFile(cfg.getSummaryPath()); - // sumFile << summary; - // std::cout << "Summary saved to file: " << cfg.getSummaryPath() << '\n'; - // } - // else { - // std::cout << "Summary:\n" << summary; - // } - } catch (const std::runtime_error &e) { std::cout << "Test harness error: " << e.what() << '\n'; diff --git a/src/testharness/TestHarness.cpp b/src/testharness/TestHarness.cpp index a3cad347..7fd81930 100644 --- a/src/testharness/TestHarness.cpp +++ b/src/testharness/TestHarness.cpp @@ -12,10 +12,6 @@ namespace tester { // Builds TestSet during object creation. -TestHarness::TestHarness(const Config &cfg) : cfg(cfg), results(), module() { - // Build the test set. - fillModule(cfg, module); -} bool TestHarness::runTests() { bool failed = false; @@ -31,82 +27,25 @@ bool TestHarness::runTests() { } std::string TestHarness::getTestInfo() const { - std::string rv = "Tests:\n"; - for (auto &tlEntry : module) { - rv += " " + tlEntry.first + ": " + std::to_string(tlEntry.second.size()) + '\n'; - } - return rv; -} - -std::string TestHarness::getTestSummary() const { - std::stringstream allInfo; - - // Iterate over executables. - for (const auto &exePair : cfg.getExecutables()) { - // Write out this executables header. - allInfo << exePair.first << ":\n"; - - // The streams for package info. Self is for an exectuable's own test package, other for the - // others. - std::stringstream selfPackageInfo; - std::stringstream otherPackageInfo; - - // We leave the above streams blank because there might not be tests in that category. These - // bools track if we've written to them. If they're false and you're about to write to it then - // you should add an appropriate header. - bool toSelf = false, toOther = false; - - // Iterate over the test packages. - for (const auto& [packageName, package] : module) { - // Success count. - unsigned int passes = 0, count = 0; - - // Iterate over toolchains. - for (const auto &tcPair : cfg.getToolChains()) { - // Get the list of results for this exe, toolchain, and package. - const ResultList &packageResults = - results.getResults(exePair.first, tcPair.first).at(packageName); - - // Iterate over the results. - for (const auto &result : packageResults) { - if (result.pass) { - ++passes; - } - } - - // Save the size. - count += packageResults.size(); - } - - // If this executable is linked with this package then it's the executable maker's set of - // tests. We handle this slightly differently. - if (exePair.first == packageName) { - // We should only ever write to the self stream once, so toSelf is more of a trap than a - // flag. We include the header in the one write as well. - assert(!toSelf && "Already written to self"); - toSelf = true; - selfPackageInfo << " Self tests:\n " << packageName << ": " << passes << " / " << count - << " -> " << (passes == count ? "PASS" : "FAIL") << '\n'; - } - else { - // Add other header. - if (!toOther) { - otherPackageInfo << " Other tests:\n"; - toOther = true; - } - - // Write info. - otherPackageInfo << " " << packageName << ": " << passes << " / " << count << '\n'; - } + std::ostringstream oss; + oss << "Test Information:\n\n"; + for (const auto& [packageName, subPackages] : testSet) { + oss << "Package: " << packageName << " (" << subPackages.size() << " subpackages)\n"; + for (const auto& [subPackageName, tests] : subPackages) { + oss << " - Subpackage: " << subPackageName << " (" << tests.size() << " tests)\n"; } - - allInfo << selfPackageInfo.str() << otherPackageInfo.str(); } - - return allInfo.str(); + oss << "Total Packages: " << testSet.size() << "\n"; + return oss.str(); } bool TestHarness::runTestsForToolChain(std::string exeName, std::string tcName) { + + if (cfg.hasSummaryPath()) { + //TODO: dup filepath to stdout and re-use this functions infra. + + } + bool failed = false; // Get the toolchain to use. @@ -129,11 +68,8 @@ bool TestHarness::runTestsForToolChain(std::string exeName, std::string tcName) // Stat tracking for toolchain tests. unsigned int toolChainCount = 0, toolChainPasses = 0; - // Track invalid tests - std::vector invalidTests; - // Iterate over each package. - for (auto& [packageName, package] : module) { + for (auto& [packageName, package] : testSet) { std::cout << "Entering package: " << packageName << '\n'; unsigned int packageCount = 0, packagePasses = 0; @@ -143,7 +79,7 @@ bool TestHarness::runTestsForToolChain(std::string exeName, std::string tcName) unsigned int subPackagePasses = 0, subPackageSize = subPackage.size(); // Iterate over each test in the package - for (std::unique_ptr& test : subPackage) { + for (const std::unique_ptr& test : subPackage) { if (test->getErrorState() == ParseError::NoError) { TestResult result = runTest(test.get(), toolChain, cfg); results.addResult(exeName, tcName, subPackageName, result); @@ -163,7 +99,6 @@ bool TestHarness::runTestsForToolChain(std::string exeName, std::string tcName) std::cout << " " << (Colors::YELLOW + "[INVALID]" + Colors::RESET) << " " << test->getTestPath().stem().string() << '\n'; --subPackageSize; - invalidTests.push_back(test.get()); } } std::cout << " Subpackage passed " << subPackagePasses << " / " << subPackageSize << '\n'; @@ -183,14 +118,123 @@ bool TestHarness::runTestsForToolChain(std::string exeName, std::string tcName) std::cout << "Invalid " << invalidTests.size() << " / " << toolChainCount + invalidTests.size() << "\n"; - for (const TestFile* test : invalidTests) { - std::cout << " Skipped: " << test->getTestPath().filename().stem() << std::endl - << " Error: " << Colors::YELLOW << test->getErrorMessage() << Colors::RESET << "\n"; + for (auto& test : invalidTests) { + std::cout << " Skipped: " << test->getTestPath().filename().stem() << std::endl + << " Error: " << Colors::YELLOW << test->getErrorMessage() << Colors::RESET << "\n"; } std::cout << "\n"; return failed; } +bool isTestFile(const fs::path& path) { + return fs::exists(path) && !fs::is_directory(path) && path.extension() != ".ins" + && path.extension() != ".out"; +} + +bool hasTestFiles(const fs::path& path) { + for (const auto& entry : fs::recursive_directory_iterator(path)) { + if (isTestFile(entry)) { + return true; + } + } + return false; +} + +void TestHarness::addTestFileToSubPackage(SubPackage& subPackage, const fs::path& file) { + + // try {} + auto testfile = std::make_unique(file); + + TestParser parser(testfile.get()); + + if (testfile->didError()) { + invalidTests.push_back(std::move(testfile)); + } else { + subPackage.push_back(std::move(testfile)); + } +} + +void TestHarness::fillSubpackage(SubPackage& subPackage, const fs::path& subPackPath) { + for (const fs::path& file : fs::directory_iterator(subPackPath)) { + if (isTestFile(file)) { + addTestFileToSubPackage(subPackage, file); + } + } +} + +void TestHarness::fillSubpackagesRecursive(Package& package, const fs::path& packPath, const std::string& parentKey) { + try { + for (const auto& file : fs::directory_iterator(packPath)) { + if (fs::is_directory(file)) { + std::string subpackageKey = parentKey + "." + file.path().stem().string(); + if (hasTestFiles(file)) { + SubPackage subpackage; + fillSubpackage(subpackage, file.path()); + package[subpackageKey] = std::move(subpackage); + } + fillSubpackagesRecursive(package, file.path(), subpackageKey); + } + } + } catch (const fs::filesystem_error& e) { + std::cerr << e.what() << std::endl; + } +} + +void TestHarness::setupDebugModule(TestSet& testSet, const fs::path &debugPath) { + + Package debugPackage; + SubPackage debugSubpackage; + std::string prefix("debugSubPackage"); + + if (fs::is_directory(debugPath)) { + if (hasTestFiles(debugPath)) { + fillSubpackage(debugSubpackage, debugPath); + if (!debugSubpackage.empty()) { + debugPackage[prefix] = std::move(debugSubpackage); + } + fillSubpackagesRecursive(debugPackage, debugPath, prefix); + } + } else if (fs::exists(debugPath) && isTestFile(debugPath)) { + addTestFileToSubPackage(debugSubpackage, debugPath); + debugPackage[prefix] = std::move(debugSubpackage); + } else { + throw std::runtime_error("Bad debug path supplied."); + } + + testSet["debugPkg"] = std::move(debugPackage); +} + + +void TestHarness::findTests() { + + const fs::path &debugPath = cfg.getDebugPath(); + const fs::path &testDirPath = cfg.getTestDirPath(); + + if (!debugPath.empty()) { + setupDebugModule(testSet, debugPath); + return; + } + + for (const auto& dir : fs::directory_iterator(testDirPath)) { + if (!fs::is_directory(dir)) { + throw std::runtime_error("All top-level files in module must be directories."); + } + + const fs::path& packagePath = dir.path(); + const std::string& packageKeyPrefix = packagePath.filename().string(); + + Package package; + SubPackage moduleSubpackage; + + fillSubpackage(moduleSubpackage, packagePath); + if (!moduleSubpackage.empty()) { + package[packageKeyPrefix] = std::move(moduleSubpackage); + } + + fillSubpackagesRecursive(package, packagePath, packageKeyPrefix); + testSet[packageKeyPrefix] = std::move(package); + } +} } // End namespace tester diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index de6a1643..0546b3bd 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -2,7 +2,6 @@ set( tests_src_files "${CMAKE_CURRENT_SOURCE_DIR}/TestRunning.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/TestFinding.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/TestParser.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/TestFile.cpp" ) diff --git a/src/tests/TestFile.cpp b/src/tests/TestFile.cpp index 13eaf640..a0e496c7 100644 --- a/src/tests/TestFile.cpp +++ b/src/tests/TestFile.cpp @@ -14,11 +14,7 @@ namespace tester { uint64_t TestFile::nextId = 0; -TestFile::TestFile(const fs::path& path) - : id(++nextId), usesInputStream(false), usesInputFile(false), - usesOutStream(false), usesOutFile(false), testPath(path), - errorState(ParseError::NoError), elapsedTime(0) -{ +TestFile::TestFile(const fs::path& path) : id(++nextId), testPath(path) { // create a unique temporary file to use as the inputs stream path std::string fileInsPath = stripFileExtension(testPath.filename()); @@ -28,11 +24,9 @@ TestFile::TestFile(const fs::path& path) std::ofstream makeInsFile(insPath); std::ofstream makeOutFile(outPath); + // closing creates the files makeInsFile.close(); makeOutFile.close(); - - // invoke the parser - auto parser = std::make_unique(*this); } TestFile::~TestFile() { diff --git a/src/tests/TestFinding.cpp b/src/tests/TestFinding.cpp deleted file mode 100644 index 5cfd4199..00000000 --- a/src/tests/TestFinding.cpp +++ /dev/null @@ -1,105 +0,0 @@ -#include "tests/Util.h" - -namespace tester { - -bool isTestFile(const fs::path& path) { - return fs::exists(path) && !fs::is_directory(path) && path.extension() != ".ins" - && path.extension() != ".out"; -} - -bool hasTestFiles(const fs::path& path) { - for (const auto& entry : fs::recursive_directory_iterator(path)) { - if (isTestFile(entry)) { - return true; - } - } - return false; -} - -void addTestFileToSubPackage(SubPackage& subPackage, const fs::path& file) { - try { - auto testfile = std::make_unique(file); - subPackage.push_back(std::move(testfile)); - } catch (const std::exception& e) { - std::cerr << "Exception creating TestFile: " << e.what() << std::endl; - } -} - -void fillSubpackage(SubPackage& subPackage, const fs::path& subPackPath) { - for (const fs::path& file : fs::directory_iterator(subPackPath)) { - if (isTestFile(file)) { - addTestFileToSubPackage(subPackage, file); - } - } -} - -void fillSubpackages(Package& package, const fs::path& packPath, const std::string& parentKey) { - try { - for (const auto& file : fs::directory_iterator(packPath)) { - if (fs::is_directory(file)) { - std::string subpackageKey = parentKey + "." + file.path().stem().string(); - if (hasTestFiles(file)) { - SubPackage subpackage; - fillSubpackage(subpackage, file.path()); - package[subpackageKey] = std::move(subpackage); - } - fillSubpackages(package, file.path(), subpackageKey); - } - } - } catch (const fs::filesystem_error& e) { - std::cerr << e.what() << std::endl; - } -} - -void setupDebugModule(TestModule& module, const fs::path &debugPath) { - Package debugPackage; - SubPackage debugSubpackage; - std::string prefix("debugSubPackage"); - - if (fs::is_directory(debugPath)) { - if (hasTestFiles(debugPath)) { - fillSubpackage(debugSubpackage, debugPath); - if (!debugSubpackage.empty()) { - debugPackage[prefix] = std::move(debugSubpackage); - } - fillSubpackages(debugPackage, debugPath, prefix); - } - } else if (fs::exists(debugPath) && isTestFile(debugPath)) { - addTestFileToSubPackage(debugSubpackage, debugPath); - debugPackage[prefix] = std::move(debugSubpackage); - } else { - throw std::runtime_error("Bad debug path supplied."); - } - - module["debugPkg"] = std::move(debugPackage); -} - -void fillModule(const Config &cfg, TestModule& module) { - const fs::path& debugPath = cfg.getDebugPath(); - if (!debugPath.empty()) { - setupDebugModule(module, debugPath); - return; - } - - const fs::path& testDirPath = cfg.getTestDirPath(); - for (const auto& dir : fs::directory_iterator(testDirPath)) { - if (!fs::is_directory(dir)) { - throw std::runtime_error("All top-level files in module must be directories."); - } - - const fs::path& packagePath = dir.path(); - const std::string& packageKeyPrefix = packagePath.filename().string(); - - Package package; - SubPackage moduleSubpackage; - fillSubpackage(moduleSubpackage, packagePath); - if (!moduleSubpackage.empty()) { - package[packageKeyPrefix] = std::move(moduleSubpackage); - } - - fillSubpackages(package, packagePath, packageKeyPrefix); - module[packageKeyPrefix] = std::move(package); - } -} - -} // namespace tester \ No newline at end of file diff --git a/src/tests/TestParser.cpp b/src/tests/TestParser.cpp index afccc10d..3de42ade 100644 --- a/src/tests/TestParser.cpp +++ b/src/tests/TestParser.cpp @@ -38,7 +38,7 @@ PathOrError TestParser::parsePathFromLine( } std::string parsedFilePath = line.substr(findIdx + directive.length()); - fs::path relPath = testfile.getTestPath().parent_path() / fs::path(parsedFilePath); + fs::path relPath = testfile->getTestPath().parent_path() / fs::path(parsedFilePath); fs::path absPath(parsedFilePath); if (fs::exists(absPath)) @@ -65,7 +65,7 @@ ParseError TestParser::matchInputDirective(std::string &line) { std::string inputLine = line.substr(findIdx + Directive::INPUT.length()); try { - insLineToFile(testfile.getInsPath(), inputLine, !foundInput); + insLineToFile(testfile->getInsPath(), inputLine, !foundInput); } catch (...) { return ParseError::FileError; } @@ -89,7 +89,7 @@ ParseError TestParser::matchCheckDirective(std::string &line) { std::string checkLine = line.substr(findIdx + Directive::CHECK.length()); try { - insLineToFile(testfile.getOutPath(), checkLine, !foundCheck); + insLineToFile(testfile->getOutPath(), checkLine, !foundCheck); } catch (...) { return ParseError::FileError; } @@ -111,7 +111,7 @@ ParseError TestParser::matchInputFileDirective(std::string &line) { PathOrError pathOrError = parsePathFromLine(line, Directive::INPUT_FILE); if (std::holds_alternative(pathOrError)) { - testfile.setInsPath(std::get(pathOrError)); + testfile->setInsPath(std::get(pathOrError)); foundInputFile = true; return ParseError::NoError; } @@ -131,7 +131,7 @@ ParseError TestParser::matchCheckFileDirective(std::string &line) { PathOrError pathOrError = parsePathFromLine(line, Directive::CHECK_FILE); if (std::holds_alternative(pathOrError)) { - testfile.setOutPath(std::get(pathOrError)); + testfile->setOutPath(std::get(pathOrError)); foundCheckFile = true; return ParseError::NoError; } @@ -155,7 +155,6 @@ ParseError TestParser::matchDirectives(std::string &line) { return ParseError::NoError; } - /** * @brief Alter the reference to line to be the substring of itself that is * contained with in a comment. Use comment state in class instance to track. @@ -204,11 +203,12 @@ void TestParser::trackCommentState(std::string &line) { * @brief open up the testfile and begin matching directives in each line, updating * the state of the testfile with resource paths and other useful data. */ -int TestParser::parseTest() { - std::ifstream testFileStream(testfile.getTestPath()); +void TestParser::parse() { + + std::ifstream testFileStream(testfile->getTestPath()); if (!testFileStream.is_open()) { std::cerr << "Failed to open the testfile" << std::endl; - return -1; + return; } std::string line; @@ -219,28 +219,27 @@ int TestParser::parseTest() { if (!line.empty()) { ParseError error = matchDirectives(line); if (error != ParseError::NoError) { - testfile.setErrorState(error); - testfile.setErrorMsg("Generic Error"); + testfile->setErrorState(error); + testfile->setErrorMsg("Generic Error"); break; } } } // Set final flags to update test state - testfile.usesInputStream = (foundInput || foundInputFile); - testfile.usesInputFile = (foundInputFile); - testfile.usesOutStream = (foundCheck || foundCheckFile); - testfile.usesOutFile = foundCheckFile; + testfile->usesInputStream = (foundInput || foundInputFile); + testfile->usesInputFile = (foundInputFile); + testfile->usesOutStream = (foundCheck || foundCheckFile); + testfile->usesOutFile = foundCheckFile; // ck if input directives have exceeded maximum - if (fs::file_size(testfile.getInsPath()) > Directive::MAX_INPUT_BYTES) { - testfile.setErrorState(ParseError::MaxInputBytesExceeded); - } else if (fs::file_size(testfile.getOutPath()) > Directive::MAX_OUTPUT_BYTES) { - testfile.setErrorState(ParseError::MaxOutputBytesExceeded); + if (fs::file_size(testfile->getInsPath()) > Directive::MAX_INPUT_BYTES) { + testfile->setErrorState(ParseError::MaxInputBytesExceeded); + } else if (fs::file_size(testfile->getOutPath()) > Directive::MAX_OUTPUT_BYTES) { + testfile->setErrorState(ParseError::MaxOutputBytesExceeded); } testFileStream.close(); - return 0; } } // namespace tester \ No newline at end of file