Merge pull request #27 from 0xc0170/utest

utest and unity
Bogdan Marinescu 2016-05-03 13:28:50 +03:00
commit 962ae83b66
19 changed files with 2313 additions and 0 deletions

1
frameworks/unity.lib Normal file
View File

@ -0,0 +1 @@
https://github.com/ARMmbed/unity.git#3b2fef7fcf60abcc

View File

@ -0,0 +1,32 @@
/* mbed Microcontroller Library
* Copyright (c) 2013-2016 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed.h"
#include "utest/utest.h"
using namespace utest::v1;
void utest_v1_enter_critical_section(void)
{
// will replaced by CriticalSectionLock
__disable_irq();
}
void utest_v1_leave_critical_section(void)
{
__enable_irq();
}

View File

@ -0,0 +1,138 @@
/****************************************************************************
* Copyright (c) 2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
****************************************************************************
*/
#include "utest/shim.h"
#if UTEST_SHIM_SCHEDULER_USE_MINAR
#include "minar/minar.h"
static int32_t utest_minar_init()
{
return 0;
}
static void *utest_minar_post(const utest_v1_harness_callback_t callback, const uint32_t delay_ms)
{
void *handle = minar::Scheduler::postCallback(callback).delay(minar::milliseconds(delay_ms)).getHandle();
return handle;
}
static int32_t utest_minar_cancel(void *handle)
{
int32_t ret = minar::Scheduler::cancelCallback(handle);
return ret;
}
static int32_t utest_minar_run()
{
return 0;
}
extern "C" {
static const utest_v1_scheduler_t utest_v1_scheduler =
{
utest_minar_init,
utest_minar_post,
utest_minar_cancel,
utest_minar_run
};
utest_v1_scheduler_t utest_v1_get_scheduler()
{
return utest_v1_scheduler;
}
}
#elif UTEST_SHIM_SCHEDULER_USE_US_TICKER
#ifdef YOTTA_MBED_HAL_VERSION_STRING
# include "mbed-hal/us_ticker_api.h"
#else
# include "us_ticker_api.h"
#endif
// only one callback is active at any given time
static volatile utest_v1_harness_callback_t minimal_callback;
static volatile utest_v1_harness_callback_t ticker_callback;
static const ticker_data_t *ticker_data;
static ticker_event_t ticker_event;
static void ticker_handler(uint32_t)
{
// printf("\t\t>>> Ticker callback fired for %p.\n", ticker_callback);
minimal_callback = ticker_callback;
}
static int32_t utest_us_ticker_init()
{
ticker_data = get_us_ticker_data();
ticker_set_handler(ticker_data, ticker_handler);
return 0;
}
static void *utest_us_ticker_post(const utest_v1_harness_callback_t callback, const uint32_t delay_ms)
{
// printf("\t\t>>> Schedule %p with %ums delay => %p.\n", callback, (unsigned int)delay_ms, (void*)1);
if (delay_ms) {
ticker_callback = callback;
// fire the interrupt in 1000us * delay_ms
ticker_insert_event(ticker_data, &ticker_event, ticker_read(ticker_data) + delay_ms * 1000, 0);
} else {
minimal_callback = callback;
}
// return a bogus handle
return (void*)1;
}
static int32_t utest_us_ticker_cancel(void *handle)
{
// printf("\t\t>>> Cancel %p => %u\n", handle, (unsigned int)0);
(void) handle;
ticker_remove_event(ticker_data, &ticker_event);
return 0;
}
static int32_t utest_us_ticker_run()
{
while(1)
{
// check if a new callback has been set
if (minimal_callback)
{
// printf("\t\t>>> Firing callback %p\n", minimal_callback);
// copy the callback
utest_v1_harness_callback_t callback = minimal_callback;
// reset the shared callback
minimal_callback = NULL;
// execute the copied callback
callback();
}
}
return 0;
}
extern "C" {
static const utest_v1_scheduler_t utest_v1_scheduler =
{
utest_us_ticker_init,
utest_us_ticker_post,
utest_us_ticker_cancel,
utest_us_ticker_run
};
utest_v1_scheduler_t utest_v1_get_scheduler()
{
return utest_v1_scheduler;
}
}
#endif
#ifdef YOTTA_CORE_UTIL_VERSION_STRING
// their functionality is implemented using the CriticalSectionLock class
void utest_v1_enter_critical_section(void) {}
void utest_v1_leave_critical_section(void) {}
#endif

View File

@ -0,0 +1,151 @@
/****************************************************************************
* Copyright (c) 2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
****************************************************************************
*/
#include "utest/case.h"
using namespace utest::v1;
// 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::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::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)
{}
// control handler
Case::Case(const char *description,
const case_setup_handler_t setup_handler,
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::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::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)
{}
// control flow handler
Case::Case(const char *description,
const case_setup_handler_t setup_handler,
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::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::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)
{}
const char*
Case::get_description() const {
return description;
}
bool
Case::is_empty() const {
return !(handler || control_handler || repeat_count_handler || setup_handler || teardown_handler);
}

View File

@ -0,0 +1,94 @@
/****************************************************************************
* Copyright (c) 2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
****************************************************************************
*/
#include "utest/default_handlers.h"
#include "utest/case.h"
using namespace utest::v1;
static void test_failure_handler(const failure_t failure);
const handlers_t utest::v1::verbose_continue_handlers = {
verbose_test_setup_handler,
verbose_test_teardown_handler,
test_failure_handler,
verbose_case_setup_handler,
verbose_case_teardown_handler,
verbose_case_failure_handler
};
// --- SPECIAL HANDLERS ---
static void test_failure_handler(const failure_t failure) {
if (failure.location == LOCATION_TEST_SETUP || failure.location == LOCATION_TEST_TEARDOWN) {
verbose_test_failure_handler(failure);
printf("{{failure}}\n{{end}}\n");
while(1) ;
}
}
// --- VERBOSE TEST HANDLERS ---
status_t utest::v1::verbose_test_setup_handler(const size_t number_of_cases)
{
printf(">>> Running %u test cases...\n", number_of_cases);
return STATUS_CONTINUE;
}
void utest::v1::verbose_test_teardown_handler(const size_t passed, const size_t failed, const failure_t failure)
{
printf("\n>>> Test cases: %u passed, %u failed", passed, failed);
if (failure.reason == REASON_NONE) {
printf("\n");
} else {
printf(" with reason '%s'\n", stringify(failure.reason));
}
if (failed) printf(">>> TESTS FAILED!\n");
}
void utest::v1::verbose_test_failure_handler(const failure_t failure)
{
printf(">>> failure with reason '%s' during '%s'\n", stringify(failure.reason), stringify(failure.location));
}
// --- VERBOSE CASE HANDLERS ---
status_t utest::v1::verbose_case_setup_handler(const Case *const source, const size_t index_of_case)
{
printf("\n>>> Running case #%u: '%s'...\n", index_of_case + 1, source->get_description());
return STATUS_CONTINUE;
}
status_t utest::v1::verbose_case_teardown_handler(const Case *const source, const size_t passed, const size_t failed, const failure_t failure)
{
printf(">>> '%s': %u passed, %u failed", source->get_description(), passed, failed);
if (failure.reason == REASON_NONE) {
printf("\n");
} else {
printf(" with reason '%s'\n", stringify(failure.reason));
}
return STATUS_CONTINUE;
}
status_t utest::v1::verbose_case_failure_handler(const Case *const /*source*/, const failure_t failure)
{
if (!(failure.reason & REASON_ASSERTION)) {
verbose_test_failure_handler(failure);
}
if (failure.reason & (REASON_TEST_TEARDOWN | REASON_CASE_TEARDOWN)) return STATUS_ABORT;
if (failure.reason & REASON_IGNORE) return STATUS_IGNORE;
return STATUS_CONTINUE;
}

