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;
// 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*

View File

@ -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 <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.
*
@ -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

View File

@ -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<const Case*>(static_cast<const CaseType*>(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<const Case*>(static_cast<const CaseType*>(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<const Case*>(static_cast<const CaseType*>(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<const Case*>(static_cast<const CaseType*>(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<const Case*>(static_cast<const CaseType*>(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<const Case*>(static_cast<const CaseType*>(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<const Case*>(static_cast<const CaseType*>(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<const Case*>(static_cast<const CaseType*>(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;