Lee Kai Xuan / mbed-os

Fork of mbed-os by erkin yucel

Committer:
xuaner
Date:
Thu Jul 20 14:26:57 2017 +0000
Revision:
1:3deb71413561
Parent:
0:f269e3021894
mbed_os

Who changed what in which revision?

UserRevisionLine numberNew contents of line
elessair 0:f269e3021894 1 /****************************************************************************
elessair 0:f269e3021894 2 * Copyright (c) 2015, ARM Limited, All Rights Reserved
elessair 0:f269e3021894 3 * SPDX-License-Identifier: Apache-2.0
elessair 0:f269e3021894 4 *
elessair 0:f269e3021894 5 * Licensed under the Apache License, Version 2.0 (the "License"); you may
elessair 0:f269e3021894 6 * not use this file except in compliance with the License.
elessair 0:f269e3021894 7 * You may obtain a copy of the License at
elessair 0:f269e3021894 8 *
elessair 0:f269e3021894 9 * http://www.apache.org/licenses/LICENSE-2.0
elessair 0:f269e3021894 10 *
elessair 0:f269e3021894 11 * Unless required by applicable law or agreed to in writing, software
elessair 0:f269e3021894 12 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
elessair 0:f269e3021894 13 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
elessair 0:f269e3021894 14 * See the License for the specific language governing permissions and
elessair 0:f269e3021894 15 * limitations under the License.
elessair 0:f269e3021894 16 ****************************************************************************
elessair 0:f269e3021894 17 */
elessair 0:f269e3021894 18
elessair 0:f269e3021894 19 #include "utest/utest_harness.h"
elessair 0:f269e3021894 20 #include "utest/utest_stack_trace.h"
elessair 0:f269e3021894 21 #include "utest/utest_serial.h"
elessair 0:f269e3021894 22
elessair 0:f269e3021894 23 #include <stdlib.h>
elessair 0:f269e3021894 24
elessair 0:f269e3021894 25 using namespace utest::v1;
elessair 0:f269e3021894 26
elessair 0:f269e3021894 27 namespace
elessair 0:f269e3021894 28 {
elessair 0:f269e3021894 29 const Case *test_cases = NULL;
elessair 0:f269e3021894 30 size_t test_length = 0;
elessair 0:f269e3021894 31
elessair 0:f269e3021894 32 size_t test_index_of_case = 0;
elessair 0:f269e3021894 33
elessair 0:f269e3021894 34 size_t test_passed = 0;
elessair 0:f269e3021894 35 size_t test_failed = 0;
elessair 0:f269e3021894 36
elessair 0:f269e3021894 37 const Case *case_current = NULL;
elessair 0:f269e3021894 38 size_t case_index = 0;
elessair 0:f269e3021894 39 base_control_t case_control = { REPEAT_SETUP_TEARDOWN, TIMEOUT_UNDECLR };
elessair 0:f269e3021894 40 size_t case_repeat_count = 1;
elessair 0:f269e3021894 41
elessair 0:f269e3021894 42 void *case_timeout_handle = NULL;
elessair 0:f269e3021894 43 size_t case_validation_count = 0;
elessair 0:f269e3021894 44 bool case_timeout_occurred = false;
elessair 0:f269e3021894 45
elessair 0:f269e3021894 46 size_t case_passed = 0;
elessair 0:f269e3021894 47 size_t case_failed = 0;
elessair 0:f269e3021894 48 size_t case_failed_before = 0;
elessair 0:f269e3021894 49
elessair 0:f269e3021894 50 struct DefaultHandlers : public handlers_t {
elessair 0:f269e3021894 51 DefaultHandlers() : handlers_t(default_handlers) { }
elessair 0:f269e3021894 52 DefaultHandlers(const handlers_t& other) : handlers_t(other) { }
elessair 0:f269e3021894 53 };
elessair 0:f269e3021894 54
elessair 0:f269e3021894 55 SingletonPtr<DefaultHandlers> defaults;
elessair 0:f269e3021894 56 SingletonPtr<DefaultHandlers> handlers;
elessair 0:f269e3021894 57
elessair 0:f269e3021894 58 location_t location = LOCATION_UNKNOWN;
elessair 0:f269e3021894 59
elessair 0:f269e3021894 60 utest_v1_scheduler_t scheduler = {NULL, NULL, NULL, NULL};
elessair 0:f269e3021894 61 }
elessair 0:f269e3021894 62
elessair 0:f269e3021894 63 static void die() {
elessair 0:f269e3021894 64 UTEST_LOG_FUNCTION();
elessair 0:f269e3021894 65 while(1) ;
elessair 0:f269e3021894 66 }
elessair 0:f269e3021894 67
elessair 0:f269e3021894 68 static bool is_scheduler_valid(const utest_v1_scheduler_t scheduler)
elessair 0:f269e3021894 69 {
elessair 0:f269e3021894 70 UTEST_LOG_FUNCTION();
elessair 0:f269e3021894 71 return (scheduler.init && scheduler.post && scheduler.cancel && scheduler.run);
elessair 0:f269e3021894 72 }
elessair 0:f269e3021894 73
elessair 0:f269e3021894 74 bool Harness::set_scheduler(const utest_v1_scheduler_t scheduler)
elessair 0:f269e3021894 75 {
elessair 0:f269e3021894 76 UTEST_LOG_FUNCTION();
elessair 0:f269e3021894 77 if (is_scheduler_valid(scheduler)) {
elessair 0:f269e3021894 78 ::scheduler = scheduler;
elessair 0:f269e3021894 79 return true;
elessair 0:f269e3021894 80 }
elessair 0:f269e3021894 81 return false;
elessair 0:f269e3021894 82 }
elessair 0:f269e3021894 83
elessair 0:f269e3021894 84
elessair 0:f269e3021894 85 void Harness::notify_testcases()
elessair 0:f269e3021894 86 {
elessair 0:f269e3021894 87 for(unsigned i = 0; i < test_length; i++) {
elessair 0:f269e3021894 88 utest::v1::greentea_testcase_notification_handler(test_cases[i].get_description());
elessair 0:f269e3021894 89 }
elessair 0:f269e3021894 90 }
elessair 0:f269e3021894 91
elessair 0:f269e3021894 92 bool Harness::run(const Specification& specification, size_t)
elessair 0:f269e3021894 93 {
elessair 0:f269e3021894 94 UTEST_LOG_FUNCTION();
elessair 0:f269e3021894 95 return run(specification);
elessair 0:f269e3021894 96 }
elessair 0:f269e3021894 97
elessair 0:f269e3021894 98 bool Harness::run(const Specification& specification)
elessair 0:f269e3021894 99 {
elessair 0:f269e3021894 100 UTEST_LOG_FUNCTION();
elessair 0:f269e3021894 101 // check if a specification is currently running
elessair 0:f269e3021894 102 if (is_busy())
elessair 0:f269e3021894 103 return false;
elessair 0:f269e3021894 104
elessair 0:f269e3021894 105 // if the scheduler is invalid, this is the first time we are calling
elessair 0:f269e3021894 106 if (!is_scheduler_valid(scheduler))
elessair 0:f269e3021894 107 scheduler = utest_v1_get_scheduler();
elessair 0:f269e3021894 108
elessair 0:f269e3021894 109 // if the scheduler is still invalid, abort
elessair 0:f269e3021894 110 if (!is_scheduler_valid(scheduler))
elessair 0:f269e3021894 111 return false;
elessair 0:f269e3021894 112
elessair 0:f269e3021894 113 // if the scheduler failed to initialize, abort
elessair 0:f269e3021894 114 if (scheduler.init() != 0)
elessair 0:f269e3021894 115 return false;
elessair 0:f269e3021894 116 test_cases = specification.cases;
elessair 0:f269e3021894 117 test_length = specification.length;
elessair 0:f269e3021894 118 *defaults.get() = specification.defaults;
elessair 0:f269e3021894 119 handlers->test_setup = defaults->get_handler(specification.setup_handler);
elessair 0:f269e3021894 120 handlers->test_teardown = defaults->get_handler(specification.teardown_handler);
elessair 0:f269e3021894 121 handlers->test_failure = defaults->get_handler(specification.failure_handler);
elessair 0:f269e3021894 122
elessair 0:f269e3021894 123 test_index_of_case = 0;
elessair 0:f269e3021894 124 test_passed = 0;
elessair 0:f269e3021894 125 test_failed = 0;
elessair 0:f269e3021894 126
elessair 0:f269e3021894 127 case_passed = 0;
elessair 0:f269e3021894 128 case_failed = 0;
elessair 0:f269e3021894 129 case_failed_before = 0;
elessair 0:f269e3021894 130
elessair 0:f269e3021894 131 location = LOCATION_TEST_SETUP;
elessair 0:f269e3021894 132 int setup_status = 0;
elessair 0:f269e3021894 133 failure_t failure(REASON_NONE, location);
elessair 0:f269e3021894 134
elessair 0:f269e3021894 135 if (handlers->test_setup) {
elessair 0:f269e3021894 136 setup_status = handlers->test_setup(test_length);
elessair 0:f269e3021894 137 if (setup_status == STATUS_CONTINUE) setup_status = 0;
elessair 0:f269e3021894 138 else if (setup_status < STATUS_CONTINUE) failure.reason = REASON_TEST_SETUP;
elessair 0:f269e3021894 139 else if (setup_status > signed(test_length)) failure.reason = REASON_CASE_INDEX;
elessair 0:f269e3021894 140 }
elessair 0:f269e3021894 141
elessair 0:f269e3021894 142 if (failure.reason != REASON_NONE) {
elessair 0:f269e3021894 143 if (handlers->test_failure) handlers->test_failure(failure);
elessair 0:f269e3021894 144 if (handlers->test_teardown) handlers->test_teardown(0, 0, failure);
elessair 0:f269e3021894 145 test_cases = NULL;
elessair 0:f269e3021894 146 exit(1);
elessair 0:f269e3021894 147 }
elessair 0:f269e3021894 148
elessair 0:f269e3021894 149 notify_testcases();
elessair 0:f269e3021894 150
elessair 0:f269e3021894 151 case_index = setup_status;
elessair 0:f269e3021894 152 case_current = &test_cases[case_index];
elessair 0:f269e3021894 153
elessair 0:f269e3021894 154 scheduler.post(run_next_case, 0);
elessair 0:f269e3021894 155 if (scheduler.run() != 0) {
elessair 0:f269e3021894 156 failure.reason = REASON_SCHEDULER;
elessair 0:f269e3021894 157 if (handlers->test_failure) handlers->test_failure(failure);
elessair 0:f269e3021894 158 if (handlers->test_teardown) handlers->test_teardown(0, 0, failure);
elessair 0:f269e3021894 159 test_cases = NULL;
elessair 0:f269e3021894 160 exit(1);
elessair 0:f269e3021894 161 }
elessair 0:f269e3021894 162 return true;
elessair 0:f269e3021894 163 }
elessair 0:f269e3021894 164
elessair 0:f269e3021894 165 void Harness::raise_failure(const failure_reason_t reason)
elessair 0:f269e3021894 166 {
elessair 0:f269e3021894 167 UTEST_LOG_FUNCTION();
elessair 0:f269e3021894 168 // ignore a failure, if the Harness has not been initialized.
elessair 0:f269e3021894 169 // this allows using unity assertion macros without setting up utest.
elessair 0:f269e3021894 170 if (test_cases == NULL) return;
elessair 0:f269e3021894 171
elessair 0:f269e3021894 172 utest::v1::status_t fail_status = STATUS_ABORT;
elessair 0:f269e3021894 173 if (handlers->test_failure) handlers->test_failure(failure_t(reason, location));
elessair 0:f269e3021894 174 if (handlers->case_failure) fail_status = handlers->case_failure(case_current, failure_t(reason, location));
elessair 0:f269e3021894 175
elessair 0:f269e3021894 176 {
elessair 0:f269e3021894 177 UTEST_ENTER_CRITICAL_SECTION;
elessair 0:f269e3021894 178
elessair 0:f269e3021894 179 if (fail_status != STATUS_IGNORE) case_failed++;
elessair 0:f269e3021894 180
elessair 0:f269e3021894 181 if ((fail_status == STATUS_ABORT) && case_timeout_handle)
elessair 0:f269e3021894 182 {
elessair 0:f269e3021894 183 scheduler.cancel(case_timeout_handle);
elessair 0:f269e3021894 184 case_timeout_handle = NULL;
elessair 0:f269e3021894 185 }
elessair 0:f269e3021894 186 UTEST_LEAVE_CRITICAL_SECTION;
elessair 0:f269e3021894 187 }
elessair 0:f269e3021894 188
elessair 0:f269e3021894 189 if (fail_status == STATUS_ABORT || reason & REASON_CASE_SETUP) {
elessair 0:f269e3021894 190 if (handlers->case_teardown && location != LOCATION_CASE_TEARDOWN) {
elessair 0:f269e3021894 191 location_t fail_loc(location);
elessair 0:f269e3021894 192 location = LOCATION_CASE_TEARDOWN;
elessair 0:f269e3021894 193
elessair 0:f269e3021894 194 utest::v1::status_t teardown_status = handlers->case_teardown(case_current, case_passed, case_failed, failure_t(reason, fail_loc));
elessair 0:f269e3021894 195 if (teardown_status < STATUS_CONTINUE) raise_failure(REASON_CASE_TEARDOWN);
elessair 0:f269e3021894 196 else if (teardown_status > signed(test_length)) raise_failure(REASON_CASE_INDEX);
elessair 0:f269e3021894 197 else if (teardown_status >= 0) case_index = teardown_status - 1;
elessair 0:f269e3021894 198
elessair 0:f269e3021894 199 // Restore case failure location once we have dealt with case teardown
elessair 0:f269e3021894 200 location = fail_loc;
elessair 0:f269e3021894 201 handlers->case_teardown = NULL;
elessair 0:f269e3021894 202 }
elessair 0:f269e3021894 203 }
elessair 0:f269e3021894 204 if (fail_status == STATUS_ABORT) {
elessair 0:f269e3021894 205 test_failed++;
elessair 0:f269e3021894 206 failure_t fail(reason, location);
elessair 0:f269e3021894 207 location = LOCATION_TEST_TEARDOWN;
elessair 0:f269e3021894 208 if (handlers->test_teardown) handlers->test_teardown(test_passed, test_failed, fail);
elessair 0:f269e3021894 209 exit(test_failed);
elessair 0:f269e3021894 210 die();
elessair 0:f269e3021894 211 }
elessair 0:f269e3021894 212 }
elessair 0:f269e3021894 213
elessair 0:f269e3021894 214 void Harness::schedule_next_case()
elessair 0:f269e3021894 215 {
elessair 0:f269e3021894 216 UTEST_LOG_FUNCTION();
elessair 0:f269e3021894 217 if (!case_timeout_occurred && case_failed_before == case_failed) {
elessair 0:f269e3021894 218 case_passed++;
elessair 0:f269e3021894 219 }
elessair 0:f269e3021894 220
elessair 0:f269e3021894 221 if (case_control.repeat & REPEAT_SETUP_TEARDOWN || !(case_control.repeat & (REPEAT_ON_TIMEOUT | REPEAT_ON_VALIDATE))) {
elessair 0:f269e3021894 222 location = LOCATION_CASE_TEARDOWN;
elessair 0:f269e3021894 223
elessair 0:f269e3021894 224 if (handlers->case_teardown) {
elessair 0:f269e3021894 225 utest::v1::status_t status = handlers->case_teardown(case_current, case_passed, case_failed,
elessair 0:f269e3021894 226 case_failed ? failure_t(REASON_CASES, LOCATION_UNKNOWN) : failure_t(REASON_NONE));
elessair 0:f269e3021894 227 if (status < STATUS_CONTINUE) raise_failure(REASON_CASE_TEARDOWN);
elessair 0:f269e3021894 228 else if (status > signed(test_length)) raise_failure(REASON_CASE_INDEX);
elessair 0:f269e3021894 229 else if (status >= 0) case_index = status - 1;
elessair 0:f269e3021894 230 }
elessair 0:f269e3021894 231 }
elessair 0:f269e3021894 232
elessair 0:f269e3021894 233 if (!(case_control.repeat & (REPEAT_ON_TIMEOUT | REPEAT_ON_VALIDATE))) {
elessair 0:f269e3021894 234 if (case_failed > 0) test_failed++;
elessair 0:f269e3021894 235 else test_passed++;
elessair 0:f269e3021894 236
elessair 0:f269e3021894 237 case_control = control_t(REPEAT_SETUP_TEARDOWN);
elessair 0:f269e3021894 238 case_index++;
elessair 0:f269e3021894 239 case_current = &test_cases[case_index];
elessair 0:f269e3021894 240 case_passed = 0;
elessair 0:f269e3021894 241 case_failed = 0;
elessair 0:f269e3021894 242 case_failed_before = 0;
elessair 0:f269e3021894 243 case_repeat_count = 1;
elessair 0:f269e3021894 244 test_index_of_case++;
elessair 0:f269e3021894 245 }
elessair 0:f269e3021894 246 scheduler.post(run_next_case, 0);
elessair 0:f269e3021894 247 }
elessair 0:f269e3021894 248
elessair 0:f269e3021894 249 void Harness::handle_timeout()
elessair 0:f269e3021894 250 {
elessair 0:f269e3021894 251 UTEST_LOG_FUNCTION();
elessair 0:f269e3021894 252 {
elessair 0:f269e3021894 253 UTEST_ENTER_CRITICAL_SECTION;
elessair 0:f269e3021894 254
elessair 0:f269e3021894 255 if (case_timeout_handle != NULL) {
elessair 0:f269e3021894 256 case_timeout_handle = NULL;
elessair 0:f269e3021894 257 case_timeout_occurred = true;
elessair 0:f269e3021894 258 }
elessair 0:f269e3021894 259 UTEST_LEAVE_CRITICAL_SECTION;
elessair 0:f269e3021894 260 }
elessair 0:f269e3021894 261 if (case_timeout_occurred) {
elessair 0:f269e3021894 262 raise_failure(failure_reason_t(REASON_TIMEOUT | ((case_control.repeat & REPEAT_ON_TIMEOUT) ? REASON_IGNORE : 0)));
elessair 0:f269e3021894 263 scheduler.post(schedule_next_case, 0);
elessair 0:f269e3021894 264 }
elessair 0:f269e3021894 265 }
elessair 0:f269e3021894 266
elessair 0:f269e3021894 267 void Harness::validate_callback(const control_t control)
elessair 0:f269e3021894 268 {
elessair 0:f269e3021894 269 UTEST_LOG_FUNCTION();
elessair 0:f269e3021894 270 UTEST_ENTER_CRITICAL_SECTION;
elessair 0:f269e3021894 271 case_validation_count++;
elessair 0:f269e3021894 272
elessair 0:f269e3021894 273 if (case_timeout_handle != NULL || case_control.timeout == TIMEOUT_FOREVER)
elessair 0:f269e3021894 274 {
elessair 0:f269e3021894 275 scheduler.cancel(case_timeout_handle);
elessair 0:f269e3021894 276 case_timeout_handle = NULL;
elessair 0:f269e3021894 277 control_t merged_control = case_control + control;
elessair 0:f269e3021894 278 case_control.repeat = repeat_t(merged_control.repeat & ~REPEAT_ON_TIMEOUT);
elessair 0:f269e3021894 279 case_control.timeout = TIMEOUT_NONE;
elessair 0:f269e3021894 280 scheduler.post(schedule_next_case, 0);
elessair 0:f269e3021894 281 }
elessair 0:f269e3021894 282 UTEST_LEAVE_CRITICAL_SECTION;
elessair 0:f269e3021894 283 }
elessair 0:f269e3021894 284
elessair 0:f269e3021894 285 bool Harness::is_busy()
elessair 0:f269e3021894 286 {
elessair 0:f269e3021894 287 UTEST_LOG_FUNCTION();
elessair 0:f269e3021894 288 UTEST_ENTER_CRITICAL_SECTION;
elessair 0:f269e3021894 289 bool res = false;
elessair 0:f269e3021894 290
elessair 0:f269e3021894 291 if (test_cases && case_current) {
elessair 0:f269e3021894 292 res = (case_current < (test_cases + test_length));
elessair 0:f269e3021894 293 }
elessair 0:f269e3021894 294
elessair 0:f269e3021894 295 UTEST_LEAVE_CRITICAL_SECTION;
elessair 0:f269e3021894 296 return res;
elessair 0:f269e3021894 297 }
elessair 0:f269e3021894 298
elessair 0:f269e3021894 299 void Harness::run_next_case()
elessair 0:f269e3021894 300 {
elessair 0:f269e3021894 301 UTEST_LOG_FUNCTION();
elessair 0:f269e3021894 302 if(case_current < (test_cases + test_length))
elessair 0:f269e3021894 303 {
elessair 0:f269e3021894 304 handlers->case_setup = defaults->get_handler(case_current->setup_handler);
elessair 0:f269e3021894 305 handlers->case_teardown = defaults->get_handler(case_current->teardown_handler);
elessair 0:f269e3021894 306 handlers->case_failure = defaults->get_handler(case_current->failure_handler);
elessair 0:f269e3021894 307
elessair 0:f269e3021894 308 if (case_current->is_empty()) {
elessair 0:f269e3021894 309 location = LOCATION_UNKNOWN;
elessair 0:f269e3021894 310 raise_failure(REASON_EMPTY_CASE);
elessair 0:f269e3021894 311 schedule_next_case();
elessair 0:f269e3021894 312 return;
elessair 0:f269e3021894 313 }
elessair 0:f269e3021894 314
elessair 0:f269e3021894 315 repeat_t setup_repeat;
elessair 0:f269e3021894 316 {
elessair 0:f269e3021894 317 UTEST_ENTER_CRITICAL_SECTION;
elessair 0:f269e3021894 318 case_validation_count = 0;
elessair 0:f269e3021894 319 case_timeout_occurred = false;
elessair 0:f269e3021894 320 setup_repeat = case_control.repeat;
elessair 0:f269e3021894 321 case_control = control_t();
elessair 0:f269e3021894 322 UTEST_LEAVE_CRITICAL_SECTION;
elessair 0:f269e3021894 323 }
elessair 0:f269e3021894 324
elessair 0:f269e3021894 325 if (setup_repeat & REPEAT_SETUP_TEARDOWN) {
elessair 0:f269e3021894 326 location = LOCATION_CASE_SETUP;
elessair 0:f269e3021894 327 if (handlers->case_setup && (handlers->case_setup(case_current, test_index_of_case) != STATUS_CONTINUE)) {
elessair 0:f269e3021894 328 raise_failure(REASON_CASE_SETUP);
elessair 0:f269e3021894 329 schedule_next_case();
elessair 0:f269e3021894 330 return;
elessair 0:f269e3021894 331 }
elessair 0:f269e3021894 332 }
elessair 0:f269e3021894 333
elessair 0:f269e3021894 334 case_failed_before = case_failed;
elessair 0:f269e3021894 335 location = LOCATION_CASE_HANDLER;
elessair 0:f269e3021894 336
elessair 0:f269e3021894 337 if (case_current->handler) {
elessair 0:f269e3021894 338 case_current->handler();
elessair 0:f269e3021894 339 } else if (case_current->control_handler) {
elessair 0:f269e3021894 340 case_control = case_control + case_current->control_handler();
elessair 0:f269e3021894 341 } else if (case_current->repeat_count_handler) {
elessair 0:f269e3021894 342 case_control = case_control + case_current->repeat_count_handler(case_repeat_count);
elessair 0:f269e3021894 343 }
elessair 0:f269e3021894 344 case_repeat_count++;
elessair 0:f269e3021894 345
elessair 0:f269e3021894 346 {
elessair 0:f269e3021894 347 UTEST_ENTER_CRITICAL_SECTION;
elessair 0:f269e3021894 348 if (case_validation_count) case_control.repeat = repeat_t(case_control.repeat & ~REPEAT_ON_TIMEOUT);
elessair 0:f269e3021894 349
elessair 0:f269e3021894 350 // if timeout valid
elessair 0:f269e3021894 351 if (case_control.timeout < TIMEOUT_UNDECLR && case_validation_count == 0) {
elessair 0:f269e3021894 352 // if await validation _with_ timeout
elessair 0:f269e3021894 353 if (case_control.timeout < TIMEOUT_FOREVER) {
elessair 0:f269e3021894 354 case_timeout_handle = scheduler.post(handle_timeout, case_control.timeout);
elessair 0:f269e3021894 355 if (case_timeout_handle == NULL) {
elessair 0:f269e3021894 356 raise_failure(REASON_SCHEDULER);
elessair 0:f269e3021894 357 schedule_next_case();
elessair 0:f269e3021894 358 }
elessair 0:f269e3021894 359 }
elessair 0:f269e3021894 360 }
elessair 0:f269e3021894 361 else {
elessair 0:f269e3021894 362 scheduler.post(schedule_next_case, 0);
elessair 0:f269e3021894 363 }
elessair 0:f269e3021894 364 UTEST_LEAVE_CRITICAL_SECTION;
elessair 0:f269e3021894 365 }
elessair 0:f269e3021894 366 }
elessair 0:f269e3021894 367 else if (handlers->test_teardown) {
elessair 0:f269e3021894 368 location = LOCATION_TEST_TEARDOWN;
elessair 0:f269e3021894 369 handlers->test_teardown(test_passed, test_failed, test_failed ? failure_t(REASON_CASES, LOCATION_UNKNOWN) : failure_t(REASON_NONE));
elessair 0:f269e3021894 370 test_cases = NULL;
elessair 0:f269e3021894 371 exit(test_failed);
elessair 0:f269e3021894 372 } else {
elessair 0:f269e3021894 373 exit(test_failed);
elessair 0:f269e3021894 374 }
elessair 0:f269e3021894 375 }