View File

@ -0,0 +1,127 @@
/****************************************************************************
* Copyright (c) 2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
****************************************************************************
*/
#include "utest/default_handlers.h"
#include "utest/case.h"
#include "greentea-client/test_env.h"
using namespace utest::v1;
static status_t unknown_test_setup_handler(const size_t);
static void selftest_failure_handler(const failure_t);
static void test_failure_handler(const failure_t);
const handlers_t utest::v1::greentea_abort_handlers = {
unknown_test_setup_handler,
greentea_test_teardown_handler,
test_failure_handler,
greentea_case_setup_handler,
greentea_case_teardown_handler,
greentea_case_failure_abort_handler
};
const handlers_t utest::v1::greentea_continue_handlers = {
unknown_test_setup_handler,
greentea_test_teardown_handler,
test_failure_handler,
greentea_case_setup_handler,
greentea_case_teardown_handler,
greentea_case_failure_continue_handler
};
const handlers_t utest::v1::selftest_handlers = {
unknown_test_setup_handler,
greentea_test_teardown_handler,
selftest_failure_handler,
greentea_case_setup_handler,
greentea_case_teardown_handler,
greentea_case_failure_continue_handler
};
// --- SPECIAL HANDLERS ---
static status_t unknown_test_setup_handler(const size_t) {
printf(">>> I do not know how to tell greentea that the test started, since\n");
printf(">>> you forgot to override the `test_setup_handler` in your specification.\n");
return STATUS_ABORT;
}
static void selftest_failure_handler(const failure_t failure) {
if (failure.location == LOCATION_TEST_SETUP || failure.location == LOCATION_TEST_TEARDOWN || failure.reason == REASON_ASSERTION) {
verbose_test_failure_handler(failure);
}
if (failure.reason == REASON_ASSERTION) {
GREENTEA_TESTSUITE_RESULT(false);
while(1) ;
}
}
static void test_failure_handler(const failure_t failure) {
if (failure.location == LOCATION_TEST_SETUP || failure.location == LOCATION_TEST_TEARDOWN) {
verbose_test_failure_handler(failure);
GREENTEA_TESTSUITE_RESULT(false);
while(1) ;
}
}
// --- GREENTEA HANDLERS ---
status_t utest::v1::greentea_test_setup_handler(const size_t number_of_cases)
{
greentea_send_kv(TEST_ENV_TESTCASE_COUNT, number_of_cases);
return verbose_test_setup_handler(number_of_cases);
}
void utest::v1::greentea_test_teardown_handler(const size_t passed, const size_t failed, const failure_t failure)
{
verbose_test_teardown_handler(passed, failed, failure);
greentea_send_kv(TEST_ENV_TESTCASE_SUMMARY, passed, failed);
int result = !(failed || (failure.reason && !(failure.reason & REASON_IGNORE)));
GREENTEA_TESTSUITE_RESULT(result);
}
void utest::v1::greentea_test_failure_handler(const failure_t failure)
{
verbose_test_failure_handler(failure);
}
// --- GREENTEA CASE HANDLERS ---
status_t utest::v1::greentea_case_setup_handler(const Case *const source, const size_t index_of_case)
{
status_t status = verbose_case_setup_handler(source, index_of_case);
greentea_send_kv(TEST_ENV_TESTCASE_START, source->get_description());
return status;
}
status_t utest::v1::greentea_case_teardown_handler(const Case *const source, const size_t passed, const size_t failed, const failure_t failure)
{
greentea_send_kv(TEST_ENV_TESTCASE_FINISH, source->get_description(), passed, failed);
return verbose_case_teardown_handler(source, passed, failed, failure);
}
status_t utest::v1::greentea_case_failure_abort_handler(const Case *const source, const failure_t failure)
{
status_t status = verbose_case_failure_handler(source, failure);
return (status == STATUS_IGNORE) ? STATUS_IGNORE : STATUS_ABORT;
}
status_t utest::v1::greentea_case_failure_continue_handler(const Case *const source, const failure_t failure)
{
return verbose_case_failure_handler(source, failure);
}

View File

