From 50e9c5aa5649187145571823b78a28ad28970844 Mon Sep 17 00:00:00 2001 From: Janusz Kozerski Date: Thu, 12 Dec 2013 11:37:41 +0100 Subject: [PATCH] Add RUNNER_PERF_TEST_BEGIN() and RUNNER_PERF_TEST_END() macros for performance tests Added RUNNER_PERF_TEST_BEGIN(max_time) and RUNNER_PERF_TEST_END() macros. Add both of these macros in test when you want to do the time measurement. The first macro is used to start the time measurement, the second is used to end the measuement. The result will be displayed if and only if the test will pass. RUNNER_PERF_TEST_BEGIN(time), takes one parameter (type of double) - the expected time. If the measured time will be shorter than expected then result will be print in console in green color, otherwise the result will be print in red. If other output method will be choosen then measured time and max time (if defined) will be displayed. In TAP output format there is no preformance results. If you don't want to give any param as the expected time then put 0 or any negative value (any value <= 0) as a param (RUNNER_PERF_TEST_BEGIN(0)) and the param will be ignored. In that case the result in console will be always printed in white. The precision of measurement is 1 microsecond - the smallest time value that can be measured is 0.000001s. Remarks: * The result of time measurement will be displayed only if the test will pass. * Make sure that you use each of these macros at most ONCE in each test. In the other case the result of first measurement will be overrwriten by the second. * Make sure that you use macros in right order. * In case of RUNNER_MULTIPROCESS_TEST the time measurement will wokrs only if the macors will be used in parent process. If you will use these macros in the child code then you will see no result. * The performance results will be displayed only in these output format: - text - html - xml - csv [Problem] No framework for performance tests [Cause] N/A [Solution] Added RUNNER_PERF_TEST_BEGIN(expected_time) and RUNNER_PERF_TEST_END() macros. [Verification] Add these macros to a few passing tests and a few failing tests, and check if results are displayed correctly. Change-Id: I9eebaade094fbdf1d2af34e7da2871b7307f89c6 Signed-off-by: Janusz Kozerski --- .../test/include/dpl/test/test_results_collector.h | 6 +- modules/test/include/dpl/test/test_runner.h | 59 +++++++++- modules/test/include/dpl/test/test_runner_child.h | 11 +- modules/test/src/test_results_collector.cpp | 121 +++++++++++++++++++-- modules/test/src/test_runner.cpp | 87 ++++++++++++++- modules/test/src/test_runner_child.cpp | 94 ++++++++++++++-- 6 files changed, 354 insertions(+), 24 deletions(-) diff --git a/modules/test/include/dpl/test/test_results_collector.h b/modules/test/include/dpl/test/test_results_collector.h index 73fe1bf..cb29921 100644 --- a/modules/test/include/dpl/test/test_results_collector.h +++ b/modules/test/include/dpl/test/test_results_collector.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -68,7 +69,10 @@ class TestResultsCollectorBase : virtual void CollectResult(const std::string& id, const std::string& description, const FailStatus::Type status = FailStatus::NONE, - const std::string& reason = "") = 0; + const std::string& reason = "", + const bool& isPerformanceTest = false, + const std::chrono::system_clock::duration& performanceTime = std::chrono::microseconds::zero(), + const std::chrono::system_clock::duration& performanceMaxTime = std::chrono::microseconds::zero()) = 0; virtual std::string CollectorSpecificHelp() const { return ""; diff --git a/modules/test/include/dpl/test/test_runner.h b/modules/test/include/dpl/test/test_runner.h index 6cd948f..53327a4 100644 --- a/modules/test/include/dpl/test/test_runner.h +++ b/modules/test/include/dpl/test/test_runner.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -47,10 +48,20 @@ class TestRunner public: TestRunner() : - m_terminate(false) + m_currentTestCase(NULL) + , m_terminate(false) , m_allowChildLogs(false) {} + void beginPerformanceTestTime(std::chrono::system_clock::duration maxTimeInMicroseconds); + void endPerformanceTestTime(); + void getCurrentTestCasePerformanceResult(bool& isPerformanceTest, + std::chrono::system_clock::duration& result, + std::chrono::system_clock::duration& resultMax); + void setCurrentTestCasePerformanceResult(bool isPerformanceTest, + std::chrono::system_clock::duration result, + std::chrono::system_clock::duration resultMax); + typedef void (*TestCase)(); private: @@ -59,6 +70,11 @@ class TestRunner std::string name; TestCase proc; + bool m_isPerformanceTest; + std::chrono::system_clock::time_point m_performanceTestStartTime; + std::chrono::system_clock::duration m_performanceTestDurationTime; + std::chrono::system_clock::duration m_performanceMaxTime; + bool operator <(const TestCaseStruct &other) const { return name < other.name; @@ -71,7 +87,8 @@ class TestRunner TestCaseStruct(const std::string &n, TestCase p) : name(n), - proc(p) + proc(p), + m_isPerformanceTest(false) {} }; @@ -79,6 +96,8 @@ class TestRunner typedef std::map TestCaseGroupMap; TestCaseGroupMap m_testGroups; + TestCaseStruct * m_currentTestCase; + typedef std::set SelectedTestNameSet; SelectedTestNameSet m_selectedTestNamesSet; typedef std::set SelectedTestGroupSet; @@ -105,13 +124,19 @@ class TestRunner Status RunTestCase(const TestCaseStruct& testCase); + void setCurrentTestCase(TestCaseStruct* testCase); + TestCaseStruct *getCurrentTestCase(); + void RunTests(); void CollectResult(const std::string& id, const std::string& description, const TestResultsCollectorBase::FailStatus::Type status = TestResultsCollectorBase::FailStatus::NONE, - const std::string& reason = std::string()); + const std::string& reason = std::string(), + const bool& isPerformanceTest = false, + const std::chrono::system_clock::duration& performanceTime = std::chrono::microseconds::zero(), + const std::chrono::system_clock::duration& performanceMaxTime = std::chrono::microseconds::zero()); public: class TestFailed @@ -226,4 +251,32 @@ typedef DPL::Singleton TestRunnerSingleton; assertMsg.str()); \ } while (0) +/* + * Use these macros to do the time measurement. The first macro will start time measurement, + * the second will gather the result. These macros can be used only once per test-case. + * The result of time measurement will be displayed only if the test will pass. + * Notice that these macros will work only if will be used in parent process. If these + * macros will be used in child process then there will be no time measure results printed. + * This macro in multiprocess tests has effect only if used in parent process. This macro + * used in child process in multiprocess test has no effect. + * The precision of measurement is 1 microsecond - the smallest time value that can be + * measured is 0.000001s. + * The time measure results will be printed only specific output format: + * - text + * - html + * - xml + * - csv + * In TAP format performance result will not be displayed. + */ +#define RUNNER_PERF_TEST_BEGIN(maxTime) \ + do { \ + DPL::Test::TestRunnerSingleton::Instance().beginPerformanceTestTime( \ + std::chrono::microseconds{static_cast(maxTime*1000000.0)}); \ + } while (0) + +#define RUNNER_PERF_TEST_END() \ + do { \ + DPL::Test::TestRunnerSingleton::Instance().endPerformanceTestTime(); \ + } while (0) + #endif // DPL_TEST_RUNNER_H diff --git a/modules/test/include/dpl/test/test_runner_child.h b/modules/test/include/dpl/test/test_runner_child.h index 1da0f1b..d1e4b1c 100644 --- a/modules/test/include/dpl/test/test_runner_child.h +++ b/modules/test/include/dpl/test/test_runner_child.h @@ -50,14 +50,23 @@ class PipeWrapper : DPL::Noncopyable virtual ~PipeWrapper(); Status send(int code, std::string &message); + Status sendTime(int code, + std::chrono::system_clock::duration time, + std::chrono::system_clock::duration timeMax); - Status receive(int &code, std::string &data, time_t deadline); + Status receive(int &code, + int &msgType, + std::string &data, + std::chrono::system_clock::duration &time, + std::chrono::system_clock::duration &timeMax, + time_t deadline); void closeAll(); protected: std::string toBinaryString(int data); + std::string toBinaryString(std::chrono::system_clock::duration data); void closeHelp(int desc); diff --git a/modules/test/src/test_results_collector.cpp b/modules/test/src/test_results_collector.cpp index 025dd84..beefc17 100644 --- a/modules/test/src/test_results_collector.cpp +++ b/modules/test/src/test_results_collector.cpp @@ -21,6 +21,7 @@ */ #include #include +#include #include #include #include @@ -37,6 +38,23 @@ #define GREEN_RESULT_OK "[%s%s%s]\n", BOLD_GREEN_BEGIN, " OK ", \ BOLD_GREEN_END +#define GREEN_RESULT_OK_TIME "[%s%s%s] [elapsed: %0.3fms]\n", BOLD_GREEN_BEGIN, \ + " OK ", BOLD_GREEN_END +#define GREEN_RESULT_OK_TIME_MAX(elapsed, max) \ + "[%s%s%s] %s[elapsed: %0.3fms, expected < %0.3fms]%s\n", BOLD_GREEN_BEGIN, \ + " OK ", BOLD_GREEN_END, BOLD_GREEN_BEGIN, elapsed, max, BOLD_GREEN_END +#define GREEN_RESULT_OK_TIME_TOO_LONG(elapsed, max) \ + "[%s%s%s] %s[elapsed: %0.3fms, expected < %0.3fms]%s\n", BOLD_GREEN_BEGIN, \ + " OK ", BOLD_GREEN_END, BOLD_RED_BEGIN, elapsed, max, BOLD_RED_END + +namespace { /* anonymous namespace */ +// Get duration as a fraction of millisecond (max precision is 1 microsecond) +double get_milliseconds (const std::chrono::system_clock::duration& performanceTime) +{ + return (static_cast(std::chrono::duration_cast + (performanceTime).count()))/1000.0; +} +} /* anonymous namespace */ namespace DPL { namespace Test { @@ -146,7 +164,10 @@ class ConsoleCollector : virtual void CollectResult(const std::string& id, const std::string& /*description*/, const FailStatus::Type status = FailStatus::NONE, - const std::string& reason = "") + const std::string& reason = "", + const bool& isPerformanceTest = true, + const std::chrono::system_clock::duration& performanceTime = std::chrono::microseconds::zero(), + const std::chrono::system_clock::duration& performanceMaxTime = std::chrono::microseconds::zero()) { using namespace DPL::Colors::Text; std::string tmp = "'" + id + "' ..."; @@ -154,6 +175,24 @@ class ConsoleCollector : printf("Running test case %-60s", tmp.c_str()); switch (status) { case TestResultsCollectorBase::FailStatus::NONE: + if (isPerformanceTest) { + if (performanceMaxTime <= std::chrono::microseconds::zero()) { + printf(GREEN_RESULT_OK_TIME, + get_milliseconds(performanceTime)); + break; + } + else { + if (performanceTime > performanceMaxTime) + printf(GREEN_RESULT_OK_TIME_TOO_LONG( + get_milliseconds(performanceTime), + get_milliseconds(performanceMaxTime))); + else + printf(GREEN_RESULT_OK_TIME_MAX( + get_milliseconds(performanceTime), + get_milliseconds(performanceMaxTime))); + break; + } + } printf(GREEN_RESULT_OK); break; case TestResultsCollectorBase::FailStatus::FAILED: @@ -319,7 +358,10 @@ class HtmlCollector : virtual void CollectResult(const std::string& id, const std::string& /*description*/, const FailStatus::Type status = FailStatus::NONE, - const std::string& reason = "") + const std::string& reason = "", + const bool& isPerformanceTest = false, + const std::chrono::system_clock::duration& performanceTime = std::chrono::microseconds::zero(), + const std::chrono::system_clock::duration& performanceMaxTime = std::chrono::microseconds::zero()) { using namespace DPL::Colors::Html; std::string tmp = "'" + id + "' ..."; @@ -327,6 +369,23 @@ class HtmlCollector : fprintf(m_fp.Get(), "Running test case %-100s", tmp.c_str()); switch (status) { case TestResultsCollectorBase::FailStatus::NONE: + if (isPerformanceTest) { + if (performanceMaxTime <= std::chrono::microseconds::zero()) { + fprintf(m_fp.Get(), GREEN_RESULT_OK_TIME, + get_milliseconds(performanceTime)); + break; + } else { + if (performanceTime > performanceMaxTime) + fprintf(m_fp.Get(), GREEN_RESULT_OK_TIME_TOO_LONG( + get_milliseconds(performanceTime), + get_milliseconds(performanceMaxTime))); + else + fprintf(m_fp.Get(), GREEN_RESULT_OK_TIME_MAX( + get_milliseconds(performanceTime), + get_milliseconds(performanceMaxTime))); + break; + } + } fprintf(m_fp.Get(), GREEN_RESULT_OK); break; case TestResultsCollectorBase::FailStatus::FAILED: @@ -510,7 +569,10 @@ class XmlCollector : virtual void CollectResult(const std::string& id, const std::string& /*description*/, const FailStatus::Type status = FailStatus::NONE, - const std::string& reason = "") + const std::string& reason = "", + const bool& isPerformanceTest = false, + const std::chrono::system_clock::duration& performanceTime = std::chrono::microseconds::zero(), + const std::chrono::system_clock::duration& performanceMaxTime = std::chrono::microseconds::zero()) { m_resultBuffer.erase(); m_resultBuffer.append("\t\t\n"); + break; + } else { + m_resultBuffer.append(" status=\"OK\" time=\""); + std::ostringstream ostr; + ostr << performanceTime.count(); + m_resultBuffer.append(ostr.str()); + m_resultBuffer.append("\" time_expected=\""); + ostr.str(""); + ostr << performanceMaxTime.count(); + m_resultBuffer.append(ostr.str()); + m_resultBuffer.append("\"/>\n"); + break; + } + } m_resultBuffer.append(" status=\"OK\"/>\n"); break; case TestResultsCollectorBase::FailStatus::FAILED: @@ -763,7 +846,7 @@ class CSVCollector : virtual void Start() { - printf("GROUP;ID;RESULT;REASON\n"); + printf("GROUP;ID;RESULT;REASON;ELAPSED [s];EXPECTED [s]\n"); } virtual void CollectCurrentTestGroupName(const std::string& name) @@ -774,11 +857,27 @@ class CSVCollector : virtual void CollectResult(const std::string& id, const std::string& /*description*/, const FailStatus::Type status = FailStatus::NONE, - const std::string& reason = "") + const std::string& reason = "", + const bool& isPerformanceTest = false, + const std::chrono::system_clock::duration& performanceTime = std::chrono::microseconds::zero(), + const std::chrono::system_clock::duration& performanceMaxTime = std::chrono::microseconds::zero()) { std::string statusMsg = ""; switch (status) { - case TestResultsCollectorBase::FailStatus::NONE: statusMsg = "OK"; + case TestResultsCollectorBase::FailStatus::NONE: + statusMsg = "OK"; + if (isPerformanceTest) { + statusMsg.append(";;"); + std::ostringstream ostr; + ostr << performanceTime.count(); + statusMsg.append(ostr.str()); + if (performanceMaxTime <= std::chrono::microseconds::zero()) { + statusMsg.append(";"); + ostr.str(""); + ostr << performanceMaxTime.count(); + statusMsg.append(ostr.str()); + } + } break; case TestResultsCollectorBase::FailStatus::FAILED: statusMsg = "FAILED"; break; @@ -856,8 +955,16 @@ class TAPCollector : virtual void CollectResult(const std::string& id, const std::string& description, const FailStatus::Type status = FailStatus::NONE, - const std::string& reason = "") + const std::string& reason = "", + const bool& isPerformanceTest = false, + const std::chrono::system_clock::duration& performanceTime = std::chrono::microseconds::zero(), + const std::chrono::system_clock::duration& performanceMaxTime = std::chrono::microseconds::zero()) { + /* Remove unused variable warning */ + DPL_UNUSED_PARAM(isPerformanceTest); + DPL_UNUSED_PARAM(performanceTime); + DPL_UNUSED_PARAM(performanceMaxTime); + m_testIndex++; switch (status) { case TestResultsCollectorBase::FailStatus::NONE: diff --git a/modules/test/src/test_runner.cpp b/modules/test/src/test_runner.cpp index 594ba0c..f9a6f4c 100644 --- a/modules/test/src/test_runner.cpp +++ b/modules/test/src/test_runner.cpp @@ -247,6 +247,7 @@ bool TestRunner::filterByXML(std::map & casesMap) TestRunner::Status TestRunner::RunTestCase(const TestCaseStruct& testCase) { + setCurrentTestCase(&(const_cast(testCase))); try { testCase.proc(); } catch (const TestFailed &e) { @@ -255,6 +256,8 @@ TestRunner::Status TestRunner::RunTestCase(const TestCaseStruct& testCase) "", TestResultsCollectorBase::FailStatus::FAILED, e.GetMessage()); + + setCurrentTestCase(NULL); return FAILED; } catch (const Ignored &e) { if (m_runIgnored) { @@ -265,6 +268,7 @@ TestRunner::Status TestRunner::RunTestCase(const TestCaseStruct& testCase) e.GetMessage()); } + setCurrentTestCase(NULL); return IGNORED; } catch (const DPL::Exception &e) { // DPL exception failure @@ -273,6 +277,7 @@ TestRunner::Status TestRunner::RunTestCase(const TestCaseStruct& testCase) TestResultsCollectorBase::FailStatus::INTERNAL, "DPL exception:" + e.GetMessage()); + setCurrentTestCase(NULL); return FAILED; } catch (const std::exception &) { // std exception failure @@ -281,6 +286,7 @@ TestRunner::Status TestRunner::RunTestCase(const TestCaseStruct& testCase) TestResultsCollectorBase::FailStatus::INTERNAL, "std exception"); + setCurrentTestCase(NULL); return FAILED; } catch (...) { // Unknown exception failure @@ -289,12 +295,18 @@ TestRunner::Status TestRunner::RunTestCase(const TestCaseStruct& testCase) TestResultsCollectorBase::FailStatus::INTERNAL, "unknown exception"); + setCurrentTestCase(NULL); return FAILED; } CollectResult(testCase.name, "", - TestResultsCollectorBase::FailStatus::NONE); + TestResultsCollectorBase::FailStatus::NONE, + "", + testCase.m_isPerformanceTest, + testCase.m_performanceTestDurationTime, + testCase.m_performanceMaxTime); + setCurrentTestCase(NULL); // Everything OK return PASS; @@ -362,11 +374,77 @@ void TestRunner::RunTests() fprintf(stderr, "%s%s%s\n\n", GREEN_BEGIN, "Finished", GREEN_END); } +TestRunner::TestCaseStruct *TestRunner::getCurrentTestCase() +{ + return m_currentTestCase; +} + +void TestRunner::setCurrentTestCase(TestCaseStruct* testCase) +{ + m_currentTestCase = testCase; +} + +void TestRunner::beginPerformanceTestTime(std::chrono::system_clock::duration maxTimeInMicroseconds) +{ + TestCaseStruct* testCase = getCurrentTestCase(); + if (!testCase) + return; + + testCase->m_isPerformanceTest = true; + testCase->m_performanceMaxTime = maxTimeInMicroseconds; + testCase->m_performanceTestStartTime = std::chrono::system_clock::now(); + + // Set result to 0 microseconds. Display 0ms result when end macro is missing. + testCase->m_performanceTestDurationTime = std::chrono::microseconds::zero(); +} + +void TestRunner::endPerformanceTestTime() +{ + TestCaseStruct* testCase = getCurrentTestCase(); + if (!testCase) + return; + + testCase->m_performanceTestDurationTime = std::chrono::system_clock::now() - + testCase->m_performanceTestStartTime; +} + +void TestRunner::getCurrentTestCasePerformanceResult(bool& isPerformanceTest, + std::chrono::system_clock::duration& result, + std::chrono::system_clock::duration& resultMax) +{ + TestCaseStruct* testCase = getCurrentTestCase(); + if (!testCase || !(testCase->m_isPerformanceTest)){ + isPerformanceTest = false; + return; + } + + isPerformanceTest = testCase->m_isPerformanceTest; + result = testCase->m_performanceTestDurationTime; + resultMax = testCase->m_performanceMaxTime; +} + +void TestRunner::setCurrentTestCasePerformanceResult(bool isPerformanceTest, + std::chrono::system_clock::duration result, + std::chrono::system_clock::duration resultMax) +{ + TestCaseStruct* testCase = getCurrentTestCase(); + if (!testCase) + return; + + testCase->m_isPerformanceTest = isPerformanceTest; + testCase->m_performanceTestDurationTime = result; + testCase->m_performanceMaxTime = resultMax; +} + + void TestRunner::CollectResult( const std::string& id, const std::string& description, const TestResultsCollectorBase::FailStatus::Type status, - const std::string& reason) + const std::string& reason, + const bool& isPerformanceTest, + const std::chrono::system_clock::duration& performanceTestDurationTime, + const std::chrono::system_clock::duration& performanceMaxTime) { std::for_each(m_collectors.begin(), m_collectors.end(), @@ -375,7 +453,10 @@ void TestRunner::CollectResult( collector.second->CollectResult(id, description, status, - reason); + reason, + isPerformanceTest, + performanceTestDurationTime, + performanceMaxTime); }); } diff --git a/modules/test/src/test_runner_child.cpp b/modules/test/src/test_runner_child.cpp index 8e793e8..a8840fc 100644 --- a/modules/test/src/test_runner_child.cpp +++ b/modules/test/src/test_runner_child.cpp @@ -49,6 +49,9 @@ const int CHILD_TEST_FAIL = 0; const int CHILD_TEST_PASS = 1; const int CHILD_TEST_IGNORED = 2; +const int MSG_TYPE_MESSAGE = 0; // sizeof(Message) + Message +const int MSG_TYPE_PERF_TIME = 1; // perfTime + maxTime + int closeOutput() { int devnull; int retcode = -1; @@ -112,6 +115,7 @@ PipeWrapper::Status PipeWrapper::send(int code, std::string &message) std::ostringstream output; output << toBinaryString(code); + output << toBinaryString(MSG_TYPE_MESSAGE); output << toBinaryString(static_cast(message.size())); output << message; @@ -127,7 +131,38 @@ PipeWrapper::Status PipeWrapper::send(int code, std::string &message) return SUCCESS; } -PipeWrapper::Status PipeWrapper::receive(int &code, std::string &data, time_t deadline) +PipeWrapper::Status PipeWrapper::sendTime(int code, + std::chrono::system_clock::duration time, + std::chrono::system_clock::duration timeMax) +{ + if (m_pipefd[1] == PIPE_CLOSED) { + return ERROR; + } + + std::ostringstream output; + output << toBinaryString(code); + output << toBinaryString(MSG_TYPE_PERF_TIME); + output << toBinaryString(time); + output << toBinaryString(timeMax); + + std::string binary = output.str(); + int size = binary.size(); + + if ((writeHelp(&size, + sizeof(int)) == ERROR) || + (writeHelp(binary.c_str(), size) == ERROR)) + { + return ERROR; + } + return SUCCESS; +} + +PipeWrapper::Status PipeWrapper::receive(int &code, + int &msgType, + std::string &data, + std::chrono::system_clock::duration &time, + std::chrono::system_clock::duration &timeMax, + time_t deadline) { if (m_pipefd[0] == PIPE_CLOSED) { return ERROR; @@ -152,12 +187,24 @@ PipeWrapper::Status PipeWrapper::receive(int &code, std::string &data, time_t de queue.AppendCopy(&buffer[0], size); queue.FlattenConsume(&code, sizeof(int)); - queue.FlattenConsume(&size, sizeof(int)); - - buffer.resize(size); - - queue.FlattenConsume(&buffer[0], size); - data.assign(buffer.begin(), buffer.end()); + queue.FlattenConsume(&msgType, sizeof(int)); + + switch (msgType) { + case MSG_TYPE_MESSAGE: + queue.FlattenConsume(&size, sizeof(int)); + + buffer.resize(size); + + queue.FlattenConsume(&buffer[0], size); + data.assign(buffer.begin(), buffer.end()); + break; + case MSG_TYPE_PERF_TIME: + queue.FlattenConsume(&time, sizeof(std::chrono::system_clock::duration)); + queue.FlattenConsume(&timeMax, sizeof(std::chrono::system_clock::duration)); + break; + default: + return ERROR; + } } catch (DPL::BinaryQueue::Exception::Base &e) { return ERROR; } @@ -177,6 +224,13 @@ std::string PipeWrapper::toBinaryString(int data) return std::string(buffer, buffer + sizeof(int)); } +std::string PipeWrapper::toBinaryString(std::chrono::system_clock::duration data) +{ + char buffer[sizeof(std::chrono::system_clock::duration)]; + memcpy(buffer, &data, sizeof(std::chrono::system_clock::duration)); + return std::string(buffer, buffer + sizeof(std::chrono::system_clock::duration)); +} + void PipeWrapper::closeHelp(int desc) { if (m_pipefd[desc] != PIPE_CLOSED) { @@ -259,9 +313,12 @@ void RunChildProc(TestRunner::TestCase procChild) pipe.setUsage(PipeWrapper::READONLY); int code; + int msgType; + std::chrono::system_clock::duration time_m; + std::chrono::system_clock::duration timeMax_m; std::string message; - int pipeReturn = pipe.receive(code, message, time(0) + 10); + int pipeReturn = pipe.receive(code, msgType, message, time_m, timeMax_m, time(0) + 10); if (pipeReturn != PipeWrapper::SUCCESS) { // Timeout or reading error pipe.closeAll(); @@ -279,6 +336,12 @@ void RunChildProc(TestRunner::TestCase procChild) throw TestRunner::TestFailed("Reading pipe error"); } + if (code == CHILD_TEST_PASS && msgType == MSG_TYPE_PERF_TIME) { + DPL::Test::TestRunnerSingleton::Instance().setCurrentTestCasePerformanceResult(true, + time_m, + timeMax_m); + } + if (code == CHILD_TEST_FAIL) { throw TestRunner::TestFailed(message); } else if (code == CHILD_TEST_IGNORED) { @@ -292,6 +355,9 @@ void RunChildProc(TestRunner::TestCase procChild) int code = CHILD_TEST_PASS; std::string msg; + bool isPerformanceTest; + std::chrono::system_clock::duration time_m; + std::chrono::system_clock::duration timeMax_m; bool allowLogs = TestRunnerSingleton::Instance().GetAllowChildLogs(); @@ -319,7 +385,17 @@ void RunChildProc(TestRunner::TestCase procChild) closeOutput(); } - pipe.send(code, msg); + DPL::Test::TestRunnerSingleton::Instance().getCurrentTestCasePerformanceResult(isPerformanceTest, + time_m, + timeMax_m); + + if (code == CHILD_TEST_PASS && isPerformanceTest){ + pipe.sendTime(code, + time_m, + timeMax_m); + } else { + pipe.send(code, msg); + } } } } // namespace Test -- 2.7.4