From 5b27d65755c42926d68ac30055d3957159de59b8 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 2 Jun 2017 12:26:59 +0100 Subject: [PATCH] utest optimization: Allow case data structure to be put in ROM. This patch split the Case class in two entities: Case and case_t. case_t contains the test case data structure while Case provide the interface to the test case. Unlike the class Case, case _t is a POD and can be instantiated at compile time and put in the constant data section (in ROM). The Specification class has also been modified to accept arrays of case_t. --- .../frameworks/utest/source/utest_case.cpp | 169 +++++++++++------- features/frameworks/utest/utest/utest_case.h | 68 +++++-- .../utest/utest/utest_specification.h | 97 ++++++---- 3 files changed, 228 insertions(+), 106 deletions(-) diff --git a/features/frameworks/utest/source/utest_case.cpp b/features/frameworks/utest/source/utest_case.cpp index 77cc4d9b53..c5650c3117 100644 --- a/features/frameworks/utest/source/utest_case.cpp +++ b/features/frameworks/utest/source/utest_case.cpp @@ -21,44 +21,75 @@ using namespace utest::v1; +// case_t factory used by Case contructor +static inline case_t make_case( + const char *description, + const case_handler_t handler, + const case_control_handler_t control_handler, + const case_call_count_handler_t repeat_count_handler, + const case_setup_handler_t setup_handler, + const case_teardown_handler_t teardown_handler, + const case_failure_handler_t failure_handler) +{ + case_t result = { + description, + handler, + control_handler, + repeat_count_handler, + setup_handler, + teardown_handler, + failure_handler + }; + + return result; +} + // normal handler Case::Case(const char *description, const case_setup_handler_t setup_handler, const case_handler_t handler, const case_teardown_handler_t teardown_handler, const case_failure_handler_t failure_handler) : - description(description), - handler(handler), - control_handler(ignore_handler), - repeat_count_handler(ignore_handler), - setup_handler(setup_handler), - teardown_handler(teardown_handler), - failure_handler(failure_handler) + case_t(make_case( + description, + handler, + ignore_handler, + ignore_handler, + setup_handler, + teardown_handler, + failure_handler + )) + {} Case::Case(const char *description, const case_handler_t handler, const case_teardown_handler_t teardown_handler, const case_failure_handler_t failure_handler) : - description(description), - handler(handler), - control_handler(ignore_handler), - repeat_count_handler(ignore_handler), - setup_handler(default_handler), - teardown_handler(teardown_handler), - failure_handler(failure_handler) + case_t(make_case( + description, + handler, + ignore_handler, + ignore_handler, + default_handler, + teardown_handler, + failure_handler + )) + {} Case::Case(const char *description, const case_handler_t handler, const case_failure_handler_t failure_handler) : - description(description), - handler(handler), - control_handler(ignore_handler), - repeat_count_handler(ignore_handler), - setup_handler(default_handler), - teardown_handler(default_handler), - failure_handler(failure_handler) + case_t(make_case( + description, + handler, + ignore_handler, + ignore_handler, + default_handler, + default_handler, + failure_handler + )) {} // control handler @@ -67,38 +98,44 @@ Case::Case(const char *description, const case_control_handler_t handler, const case_teardown_handler_t teardown_handler, const case_failure_handler_t failure_handler) : - description(description), - handler(ignore_handler), - control_handler(handler), - repeat_count_handler(ignore_handler), - setup_handler(setup_handler), - teardown_handler(teardown_handler), - failure_handler(failure_handler) + case_t(make_case( + description, + ignore_handler, + handler, + ignore_handler, + setup_handler, + teardown_handler, + failure_handler + )) {} Case::Case(const char *description, const case_control_handler_t handler, const case_teardown_handler_t teardown_handler, const case_failure_handler_t failure_handler) : - description(description), - handler(ignore_handler), - control_handler(handler), - repeat_count_handler(ignore_handler), - setup_handler(default_handler), - teardown_handler(teardown_handler), - failure_handler(failure_handler) + case_t(make_case( + description, + ignore_handler, + handler, + ignore_handler, + default_handler, + teardown_handler, + failure_handler + )) {} Case::Case(const char *description, const case_control_handler_t handler, const case_failure_handler_t failure_handler) : - description(description), - handler(ignore_handler), - control_handler(handler), - repeat_count_handler(ignore_handler), - setup_handler(default_handler), - teardown_handler(default_handler), - failure_handler(failure_handler) + case_t(make_case( + description, + ignore_handler, + handler, + ignore_handler, + default_handler, + default_handler, + failure_handler + )) {} // control flow handler @@ -107,38 +144,44 @@ Case::Case(const char *description, const case_call_count_handler_t case_repeat_count_handler, const case_teardown_handler_t teardown_handler, const case_failure_handler_t failure_handler) : - description(description), - handler(ignore_handler), - control_handler(ignore_handler), - repeat_count_handler(case_repeat_count_handler), - setup_handler(setup_handler), - teardown_handler(teardown_handler), - failure_handler(failure_handler) + case_t(make_case( + description, + ignore_handler, + ignore_handler, + case_repeat_count_handler, + setup_handler, + teardown_handler, + failure_handler + )) {} Case::Case(const char *description, const case_call_count_handler_t case_repeat_count_handler, const case_failure_handler_t failure_handler) : - description(description), - handler(ignore_handler), - control_handler(ignore_handler), - repeat_count_handler(case_repeat_count_handler), - setup_handler(default_handler), - teardown_handler(default_handler), - failure_handler(failure_handler) + case_t(make_case( + description, + ignore_handler, + ignore_handler, + case_repeat_count_handler, + default_handler, + default_handler, + failure_handler + )) {} Case::Case(const char *description, const case_call_count_handler_t case_repeat_count_handler, const case_teardown_handler_t teardown_handler, const case_failure_handler_t failure_handler) : - description(description), - handler(ignore_handler), - control_handler(ignore_handler), - repeat_count_handler(case_repeat_count_handler), - setup_handler(default_handler), - teardown_handler(teardown_handler), - failure_handler(failure_handler) + case_t(make_case( + description, + ignore_handler, + ignore_handler, + case_repeat_count_handler, + default_handler, + teardown_handler, + failure_handler + )) {} const char* diff --git a/features/frameworks/utest/utest/utest_case.h b/features/frameworks/utest/utest/utest_case.h index 8423d35f80..08c314ce15 100644 --- a/features/frameworks/utest/utest/utest_case.h +++ b/features/frameworks/utest/utest/utest_case.h @@ -30,6 +30,59 @@ namespace utest { /** \addtogroup frameworks */ /** @{*/ namespace v1 { + /** + * POD data structure of the Case class. + * Unlike the Case class it can be used as a POD and be put in ROM. + * + * @warning Initialization of handlers with either default_handler or + * ignore_handler helpers will prevent the object to be a POD. Prefer usage + * of NULL in favor of ignore_handler or (1) for default + * handler. + * + * @see Case. + */ + struct case_t + { + /** + * Textual description of the test case + */ + const char *description; + + /** + * Primitive test case handler + * This is called only if the case setup succeeded. It is followed by + * the test case teardown handler. + */ + const case_handler_t handler; + + /** + * @see case_control_handler_t + */ + const case_control_handler_t control_handler; + + /** + * @see case_call_count_handler_t + */ + const case_call_count_handler_t repeat_count_handler; + + /** + * Handler called before the execution of the case handler. It sets up + * the case environment. + */ + const case_setup_handler_t setup_handler; + + /** + * Handler called after the execution of the case handler. It cleans up + * the case environment. + */ + const case_teardown_handler_t teardown_handler; + + /** + * Handler called whenever a faillure occur; at any stage of the case + * execution (including setup and teardown). + */ + const case_failure_handler_t failure_handler; + }; /** Test case wrapper class. * @@ -52,7 +105,7 @@ namespace v1 { * @note While you can specify an empty test case (ie. use `ignore_handler` for all callbacks), * the harness will abort the test unconditionally. */ - class Case + class Case : private case_t { public: // overloads for case_handler_t @@ -111,18 +164,9 @@ namespace v1 { bool is_empty() const; private: - const char *description; - - const case_handler_t handler; - const case_control_handler_t control_handler; - const case_call_count_handler_t repeat_count_handler; - - const case_setup_handler_t setup_handler; - const case_teardown_handler_t teardown_handler; - - const case_failure_handler_t failure_handler; - + // see data member in case_t friend class Harness; + friend class Specification; }; } // namespace v1 diff --git a/features/frameworks/utest/utest/utest_specification.h b/features/frameworks/utest/utest/utest_specification.h index 6b3ff66f23..60b81ede78 100644 --- a/features/frameworks/utest/utest/utest_specification.h +++ b/features/frameworks/utest/utest/utest_specification.h @@ -48,81 +48,116 @@ namespace v1 { class Specification { public: - template< size_t N > - Specification(const Case (&cases)[N], + template< size_t N, typename CaseType > + Specification(const CaseType (&cases)[N], const handlers_t defaults = default_handlers) : setup_handler(default_handler), teardown_handler(default_handler), failure_handler(default_handler), - cases(cases), length(N), + cases(static_cast(static_cast(cases))), length(N), defaults(defaults) - {} + { + MBED_STATIC_ASSERT( + sizeof(CaseType) == sizeof(Case), + "CaseType and Case should have the same size" + ); + } - template< size_t N > - Specification(const Case (&cases)[N], + template< size_t N, typename CaseType > + Specification(const CaseType (&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), + cases(static_cast(static_cast(cases))), length(N), defaults(defaults) - {} + { + MBED_STATIC_ASSERT( + sizeof(CaseType) == sizeof(Case), + "CaseType and Case should have the same size" + ); + } - template< size_t N > - Specification(const Case (&cases)[N], + template< size_t N, typename CaseType > + Specification(const CaseType (&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), + cases(static_cast(static_cast(cases))), length(N), defaults(defaults) - {} + { + MBED_STATIC_ASSERT( + sizeof(CaseType) == sizeof(Case), + "CaseType and Case should have the same size" + ); + } - template< size_t N > - Specification(const Case (&cases)[N], + template< size_t N, typename CaseType > + Specification(const CaseType (&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), + cases(static_cast(static_cast(cases))), length(N), defaults(defaults) - {} + { + MBED_STATIC_ASSERT( + sizeof(CaseType) == sizeof(Case), + "CaseType and Case should have the same size" + ); + } - template< size_t N > + template< size_t N, typename CaseType > Specification(const test_setup_handler_t setup_handler, - const Case (&cases)[N], + const CaseType (&cases)[N], const handlers_t defaults = default_handlers) : setup_handler(setup_handler), teardown_handler(default_handler), failure_handler(default_handler), - cases(cases), length(N), + cases(static_cast(static_cast(cases))), length(N), defaults(defaults) {} - template< size_t N > + template< size_t N, typename CaseType > Specification(const test_setup_handler_t setup_handler, - const Case (&cases)[N], + const CaseType (&cases)[N], 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), + cases(static_cast(static_cast(cases))), length(N), defaults(defaults) - {} + { + MBED_STATIC_ASSERT( + sizeof(CaseType) == sizeof(Case), + "CaseType and Case should have the same size" + ); + } - template< size_t N > + template< size_t N, typename CaseType > Specification(const test_setup_handler_t setup_handler, - const Case (&cases)[N], + const CaseType (&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), + cases(static_cast(static_cast(cases))), length(N), defaults(defaults) - {} + { + MBED_STATIC_ASSERT( + sizeof(CaseType) == sizeof(Case), + "CaseType and Case should have the same size" + ); + } - template< size_t N > + template< size_t N, typename CaseType > Specification(const test_setup_handler_t setup_handler, - const Case (&cases)[N], + const CaseType (&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), + cases(static_cast(static_cast(cases))), length(N), defaults(defaults) - {} + { + MBED_STATIC_ASSERT( + sizeof(CaseType) == sizeof(Case), + "CaseType and Case should have the same size" + ); + } private: const test_setup_handler_t setup_handler;