@ -0,0 +1,342 @@
/****************************************************************************
* Copyright (c) 2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
****************************************************************************
*/
#include "utest/harness.h"
#include <stdlib.h>
using namespace utest::v1;
namespace
{
const Case *test_cases = NULL;
size_t test_length = 0;
size_t test_index_of_case = 0;
size_t test_passed = 0;
size_t test_failed = 0;
const Case *case_current = NULL;
size_t case_index = 0;
control_t case_control = control_t(REPEAT_SETUP_TEARDOWN);
size_t case_repeat_count = 1;
void *case_timeout_handle = NULL;
size_t case_validation_count = 0;
bool case_timeout_occurred = false;
size_t case_passed = 0;
size_t case_failed = 0;
size_t case_failed_before = 0;
handlers_t defaults = default_handlers;
handlers_t handlers = defaults;
location_t location = LOCATION_UNKNOWN;
utest_v1_scheduler_t scheduler = {NULL, NULL, NULL, NULL};
}
static void die() {
while(1) ;
}
static bool is_scheduler_valid(const utest_v1_scheduler_t scheduler)
{
return (scheduler.init && scheduler.post && scheduler.cancel && scheduler.run);
}
bool Harness::set_scheduler(const utest_v1_scheduler_t scheduler)
{
if (is_scheduler_valid(scheduler)) {
::scheduler = scheduler;
return true;
}
return false;
}
bool Harness::run(const Specification& specification, size_t)
{
return run(specification);
}
bool Harness::run(const Specification& specification)
{
// check if a specification is currently running
if (is_busy())
return false;
// if the scheduler is invalid, this is the first time we are calling
if (!is_scheduler_valid(scheduler))
scheduler = utest_v1_get_scheduler();
// if the scheduler is still invalid, abort
if (!is_scheduler_valid(scheduler))
return false;
// if the scheduler failed to initialize, abort
if (scheduler.init() != 0)
return false;
test_cases = specification.cases;
test_length = specification.length;
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;
test_failed = 0;
case_passed = 0;
case_failed = 0;
case_failed_before = 0;
location = LOCATION_TEST_SETUP;
int setup_status = 0;
failure_t failure(REASON_NONE, location);
if (handlers.test_setup) {
setup_status = handlers.test_setup(test_length);
if (setup_status == STATUS_CONTINUE) setup_status = 0;
else if (setup_status < STATUS_CONTINUE) failure.reason = REASON_TEST_SETUP;
else if (setup_status > signed(test_length)) failure.reason = REASON_CASE_INDEX;
}
if (failure.reason != REASON_NONE) {
if (handlers.test_failure) handlers.test_failure(failure);
if (handlers.test_teardown) handlers.test_teardown(0, 0, failure);
test_cases = NULL;
exit(1);
return true;
}
case_index = setup_status;
case_current = &test_cases[case_index];
scheduler.post(run_next_case, 0);
if (scheduler.run() != 0) {
failure.reason = REASON_SCHEDULER;
if (handlers.test_failure) handlers.test_failure(failure);
if (handlers.test_teardown) handlers.test_teardown(0, 0, failure);
test_cases = NULL;
exit(1);
return true;
}
return true;
}
void Harness::raise_failure(const failure_reason_t reason)
{
// ignore a failure, if the Harness has not been initialized.
// this allows using unity assertion macros without setting up utest.
if (test_cases == NULL) return;
status_t fail_status = STATUS_ABORT;
{
UTEST_ENTER_CRITICAL_SECTION;
if (handlers.test_failure) handlers.test_failure(failure_t(reason, location));
if (handlers.case_failure) fail_status = handlers.case_failure(case_current, failure_t(reason, location));
if (fail_status != STATUS_IGNORE) case_failed++;
if ((fail_status == STATUS_ABORT) && case_timeout_handle)
{
scheduler.cancel(case_timeout_handle);
case_timeout_handle = NULL;
}
UTEST_LEAVE_CRITICAL_SECTION;
}
if (fail_status == STATUS_ABORT || reason & REASON_CASE_SETUP) {
if (handlers.case_teardown && location != LOCATION_CASE_TEARDOWN) {
location_t fail_loc(location);
location = LOCATION_CASE_TEARDOWN;
status_t teardown_status = handlers.case_teardown(case_current, case_passed, case_failed, failure_t(reason, fail_loc));
if (teardown_status < STATUS_CONTINUE) raise_failure(REASON_CASE_TEARDOWN);
else if (teardown_status > signed(test_length)) raise_failure(REASON_CASE_INDEX);
else if (teardown_status >= 0) case_index = teardown_status - 1;
handlers.case_teardown = NULL;
}
}
if (fail_status == STATUS_ABORT) {
test_failed++;
failure_t fail(reason, location);
location = LOCATION_TEST_TEARDOWN;
if (handlers.test_teardown) handlers.test_teardown(test_passed, test_failed, fail);
exit(test_failed);
die();
}
}
void Harness::schedule_next_case()
{
if (!case_timeout_occurred && case_failed_before == case_failed) {
case_passed++;
}
if (case_control.repeat & REPEAT_SETUP_TEARDOWN || !(case_control.repeat & (REPEAT_ON_TIMEOUT | REPEAT_ON_VALIDATE))) {
location = LOCATION_CASE_TEARDOWN;
if (handlers.case_teardown) {
status_t status = handlers.case_teardown(case_current, case_passed, case_failed,
case_failed ? failure_t(REASON_CASES, LOCATION_UNKNOWN) : failure_t(REASON_NONE));
if (status < STATUS_CONTINUE) raise_failure(REASON_CASE_TEARDOWN);
else if (status > signed(test_length)) raise_failure(REASON_CASE_INDEX);
else if (status >= 0) case_index = status - 1;
}
}
if (!(case_control.repeat & (REPEAT_ON_TIMEOUT | REPEAT_ON_VALIDATE))) {
if (case_failed > 0) test_failed++;
else test_passed++;
case_control = control_t(REPEAT_SETUP_TEARDOWN);
case_index++;
case_current = &test_cases[case_index];
case_passed = 0;
case_failed = 0;
case_failed_before = 0;
case_repeat_count = 1;
test_index_of_case++;
}
scheduler.post(run_next_case, 0);
}
void Harness::handle_timeout()
{
{
UTEST_ENTER_CRITICAL_SECTION;
if (case_timeout_handle != NULL) {
case_timeout_handle = NULL;
case_timeout_occurred = true;
}
UTEST_LEAVE_CRITICAL_SECTION;
}
if (case_timeout_occurred) {
raise_failure(failure_reason_t(REASON_TIMEOUT | ((case_control.repeat & REPEAT_ON_TIMEOUT) ? REASON_IGNORE : 0)));
scheduler.post(schedule_next_case, 0);
}
}
void Harness::validate_callback(const control_t control)
{
UTEST_ENTER_CRITICAL_SECTION;
case_validation_count++;
if (case_timeout_handle != NULL || case_control.timeout == TIMEOUT_FOREVER)
{
scheduler.cancel(case_timeout_handle);
case_timeout_handle = NULL;
control_t merged_control = case_control + control;
case_control.repeat = repeat_t(merged_control.repeat & ~REPEAT_ON_TIMEOUT);
case_control.timeout = TIMEOUT_NONE;
scheduler.post(schedule_next_case, 0);
}
UTEST_LEAVE_CRITICAL_SECTION;
}
bool Harness::is_busy()
{
UTEST_ENTER_CRITICAL_SECTION;
if (!test_cases) return false;
if (!case_current) return false;
bool res = (case_current < (test_cases + test_length));
UTEST_LEAVE_CRITICAL_SECTION;
return res;
}
void Harness::run_next_case()
{
if(case_current < (test_cases + test_length))
{
handlers.case_setup = defaults.get_handler(case_current->setup_handler);
handlers.case_teardown = defaults.get_handler(case_current->teardown_handler);
handlers.case_failure = defaults.get_handler(case_current->failure_handler);
if (case_current->is_empty()) {
location = LOCATION_UNKNOWN;
raise_failure(REASON_EMPTY_CASE);
schedule_next_case();
return;
}
repeat_t setup_repeat;
{
UTEST_ENTER_CRITICAL_SECTION;
case_validation_count = 0;
case_timeout_occurred = false;
setup_repeat = case_control.repeat;
case_control = control_t();
UTEST_LEAVE_CRITICAL_SECTION;
}
if (setup_repeat & REPEAT_SETUP_TEARDOWN) {
location = LOCATION_CASE_SETUP;
if (handlers.case_setup && (handlers.case_setup(case_current, test_index_of_case) != STATUS_CONTINUE)) {
raise_failure(REASON_CASE_SETUP);
schedule_next_case();
return;
}
}
case_failed_before = case_failed;
location = LOCATION_CASE_HANDLER;
if (case_current->handler) {
case_current->handler();
} else if (case_current->control_handler) {
case_control = case_control + case_current->control_handler();
} else if (case_current->repeat_count_handler) {
case_control = case_control + case_current->repeat_count_handler(case_repeat_count);
}
case_repeat_count++;
{
UTEST_ENTER_CRITICAL_SECTION;
if (case_validation_count) case_control.repeat = repeat_t(case_control.repeat & ~REPEAT_ON_TIMEOUT);
// if timeout valid
if (case_control.timeout < TIMEOUT_UNDECLR && case_validation_count == 0) {
// if await validation _with_ timeout
if (case_control.timeout < TIMEOUT_FOREVER) {
case_timeout_handle = scheduler.post(handle_timeout, case_control.timeout);
if (case_timeout_handle == NULL) {
raise_failure(REASON_SCHEDULER);
schedule_next_case();
}
}
}
else {
scheduler.post(schedule_next_case, 0);
}
UTEST_LEAVE_CRITICAL_SECTION;
}
}
else if (handlers.test_teardown) {
location = LOCATION_TEST_TEARDOWN;
handlers.test_teardown(test_passed, test_failed, test_failed ? failure_t(REASON_CASES, LOCATION_UNKNOWN) : failure_t(REASON_NONE));
test_cases = NULL;
exit(test_failed);
} else {
exit(test_failed);
}
}

View File

