Skip to content

Commit 878ce59

Browse files
committed
Updated utest ticker scheduler to use the c++ Timeout class rather than
the C based function calls directly into ticker. Added a software based backtrace functionality, plus utest instrumentation using that functionality.
1 parent 27c6721 commit 878ce59

File tree

8 files changed

+181
-15
lines changed

8 files changed

+181
-15
lines changed

frameworks/utest/source/default_handlers.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
#include "utest/default_handlers.h"
2020
#include "utest/case.h"
21+
#include "utest/stack_trace.h"
22+
2123

2224
using namespace utest::v1;
2325

@@ -35,6 +37,7 @@ const handlers_t utest::v1::verbose_continue_handlers = {
3537

3638
// --- SPECIAL HANDLERS ---
3739
static void test_failure_handler(const failure_t failure) {
40+
UTEST_LOG_FUNCTION
3841
if (failure.location == LOCATION_TEST_SETUP || failure.location == LOCATION_TEST_TEARDOWN) {
3942
verbose_test_failure_handler(failure);
4043
printf("{{failure}}\n{{end}}\n");
@@ -45,12 +48,14 @@ static void test_failure_handler(const failure_t failure) {
4548
// --- VERBOSE TEST HANDLERS ---
4649
status_t utest::v1::verbose_test_setup_handler(const size_t number_of_cases)
4750
{
51+
UTEST_LOG_FUNCTION
4852
printf(">>> Running %u test cases...\n", number_of_cases);
4953
return STATUS_CONTINUE;
5054
}
5155

5256
void utest::v1::verbose_test_teardown_handler(const size_t passed, const size_t failed, const failure_t failure)
5357
{
58+
UTEST_LOG_FUNCTION
5459
printf("\n>>> Test cases: %u passed, %u failed", passed, failed);
5560
if (failure.reason == REASON_NONE) {
5661
printf("\n");
@@ -63,17 +68,20 @@ void utest::v1::verbose_test_teardown_handler(const size_t passed, const size_t
6368
void utest::v1::verbose_test_failure_handler(const failure_t failure)
6469
{
6570
printf(">>> failure with reason '%s' during '%s'\n", stringify(failure.reason), stringify(failure.location));
71+
6672
}
6773

6874
// --- VERBOSE CASE HANDLERS ---
6975
status_t utest::v1::verbose_case_setup_handler(const Case *const source, const size_t index_of_case)
7076
{
77+
UTEST_LOG_FUNCTION
7178
printf("\n>>> Running case #%u: '%s'...\n", index_of_case + 1, source->get_description());
7279
return STATUS_CONTINUE;
7380
}
7481

7582
status_t utest::v1::verbose_case_teardown_handler(const Case *const source, const size_t passed, const size_t failed, const failure_t failure)
7683
{
84+
UTEST_LOG_FUNCTION
7785
printf(">>> '%s': %u passed, %u failed", source->get_description(), passed, failed);
7886
if (failure.reason == REASON_NONE) {
7987
printf("\n");
@@ -85,6 +93,7 @@ status_t utest::v1::verbose_case_teardown_handler(const Case *const source, cons
8593

8694
status_t utest::v1::verbose_case_failure_handler(const Case *const /*source*/, const failure_t failure)
8795
{
96+
UTEST_LOG_FUNCTION
8897
if (!(failure.reason & REASON_ASSERTION)) {
8998
verbose_test_failure_handler(failure);
9099
}

frameworks/utest/source/greentea_handlers.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "utest/default_handlers.h"
2020
#include "utest/case.h"
2121
#include "greentea-client/test_env.h"
22+
#include "utest/stack_trace.h"
2223

2324
using namespace utest::v1;
2425

@@ -57,23 +58,27 @@ const handlers_t utest::v1::selftest_handlers = {
5758

5859
// --- SPECIAL HANDLERS ---
5960
static status_t unknown_test_setup_handler(const size_t) {
61+
UTEST_LOG_FUNCTION
6062
printf(">>> I do not know how to tell greentea that the test started, since\n");
6163
printf(">>> you forgot to override the `test_setup_handler` in your specification.\n");
6264

6365
return STATUS_ABORT;
6466
}
6567

6668
static void selftest_failure_handler(const failure_t failure) {
69+
UTEST_LOG_FUNCTION
6770
if (failure.location == LOCATION_TEST_SETUP || failure.location == LOCATION_TEST_TEARDOWN || failure.reason == REASON_ASSERTION) {
6871
verbose_test_failure_handler(failure);
6972
}
7073
if (failure.reason == REASON_ASSERTION) {
74+
UTEST_DUMP_TRACE
7175
GREENTEA_TESTSUITE_RESULT(false);
7276
while(1) ;
7377
}
7478
}
7579

7680
static void test_failure_handler(const failure_t failure) {
81+
UTEST_LOG_FUNCTION
7782
if (failure.location == LOCATION_TEST_SETUP || failure.location == LOCATION_TEST_TEARDOWN) {
7883
verbose_test_failure_handler(failure);
7984
GREENTEA_TESTSUITE_RESULT(false);
@@ -84,12 +89,14 @@ static void test_failure_handler(const failure_t failure) {
8489
// --- GREENTEA HANDLERS ---
8590
status_t utest::v1::greentea_test_setup_handler(const size_t number_of_cases)
8691
{
92+
UTEST_LOG_FUNCTION
8793
greentea_send_kv(TEST_ENV_TESTCASE_COUNT, number_of_cases);
8894
return verbose_test_setup_handler(number_of_cases);
8995
}
9096

9197
void utest::v1::greentea_test_teardown_handler(const size_t passed, const size_t failed, const failure_t failure)
9298
{
99+
UTEST_LOG_FUNCTION
93100
verbose_test_teardown_handler(passed, failed, failure);
94101
greentea_send_kv(TEST_ENV_TESTCASE_SUMMARY, passed, failed);
95102
int result = !(failed || (failure.reason && !(failure.reason & REASON_IGNORE)));
@@ -98,30 +105,35 @@ void utest::v1::greentea_test_teardown_handler(const size_t passed, const size_t
98105

99106
void utest::v1::greentea_test_failure_handler(const failure_t failure)
100107
{
108+
UTEST_LOG_FUNCTION
101109
verbose_test_failure_handler(failure);
102110
}
103111

104112
// --- GREENTEA CASE HANDLERS ---
105113
status_t utest::v1::greentea_case_setup_handler(const Case *const source, const size_t index_of_case)
106114
{
115+
UTEST_LOG_FUNCTION
107116
status_t status = verbose_case_setup_handler(source, index_of_case);
108117
greentea_send_kv(TEST_ENV_TESTCASE_START, source->get_description());
109118
return status;
110119
}
111120

112121
status_t utest::v1::greentea_case_teardown_handler(const Case *const source, const size_t passed, const size_t failed, const failure_t failure)
113122
{
123+
UTEST_LOG_FUNCTION
114124
greentea_send_kv(TEST_ENV_TESTCASE_FINISH, source->get_description(), passed, failed);
115125
return verbose_case_teardown_handler(source, passed, failed, failure);
116126
}
117127

118128
status_t utest::v1::greentea_case_failure_abort_handler(const Case *const source, const failure_t failure)
119129
{
130+
UTEST_LOG_FUNCTION
120131
status_t status = verbose_case_failure_handler(source, failure);
121132
return (status == STATUS_IGNORE) ? STATUS_IGNORE : STATUS_ABORT;
122133
}
123134

124135
status_t utest::v1::greentea_case_failure_continue_handler(const Case *const source, const failure_t failure)
125136
{
137+
UTEST_LOG_FUNCTION
126138
return verbose_case_failure_handler(source, failure);
127139
}

frameworks/utest/source/harness.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
*/
1818

1919
#include "utest/harness.h"
20+
#include "utest/stack_trace.h"
21+
2022
#include <stdlib.h>
2123

2224
using namespace utest::v1;
@@ -53,16 +55,19 @@ namespace
5355
}
5456

5557
static void die() {
58+
UTEST_LOG_FUNCTION
5659
while(1) ;
5760
}
5861

5962
static bool is_scheduler_valid(const utest_v1_scheduler_t scheduler)
6063
{
64+
UTEST_LOG_FUNCTION
6165
return (scheduler.init && scheduler.post && scheduler.cancel && scheduler.run);
6266
}
6367

6468
bool Harness::set_scheduler(const utest_v1_scheduler_t scheduler)
6569
{
70+
UTEST_LOG_FUNCTION
6671
if (is_scheduler_valid(scheduler)) {
6772
::scheduler = scheduler;
6873
return true;
@@ -72,11 +77,13 @@ bool Harness::set_scheduler(const utest_v1_scheduler_t scheduler)
7277

7378
bool Harness::run(const Specification& specification, size_t)
7479
{
80+
UTEST_LOG_FUNCTION
7581
return run(specification);
7682
}
7783

7884
bool Harness::run(const Specification& specification)
7985
{
86+
UTEST_LOG_FUNCTION
8087
// check if a specification is currently running
8188
if (is_busy())
8289
return false;
@@ -142,6 +149,7 @@ bool Harness::run(const Specification& specification)
142149

143150
void Harness::raise_failure(const failure_reason_t reason)
144151
{
152+
UTEST_LOG_FUNCTION
145153
// ignore a failure, if the Harness has not been initialized.
146154
// this allows using unity assertion macros without setting up utest.
147155
if (test_cases == NULL) return;
@@ -187,6 +195,7 @@ void Harness::raise_failure(const failure_reason_t reason)
187195

188196
void Harness::schedule_next_case()
189197
{
198+
UTEST_LOG_FUNCTION
190199
if (!case_timeout_occurred && case_failed_before == case_failed) {
191200
case_passed++;
192201
}
@@ -195,6 +204,7 @@ void Harness::schedule_next_case()
195204
location = LOCATION_CASE_TEARDOWN;
196205

197206
if (handlers.case_teardown) {
207+
// printf("Schedule next case: case_passed = %d, case_failed = %d\n", case_passed, case_failed);
198208
status_t status = handlers.case_teardown(case_current, case_passed, case_failed,
199209
case_failed ? failure_t(REASON_CASES, LOCATION_UNKNOWN) : failure_t(REASON_NONE));
200210
if (status < STATUS_CONTINUE) raise_failure(REASON_CASE_TEARDOWN);
@@ -221,6 +231,7 @@ void Harness::schedule_next_case()
221231

222232
void Harness::handle_timeout()
223233
{
234+
UTEST_LOG_FUNCTION
224235
{
225236
UTEST_ENTER_CRITICAL_SECTION;
226237

@@ -238,11 +249,14 @@ void Harness::handle_timeout()
238249

239250
void Harness::validate_callback(const control_t control)
240251
{
252+
UTEST_LOG_FUNCTION
241253
UTEST_ENTER_CRITICAL_SECTION;
242254
case_validation_count++;
243255

256+
// printf("validate_callback: case_validation_count = %d\n", case_validation_count);
244257
if (case_timeout_handle != NULL || case_control.timeout == TIMEOUT_FOREVER)
245258
{
259+
// printf("Cancelling scheduled callback\n");
246260
scheduler.cancel(case_timeout_handle);
247261
case_timeout_handle = NULL;
248262
control_t merged_control = case_control + control;
@@ -255,6 +269,7 @@ void Harness::validate_callback(const control_t control)
255269

256270
bool Harness::is_busy()
257271
{
272+
UTEST_LOG_FUNCTION
258273
UTEST_ENTER_CRITICAL_SECTION;
259274
if (!test_cases) return false;
260275
if (!case_current) return false;
@@ -266,6 +281,7 @@ bool Harness::is_busy()
266281

267282
void Harness::run_next_case()
268283
{
284+
UTEST_LOG_FUNCTION
269285
if(case_current < (test_cases + test_length))
270286
{
271287
handlers.case_setup = defaults.get_handler(case_current->setup_handler);

frameworks/utest/source/shim.cpp

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
*/
1818

1919
#include "utest/shim.h"
20+
#include "utest/stack_trace.h"
2021

2122
#if UTEST_SHIM_SCHEDULER_USE_MINAR
2223
#include "minar/minar.h"
@@ -57,55 +58,66 @@ utest_v1_scheduler_t utest_v1_get_scheduler()
5758
#ifdef YOTTA_MBED_HAL_VERSION_STRING
5859
# include "mbed-hal/us_ticker_api.h"
5960
#else
60-
# include "us_ticker_api.h"
61+
# include "mbed.h"
6162
#endif
6263
// only one callback is active at any given time
6364
static volatile utest_v1_harness_callback_t minimal_callback;
6465
static volatile utest_v1_harness_callback_t ticker_callback;
65-
static const ticker_data_t *ticker_data;
66-
static ticker_event_t ticker_event;
6766

68-
static void ticker_handler(uint32_t)
67+
// Timeout object used to control the scheduling of test case callbacks
68+
Timeout utest_timeout_object;
69+
70+
static void ticker_handler()
6971
{
70-
// printf("\t\t>>> Ticker callback fired for %p.\n", ticker_callback);
72+
UTEST_LOG_FUNCTION
73+
//printf("\t\t>>> Ticker callback fired for %p.\n", ticker_callback);
7174
minimal_callback = ticker_callback;
7275
}
7376

7477
static int32_t utest_us_ticker_init()
7578
{
76-
ticker_data = get_us_ticker_data();
77-
ticker_set_handler(ticker_data, ticker_handler);
79+
UTEST_LOG_FUNCTION
80+
// Ticker scheduler does not require any initialisation so return immediately
7881
return 0;
7982
}
80-
static void *utest_us_ticker_post(const utest_v1_harness_callback_t callback, const uint32_t delay_ms)
83+
static void *utest_us_ticker_post(const utest_v1_harness_callback_t callback, timestamp_t delay_ms)
8184
{
82-
// printf("\t\t>>> Schedule %p with %ums delay => %p.\n", callback, (unsigned int)delay_ms, (void*)1);
85+
UTEST_LOG_FUNCTION
86+
timestamp_t delay_us = delay_ms *1000;
87+
88+
//printf("\t\t>>> Schedule %p with %ums delay => %p.\n", callback, (unsigned int)delay_ms, (void*)1);
8389
if (delay_ms) {
8490
ticker_callback = callback;
8591
// fire the interrupt in 1000us * delay_ms
86-
ticker_insert_event(ticker_data, &ticker_event, ticker_read(ticker_data) + delay_ms * 1000, 0);
87-
} else {
92+
utest_timeout_object.attach_us(ticker_handler, delay_us);
93+
94+
}
95+
else {
8896
minimal_callback = callback;
8997
}
9098

99+
//printf("Minimal callback = %p, ticker_callback = %p\n", minimal_callback, ticker_callback);
100+
91101
// return a bogus handle
92102
return (void*)1;
93103
}
94104
static int32_t utest_us_ticker_cancel(void *handle)
95105
{
96-
// printf("\t\t>>> Cancel %p => %u\n", handle, (unsigned int)0);
106+
UTEST_LOG_FUNCTION
107+
//printf("\t\t>>> Cancel %p => %u\n", handle, (unsigned int)0);
97108
(void) handle;
98-
ticker_remove_event(ticker_data, &ticker_event);
109+
utest_timeout_object.detach();
99110
return 0;
100111
}
101112
static int32_t utest_us_ticker_run()
102113
{
114+
UTEST_LOG_FUNCTION
103115
while(1)
104116
{
105117
// check if a new callback has been set
106118
if (minimal_callback)
107119
{
108-
// printf("\t\t>>> Firing callback %p\n", minimal_callback);
120+
//printf("\t\t>>> Firing callback %p\n", minimal_callback);
109121
// copy the callback
110122
utest_v1_harness_callback_t callback = minimal_callback;
111123
// reset the shared callback
@@ -126,6 +138,7 @@ static const utest_v1_scheduler_t utest_v1_scheduler =
126138
};
127139
utest_v1_scheduler_t utest_v1_get_scheduler()
128140
{
141+
UTEST_LOG_FUNCTION
129142
return utest_v1_scheduler;
130143
}
131144
}

0 commit comments

Comments
 (0)