#define DPL_TEST_RUNNER_H
#include <chrono>
+#include <cstdlib>
#include <cstring>
#include <exception>
#include <iostream>
#include <dpl/gdbbacktrace.h>
#include <dpl/singleton.h>
#include <dpl/test/performance_result.h>
+#include <dpl/test/test_exception.h>
+#include <dpl/test/test_failed.h>
+#include <dpl/test/test_ignored.h>
#include <dpl/test/test_result.h>
#include <dpl/test/test_results_collector.h>
m_currentTestCase(nullptr)
, m_terminate(false)
, m_allowChildLogs(false)
+ , m_deferDeepness(0U)
+ , m_firstDeferredExceptionType(DeferredExceptionType::DEFERRED_FAILED)
{}
void beginPerformance(std::chrono::system_clock::duration maxDurationInMicroseconds);
void CollectResult(const std::string& id, const TestResult &result);
public:
- class TestFailed
- {
- private:
- std::string m_message;
-
- public:
- TestFailed()
- {}
-
- //! \brief Failed test message creator
- //!
- //! \param[in] aTest string for tested expression
- //! \param[in] aFile source file name
- //! \param[in] aLine source file line
- //! \param[in] aMessage error message
- TestFailed(const char* aTest,
- const char* aFile,
- int aLine,
- const std::string &aMessage);
-
- TestFailed(const std::string &message);
-
- std::string GetMessage() const
- {
- return m_message;
- }
- };
-
- class Ignored
- {
- private:
- std::string m_message;
-
- public:
- Ignored()
- {}
-
- Ignored(const std::string &message) :
- m_message(message)
- {}
-
- std::string GetMessage() const
- {
- return m_message;
- }
- };
-
void MarkAssertion();
void RegisterTest(const char *testName, TestCase proc);
// 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<std::string> 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<TestRunner> TestRunnerSingleton;
{ \
std::ostringstream assertMsg; \
assertMsg << message << DPL::gdbbacktrace(); \
- DPL::Test::TestRunner::TestFailed e(#test, \
- __FILE__, \
- __LINE__, \
- assertMsg.str()); \
+ DPL::Test::TestFailed e(#test, \
+ __FILE__, \
+ __LINE__, \
+ assertMsg.str()); \
if (!std::uncaught_exception()) \
throw e; \
DPL::Test::TestRunnerSingleton::Instance().addFailReason(e.GetMessage()); \
if (!assertMsg.str().empty()) \
assertMsg << ". "; \
assertMsg << err << DPL::gdbbacktrace(); \
- DPL::Test::TestRunner::TestFailed e(#test, \
- __FILE__, \
- __LINE__, \
- assertMsg.str()); \
+ DPL::Test::TestFailed e(#test, \
+ __FILE__, \
+ __LINE__, \
+ assertMsg.str()); \
if (!std::uncaught_exception()) \
throw e; \
DPL::Test::TestRunnerSingleton::Instance().addFailReason(e.GetMessage()); \
* body.
*/
-#define RUNNER_IGNORED_MSG(message) \
- do \
- { \
- std::ostringstream assertMsg; \
- assertMsg << message; \
- throw DPL::Test::TestRunner::Ignored(assertMsg.str()); \
+#define RUNNER_IGNORED_MSG(message) \
+ do \
+ { \
+ std::ostringstream assertMsg; \
+ assertMsg << message; \
+ throw DPL::Test::TestIgnored(assertMsg.str()); \
} while (0)
/**
<< 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