@ -0,0 +1,138 @@
/****************************************************************************
* Copyright (c) 2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
****************************************************************************
*/
#include "utest/shim.h"
#if UTEST_SHIM_SCHEDULER_USE_MINAR
#include "minar/minar.h"
static int32_t utest_minar_init()
{
return 0;
}
static void *utest_minar_post(const utest_v1_harness_callback_t callback, const uint32_t delay_ms)
{
void *handle = minar::Scheduler::postCallback(callback).delay(minar::milliseconds(delay_ms)).getHandle();
return handle;
}
static int32_t utest_minar_cancel(void *handle)
{
int32_t ret = minar::Scheduler::cancelCallback(handle);
return ret;
}
static int32_t utest_minar_run()
{
return 0;
}
extern "C" {
static const utest_v1_scheduler_t utest_v1_scheduler =
{
utest_minar_init,
utest_minar_post,
utest_minar_cancel,
utest_minar_run
};
utest_v1_scheduler_t utest_v1_get_scheduler()
{
return utest_v1_scheduler;
}
}
#elif UTEST_SHIM_SCHEDULER_USE_US_TICKER
#ifdef YOTTA_MBED_HAL_VERSION_STRING
# include "mbed-hal/us_ticker.h"
#else
# include "us_ticker.h"
#endif
// only one callback is active at any given time
static volatile utest_v1_harness_callback_t minimal_callback;
static volatile utest_v1_harness_callback_t ticker_callback;
static const ticker_data_t *ticker_data;
static ticker_event_t ticker_event;
static void ticker_handler(uint32_t)
{
// printf("\t\t>>> Ticker callback fired for %p.\n", ticker_callback);
minimal_callback = ticker_callback;
}
static int32_t utest_us_ticker_init()
{
ticker_data = get_us_ticker_data();
ticker_set_handler(ticker_data, ticker_handler);
return 0;
}
static void *utest_us_ticker_post(const utest_v1_harness_callback_t callback, const uint32_t delay_ms)
{
// printf("\t\t>>> Schedule %p with %ums delay => %p.\n", callback, (unsigned int)delay_ms, (void*)1);
if (delay_ms) {
ticker_callback = callback;
// fire the interrupt in 1000us * delay_ms
ticker_insert_event(ticker_data, &ticker_event, ticker_read(ticker_data) + delay_ms * 1000, 0);
} else {
minimal_callback = callback;
}
// return a bogus handle
return (void*)1;
}
static int32_t utest_us_ticker_cancel(void *handle)
{
// printf("\t\t>>> Cancel %p => %u\n", handle, (unsigned int)0);
(void) handle;
ticker_remove_event(ticker_data, &ticker_event);
return 0;
}
static int32_t utest_us_ticker_run()
{
while(1)
{
// check if a new callback has been set
if (minimal_callback)
{
// printf("\t\t>>> Firing callback %p\n", minimal_callback);
// copy the callback
utest_v1_harness_callback_t callback = minimal_callback;
// reset the shared callback
minimal_callback = NULL;
// execute the copied callback
callback();
}
}
return 0;
}
extern "C" {
static const utest_v1_scheduler_t utest_v1_scheduler =
{
utest_us_ticker_init,
utest_us_ticker_post,
utest_us_ticker_cancel,
utest_us_ticker_run
};
utest_v1_scheduler_t utest_v1_get_scheduler()
{
return utest_v1_scheduler;
}
}
#endif
#ifdef YOTTA_CORE_UTIL_VERSION_STRING
// their functionality is implemented using the CriticalSectionLock class
void utest_v1_enter_critical_section(void) {}
void utest_v1_leave_critical_section(void) {}
#endif

View File

@ -0,0 +1,116 @@
/****************************************************************************
* Copyright (c) 2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
****************************************************************************
*/
#include "utest/types.h"
const char* utest::v1::stringify(utest::v1::failure_reason_t reason)
{
const char *string;
switch(reason & ~REASON_IGNORE)
{
case REASON_NONE:
string = "Ignored: No Failure";
break;
case REASON_CASES:
string = "Ignored: Test Cases Failed";
break;
case REASON_EMPTY_CASE:
string = "Ignored: Test Case is Empty";
break;
case REASON_TIMEOUT:
string = "Ignored: Timed Out";
break;
case REASON_ASSERTION:
string = "Ignored: Assertion Failed";
break;
case REASON_TEST_SETUP:
string = "Ignored: Test Setup Failed";
break;
case REASON_TEST_TEARDOWN:
string = "Ignored: Test Teardown Failed";
break;
case REASON_CASE_SETUP:
string = "Ignored: Case Setup Failed";
break;
case REASON_CASE_HANDLER:
string = "Ignored: Case Handler Failed";
break;
case REASON_CASE_TEARDOWN:
string = "Ignored: Case Teardown Failed";
break;
case REASON_CASE_INDEX:
string = "Ignored: Case Index Invalid";
break;
case REASON_SCHEDULER:
string = "Ignored: Scheduling Asynchronous Callback Failed";
break;
default:
case REASON_UNKNOWN:
string = "Ignored: Unknown Failure";
break;
}
if (!(reason & REASON_IGNORE)) string += 9;
return string;
}
const char* utest::v1::stringify(utest::v1::failure_t failure)
{
return stringify(failure.reason);
}
const char* utest::v1::stringify(utest::v1::location_t location)
{
const char *string;
switch(location)
{
case LOCATION_TEST_SETUP:
string = "Test Setup Handler";
break;
case LOCATION_TEST_TEARDOWN:
string = "Test Teardown Handler";
break;
case LOCATION_CASE_SETUP:
string = "Case Setup Handler";
break;
case LOCATION_CASE_HANDLER:
string = "Case Handler";
break;
case LOCATION_CASE_TEARDOWN:
string = "Case Teardown Handler";
break;
default:
case LOCATION_UNKNOWN:
string = "Unknown Location";
break;
}
return string;
}
const char* utest::v1::stringify(utest::v1::status_t status)
{
switch(status)
{
case STATUS_CONTINUE:
return "Continue";
case STATUS_IGNORE:
return "Ignore";
case STATUS_ABORT:
return "Abort";
}
return "Unknown Status";
}

View File

@ -0,0 +1,31 @@
/****************************************************************************
* Copyright (c) 2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
****************************************************************************
*/
#include "utest/harness.h"
extern "C"
void utest_unity_assert_failure()
{
utest::v1::Harness::raise_failure(utest::v1::REASON_ASSERTION);
}
extern "C"
void utest_unity_ignore_failure()
{
utest::v1::Harness::raise_failure(utest::v1::failure_reason_t(utest::v1::REASON_ASSERTION | utest::v1::REASON_IGNORE));
}

View File

