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.
pull/4430/head
Vincent Coubard 2017-06-02 12:26:59 +01:00
parent a41e08c7bf
commit 5b27d65755
3 changed files with 228 additions and 106 deletions

View File

@ -21,44 +21,75 @@
using namespace utest::v1; 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 // normal handler
Case::Case(const char *description, Case::Case(const char *description,
const case_setup_handler_t setup_handler, const case_setup_handler_t setup_handler,
const case_handler_t handler, const case_handler_t handler,
const case_teardown_handler_t teardown_handler, const case_teardown_handler_t teardown_handler,
const case_failure_handler_t failure_handler) : const case_failure_handler_t failure_handler) :
description(description), case_t(make_case(
handler(handler), description,
control_handler(ignore_handler), handler,
repeat_count_handler(ignore_handler), ignore_handler,
setup_handler(setup_handler), ignore_handler,
teardown_handler(teardown_handler), setup_handler,
failure_handler(failure_handler) teardown_handler,
failure_handler
))
{} {}
Case::Case(const char *description, Case::Case(const char *description,
const case_handler_t handler, const case_handler_t handler,
const case_teardown_handler_t teardown_handler, const case_teardown_handler_t teardown_handler,
const case_failure_handler_t failure_handler) : const case_failure_handler_t failure_handler) :
description(description), case_t(make_case(
handler(handler), description,
control_handler(ignore_handler), handler,
repeat_count_handler(ignore_handler), ignore_handler,
setup_handler(default_handler), ignore_handler,
teardown_handler(teardown_handler), default_handler,
failure_handler(failure_handler) teardown_handler,
failure_handler
))
{} {}
Case::Case(const char *description, Case::Case(const char *description,
const case_handler_t handler, const case_handler_t handler,
const case_failure_handler_t failure_handler) : const case_failure_handler_t failure_handler) :
description(description), case_t(make_case(
handler(handler), description,
control_handler(ignore_handler), handler,
repeat_count_handler(ignore_handler), ignore_handler,
setup_handler(default_handler), ignore_handler,
teardown_handler(default_handler), default_handler,
failure_handler(failure_handler) default_handler,
failure_handler
))
{} {}
// control handler // control handler
@ -67,38 +98,44 @@ Case::Case(const char *description,
const case_control_handler_t handler, const case_control_handler_t handler,
const case_teardown_handler_t teardown_handler, const case_teardown_handler_t teardown_handler,
const case_failure_handler_t failure_handler) : const case_failure_handler_t failure_handler) :
description(description), case_t(make_case(
handler(ignore_handler), description,
control_handler(handler), ignore_handler,
repeat_count_handler(ignore_handler), handler,
setup_handler(setup_handler), ignore_handler,
teardown_handler(teardown_handler), setup_handler,
failure_handler(failure_handler) teardown_handler,
failure_handler
))
{} {}
Case::Case(const char *description, Case::Case(const char *description,
const case_control_handler_t handler, const case_control_handler_t handler,
const case_teardown_handler_t teardown_handler, const case_teardown_handler_t teardown_handler,
const case_failure_handler_t failure_handler) : const case_failure_handler_t failure_handler) :
description(description), case_t(make_case(
handler(ignore_handler), description,
control_handler(handler), ignore_handler,
repeat_count_handler(ignore_handler), handler,
setup_handler(default_handler), ignore_handler,
teardown_handler(teardown_handler), default_handler,
failure_handler(failure_handler) teardown_handler,
failure_handler
))
{} {}
Case::Case(const char *description, Case::Case(const char *description,
const case_control_handler_t handler, const case_control_handler_t handler,
const case_failure_handler_t failure_handler) : const case_failure_handler_t failure_handler) :
description(description), case_t(make_case(
handler(ignore_handler), description,
control_handler(handler), ignore_handler,
repeat_count_handler(ignore_handler), handler,
setup_handler(default_handler), ignore_handler,
teardown_handler(default_handler), default_handler,
failure_handler(failure_handler) default_handler,
failure_handler
))
{} {}
// control flow 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_call_count_handler_t case_repeat_count_handler,
const case_teardown_handler_t teardown_handler, const case_teardown_handler_t teardown_handler,
const case_failure_handler_t failure_handler) : const case_failure_handler_t failure_handler) :
description(description), case_t(make_case(
handler(ignore_handler), description,
control_handler(ignore_handler), ignore_handler,
repeat_count_handler(case_repeat_count_handler), ignore_handler,
setup_handler(setup_handler), case_repeat_count_handler,
teardown_handler(teardown_handler), setup_handler,
failure_handler(failure_handler) teardown_handler,
failure_handler
))
{} {}
Case::Case(const char *description, Case::Case(const char *description,
const case_call_count_handler_t case_repeat_count_handler, const case_call_count_handler_t case_repeat_count_handler,
const case_failure_handler_t failure_handler) : const case_failure_handler_t failure_handler) :
description(description), case_t(make_case(
handler(ignore_handler), description,
control_handler(ignore_handler), ignore_handler,
repeat_count_handler(case_repeat_count_handler), ignore_handler,
setup_handler(default_handler), case_repeat_count_handler,
teardown_handler(default_handler), default_handler,
failure_handler(failure_handler) default_handler,
failure_handler
))
{} {}
Case::Case(const char *description, Case::Case(const char *description,
const case_call_count_handler_t case_repeat_count_handler, const case_call_count_handler_t case_repeat_count_handler,
const case_teardown_handler_t teardown_handler, const case_teardown_handler_t teardown_handler,
const case_failure_handler_t failure_handler) : const case_failure_handler_t failure_handler) :
description(description), case_t(make_case(
handler(ignore_handler), description,
control_handler(ignore_handler), ignore_handler,
repeat_count_handler(case_repeat_count_handler), ignore_handler,
setup_handler(default_handler), case_repeat_count_handler,
teardown_handler(teardown_handler), default_handler,
failure_handler(failure_handler) teardown_handler,
failure_handler
))
{} {}
const char* const char*

