From: Lukasz Wojciechowski Date: Tue, 20 Jan 2015 14:17:12 +0000 (+0100) Subject: Add defer macros X-Git-Tag: security-manager_5.5_testing~129 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F50%2F34050%2F9;p=platform%2Fcore%2Ftest%2Fsecurity-tests.git Add defer macros Used to defer throwing TestException exceptions (TestFailed, TestIgnored) by catching them and rethrowing later. This mechanism can help in breaking test and passing test result from places where throwing exceptions is not allowed Change-Id: Ic9baa96596d15fccbbff4ac81b18f91b2eb89c8e --- diff --git a/README b/README index 92d11b3..c946fe7 100644 --- a/README +++ b/README @@ -156,6 +156,25 @@ dpl-test-framework RUNNER_ERROR_MSG Print error message using red color. +--Defer macros----------------------------------------------------------------- +Used to defer throwing TestException exceptions (TestFailed, TestIgnored) +by catching them and rethrowing later. This mechanism can help in breaking +test and passing test result from places where throwing exceptions +is not allowed + +dpl-test-framework + test_runner.h + RUNNER_DEFER_TRYCATCH + Catches thrown TestException exceptions and stores them in TestRunner + structures for later use. This macro works only inside deffered scope + defined by RUNNER_DEFER_SCOPE, otherwise it won't catch exceptions + RUNNER_DEFER_SCOPE + Defines deferred scope. All RUNNER_DEFER_TRYCATCH macros used inside + the scope catch and save TestException exceptions. After scope is left + all saved exceptions take part in setting result of test. If there + is no any uncaught exception then additionally first of saved + exceptions is thrown. + --Collectors------------------------------------------------------------------- Collectors are classes which collect test results. Each class does it differently. Collectors can be registered by --output parameter (see HOW TO RUN section) but diff --git a/src/framework/include/dpl/test/test_runner.h b/src/framework/include/dpl/test/test_runner.h index 5f070c8..53764bf 100644 --- a/src/framework/include/dpl/test/test_runner.h +++ b/src/framework/include/dpl/test/test_runner.h @@ -25,6 +25,7 @@ #define DPL_TEST_RUNNER_H #include +#include #include #include #include @@ -41,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -63,6 +65,8 @@ class TestRunner m_currentTestCase(nullptr) , m_terminate(false) , m_allowChildLogs(false) + , m_deferDeepness(0U) + , m_firstDeferredExceptionType(DeferredExceptionType::DEFERRED_FAILED) {} void beginPerformanceTestTime(std::chrono::system_clock::duration maxTimeInMicroseconds); @@ -166,6 +170,21 @@ class TestRunner // The runner will terminate as soon as possible (after current test). void Terminate(); bool GetAllowChildLogs(); + + void deferFailedException(const DPL::Test::TestFailed &ex); + void deferIgnoredException(const DPL::Test::TestIgnored &ex); + void deferBegin(); + void deferEnd(); + +private: + std::vector m_deferredExceptionsMessages; + std::size_t m_deferDeepness; + enum DeferredExceptionType { + DEFERRED_FAILED, + DEFERRED_IGNORED, + } m_firstDeferredExceptionType; + DPL::Test::TestFailed m_firstDeferredFail; + DPL::Test::TestIgnored m_firstDeferredIgnore; }; typedef DPL::Singleton TestRunnerSingleton; @@ -307,4 +326,39 @@ typedef DPL::Singleton TestRunnerSingleton; << DPL::Colors::Text::RED_END << std::endl; \ } while (0) +/** + * DEFER MACROS + * + * Use them to defer fails and ignores in test cases. + * Some code constructions disallow to throw. Such places can be surrounded + * with RUNNER_DEFER_SCOPE macro. RUNNER_DEFER_TRYCATCH macro can be used to catch possibly thrown + * exceptions within such scope. Possibly catched exceptions will be rethrown + * when leaving RUNNER_DEFER_SCOPE scope. + * Macros can be safely nested. + */ + + +#define RUNNER_DEFER_TRYCATCH(scope) \ + do { \ + try \ + { \ + scope \ + } \ + catch (const DPL::Test::TestFailed &ex) \ + { \ + DPL::Test::TestRunnerSingleton::Instance().deferFailedException(ex); \ + } \ + catch (const DPL::Test::TestIgnored &ex) \ + { \ + DPL::Test::TestRunnerSingleton::Instance().deferIgnoredException(ex); \ + } \ + } while (0) \ + +#define RUNNER_DEFER_SCOPE(scope) \ + do { \ + DPL::Test::TestRunnerSingleton::Instance().deferBegin(); \ + scope \ + DPL::Test::TestRunnerSingleton::Instance().deferEnd(); \ + } while (0) \ + #endif // DPL_TEST_RUNNER_H diff --git a/src/framework/src/test_runner.cpp b/src/framework/src/test_runner.cpp index dea2dda..0b4099c 100644 --- a/src/framework/src/test_runner.cpp +++ b/src/framework/src/test_runner.cpp @@ -209,6 +209,7 @@ bool TestRunner::filterByXML(std::map & casesMap) TestRunner::Status TestRunner::RunTestCase(const TestCaseStruct& testCase) { setCurrentTestCase(&(const_cast(testCase))); + m_deferDeepness = 0U; try { testCase.proc(); } catch (const TestFailed &e) { @@ -720,5 +721,60 @@ bool TestRunner::GetAllowChildLogs() return m_allowChildLogs; } +void TestRunner::deferFailedException(const DPL::Test::TestFailed &ex) +{ + if (m_deferDeepness <= 0) + throw ex; + + if (m_deferredExceptionsMessages.empty()) { + m_firstDeferredFail = ex; + m_firstDeferredExceptionType = DeferredExceptionType::DEFERRED_FAILED; + } + m_deferredExceptionsMessages.push_back(ex.GetMessage()); +} + +void TestRunner::deferIgnoredException(const DPL::Test::TestIgnored &ex) +{ + if (m_deferDeepness <= 0) + throw ex; + + if (m_deferredExceptionsMessages.empty()) { + m_firstDeferredIgnore = ex; + m_firstDeferredExceptionType = DeferredExceptionType::DEFERRED_IGNORED; + } + m_deferredExceptionsMessages.push_back(ex.GetMessage()); +} + +void TestRunner::deferBegin() +{ + m_deferDeepness++; } + +void TestRunner::deferEnd() +{ + if (m_deferDeepness > 0) + m_deferDeepness--; + + if (m_deferDeepness > 0) + return; + + bool oops = std::uncaught_exception(); + size_t additionalExceptions = oops ? 0 : 1; + for (size_t i = additionalExceptions; i < m_deferredExceptionsMessages.size(); ++i) + addFailReason(m_deferredExceptionsMessages[i]); + + if (!oops && !m_deferredExceptionsMessages.empty()) + { + m_deferredExceptionsMessages.clear(); + switch (m_firstDeferredExceptionType) { + case DeferredExceptionType::DEFERRED_FAILED: + throw m_firstDeferredFail; + case DeferredExceptionType::DEFERRED_IGNORED: + throw m_firstDeferredIgnore; + } + } + m_deferredExceptionsMessages.clear(); +} + +} // namespace Test } // namespace DPL