diff --git "a/frameworks\\utest/source/default_handlers.cpp" "b/frameworks\\utest/source/default_handlers.cpp" index d9c9847f1a..4a41610614 100644 --- "a/frameworks\\utest/source/default_handlers.cpp" +++ "b/frameworks\\utest/source/default_handlers.cpp" @@ -24,6 +24,7 @@ using namespace utest::v1; const handlers_t utest::v1::verbose_continue_handlers = { verbose_test_setup_handler, verbose_test_teardown_handler, + ignore_handler, verbose_case_setup_handler, verbose_case_teardown_handler, verbose_case_failure_handler @@ -31,6 +32,7 @@ const handlers_t utest::v1::verbose_continue_handlers = { const handlers_t utest::v1::greentea_abort_handlers = { greentea_test_setup_handler, greentea_test_teardown_handler, + ignore_handler, verbose_case_setup_handler, verbose_case_teardown_handler, greentea_case_failure_handler @@ -38,6 +40,23 @@ const handlers_t utest::v1::greentea_abort_handlers = { const handlers_t utest::v1::greentea_continue_handlers = { greentea_test_setup_handler, greentea_test_teardown_handler, + ignore_handler, + verbose_case_setup_handler, + verbose_case_teardown_handler, + verbose_case_failure_handler +}; + +static void selftest_failure_handler(const failure_t reason) { + if (reason == FAILURE_ASSERTION) { + printf(">>> failure with reason '%s (in selftest)'\n{{failure}}\n{{end}}\n", stringify(reason)); + while(1) ; + } +} + +const handlers_t utest::v1::selftest_handlers = { + greentea_test_setup_handler, + greentea_test_teardown_handler, + selftest_failure_handler, verbose_case_setup_handler, verbose_case_teardown_handler, verbose_case_failure_handler diff --git "a/frameworks\\utest/source/harness.cpp" "b/frameworks\\utest/source/harness.cpp" index f3faab68bc..b574853cd9 100644 --- "a/frameworks\\utest/source/harness.cpp" +++ "b/frameworks\\utest/source/harness.cpp" @@ -22,7 +22,6 @@ using namespace utest::v1; - namespace { const Case *test_cases = NULL; @@ -67,11 +66,12 @@ bool Harness::run(const Specification& specification, std::size_t start_case) if (is_busy()) return false; - test_cases = specification.cases; + test_cases = specification.cases; test_length = specification.length; - defaults = specification.defaults; - handlers.test_setup = defaults.get_handler(specification.setup_handler); + defaults = specification.defaults; + handlers.test_setup = defaults.get_handler(specification.setup_handler); handlers.test_teardown = defaults.get_handler(specification.teardown_handler); + handlers.test_failure = defaults.get_handler(specification.failure_handler); test_index_of_case = 0; test_passed = 0; @@ -83,6 +83,7 @@ bool Harness::run(const Specification& specification, std::size_t start_case) case_current = &test_cases[start_case]; if (handlers.test_setup && (handlers.test_setup(test_length) != STATUS_CONTINUE)) { + if (handlers.test_failure) handlers.test_failure(FAILURE_SETUP); if (handlers.test_teardown) handlers.test_teardown(0, 0, FAILURE_SETUP); test_cases = NULL; return true; @@ -98,6 +99,7 @@ void Harness::raise_failure(failure_t reason) { mbed::util::CriticalSectionLock lock; + if (handlers.test_failure) handlers.test_failure(reason); if (handlers.case_failure) fail_status = handlers.case_failure(case_current, reason); if (!(fail_status & STATUS_IGNORE)) case_failed++; diff --git "a/frameworks\\utest/utest/default_handlers.h" "b/frameworks\\utest/utest/default_handlers.h" index 02c19dc448..0e1e6d6a45 100644 --- "a/frameworks\\utest/utest/default_handlers.h" +++ "b/frameworks\\utest/utest/default_handlers.h" @@ -37,10 +37,11 @@ namespace v1 { { operator test_setup_handler_t() const { return test_setup_handler_t(1); } operator test_teardown_handler_t() const { return test_teardown_handler_t(1); } + operator test_failure_handler_t() const { return test_failure_handler_t(1); } operator case_setup_handler_t() const { return case_setup_handler_t(1); } operator case_teardown_handler_t() const { return case_teardown_handler_t(1); } - operator case_failure_handler_t() const { return case_failure_handler_t(1); } + operator case_failure_handler_t() const { return case_failure_handler_t(1); } } default_handler; /** Ignore handler hint. @@ -56,10 +57,11 @@ namespace v1 { operator test_setup_handler_t() const { return test_setup_handler_t(NULL); } operator test_teardown_handler_t() const { return test_teardown_handler_t(NULL); } + operator test_failure_handler_t() const { return test_failure_handler_t(NULL); } operator case_setup_handler_t() const { return case_setup_handler_t(NULL); } operator case_teardown_handler_t() const { return case_teardown_handler_t(NULL); } - operator case_failure_handler_t() const { return case_failure_handler_t(NULL); } + operator case_failure_handler_t() const { return case_failure_handler_t(NULL); } } ignore_handler; /** A table of handlers. @@ -88,6 +90,7 @@ namespace v1 { { test_setup_handler_t test_setup; test_teardown_handler_t test_teardown; + test_failure_handler_t test_failure; case_setup_handler_t case_setup; case_teardown_handler_t case_teardown; @@ -101,6 +104,10 @@ namespace v1 { if (handler == default_handler) return test_teardown; return handler; } + inline test_failure_handler_t get_handler(test_failure_handler_t handler) const { + if (handler == default_handler) return test_failure; + return handler; + } inline case_setup_handler_t get_handler(case_setup_handler_t handler) const { if (handler == default_handler) return case_setup; @@ -146,6 +153,9 @@ namespace v1 { /// The greentea default handlers that always continue on failure extern const handlers_t greentea_continue_handlers; + /// The selftest default handlers that always abort on _any_ assertion failure, otherwise continue + extern const handlers_t selftest_handlers; + /// The greentea aborting handlers are the default const handlers_t default_handlers = greentea_abort_handlers; diff --git "a/frameworks\\utest/utest/specification.h" "b/frameworks\\utest/utest/specification.h" index 4ba520d9b9..3e0747d2d7 100644 --- "a/frameworks\\utest/utest/specification.h" +++ "b/frameworks\\utest/utest/specification.h" @@ -48,16 +48,36 @@ namespace v1 { public: template< size_t N > Specification(const Case (&cases)[N], - const test_teardown_handler_t teardown_handler = default_handler, const handlers_t defaults = default_handlers) : - setup_handler(default_handler), teardown_handler(teardown_handler), + setup_handler(default_handler), teardown_handler(default_handler), failure_handler(default_handler), cases(cases), length(N), defaults(defaults) {} template< size_t N > - Specification(const Case (&cases)[N], const handlers_t defaults) : - setup_handler(default_handler), teardown_handler(default_handler), + Specification(const Case (&cases)[N], + const test_failure_handler_t failure_handler, + const handlers_t defaults = default_handlers) : + setup_handler(default_handler), teardown_handler(default_handler), failure_handler(failure_handler), + cases(cases), length(N), + defaults(defaults) + {} + + template< size_t N > + Specification(const Case (&cases)[N], + const test_teardown_handler_t teardown_handler, + const handlers_t defaults = default_handlers) : + setup_handler(default_handler), teardown_handler(teardown_handler), failure_handler(default_handler), + cases(cases), length(N), + defaults(defaults) + {} + + template< size_t N > + Specification(const Case (&cases)[N], + const test_teardown_handler_t teardown_handler, + const test_failure_handler_t failure_handler, + const handlers_t defaults = default_handlers) : + setup_handler(default_handler), teardown_handler(teardown_handler), failure_handler(failure_handler), cases(cases), length(N), defaults(defaults) {} @@ -65,9 +85,8 @@ namespace v1 { template< size_t N > Specification(const test_setup_handler_t setup_handler, const Case (&cases)[N], - const test_teardown_handler_t teardown_handler = default_handler, const handlers_t defaults = default_handlers) : - setup_handler(setup_handler), teardown_handler(teardown_handler), + setup_handler(setup_handler), teardown_handler(default_handler), failure_handler(default_handler), cases(cases), length(N), defaults(defaults) {} @@ -75,8 +94,30 @@ namespace v1 { template< size_t N > Specification(const test_setup_handler_t setup_handler, const Case (&cases)[N], - const handlers_t defaults) : - setup_handler(setup_handler), teardown_handler(default_handler), + const test_failure_handler_t failure_handler, + const handlers_t defaults = default_handlers) : + setup_handler(setup_handler), teardown_handler(default_handler), failure_handler(failure_handler), + cases(cases), length(N), + defaults(defaults) + {} + + template< size_t N > + Specification(const test_setup_handler_t setup_handler, + const Case (&cases)[N], + const test_teardown_handler_t teardown_handler, + const handlers_t defaults = default_handlers) : + setup_handler(setup_handler), teardown_handler(teardown_handler), failure_handler(default_handler), + cases(cases), length(N), + defaults(defaults) + {} + + template< size_t N > + Specification(const test_setup_handler_t setup_handler, + const Case (&cases)[N], + const test_teardown_handler_t teardown_handler, + const test_failure_handler_t failure_handler, + const handlers_t defaults = default_handlers) : + setup_handler(setup_handler), teardown_handler(teardown_handler), failure_handler(failure_handler), cases(cases), length(N), defaults(defaults) {} @@ -84,6 +125,7 @@ namespace v1 { private: const test_setup_handler_t setup_handler; const test_teardown_handler_t teardown_handler; + const test_failure_handler_t failure_handler; const Case *const cases; const size_t length; const handlers_t defaults; diff --git "a/frameworks\\utest/utest/types.h" "b/frameworks\\utest/utest/types.h" index 9016d6b4f4..62064d2157 100644 --- "a/frameworks\\utest/utest/types.h" +++ "b/frameworks\\utest/utest/types.h" @@ -163,6 +163,15 @@ namespace v1 { */ typedef void (*test_teardown_handler_t)(const size_t passed, const size_t failed, const failure_t failure); + /** Test failure handler. + * + * This handler is called anytime a failure occurs during the execution of a test speficication. + * The handler only allows logging of failures and cannot influence test execution. + * + * @param failure the reason why this handler was called + */ + typedef void (*test_failure_handler_t)(const failure_t reason); + /** Test case setup handler. * * This handler is called before execution of each test case and