@ -0,0 +1,129 @@
/****************************************************************************
* Copyright (c) 2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
****************************************************************************
*/
#ifndef UTEST_CASES_H
#define UTEST_CASES_H
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include "types.h"
#include "default_handlers.h"
namespace utest {
namespace v1 {
/** Test case wrapper class.
*
* This class contains the description of the test case and all handlers
* for setting up, running the test case, tearing down and handling failures.
*
* By default you only need to provide a description and a test case handler.
* You may override the setup, teardown and failure handlers, but you do not have to.
* If you do not override these handler, the specified default handlers will be called.
*
* These constructors are overloaded to allow you a comfortable declaration of all your
* callbacks.
* The order is always:
* - description (required)
* - setup handler (optional)
* - test case handler (required)
* - teardown handler (optional)
* - failure handler (optional)
*
* @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
{
public:
// overloads for case_handler_t
Case(const char *description,
const case_setup_handler_t setup_handler,
const case_handler_t case_handler,
const case_teardown_handler_t teardown_handler = default_handler,
const case_failure_handler_t failure_handler = default_handler);
Case(const char *description,
const case_handler_t case_handler,
const case_failure_handler_t failure_handler = default_handler);
Case(const char *description,
const case_handler_t case_handler,
const case_teardown_handler_t teardown_handler,
const case_failure_handler_t failure_handler = default_handler);
// overloads for case_control_handler_t
Case(const char *description,
const case_setup_handler_t setup_handler,
const case_control_handler_t case_handler,
const case_teardown_handler_t teardown_handler = default_handler,
const case_failure_handler_t failure_handler = default_handler);
Case(const char *description,
const case_control_handler_t case_handler,
const case_failure_handler_t failure_handler = default_handler);
Case(const char *description,
const case_control_handler_t case_handler,
const case_teardown_handler_t teardown_handler,
const case_failure_handler_t failure_handler = default_handler);
// overloads for case_call_count_handler_t
Case(const char *description,
const case_setup_handler_t setup_handler,
const case_call_count_handler_t case_handler,
const case_teardown_handler_t teardown_handler = default_handler,
const case_failure_handler_t failure_handler = default_handler);
Case(const char *description,
const case_call_count_handler_t case_handler,
const case_failure_handler_t failure_handler = default_handler);
Case(const char *description,
const case_call_count_handler_t case_handler,
const case_teardown_handler_t teardown_handler,
const case_failure_handler_t failure_handler = default_handler);
/// @returns the textual description of the test case
const char* get_description() const;
/// @returns `true` if setup, test and teardown handlers are set to `ignore_handler`
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;
friend class Harness;
};
} // namespace v1
} // namespace utest
#endif // UTEST_CASES_H

View File

@ -0,0 +1,176 @@
/****************************************************************************
* Copyright (c) 2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
****************************************************************************
*/
#ifndef UTEST_DEFAULT_HANDLER_H
#define UTEST_DEFAULT_HANDLER_H
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include "types.h"
namespace utest {
namespace v1 {
/** Default handler hint.
*
* Use this handler to indicate the you want the default handler to be called.
* This type automatically casts itself into the appropriate handler type, when possible.
* Use the constants to default a handler unambigously.
*/
static const struct
{
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); }
} default_handler;
/** Ignore handler hint.
*
* Use this handler to indicate the you want to ignore this handler and it will not be called.
* This type automatically casts itself into the appropriate handler type, when possible.
* Use the constants to ignore a handler unambigously.
*/
static const struct
{
operator case_handler_t() const { return case_handler_t(NULL); }
operator case_control_handler_t() const { return case_control_handler_t(NULL); }
operator case_call_count_handler_t() const { return case_call_count_handler_t(NULL); }
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); }
} ignore_handler;
/** A table of handlers.
*
* This structure stores all modifyable handlers and provides accessors to
* filter out the default handler.
* So if this structure contains handlers, and you want to use these handlers
* as a default backup, you can use the `get_handler` function to choose the right handler.
*
* Example:
* @code
* const handler_t defaults = { ... }; // your default handlers
* // will return the handler in defaults.
* test_setup_handler_t handler = defaults.get_handler(default_handler);
* // you will still need to manually check the handler before executing it
* if (handler != ignore_handler) handler(...);
*
* extern test_teardown_handler_t custom_handler(...);
* // will return `custom_handler`
* test_teardown_handler_t handler = defaults.get_handler(custom_handler);
* // you will still need to manually check the handler before executing it
* if (handler != ignore_handler) handler(...);
* @endcode
*/
struct handlers_t
{
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;
case_failure_handler_t case_failure;
inline test_setup_handler_t get_handler(test_setup_handler_t handler) const {
if (handler == default_handler) return test_setup;
return handler;
}
inline test_teardown_handler_t get_handler(test_teardown_handler_t handler) const {
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;
return handler;
}
inline case_teardown_handler_t get_handler(case_teardown_handler_t handler) const {
if (handler == default_handler) return case_teardown;
return handler;
}
inline case_failure_handler_t get_handler(case_failure_handler_t handler) const {
if (handler == default_handler) return case_failure;
return handler;
}
};
/// Prints the number of tests to run and continues.
status_t verbose_test_setup_handler (const size_t number_of_cases);
/// Prints the number of tests that passed and failed with a reason if provided.
void verbose_test_teardown_handler(const size_t passed, const size_t failed, const failure_t failure);
/// Prints the failure for `REASON_TEST_SETUP` and `REASON_TEST_TEARDOWN` and then dies.
void verbose_test_failure_handler (const failure_t failure);
/// Prints the index and description of the case being run and continues.
status_t verbose_case_setup_handler (const Case *const source, const size_t index_of_case);
/// Prints the number of tests that passed and failed with a reason if provided within this case and continues.
status_t verbose_case_teardown_handler(const Case *const source, const size_t passed, const size_t failed, const failure_t failure);
/// Prints the reason of the failure and continues, unless the teardown handler failed, for which it aborts.
status_t verbose_case_failure_handler (const Case *const source, const failure_t reason);
/// Requests the start test case from greentea and continues.
status_t greentea_test_setup_handler (const size_t number_of_cases);
/// Reports the test results to greentea.
void greentea_test_teardown_handler(const size_t passed, const size_t failed, const failure_t failure);
/// Reports the failure for `REASON_TEST_SETUP` and `REASON_TEST_TEARDOWN` to greentea and then dies.
void greentea_test_failure_handler (const failure_t failure);
/// Registers the test case setup with greentea.
status_t greentea_case_setup_handler (const Case *const source, const size_t index_of_case);
/// Registers the test case teardown with greentea.
status_t greentea_case_teardown_handler(const Case *const source, const size_t passed, const size_t failed, const failure_t failure);
/// Reports the failure to greentea and then aborts.
status_t greentea_case_failure_abort_handler (const Case *const source, const failure_t reason);
/// Reports the failure to greentea and then continues.
status_t greentea_case_failure_continue_handler(const Case *const source, const failure_t reason);
/// The verbose default handlers that always continue on failure
extern const handlers_t verbose_continue_handlers;
/// The greentea default handlers that always abort on the first encountered failure
extern const handlers_t greentea_abort_handlers;
/// 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;
} // namespace v1
} // namespace utest
#endif // UTEST_DEFAULT_HANDLER_H

View File

@ -0,0 +1,99 @@
/****************************************************************************
* Copyright (c) 2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
****************************************************************************
*/
#ifndef UTEST_HARNESS_H
#define UTEST_HARNESS_H
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include "types.h"
#include "case.h"
#include "default_handlers.h"
#include "specification.h"
#include "scheduler.h"
namespace utest {
namespace v1 {
/** Test Harness.
*
* This class runs a test specification for you and calls all required handlers.
* The harness executes the test specification in an asynchronous fashion, therefore
* `run()` returns immediately.
*
* By default, this harness uses the MINAR scheduler for asynchronous callbacks.
* If you wamt to provide your own custom scheduler, set `config.utest.use_custom_scheduler` to `true`
* inside your yotta config and set a custom scheduler implementation using the `set_scheduler()` function.
* You must set the scheduler before running a specification.
*
* @note In case of an test abort, the harness will busy-wait and never finish.
*/
class Harness
{
public:
/// Runs a test specification
/// @retval `true` if the specification can be run
/// @retval `false` if another specification is currently running
static bool run(const Specification& specification);
/// @cond
__deprecated_message("Start case selection is done by returning the index from the test setup handler!")
static bool run(const Specification& specification, size_t start_case);
/// @endcond
/// @returns `true` if a test specification is being executed, `false` otherwise
static bool is_busy();
/// Sets the scheduler to be used.
/// @return `true` if scheduler is properly specified (all functions non-null).
static bool set_scheduler(utest_v1_scheduler_t scheduler);
/** Call this function in the asynchronous callback that you have been waiting for.
*
* You can only validate a callback once, calling this function when no callback is expected
* has no side effects.
* After callback validation, the next test case is scheduled.
*
* You may specify additional test case attributes with this callback.
* So for example, you may delay the decision to repeat an asynchronous test case until the callback
* needs to be validated.
*
* However, be aware, that only the repeat attributes can be modified and the usual arbitration rules apply.
* The modified case attributes are only valid until the case handler returns updated attributes.
*
* @param control the test case attribute to be added to the existing attributes.
*/
static void validate_callback(const control_t control = control_t());
/// Raising a failure causes the failure to be counted and the failure handler to be called.
/// Further action then depends on its return state.
static void raise_failure(const failure_reason_t reason);
protected:
static void run_next_case();
static void handle_timeout();
static void schedule_next_case();
};
} // namespace v1
} // namespace utest
#endif // UTEST_HARNESS_H

