diff --git a/Tests/PcppTestFramework/PcppTestFrameworkRun.h b/Tests/PcppTestFramework/PcppTestFrameworkRun.h index e3f5f8244f..791db1f0f2 100644 --- a/Tests/PcppTestFramework/PcppTestFrameworkRun.h +++ b/Tests/PcppTestFramework/PcppTestFrameworkRun.h @@ -6,9 +6,13 @@ #include #include #include +#include #include "memplumber.h" #include "PcppTestFrameworkCommon.h" +static bool verboseMode = false; +static bool showSkippedTests = false; + static void __ptfSplitString(const std::string& input, std::vector& result) { std::istringstream ss(input); @@ -44,97 +48,125 @@ static bool __ptfCheckTags(const std::string& tagSet, const std::string& tagSetT return false; } +namespace ptf +{ + class TestRunner + { + public: + using TestFunc = std::function; + + TestRunner(std::string userIncludeTags, std::string userExcludeTags, std::string configTags) + : m_UserIncludeTags(std::move(userIncludeTags)), m_UserExcludeTags(std::move(userExcludeTags)), + m_ConfigTagsToRun(std::move(configTags)) + {} + + int runTest(TestFunc testFn, std::string const& testName, std::string const& additionalTestTags) + { + std::string allTestTags = testName + ";" + additionalTestTags; + int result = PTF_RESULT_PASSED; + + if (!__ptfCheckTags(allTestTags, m_UserIncludeTags, true) || + __ptfCheckTags(allTestTags, m_UserExcludeTags, false)) + { + if (showSkippedTests) + { + std::cout << std::left << std::setw(PTF_TESTNAME_WIDTH) << testName + << ": SKIPPED (tags don't match)" << std::endl; + } + result = PTF_RESULT_SKIPPED; + } + else + { + bool runMemLeakCheck = !__ptfCheckTags("skip_mem_leak_check", m_ConfigTagsToRun, false) && + !__ptfCheckTags(allTestTags, "skip_mem_leak_check", false); + if (runMemLeakCheck) + { + bool memAllocVerbose = __ptfCheckTags("mem_leak_check_verbose", m_ConfigTagsToRun, false); + MemPlumber::start(memAllocVerbose); + } + try + { + testFn(result, verboseMode, showSkippedTests); + } + catch (std::exception const& e) + { + result = PTF_RESULT_FAILED; + std::cout << std::left << std::setw(PTF_TESTNAME_WIDTH) << testName + << ": FAILED. Unhandled exception occurred! " + << "Exception: " << e.what() << std::endl; + } + if (runMemLeakCheck) + { + if (result != PTF_RESULT_PASSED) + { + MemPlumber::stopAndFreeAllMemory(); + } + else + { + size_t memLeakCount = 0; + uint64_t memLeakSize = 0; + MemPlumber::memLeakCheck(memLeakCount, memLeakSize, true); + MemPlumber::stopAndFreeAllMemory(); + if (memLeakCount > 0 || memLeakSize > 0) + { + result = PTF_RESULT_FAILED; + std::cout << std::left << std::setw(PTF_TESTNAME_WIDTH) << testName + << ": FAILED. Memory leak found! " << memLeakCount << " objects and " + << memLeakSize << "[bytes] leaked" << std::endl; + } + } + } + if (result == PTF_RESULT_PASSED) + { + std::cout << std::left << std::setw(PTF_TESTNAME_WIDTH) << testName << ": PASSED" << std::endl; + } + } + if (result == PTF_RESULT_PASSED) + testsPassed++; + if (result == PTF_RESULT_FAILED) + testsFailed++; + if (result == PTF_RESULT_SKIPPED) + testsSkipped++; + + return result; + } + + int finalizeResults() + { + std::string message = (!hasFailures() ? "ALL TESTS PASSED!!" : "NOT ALL TESTS PASSED!!"); + std::cout << std::endl + << message << std::endl + << "Test cases: " << testsPassed + testsFailed + testsSkipped << ", " + << "Passed: " << testsPassed << ", " + << "Failed: " << testsFailed << ", " + << "Skipped: " << testsSkipped << std::endl; + return hasFailures(); + } + + private: + bool hasFailures(bool ignoreSkipped = true) const + { + if (ignoreSkipped) + return testsFailed != 0; + return testsFailed + testsSkipped != 0; + } + + std::string m_UserIncludeTags; + std::string m_UserExcludeTags; + std::string m_ConfigTagsToRun; + int testsPassed = 0; + int testsFailed = 0; + int testsSkipped = 0; + }; +} // namespace ptf + #define PTF_START_RUNNING_TESTS(userIncludeTags, userExcludeTags, configTags) \ - bool allTestsPassed = true; \ - int testsPassed = 0; \ - int testsFailed = 0; \ - int testsSkipped = 0; \ - std::string ptfUserIncludeTags = userIncludeTags; \ - std::string ptfUserExcludeTags = userExcludeTags; \ - std::string configTagsToRun = configTags; \ + ptf::TestRunner testRunner(userIncludeTags, userExcludeTags, configTags); \ std::cout << "Start running tests..." << std::endl << std::endl -#define PTF_RUN_TEST(TestName, tags) \ - std::string TestName##_tags = std::string(#TestName) + ";" + tags; \ - int TestName##_result = PTF_RESULT_PASSED; \ - if (!__ptfCheckTags(TestName##_tags, ptfUserIncludeTags, true) || \ - __ptfCheckTags(TestName##_tags, ptfUserExcludeTags, false)) \ - { \ - if (showSkippedTests) \ - { \ - std::cout << std::left << std::setw(PTF_TESTNAME_WIDTH) << #TestName << ": SKIPPED (tags don't match)" \ - << std::endl; \ - } \ - TestName##_result = PTF_RESULT_SKIPPED; \ - } \ - else \ - { \ - bool runMemLeakCheck = !__ptfCheckTags("skip_mem_leak_check", configTagsToRun, false) && \ - !__ptfCheckTags(TestName##_tags, "skip_mem_leak_check", false); \ - if (runMemLeakCheck) \ - { \ - bool memAllocVerbose = __ptfCheckTags("mem_leak_check_verbose", configTagsToRun, false); \ - MemPlumber::start(memAllocVerbose); \ - } \ - try \ - { \ - TestName(TestName##_result, verboseMode, showSkippedTests); \ - } \ - catch (std::exception const& e) \ - { \ - TestName##_result = PTF_RESULT_FAILED; \ - std::cout << std::left << std::setw(PTF_TESTNAME_WIDTH) << #TestName \ - << ": FAILED. Unhandled exception occurred! " \ - << "Exception: " << e.what() << std::endl; \ - } \ - if (runMemLeakCheck) \ - { \ - if (TestName##_result != PTF_RESULT_PASSED) \ - { \ - MemPlumber::stopAndFreeAllMemory(); \ - } \ - else \ - { \ - size_t memLeakCount = 0; \ - uint64_t memLeakSize = 0; \ - MemPlumber::memLeakCheck(memLeakCount, memLeakSize, true); \ - MemPlumber::stopAndFreeAllMemory(); \ - if (memLeakCount > 0 || memLeakSize > 0) \ - { \ - TestName##_result = PTF_RESULT_FAILED; \ - std::cout << std::left << std::setw(PTF_TESTNAME_WIDTH) << #TestName \ - << ": FAILED. Memory leak found! " << memLeakCount << " objects and " << memLeakSize \ - << "[bytes] leaked" << std::endl; \ - } \ - } \ - } \ - if (TestName##_result == PTF_RESULT_PASSED) \ - { \ - std::cout << std::left << std::setw(PTF_TESTNAME_WIDTH) << #TestName << ": PASSED" << std::endl; \ - } \ - } \ - if (TestName##_result == PTF_RESULT_PASSED) \ - testsPassed++; \ - if (TestName##_result == PTF_RESULT_FAILED) \ - testsFailed++; \ - if (TestName##_result == PTF_RESULT_SKIPPED) \ - testsSkipped++; \ - allTestsPassed &= (TestName##_result != PTF_RESULT_FAILED) - -#define PTF_END_RUNNING_TESTS \ - std::string message = (allTestsPassed ? "ALL TESTS PASSED!!" : "NOT ALL TESTS PASSED!!"); \ - std::cout << std::endl \ - << message << std::endl \ - << "Test cases: " << testsPassed + testsFailed + testsSkipped << ", " \ - << "Passed: " << testsPassed << ", " \ - << "Failed: " << testsFailed << ", " \ - << "Skipped: " << testsSkipped << std::endl; \ - return (allTestsPassed ? 0 : 1); +#define PTF_RUN_TEST(TestName, tags) testRunner.runTest(TestName, #TestName, tags) -static bool verboseMode = false; +#define PTF_END_RUNNING_TESTS return testRunner.finalizeResults(); #define PTF_SET_VERBOSE_MODE(flag) verboseMode = flag - -static bool showSkippedTests = false; - #define PTF_SHOW_SKIPPED_TESTS(flag) showSkippedTests = flag