View File

@ -30,6 +30,59 @@ namespace utest {
/** \addtogroup frameworks */ /** \addtogroup frameworks */
/** @{*/ /** @{*/
namespace v1 { 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 <handler_type>(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. /** 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), * @note While you can specify an empty test case (ie. use `ignore_handler` for all callbacks),
* the harness will abort the test unconditionally. * the harness will abort the test unconditionally.
*/ */
class Case class Case : private case_t
{ {
public: public:
// overloads for case_handler_t // overloads for case_handler_t
@ -111,18 +164,9 @@ namespace v1 {
bool is_empty() const; bool is_empty() const;
private: private:
const char *description; // see data member in case_t
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;
friend class Harness; friend class Harness;
friend class Specification;
}; };
} // namespace v1 } // namespace v1

View File

@ -48,81 +48,116 @@ namespace v1 {
class Specification class Specification
{ {
public: public:
template< size_t N > template< size_t N, typename CaseType >
Specification(const Case (&cases)[N], Specification(const CaseType (&cases)[N],
const handlers_t defaults = default_handlers) : const handlers_t defaults = default_handlers) :
setup_handler(default_handler), teardown_handler(default_handler), failure_handler(default_handler), setup_handler(default_handler), teardown_handler(default_handler), failure_handler(default_handler),
cases(cases), length(N), cases(static_cast<const Case*>(static_cast<const CaseType*>(cases))), length(N),
defaults(defaults) 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 Case (&cases)[N], Specification(const CaseType (&cases)[N],
const test_failure_handler_t failure_handler, const test_failure_handler_t failure_handler,
const handlers_t defaults = default_handlers) : const handlers_t defaults = default_handlers) :
setup_handler(default_handler), teardown_handler(default_handler), failure_handler(failure_handler), setup_handler(default_handler), teardown_handler(default_handler), failure_handler(failure_handler),
cases(cases), length(N), cases(static_cast<const Case*>(static_cast<const CaseType*>(cases))), length(N),
defaults(defaults) 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 Case (&cases)[N], Specification(const CaseType (&cases)[N],
const test_teardown_handler_t teardown_handler, const test_teardown_handler_t teardown_handler,
const handlers_t defaults = default_handlers) : const handlers_t defaults = default_handlers) :
setup_handler(default_handler), teardown_handler(teardown_handler), failure_handler(default_handler), setup_handler(default_handler), teardown_handler(teardown_handler), failure_handler(default_handler),
cases(cases), length(N), cases(static_cast<const Case*>(static_cast<const CaseType*>(cases))), length(N),
defaults(defaults) 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 Case (&cases)[N], Specification(const CaseType (&cases)[N],
const test_teardown_handler_t teardown_handler, const test_teardown_handler_t teardown_handler,
const test_failure_handler_t failure_handler, const test_failure_handler_t failure_handler,
const handlers_t defaults = default_handlers) : const handlers_t defaults = default_handlers) :
setup_handler(default_handler), teardown_handler(teardown_handler), failure_handler(failure_handler), setup_handler(default_handler), teardown_handler(teardown_handler), failure_handler(failure_handler),
cases(cases), length(N), cases(static_cast<const Case*>(static_cast<const CaseType*>(cases))), length(N),
defaults(defaults) 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, Specification(const test_setup_handler_t setup_handler,
const Case (&cases)[N], const CaseType (&cases)[N],
const handlers_t defaults = default_handlers) : const handlers_t defaults = default_handlers) :
setup_handler(setup_handler), teardown_handler(default_handler), failure_handler(default_handler), setup_handler(setup_handler), teardown_handler(default_handler), failure_handler(default_handler),
cases(cases), length(N), cases(static_cast<const Case*>(static_cast<const CaseType*>(cases))), length(N),
defaults(defaults) defaults(defaults)
{} {}
template< size_t N > template< size_t N, typename CaseType >
Specification(const test_setup_handler_t setup_handler, Specification(const test_setup_handler_t setup_handler,
const Case (&cases)[N], const CaseType (&cases)[N],
const test_failure_handler_t failure_handler, const test_failure_handler_t failure_handler,
const handlers_t defaults = default_handlers) : const handlers_t defaults = default_handlers) :
setup_handler(setup_handler), teardown_handler(default_handler), failure_handler(failure_handler), setup_handler(setup_handler), teardown_handler(default_handler), failure_handler(failure_handler),
cases(cases), length(N), cases(static_cast<const Case*>(static_cast<const CaseType*>(cases))), length(N),
defaults(defaults) 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, 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_teardown_handler_t teardown_handler,
const handlers_t defaults = default_handlers) : const handlers_t defaults = default_handlers) :
setup_handler(setup_handler), teardown_handler(teardown_handler), failure_handler(default_handler), setup_handler(setup_handler), teardown_handler(teardown_handler), failure_handler(default_handler),
cases(cases), length(N), cases(static_cast<const Case*>(static_cast<const CaseType*>(cases))), length(N),
defaults(defaults) 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, 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_teardown_handler_t teardown_handler,
const test_failure_handler_t failure_handler, const test_failure_handler_t failure_handler,
const handlers_t defaults = default_handlers) : const handlers_t defaults = default_handlers) :
setup_handler(setup_handler), teardown_handler(teardown_handler), failure_handler(failure_handler), setup_handler(setup_handler), teardown_handler(teardown_handler), failure_handler(failure_handler),
cases(cases), length(N), cases(static_cast<const Case*>(static_cast<const CaseType*>(cases))), length(N),
defaults(defaults) defaults(defaults)
{} {
MBED_STATIC_ASSERT(
sizeof(CaseType) == sizeof(Case),
"CaseType and Case should have the same size"
);
}
private: private:
const test_setup_handler_t setup_handler; const test_setup_handler_t setup_handler;