View File

@ -0,0 +1,103 @@
/****************************************************************************
* Copyright (c) 2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
****************************************************************************
*/
#ifndef UTEST_SCHEDULER_H
#define UTEST_SCHEDULER_H
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* The utest harness manages its own state and therefore does not require the scheduler to
* bind any arguments to the scheduled callback.
*/
typedef void (*utest_v1_harness_callback_t)(void);
/**
* utest calls this function before running the test specification.
* Use this function to initialize your scheduler before the first callback is requested.
*
* @retval `0` if success
* @retval non-zero if failure
*/
typedef int32_t (*utest_v1_scheduler_init_callback_t)(void);
/**
* utest calls this function when it needs to schedule a callback with a delay in milliseconds.
* `delay_ms` will only be non-zero if an asynchronous test case exists in the test specification.
* @note If your scheduler cannot provide asynchronous callbacks (which probably require a hardware timer),
* then this scheduler may return `NULL` as a handle and `utest` will fail the asynchronous request and move on.
* Note that test cases which do not require asynchronous callback support will still work fine then.
*
* @warning You MUST NOT execute the callback inside this function, even for a delay of 0ms.
* Buffer the callback and call it in your main loop.
* @warning You MUST NOT execute the callback in an interrupt context!
* Buffer the callback and call it in your main loop.
* @note utest only schedules one callback at any given time.
* This should make the implementation of this scheduler a lot simpler for you.
*
* @param callback the pointer to the callback function
* @param delay_ms the delay in milliseconds after which the callback should be executed
* @return A handle to identify the scheduled callback, or `NULL` for failure.
*/
typedef void *(*utest_v1_scheduler_post_callback_t)(const utest_v1_harness_callback_t callback, const uint32_t delay_ms);
/**
* utest needs to cancel callbacks with a non-zero delay some time later.
* Even though `utest` only schedules one callback at any given time, it can cancel a callback more than once.
* You should therefore make use of the handle to make sure you do not cancel the wrong callback.
*
* @note If your scheduler cannot provide asynchronous callbacks, do nothing in this function and return non-zero.
*
* @param handle the handle returned from the `post` call to identify which callback to be cancelled.
* @retval `0` if success
* @retval non-zero if failure
*/
typedef int32_t (*utest_v1_scheduler_cancel_callback_t)(void *handle);
/**
* utest calls this function at the end of the `Harness::run()` function, after (!) the first callback has been requested.
* This function is meant to implement an optional event loop, which may very well be blocking (if your scheduler works with that).
* This assumes that `Harness::run()` will be called on the main stack (ie. not in an interrupt!).
*
* @retval `0` if success
* @retval non-zero if failure
*/
typedef int32_t (*utest_v1_scheduler_run_callback_t)(void);
/**
* The scheduler interface consists out of the `post` and `cancel` functions,
* which you must implement to use `utest`.
*/
typedef struct {
utest_v1_scheduler_init_callback_t init;
utest_v1_scheduler_post_callback_t post;
utest_v1_scheduler_cancel_callback_t cancel;
utest_v1_scheduler_run_callback_t run;
} utest_v1_scheduler_t;
#ifdef __cplusplus
}
#endif
#endif // UTEST_SCHEDULER_H

View File

@ -0,0 +1,85 @@
/****************************************************************************
* Copyright (c) 2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
****************************************************************************
*/
#ifndef UTEST_SHIM_H
#define UTEST_SHIM_H
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include "scheduler.h"
#ifdef YOTTA_CFG
# include "compiler-polyfill/attributes.h"
#else
# ifndef __deprecated_message
# if defined(__CC_ARM)
# define __deprecated_message(msg) __attribute__((deprecated))
# else
# define __deprecated_message(msg) __attribute__((deprecated(msg)))
# endif
# endif
#endif
#ifdef YOTTA_CORE_UTIL_VERSION_STRING
# include "core-util/CriticalSectionLock.h"
# define UTEST_ENTER_CRITICAL_SECTION mbed::util::CriticalSectionLock lock
# define UTEST_LEAVE_CRITICAL_SECTION
#else
# ifndef UTEST_ENTER_CRITICAL_SECTION
# define UTEST_ENTER_CRITICAL_SECTION utest_v1_enter_critical_section()
# endif
# ifndef UTEST_LEAVE_CRITICAL_SECTION
# define UTEST_LEAVE_CRITICAL_SECTION utest_v1_leave_critical_section()
# endif
#endif
#ifndef YOTTA_CFG_UTEST_USE_CUSTOM_SCHEDULER
# ifdef YOTTA_MINAR_VERSION_STRING
# define UTEST_MINAR_AVAILABLE 1
# else
# define UTEST_MINAR_AVAILABLE 0
# endif
# ifndef UTEST_SHIM_SCHEDULER_USE_MINAR
# define UTEST_SHIM_SCHEDULER_USE_MINAR UTEST_MINAR_AVAILABLE
# endif
# ifndef UTEST_SHIM_SCHEDULER_USE_US_TICKER
# ifdef __MBED__
# define UTEST_SHIM_SCHEDULER_USE_US_TICKER 1
# else
# define UTEST_SHIM_SCHEDULER_USE_US_TICKER 0
# endif
# endif
#endif // YOTTA_CFG_UTEST_USE_CUSTOM_SCHEDULER
#ifdef __cplusplus
extern "C" {
#endif
/// must be implemented by the port
void utest_v1_enter_critical_section(void);
void utest_v1_leave_critical_section(void);
/// This is the default scheduler implementation used by the harness.
utest_v1_scheduler_t utest_v1_get_scheduler(void);
#ifdef __cplusplus
}
#endif
#endif // UTEST_SHIM_H

View File

@ -0,0 +1,139 @@
/****************************************************************************
* Copyright (c) 2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
****************************************************************************
*/
#ifndef UTEST_SPECIFICATION_H
#define UTEST_SPECIFICATION_H
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include "types.h"
#include "case.h"
#include "default_handlers.h"
namespace utest {
namespace v1 {
/** Test specification containing the setup and teardown handlers and test cases.
*
* This class simply holds the test cases and allows you to specify default handlers, and
* override setup and teardown handlers.
* The order of arguments is:
* - test setup handler (optional)
* - array of test cases (required)
* - test teardown handler (optional)
* - default handlers (optional)
*
* @note You cannot set the size of the test case array dynamically, it is template deducted at compile
* time. Creating test specifications for unittests at runtime is explicitly not supported.
*/
class Specification
{
public:
template< size_t N >
Specification(const Case (&cases)[N],
const handlers_t defaults = default_handlers) :
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 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)
{}
template< size_t N >
Specification(const test_setup_handler_t setup_handler,
const Case (&cases)[N],
const handlers_t defaults = default_handlers) :
setup_handler(setup_handler), teardown_handler(default_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_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)
{}
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;
friend class Harness;
};
} // namespace v1
} // namespace utest
#endif // UTEST_SPECIFICATION_H

View File

@ -0,0 +1,354 @@
/****************************************************************************
* Copyright (c) 2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
****************************************************************************
*/
#ifndef UTEST_TYPES_H
#define UTEST_TYPES_H
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include "shim.h"
namespace utest {
namespace v1 {
enum repeat_t {
REPEAT_UNDECLR = 0,
REPEAT_NONE = 1, ///< continue with the next test case
REPEAT_ON_TIMEOUT = 2,
REPEAT_ON_VALIDATE = 4,
REPEAT_CASE_ONLY = 8,
REPEAT_SETUP_TEARDOWN = 16,
REPEAT_MASK = REPEAT_ON_TIMEOUT | REPEAT_ON_VALIDATE | REPEAT_CASE_ONLY | REPEAT_SETUP_TEARDOWN,
REPEAT_ALL_ON_TIMEOUT = REPEAT_SETUP_TEARDOWN | REPEAT_ON_TIMEOUT, ///< repeat the handler with setup and teardown on timeout
REPEAT_HANDLER_ON_TIMEOUT = REPEAT_CASE_ONLY | REPEAT_ON_TIMEOUT, ///< repeat only the handler on timeout
REPEAT_ALL = REPEAT_SETUP_TEARDOWN | REPEAT_ON_VALIDATE, ///< repeat the handler with setup and teardown
REPEAT_HANDLER = REPEAT_CASE_ONLY | REPEAT_ON_VALIDATE ///< repeat only the handler
};
enum status_t {
STATUS_CONTINUE = -1, ///< continues testing
STATUS_IGNORE = -2, ///< ignores failure and continues testing
STATUS_ABORT = -3 ///< stops testing
};
enum failure_reason_t {
REASON_NONE = 0, ///< No failure occurred
REASON_UNKNOWN = (1 << 0), ///< An unknown failure occurred
REASON_CASES = (1 << 1), ///< A failure occurred in at least one test case
REASON_EMPTY_CASE = (1 << 2), ///< The test case contains only empty handlers
REASON_TIMEOUT = (1 << 3), ///< An expected asynchronous call timed out
REASON_ASSERTION = (1 << 4), ///< An assertion failed
REASON_TEST_SETUP = (1 << 5), ///< Test setup failed
REASON_TEST_TEARDOWN = (1 << 6), ///< Test teardown failed
REASON_CASE_SETUP = (1 << 7), ///< Case setup failed
REASON_CASE_HANDLER = (1 << 8), ///< Case handler failed
REASON_CASE_TEARDOWN = (1 << 9), ///< Case teardown failed
REASON_CASE_INDEX = (1 << 10), ///< Case index out-of-range
REASON_SCHEDULER = (1 << 11), ///< Asynchronous callback scheduling failed
REASON_IGNORE = 0x8000 ///< The failure may be ignored
};
enum location_t {
LOCATION_NONE = 0, ///< No location information
LOCATION_TEST_SETUP, ///< A failure occurred in the test setup
LOCATION_TEST_TEARDOWN, ///< A failure occurred in the test teardown
LOCATION_CASE_SETUP, ///< A failure occurred in the case setup
LOCATION_CASE_HANDLER, ///< A failure occurred in the case handler
LOCATION_CASE_TEARDOWN, ///< A failure occurred in the case teardown
LOCATION_UNKNOWN ///< A failure occurred in an unknown location
};
/// Contains the reason and location of the failure.
struct failure_t {
failure_t() : reason(REASON_NONE), location(LOCATION_NONE) {}
failure_t(failure_reason_t reason) : reason(reason), location(LOCATION_NONE) {}
failure_t(location_t location) : reason(REASON_NONE), location(location) {}
failure_t(failure_reason_t reason, location_t location) : reason(reason), location(location) {}
/// @returns a copy of the failure with the reason ignored.
failure_t ignored() const {
return failure_t(failure_reason_t(reason | REASON_IGNORE), location);
}
failure_reason_t reason;
location_t location;
};
enum {
TIMEOUT_NONE = uint32_t(-1), ///< Do not use a timeout
TIMEOUT_UNDECLR = uint32_t(-2), ///< Timeout not explicitly specified, defaults to NONE
TIMEOUT_FOREVER = uint32_t(-3) ///< Never time out
};
/// Stringifies a failure reason for understandable error messages.
const char* stringify(failure_reason_t reason);
/// Stringifies a failure for understandable error messages.
const char* stringify(failure_t failure);
/// Stringifies a location.
const char* stringify(location_t location);
/// Stringifies a status.
const char* stringify(status_t status);
/** Control class for specifying test case attributes
*
* This class encapsulated control information about test cases which, when returned from
* a test case influences the behavior of the test harness.
* Instead of using this class directly it is recommended to use the aliases for clearer
* semantics:
* @code
* control_t test_case(const size_t call_count) {
* // repeat 5 times for a total of 6 calls
* return (call_count < 6) ? CaseRepeatHandler : CaseNext;
* }
* @endcode
*
* This class overloads the `+` operator to implement something similiar to saturated arbitration:
* - The lower timeout value "wins".
* - A more involved repeat "wins" (ie. `ALL` > 'HANDLER' > 'NONE').
* - Next Case always wins.
*
* You may then add timeouts and repeats together:
* @code
* control_t test_case(const size_t call_count) {
* // repeat 5 times for a total of 6 calls, each with a 500ms asynchronous timeout
* return CaseTimeout(500) + ((call_count < 6) ? CaseRepeatAll : CaseNoRepeat);
* }
* @endcode
*
* In the future, more control information may be added transparently and backwards compatible.
*/
struct control_t
{
control_t() : repeat(REPEAT_UNDECLR), timeout(TIMEOUT_UNDECLR) {}
control_t(repeat_t repeat, uint32_t timeout_ms) :
repeat(repeat), timeout(timeout_ms) {}
control_t(repeat_t repeat) :
repeat(repeat), timeout(TIMEOUT_UNDECLR) {}
control_t(uint32_t timeout_ms) :
repeat(REPEAT_UNDECLR), timeout(timeout_ms) {}
control_t
inline operator+(const control_t& rhs) const {
control_t result(
repeat_t(this->repeat | rhs.repeat),
(rhs.timeout == TIMEOUT_NONE) ? rhs.timeout : this->timeout);
if (result.timeout != TIMEOUT_NONE && result.timeout > rhs.timeout) {
result.timeout = rhs.timeout;
}
if (result.repeat & REPEAT_NONE) {
result.repeat = REPEAT_NONE;
}
else {
if (result.repeat & REPEAT_SETUP_TEARDOWN) {
result.repeat = repeat_t(result.repeat & ~REPEAT_CASE_ONLY);
}
if (result.timeout == TIMEOUT_NONE && result.repeat & REPEAT_ON_TIMEOUT) {
result.repeat = repeat_t(result.repeat & ~REPEAT_ON_TIMEOUT);
}
}
return result;
}
repeat_t
inline get_repeat() const {
return repeat;
}
uint32_t
inline get_timeout() const {
return timeout;
}
private:
repeat_t repeat;
uint32_t timeout;
friend class Harness;
};
/// does not repeat this test case and immediately moves on to the next one without timeout
const control_t CaseNext(REPEAT_NONE, TIMEOUT_NONE);
/// does not repeat this test case, moves on to the next one
const control_t CaseNoRepeat(REPEAT_NONE);
/// repeats the test case handler with calling teardown and setup handlers
const control_t CaseRepeatAll(REPEAT_ALL);
/// repeats only the test case handler without calling teardown and setup handlers
const control_t CaseRepeatHandler(REPEAT_HANDLER);
/// No timeout, immediately moves on to the next case, but allows repeats
const control_t CaseNoTimeout(TIMEOUT_NONE);
/// Awaits until the callback is validated and never times out. Use with caution!
const control_t CaseAwait(TIMEOUT_FOREVER);
/// Alias class for asynchronous timeout control in milliseconds
inline control_t CaseTimeout(uint32_t ms) { return ms; }
/// Alias class for asynchronous timeout control in milliseconds and
/// repeats the test case handler with calling teardown and setup handlers
inline control_t CaseRepeatAllOnTimeout(uint32_t ms) { return control_t(REPEAT_ALL_ON_TIMEOUT, ms); }
/// Alias class for asynchronous timeout control in milliseconds and
/// repeats only the test case handler without calling teardown and setup handlers
inline control_t CaseRepeatHandlerOnTimeout(uint32_t ms) { return control_t(REPEAT_HANDLER_ON_TIMEOUT, ms); }
class Case; // forward declaration
/** Test setup handler.
*
* This handler is called before execution of any test case and
* allows you to initialize your common test environment.
*
* @param number_of_cases the total number of test cases in the test specification
*
* @returns
* You can return `STATUS_ABORT` if you initialization failed and the test teardown handler will
* then be called with the `REASON_SETUP`.
*/
typedef status_t (*test_setup_handler_t)(const size_t number_of_cases);
/** Test teardown handler.
*
* This handler is called after execution of all test case or if test execution is aborted.
* You can use this handler to de-initialize your test environment and output test statistics.
* The failure argument contains the immediate reason why this handler is called.
* If the test completed normally without failures, this will contain `REASON_NONE`.
*
* After execution of this handler, the test harness will stop execution.
*
* @param passed the number of cases without failures
* @param failed the number of cases with at least one failure
* @param failure the reason why this handler was called
*/
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
* allows you to modify your environment before each test case.
*
* @param source the test case to be setup
* @param index_of_case the current index of the test case within the specification
*
* @returns
* You can return `STATUS_ABORT` to indicate that your setup failed, which will call the case
* failure handler with `REASON_SETUP` and then the case teardown handler with `REASON_SETUP`.
* This gives the teardown handler a chance to clean up a failed setup.
*/
typedef status_t (*case_setup_handler_t)(const Case *const source, const size_t index_of_case);
/** Primitive test case handler
*
* This handler is called only if the case setup succeeded and is followed by the test case teardown handler.
*
* @note This handler is executed only once.
*/
typedef void (*case_handler_t)(void);
/** Complex test case handler
*
* This handler is called only if the case setup succeeded and then may be repeated or
* awaiting a asynchronous callback, depending on the return modifiers.
*
* @returns
* A combination of control modifiers.
*/
typedef control_t (*case_control_handler_t)(void);
/** Test case handler (repeatable)
*
* This handler is called only if the case setup succeeded and then may be repeated or
* awaiting a asynchronous callback, depending on the return modifiers.
*
* @param call_count starting at `1`, contains the number of times this handler has been called
*
* @returns
* A combination of control modifiers.
*/
typedef control_t (*case_call_count_handler_t)(const size_t call_count);
/** Test case teardown handler.
*
* This handler is called after execution of each test case or all repeated test cases and
* allows you to reset your environment after each test case.
*
* @param source the test case to be torn down
* @param passed the number of cases without failures (can be >1 for repeated test cases)
* @param failed the number failures (can be larger than the number of (repeated) test cases)
* @param failure the reason why this handler was called
*
* @returns
* You can return `STATUS_ABORT` to indicate that your teardown failed, which will call the case
* failure handler with `REASON_TEARDOWN`.
*/
typedef status_t (*case_teardown_handler_t)(const Case *const source, const size_t passed, const size_t failed, const failure_t reason);
/** Test case failure handler.
*
* This handler is called whenever a failure occurred during the setup, execution or teardown.
*
* @param source the test case in which the failure occurred
* @param reason the reason why this handler was called
*
* @returns
* You can return `STATUS_ABORT` to indicate that this failure is non-recoverable, which will call the case
* teardown handler with reason. If a failure occurs during teardown, the teardown will not be called again.
* You may return `STATUS_IGNORE` which will cause the harness to ignore and not count the failure.
*/
typedef status_t (*case_failure_handler_t)(const Case *const source, const failure_t reason);
// deprecations
__deprecated_message("Use CaseRepeatAll instead.") const control_t CaseRepeat = CaseRepeatAll;
__deprecated_message("Use CaseRepeatHandler instead.") const control_t CaseRepeatHandlerOnly = CaseRepeatHandler;
__deprecated_message("Use REASON_NONE instead.") const failure_reason_t FAILURE_NONE = REASON_NONE;
__deprecated_message("Use REASON_UNKNOWN instead.") const failure_reason_t FAILURE_UNKNOWN = REASON_UNKNOWN;
__deprecated_message("Use REASON_CASES instead.") const failure_reason_t FAILURE_CASES = REASON_CASES;
__deprecated_message("Use REASON_EMPTY_CASE instead.") const failure_reason_t FAILURE_EMPTY_CASE = REASON_EMPTY_CASE;
__deprecated_message("Use REASON_TIMEOUT instead.") const failure_reason_t FAILURE_TIMEOUT = REASON_TIMEOUT;
__deprecated_message("Use REASON_ASSERTION instead.") const failure_reason_t FAILURE_ASSERTION = REASON_ASSERTION;
__deprecated_message("Use REASON_CASE_SETUP instead.") const failure_reason_t FAILURE_SETUP = REASON_CASE_SETUP;
__deprecated_message("Use REASON_CASE_TEARDOWN instead.") const failure_reason_t FAILURE_TEARDOWN = REASON_CASE_TEARDOWN;
__deprecated_message("Use REASON_IGNORE instead.") const failure_reason_t FAILURE_IGNORE = REASON_IGNORE;
} // namespace v1
} // namespace utest
#endif // UTEST_TYPES_H

View File

@ -0,0 +1,30 @@
/****************************************************************************
* Copyright (c) 2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
****************************************************************************
*/
#ifndef UTEST_UNITY_ASSERT_FAILURE_H
#define UTEST_UNITY_ASSERT_FAILURE_H
#include <stdint.h>
/// this function is called from the unity module when an assertion failed.
void utest_unity_assert_failure();
/// this function is called from the unity module when an assertion failed, but is ignored.
void utest_unity_ignore_failure();
#endif // UTEST_UNITY_ASSERT_FAILURE_H

View File

@ -0,0 +1,28 @@
/****************************************************************************
* Copyright (c) 2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
****************************************************************************
*/
#ifndef UTEST_H
#define UTEST_H
#include "types.h"
#include "case.h"
#include "default_handlers.h"
#include "harness.h"
#endif // UTEST_H