diff --git a/frameworks/utest/TESTS/readme/main_cpp_template b/frameworks/utest/TESTS/readme/main_cpp_template new file mode 100644 index 0000000000..74475d78a7 --- /dev/null +++ b/frameworks/utest/TESTS/readme/main_cpp_template @@ -0,0 +1,96 @@ +/* mbed Microcontroller Library + * Copyright (c) 2013-2015 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. + * + * This file describes how to use some of the basic utest features to write your + * unit test. + * + */ +#include "mbed.h" +#include "greentea-client/test_env.h" +#include "utest.h" +#include "unity.h" + +using namespace utest::v1; + +static Timeout utest_to; + +void test_simple() { + TEST_ASSERT_EQUAL(0, 0); + printf("Simple test called\n"); +} + +status_t test_repeats_setup(const Case *const source, const size_t index_of_case) { + // Call the default handler for proper reporting + status_t status = greentea_case_setup_handler(source, index_of_case); + printf("Setting up for '%s'\n", source->get_description()); + return status; +} +control_t test_repeats(const size_t call_count) { + printf("Called for the %u. time\n", call_count); + TEST_ASSERT_NOT_EQUAL(3, call_count); + // Specify how often this test is repeated ie. n total calls + return (call_count < 2) ? CaseRepeatAll : CaseNext; +} + +void test_callback_validate() { + // You may also use assertions here! + TEST_ASSERT_EQUAL_PTR(0, 0); + // Validate the callback + Harness::validate_callback(); +} +control_t test_asynchronous() { + TEST_ASSERT_TRUE_MESSAGE(true, "(true == false) o_O"); + // Set up a callback in the future. This may also be an interrupt! + utest_to.attach_us(test_callback_validate, (100*1000)); // Fire after 100 ms + + // Set a 200ms timeout starting from now + return CaseTimeout(200); +} + +control_t test_asynchronous_timeout(const size_t call_count) { + TEST_ASSERT_TRUE_MESSAGE(true, "(true == false) o_O"); + // Set a 200ms timeout starting from now, + // but automatically repeat only this handler on timeout. + if (call_count >= 5) { + // but after the 5th call, the callback finally gets validated + utest_to.attach_us(test_callback_validate, (100*1000)); // Fire after 100 ms + } + return CaseRepeatHandlerOnTimeout(200); +} + +// Custom setup handler required for proper Greentea support +status_t greentea_setup(const size_t number_of_cases) { + GREENTEA_SETUP(20, "default_auto"); + + // Call the default reporting function + return greentea_test_setup_handler(number_of_cases); +} + +// Specify all your test cases here +Case cases[] = { + Case("Simple Test", test_simple), + Case("Repeating Test", test_repeats_setup, test_repeats), + Case("Asynchronous Test (200ms timeout)", test_asynchronous), + Case("Asynchronous Timeout Repeat", test_asynchronous_timeout) +}; + +// Declare your test specification with a custom setup handler +Specification specification(greentea_setup, cases); + +int main() +{ + // Run the specification only AFTER setting the custom scheduler. + Harness::run(specification); +} diff --git a/frameworks/utest/TESTS/unit_tests/basic_test/main.cpp b/frameworks/utest/TESTS/unit_tests/basic_test/main.cpp new file mode 100644 index 0000000000..bfd0d9576f --- /dev/null +++ b/frameworks/utest/TESTS/unit_tests/basic_test/main.cpp @@ -0,0 +1,54 @@ +#include "mbed-drivers/mbed.h" +#include "greentea-client/test_env.h" +#include "utest/utest.h" +#include "unity/unity.h" +#include "stack_trace.h" + +using namespace utest::v1; + +void test_simple() { + UTEST_LOG_FUNCTION(); + TEST_ASSERT_EQUAL(0, 0); + printf("Simple test called\n"); +} + +status_t test_repeats_setup(const Case *const source, const size_t index_of_case) { + UTEST_LOG_FUNCTION(); + // Call the default handler for proper reporting + status_t status = greentea_case_setup_handler(source, index_of_case); + printf("Setting up for '%s'\n", source->get_description()); + return status; +} +control_t test_repeats(const size_t call_count) { + UTEST_LOG_FUNCTION(); + printf("Called for the %u. time\n", call_count); + TEST_ASSERT_NOT_EQUAL(3, call_count); + // Specify how often this test is repeated ie. n total calls + return (call_count < 2) ? CaseRepeatAll : CaseNext; +} + +// Custom setup handler required for proper Greentea support +status_t greentea_setup(const size_t number_of_cases) { + UTEST_LOG_FUNCTION(); + GREENTEA_SETUP(20, "default_auto"); + // Call the default reporting function + return greentea_test_setup_handler(number_of_cases); +} + +// Specify all your test cases here +Case cases[] = { + Case("Simple Test", test_simple), + Case("Repeating Test", test_repeats_setup, test_repeats) +}; + +// Declare your test specification with a custom setup handler +Specification specification(greentea_setup, cases); + +extern void utest_run(const Specification& specification); + +int main() +{ + UTEST_LOG_FUNCTION(); + // Run the specification only AFTER setting the custom scheduler. + Harness::run(specification); +} diff --git a/frameworks/utest/TESTS/unit_tests/case_async_validate/main.cpp b/frameworks/utest/TESTS/unit_tests/case_async_validate/main.cpp new file mode 100644 index 0000000000..411c35c984 --- /dev/null +++ b/frameworks/utest/TESTS/unit_tests/case_async_validate/main.cpp @@ -0,0 +1,233 @@ + +/* mbed Microcontroller Library + * Copyright (c) 2013-2015 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-drivers/mbed.h" +#include "greentea-client/test_env.h" +#include "utest/utest.h" +#include "unity/unity.h" + +#include + +using namespace utest::v1; + +static int call_counter(0); + +static Timeout utest_to; + +// Validate: Simple Validation ---------------------------------------------------------------------------------------- +void simple_validation() +{ + TEST_ASSERT_EQUAL(1, call_counter++); + printf("Simple validation callback executed.\n"); + Harness::validate_callback(); +} + +control_t simple_validation_case() +{ + printf("Simple validation, posting callback\n"); + TEST_ASSERT_EQUAL(0, call_counter++); + utest_to.attach_us(simple_validation, 100); // Fire after 100 us + + return CaseAwait; +} + +// Validate: Multiple Validation -------------------------------------------------------------------------------------- +void multiple_validation() +{ + printf("Multiple validation callback executed.\n"); + + // make sure validation is side-effect free + TEST_ASSERT_EQUAL(3, call_counter++); + Harness::validate_callback(); + TEST_ASSERT_EQUAL(4, call_counter++); + Harness::validate_callback(); + TEST_ASSERT_EQUAL(5, call_counter++); + Harness::validate_callback(); + TEST_ASSERT_EQUAL(6, call_counter++); + Harness::validate_callback(); + TEST_ASSERT_EQUAL(7, call_counter++); + Harness::validate_callback(); + TEST_ASSERT_EQUAL(8, call_counter++); + +} + +control_t multiple_validation_case() +{ + TEST_ASSERT_EQUAL(2, call_counter++); + printf("Multiple validation callback posted.\n"); + utest_to.attach_us(multiple_validation, 100000); // Fire after 100 ms + return CaseAwait; +} + +status_t multiple_validation_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t failure) +{ + TEST_ASSERT_EQUAL(1, passed); + TEST_ASSERT_EQUAL(0, failed); + TEST_ASSERT_EQUAL(REASON_NONE, failure.reason); + TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location); + TEST_ASSERT_EQUAL(9, call_counter++); + return greentea_case_teardown_handler(source, passed, failed, failure); +} + +// Validate: Premature Validation ------------------------------------------------------------------------------------- +control_t premature_validation_case() +{ + TEST_ASSERT_EQUAL(10, call_counter++); + /* Prematurely validate the callback. + * This can happen, when you set up a callback that occurs in an interrupt + * and it fires and validates the callback before this function completes. + * The harness only knows whether to expect a callback after the case Handler + * completes (obviously), so the callback validations are logged. + */ + Harness::validate_callback(); + return CaseAwait; +} + +status_t premature_validation_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t failure) +{ + TEST_ASSERT_EQUAL(1, passed); + TEST_ASSERT_EQUAL(0, failed); + TEST_ASSERT_EQUAL(REASON_NONE, failure.reason); + TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location); + TEST_ASSERT_EQUAL(11, call_counter++); + return greentea_case_teardown_handler(source, passed, failed, failure); +} + +// Validate: Multiple Premature Validation ---------------------------------------------------------------------------- +control_t multiple_premature_validation_case() +{ + TEST_ASSERT_EQUAL(12, call_counter++); + Harness::validate_callback(); + TEST_ASSERT_EQUAL(13, call_counter++); + Harness::validate_callback(); + TEST_ASSERT_EQUAL(14, call_counter++); + Harness::validate_callback(); + TEST_ASSERT_EQUAL(15, call_counter++); + Harness::validate_callback(); + TEST_ASSERT_EQUAL(16, call_counter++); + return CaseAwait; +} + +status_t multiple_premature_validation_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t failure) +{ + TEST_ASSERT_EQUAL(1, passed); + TEST_ASSERT_EQUAL(0, failed); + TEST_ASSERT_EQUAL(REASON_NONE, failure.reason); + TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location); + TEST_ASSERT_EQUAL(17, call_counter++); + return greentea_case_teardown_handler(source, passed, failed, failure); +} + +// Validate: Attributed Validation: Cancel Repeat --------------------------------------------------------------------- +void attributed_validation_cancel_repeat() +{ + TEST_ASSERT_EQUAL(19, call_counter++); + printf("Validation cancel repeat callback executed.\n"); + // cancel all repeats + Harness::validate_callback(CaseNoRepeat); +} + +control_t attributed_validation_cancel_repeat_case() +{ + TEST_ASSERT_EQUAL(18, call_counter++); + printf("Validation cancel repeat callback posted.\n"); + + utest_to.attach_us(attributed_validation_cancel_repeat, 100000); // Fire after 100 ms + // the RepeatAll will be cancelled during callback validation + return CaseRepeatAll + CaseAwait; +} + +status_t attributed_validation_cancel_repeat_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t failure) +{ + TEST_ASSERT_EQUAL(1, passed); + TEST_ASSERT_EQUAL(0, failed); + TEST_ASSERT_EQUAL(REASON_NONE, failure.reason); + TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location); + TEST_ASSERT_EQUAL(20, call_counter++); + return greentea_case_teardown_handler(source, passed, failed, failure); +} + +// Validate: Attributed Validation: Enable Repeat Handler ------------------------------------------------------------- +void attributed_validation_enable_repeat() +{ + printf("Validation enable repeat callback executed.\n"); + TEST_ASSERT_EQUAL(22, call_counter++); + // cancel all repeats + Harness::validate_callback(CaseRepeatHandler); + TEST_ASSERT_EQUAL(23, call_counter++); + // only the first validation counts + Harness::validate_callback(CaseNoRepeat); + TEST_ASSERT_EQUAL(24, call_counter++); +} + +control_t attributed_validation_enable_repeat_case(const size_t call_count) +{ + if (call_count == 1) { + TEST_ASSERT_EQUAL(21, call_counter++); + printf("Validation enable repeat callback posted.\n"); + utest_to.attach_us(attributed_validation_enable_repeat, 100000); // Fire after 100 ms + // the RepeatAll will be cancelled during callback validation + return CaseAwait; + } + TEST_ASSERT_EQUAL(25, call_counter++); + return CaseNext; +} + +status_t attributed_validation_enable_repeat_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t failure) +{ + TEST_ASSERT_EQUAL(2, passed); + TEST_ASSERT_EQUAL(0, failed); + TEST_ASSERT_EQUAL(REASON_NONE, failure.reason); + TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location); + TEST_ASSERT_EQUAL(26, call_counter++); + return greentea_case_teardown_handler(source, passed, failed, failure); +} + +// Cases -------------------------------------------------------------------------------------------------------------- +Case cases[] = { + Case("Validate: Simple Validation", simple_validation_case), + Case("Validate: Multiple Validation", multiple_validation_case, multiple_validation_case_teardown), + Case("Validate: Premature Validation", premature_validation_case, premature_validation_case_teardown), + Case("Validate: Multiple Premature Validation", multiple_premature_validation_case, multiple_premature_validation_case_teardown), + Case("Validate: Attributed Validation: Cancel Repeat", attributed_validation_cancel_repeat_case, attributed_validation_cancel_repeat_case_teardown), + Case("Validate: Attributed Validation: Enable Repeat Handler", attributed_validation_enable_repeat_case, attributed_validation_enable_repeat_case_teardown) +}; + +status_t greentea_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(15, "default_auto"); + + return greentea_test_setup_handler(number_of_cases); +} + +void greentea_teardown(const size_t passed, const size_t failed, const failure_t failure) +{ + TEST_ASSERT_EQUAL(27, call_counter++); + TEST_ASSERT_EQUAL(6, passed); + TEST_ASSERT_EQUAL(0, failed); + TEST_ASSERT_EQUAL(REASON_NONE, failure.reason); + TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location); + greentea_test_teardown_handler(passed, failed, failure); +} + +Specification specification(greentea_setup, cases, greentea_teardown, selftest_handlers); +extern void utest_run(const Specification& specification); + +int main() +{ + // Run the specification only AFTER setting the custom scheduler. + Harness::run(specification); +} diff --git a/frameworks/utest/TESTS/unit_tests/case_control_async/main.cpp b/frameworks/utest/TESTS/unit_tests/case_control_async/main.cpp new file mode 100644 index 0000000000..f57ec1abe6 --- /dev/null +++ b/frameworks/utest/TESTS/unit_tests/case_control_async/main.cpp @@ -0,0 +1,257 @@ + +/* mbed Microcontroller Library + * Copyright (c) 2013-2015 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-drivers/mbed.h" +#include "greentea-client/test_env.h" +#include "utest/utest.h" +#include "unity/unity.h" +#include "utest/stack_trace.h" + +using namespace utest::v1; + + +static int call_counter(0); +static Timeout utest_to; + +class Utest_func_bind { + +public: + inline Utest_func_bind( void (*f)(int), int v) : _callback_fn(f), _callback_value(v) + {} + + inline void callback() { + (*_callback_fn)(_callback_value); + } + +private: + void (*_callback_fn)(int); + int _callback_value; +}; + + + +void await_case_validate(int expected_call_count) +{ + UTEST_LOG_FUNCTION(); + printf("await_case_validate called with expected call count of %d\n", expected_call_count); + TEST_ASSERT_EQUAL(expected_call_count, call_counter++); + Harness::validate_callback(); +} + +static Utest_func_bind validate1(await_case_validate, 7); +static Utest_func_bind validate2(await_case_validate, 37); +static Utest_func_bind validate3(await_case_validate, 50); + + + +// Control: Timeout (Failure) ----------------------------------------------------------------------------------------- +control_t timeout_failure_case(const size_t call_count) +{ + UTEST_LOG_FUNCTION(); + TEST_ASSERT_EQUAL(1, call_count); + TEST_ASSERT_EQUAL(0, call_counter++); + return CaseTimeout(100); +} +status_t timeout_failure_case_failure_handler(const Case *const source, const failure_t failure) +{ + UTEST_LOG_FUNCTION(); + TEST_ASSERT_EQUAL(1, call_counter++); + TEST_ASSERT_EQUAL(REASON_TIMEOUT, failure.reason); + TEST_ASSERT_EQUAL(LOCATION_CASE_HANDLER, failure.location); + verbose_case_failure_handler(source, failure); + return STATUS_CONTINUE; +} +status_t timeout_failure_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t failure) +{ + UTEST_LOG_FUNCTION(); + TEST_ASSERT_EQUAL(2, call_counter++); + TEST_ASSERT_EQUAL(0, passed); + TEST_ASSERT_EQUAL(1, failed); + TEST_ASSERT_EQUAL(REASON_CASES, failure.reason); + TEST_ASSERT_EQUAL(LOCATION_UNKNOWN, failure.location); + return greentea_case_teardown_handler(source, 1, 0, REASON_NONE); +} + +// Control: Timeout (Success) ----------------------------------------------------------------------------------------- +void timeout_success_case_validate() { + UTEST_LOG_FUNCTION(); + TEST_ASSERT_EQUAL(4, call_counter++); + Harness::validate_callback(); +} + +control_t timeout_success_case(const size_t call_count) +{ + UTEST_LOG_FUNCTION(); + TEST_ASSERT_EQUAL(1, call_count); + TEST_ASSERT_EQUAL(3, call_counter++); + utest_to.attach_us(timeout_success_case_validate, 100000); // Fire after 100 ms + + return CaseTimeout(200); +} +status_t timeout_success_case_failure_handler(const Case *const source, const size_t passed, const size_t failed, const failure_t failure) +{ + UTEST_LOG_FUNCTION(); + TEST_ASSERT_EQUAL(5, call_counter++); + TEST_ASSERT_EQUAL(1, passed); + TEST_ASSERT_EQUAL(0, failed); + TEST_ASSERT_EQUAL(REASON_NONE, failure.reason); + TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location); + return greentea_case_teardown_handler(source, passed, failed, failure); +} + +// Control: Await ----------------------------------------------------------------------------------------------------- +control_t await_case(const size_t call_count) +{ + UTEST_LOG_FUNCTION(); + TEST_ASSERT_EQUAL(1, call_count); + TEST_ASSERT_EQUAL(6, call_counter++); + + utest_to.attach_us(&validate1, &Utest_func_bind::callback, (1372*1000)); // Fire after 1372 ms + + return CaseAwait; +} + +// Control: RepeatAllOnTimeout ---------------------------------------------------------------------------------------- +bool repeat_all_start_flag = true; +status_t repeat_all_on_timeout_case_setup(const Case *const source, const size_t index_of_case) +{ + if (repeat_all_start_flag){ + UTEST_TRACE_START + repeat_all_start_flag = false; + } + UTEST_LOG_FUNCTION(); + static int repeat_counter(0); + TEST_ASSERT_EQUAL(3, index_of_case); + TEST_ASSERT_EQUAL(repeat_counter*3 + 8, call_counter++); + repeat_counter++; + return greentea_case_setup_handler(source, index_of_case); +} +control_t repeat_all_on_timeout_case(const size_t call_count) +{ + UTEST_LOG_FUNCTION(); + printf("Running case handler for %u. time\n", call_count); + static int repeat_counter(1); + TEST_ASSERT_EQUAL(repeat_counter++, call_count); + TEST_ASSERT(call_count <= 10); + TEST_ASSERT_EQUAL((call_count-1)*3 + 9, call_counter++); + if (call_count == 10) { + printf("Scheduling await_case_validate with value 37"); + utest_to.attach_us(&validate2, &Utest_func_bind::callback, (50*1000)); // Fire after 50ms + } + return CaseRepeatAllOnTimeout(100); +} +status_t repeat_all_on_timeout_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t failure) +{ + UTEST_LOG_FUNCTION(); + static int repeat_counter(0); + printf("Call counter = %d, passed =%u, failed = %u\n", call_counter, passed, failed); + + TEST_ASSERT_EQUAL((call_counter == 38) ? 1 : 0, passed); + TEST_ASSERT_EQUAL(0, failed); + TEST_ASSERT_EQUAL(REASON_NONE, failure.reason); + TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location); + TEST_ASSERT_EQUAL(repeat_counter*3 + ((repeat_counter == 9) ? 11 : 10), call_counter++); + repeat_counter++; + return greentea_case_teardown_handler(source, passed, failed, failure); +} + +// Control: RepeatAllOnTimeout ---------------------------------------------------------------------------------------- +status_t repeat_handler_on_timeout_case_setup(const Case *const source, const size_t index_of_case) +{ + UTEST_LOG_FUNCTION(); + TEST_ASSERT_EQUAL(4, index_of_case); + TEST_ASSERT_EQUAL(39, call_counter++); + return greentea_case_setup_handler(source, index_of_case); +} + +control_t repeat_handler_on_timeout_case(const size_t call_count) +{ + UTEST_LOG_FUNCTION(); + printf("Running case handler for %u. time\n", call_count); + static int repeat_counter(1); + TEST_ASSERT_EQUAL(repeat_counter++, call_count); + TEST_ASSERT(call_count <= 10); + TEST_ASSERT_EQUAL(call_count-1 + 40, call_counter++); + if (call_count == 10) { + printf("Scheduling await_case_validate with value 50"); + utest_to.attach_us(&validate3, &Utest_func_bind::callback, (50*1000)); // Fire after 50ms + } + return CaseRepeatHandlerOnTimeout(100); +} +status_t repeat_handler_on_timeout_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t failure) +{ + UTEST_LOG_FUNCTION(); + TEST_ASSERT_EQUAL(1, passed); + TEST_ASSERT_EQUAL(0, failed); + TEST_ASSERT_EQUAL(REASON_NONE, failure.reason); + TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location); + TEST_ASSERT_EQUAL(51, call_counter++); + return greentea_case_teardown_handler(source, passed, failed, failure); +} + +// Control: NoTimeout ------------------------------------------------------------------------------------------------- +control_t no_timeout_case(const size_t call_count) +{ + UTEST_LOG_FUNCTION(); + TEST_ASSERT_EQUAL(1, call_count); + TEST_ASSERT_EQUAL(52, call_counter++); + return CaseNoTimeout; +} + +// Control: NoTimeout ------------------------------------------------------------------------------------------------- +control_t next_case(const size_t call_count) +{ + UTEST_LOG_FUNCTION(); + TEST_ASSERT_EQUAL(1, call_count); + TEST_ASSERT_EQUAL(53, call_counter++); + return CaseNoTimeout; +} + +// Cases -------------------------------------------------------------------------------------------------------------- +Case cases[] = { + Case("Control: Timeout (Failure)", timeout_failure_case, timeout_failure_case_teardown, timeout_failure_case_failure_handler), + Case("Control: Timeout (Success)", timeout_success_case, timeout_success_case_failure_handler), + Case("Control: Await", await_case), + Case("Control: RepeatAllOnTimeout", repeat_all_on_timeout_case_setup, repeat_all_on_timeout_case, repeat_all_on_timeout_case_teardown), + Case("Control: RepeatHandlerOnTimeout", repeat_handler_on_timeout_case_setup, repeat_handler_on_timeout_case, repeat_handler_on_timeout_case_teardown), + Case("Control: NoTimeout", no_timeout_case), + Case("Control: CaseNext", next_case) +}; + +// Specification: Setup & Teardown ------------------------------------------------------------------------------------ +status_t greentea_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(15, "default_auto"); + + return verbose_test_setup_handler(number_of_cases); +} +void greentea_teardown(const size_t passed, const size_t failed, const failure_t failure) +{ + TEST_ASSERT_EQUAL(54, call_counter++); + TEST_ASSERT_EQUAL(6, passed); + TEST_ASSERT_EQUAL(1, failed); + TEST_ASSERT_EQUAL(REASON_CASES, failure.reason); + TEST_ASSERT_EQUAL(LOCATION_UNKNOWN, failure.location); + greentea_test_teardown_handler(7, 0, REASON_NONE); +} + +Specification specification(greentea_setup, cases, greentea_teardown, selftest_handlers); + +int main() +{ + // Run the specification only AFTER setting the custom scheduler(if required). + Harness::run(specification); +} diff --git a/frameworks/utest/TESTS/unit_tests/case_control_repeat/main.cpp b/frameworks/utest/TESTS/unit_tests/case_control_repeat/main.cpp new file mode 100644 index 0000000000..15ed8fd127 --- /dev/null +++ b/frameworks/utest/TESTS/unit_tests/case_control_repeat/main.cpp @@ -0,0 +1,130 @@ + +/* mbed Microcontroller Library + * Copyright (c) 2013-2015 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-drivers/mbed.h" +#include "greentea-client/test_env.h" +#include "utest/utest.h" +#include "unity/unity.h" + +using namespace utest::v1; + +static int call_counter(0); + +// Control: RepeatAll ------------------------------------------------------------------------------------------------- +status_t repeat_all_case_setup(const Case *const source, const size_t index_of_case) +{ + static int repeat_counter(0); + TEST_ASSERT_EQUAL(0, index_of_case); + TEST_ASSERT_EQUAL(repeat_counter*3, call_counter++); + repeat_counter++; + return greentea_case_setup_handler(source, index_of_case); +} +control_t repeat_all_case(const size_t call_count) +{ + printf("Running case handler for %u. time\n", call_count); + static int repeat_counter(1); + TEST_ASSERT_EQUAL(repeat_counter++, call_count); + TEST_ASSERT_EQUAL((call_count-1)*3 + 1, call_counter++); + return (call_count < 10) ? CaseRepeatAll : CaseNoRepeat; +} +status_t repeat_all_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t failure) +{ + static int repeat_counter(0); + TEST_ASSERT_EQUAL(repeat_counter*3 + 2, call_counter++); + TEST_ASSERT_EQUAL(repeat_counter+1, passed); + TEST_ASSERT_EQUAL(0, failed); + TEST_ASSERT_EQUAL(REASON_NONE, failure.reason); + TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location); + repeat_counter++; + return greentea_case_teardown_handler(source, passed, failed, failure); +} + +// Control: RepeatHandler --------------------------------------------------------------------------------------------- +status_t repeat_handler_case_setup(const Case *const source, const size_t index_of_case) +{ + TEST_ASSERT_EQUAL(1, index_of_case); + TEST_ASSERT_EQUAL(30, call_counter++); + return greentea_case_setup_handler(source, index_of_case); +} +control_t repeat_handler_case(const size_t call_count) +{ + printf("Running case handler for %u. time\n", call_count); + static int repeat_counter(1); + TEST_ASSERT_EQUAL(repeat_counter++, call_count); + TEST_ASSERT_EQUAL((call_count-1) + 31, call_counter++); + return (call_count < 10) ? CaseRepeatHandler : CaseNoRepeat; +} +status_t repeat_handler_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t failure) +{ + TEST_ASSERT_EQUAL(41, call_counter++); + TEST_ASSERT_EQUAL(10, passed); + TEST_ASSERT_EQUAL(0, failed); + TEST_ASSERT_EQUAL(REASON_NONE, failure.reason); + TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location); + return greentea_case_teardown_handler(source, passed, failed, failure); +} + +// Control: NoRepeat -------------------------------------------------------------------------------------------------- +control_t no_repeat_handler_case(const size_t call_count) +{ + static int repeat_counter(1); + TEST_ASSERT_EQUAL(repeat_counter++, call_count); + TEST_ASSERT_EQUAL(1, call_count); + TEST_ASSERT_EQUAL(42, call_counter++); + return CaseNoRepeat; +} + +// Control: CaseNext -------------------------------------------------------------------------------------------------- +control_t next_handler_case(const size_t call_count) +{ + static int repeat_counter(1); + TEST_ASSERT_EQUAL(repeat_counter++, call_count); + TEST_ASSERT_EQUAL(1, call_count); + TEST_ASSERT_EQUAL(43, call_counter++); + return CaseNext; +} + +Case cases[] = { + Case("Control: RepeatAll", repeat_all_case_setup, repeat_all_case, repeat_all_case_teardown), + Case("Control: RepeatHandler", repeat_handler_case_setup, repeat_handler_case, repeat_handler_case_teardown), + Case("Control: NoRepeat", no_repeat_handler_case), + Case("Control: CaseNext", next_handler_case) +}; + +status_t greentea_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(15, "default_auto"); + + return greentea_test_setup_handler(number_of_cases); +} +void greentea_teardown(const size_t passed, const size_t failed, const failure_t failure) +{ + TEST_ASSERT_EQUAL(44, call_counter); + TEST_ASSERT_EQUAL(4, passed); + TEST_ASSERT_EQUAL(0, failed); + TEST_ASSERT_EQUAL(REASON_NONE, failure.reason); + TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location); + greentea_test_teardown_handler(passed, failed, failure); +} + + +Specification specification(greentea_setup, cases, greentea_teardown, selftest_handlers); + +int main() +{ + // Run the specification only AFTER setting the custom scheduler(if required). + Harness::run(specification); +} diff --git a/frameworks/utest/TESTS/unit_tests/case_selection/main.cpp b/frameworks/utest/TESTS/unit_tests/case_selection/main.cpp new file mode 100644 index 0000000000..c11fc0df15 --- /dev/null +++ b/frameworks/utest/TESTS/unit_tests/case_selection/main.cpp @@ -0,0 +1,101 @@ + +/* 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-drivers/mbed.h" +#include "greentea-client/test_env.h" +#include "utest/utest.h" +#include "unity/unity.h" + + +using namespace utest::v1; + +static int call_counter(0); + +void handler_case_2() +{ + printf("Executing Case 2...\n"); +} +status_t teardown_case_2(const Case *const source, const size_t passed, const size_t failed, const failure_t failure) +{ + TEST_ASSERT_EQUAL(1, passed); + TEST_ASSERT_EQUAL(0, failed); + TEST_ASSERT_EQUAL(REASON_NONE, failure.reason); + TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location); + TEST_ASSERT_EQUAL(0, call_counter++); + greentea_case_teardown_handler(source, passed, failed, failure); + return status_t(0); +} +void handler_case_0() +{ + printf("Executing Case 0...\n"); +} +status_t teardown_case_0(const Case *const source, const size_t passed, const size_t failed, const failure_t failure) +{ + TEST_ASSERT_EQUAL(1, passed); + TEST_ASSERT_EQUAL(0, failed); + TEST_ASSERT_EQUAL(REASON_NONE, failure.reason); + TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location); + TEST_ASSERT_EQUAL(1, call_counter++); + greentea_case_teardown_handler(source, passed, failed, failure); + return status_t(1); +} +void handler_case_1() +{ + printf("Executing Case 1...\n"); +} +status_t teardown_case_1(const Case *const source, const size_t passed, const size_t failed, const failure_t failure) +{ + TEST_ASSERT_EQUAL(1, passed); + TEST_ASSERT_EQUAL(0, failed); + TEST_ASSERT_EQUAL(REASON_NONE, failure.reason); + TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location); + TEST_ASSERT_EQUAL(2, call_counter++); + greentea_case_teardown_handler(source, passed, failed, failure); + return status_t(3); +} + +Case cases[] = +{ + Case("Case 1", handler_case_0, teardown_case_0), + Case("Case 2", handler_case_1, teardown_case_1), + Case("Case 3", handler_case_2, teardown_case_2) +}; + +status_t test_setup_handler(const size_t number_of_cases) +{ + GREENTEA_SETUP(5, "default_auto"); + + greentea_test_setup_handler(number_of_cases); + return status_t(2); +}; +void test_teardown_handler(const size_t passed, const size_t failed, const failure_t failure) +{ + TEST_ASSERT_EQUAL(3, passed); + TEST_ASSERT_EQUAL(0, failed); + TEST_ASSERT_EQUAL(REASON_NONE, failure.reason); + TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location); + TEST_ASSERT_EQUAL(3, call_counter++); + + greentea_test_teardown_handler(passed, failed, failure); +}; + +Specification specification(test_setup_handler, cases, test_teardown_handler, selftest_handlers); + +int main() +{ + // Run the specification only AFTER setting the custom scheduler(if required). + Harness::run(specification); +} diff --git a/frameworks/utest/TESTS/unit_tests/case_setup_failure/main.cpp b/frameworks/utest/TESTS/unit_tests/case_setup_failure/main.cpp new file mode 100644 index 0000000000..5afe58fb97 --- /dev/null +++ b/frameworks/utest/TESTS/unit_tests/case_setup_failure/main.cpp @@ -0,0 +1,127 @@ + +/* mbed Microcontroller Library + * Copyright (c) 2013-2015 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-drivers/mbed.h" +#include "greentea-client/test_env.h" +#include "utest/utest.h" +#include "unity/unity.h" + +using namespace utest::v1; + +static int call_counter(0); + +void never_call_case() +{ + TEST_FAIL_MESSAGE("Case handler should have never been called!"); +} + +status_t abort_case_setup(const Case *const source, const size_t index_of_case) +{ + call_counter++; + TEST_ASSERT_EQUAL(0, index_of_case); + greentea_case_setup_handler(source, index_of_case); + return STATUS_ABORT; +} + +status_t abort_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t failure) +{ + TEST_ASSERT_EQUAL(1, call_counter); + TEST_ASSERT_EQUAL(0, passed); + TEST_ASSERT_EQUAL(1, failed); + TEST_ASSERT_EQUAL(REASON_CASE_SETUP, failure.reason); + TEST_ASSERT_EQUAL(LOCATION_CASE_SETUP, failure.location); + call_counter++; + return greentea_case_teardown_handler(source, 1, 0, failure); +} + +status_t ignore_case_setup(const Case *const source, const size_t index_of_case) +{ + TEST_ASSERT_EQUAL(2, call_counter); + TEST_ASSERT_EQUAL(1, index_of_case); + greentea_case_setup_handler(source, index_of_case); + call_counter++; + return STATUS_IGNORE; // this is the same +} + +status_t ignore_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t failure) +{ + TEST_ASSERT_EQUAL(3, call_counter); + TEST_ASSERT_EQUAL(0, passed); + TEST_ASSERT_EQUAL(1, failed); + TEST_ASSERT_EQUAL(REASON_CASE_SETUP, failure.reason); + TEST_ASSERT_EQUAL(LOCATION_CASE_SETUP, failure.location); + call_counter++; + return greentea_case_teardown_handler(source, 1, 0, failure); +} + +status_t continue_case_setup(const Case *const source, const size_t index_of_case) +{ + TEST_ASSERT_EQUAL(4, call_counter); + TEST_ASSERT_EQUAL(2, index_of_case); + greentea_case_setup_handler(source, index_of_case); + call_counter++; + return STATUS_CONTINUE; // this is the same +} + +void continue_case_handler() +{ + TEST_ASSERT_EQUAL(5, call_counter); + call_counter++; +} + +status_t continue_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t failure) +{ + TEST_ASSERT_EQUAL(6, call_counter); + TEST_ASSERT_EQUAL(1, passed); + TEST_ASSERT_EQUAL(0, failed); + TEST_ASSERT_EQUAL(REASON_NONE, failure.reason); + TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location); + call_counter++; + return greentea_case_teardown_handler(source, passed, failed, failure); +} + +Case cases[] = { + Case("Setup handler returns ABORT", abort_case_setup, never_call_case, abort_case_teardown), + Case("Setup handler returns IGNORE", ignore_case_setup, never_call_case, ignore_case_teardown), + Case("Setup handler returns CONTINUE", continue_case_setup, continue_case_handler, continue_case_teardown) +}; + +status_t greentea_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(15, "default_auto"); + + return greentea_test_setup_handler(number_of_cases); +} + +void greentea_teardown(const size_t passed, const size_t failed, const failure_t failure) +{ + TEST_ASSERT_EQUAL(7, call_counter); + TEST_ASSERT_EQUAL(1, passed); + TEST_ASSERT_EQUAL(2, failed); + TEST_ASSERT_EQUAL(REASON_CASES, failure.reason); + TEST_ASSERT_EQUAL(LOCATION_UNKNOWN, failure.location); + + // pretend to greentea that the test was successful + greentea_test_teardown_handler(3, 0, REASON_NONE); +} + +Specification specification(greentea_setup, cases, greentea_teardown, selftest_handlers); + +int main() +{ + // Run the specification only AFTER setting the custom scheduler(if required). + Harness::run(specification); +} diff --git a/frameworks/utest/TESTS/unit_tests/case_teardown_failure/main.cpp b/frameworks/utest/TESTS/unit_tests/case_teardown_failure/main.cpp new file mode 100644 index 0000000000..daebf720fe --- /dev/null +++ b/frameworks/utest/TESTS/unit_tests/case_teardown_failure/main.cpp @@ -0,0 +1,126 @@ + +/* mbed Microcontroller Library + * Copyright (c) 2013-2015 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-drivers/mbed.h" +#include "greentea-client/test_env.h" +#include "utest/utest.h" +#include "unity/unity.h" + +using namespace utest::v1; + +static int call_counter(0); + +// Continue Teardown Handler ------------------------------------------------------------------------------------------ +void continue_case() +{ + TEST_ASSERT_EQUAL(0, call_counter++); +} +status_t continue_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t failure) +{ + TEST_ASSERT_EQUAL(1, passed); + TEST_ASSERT_EQUAL(0, failed); + TEST_ASSERT_EQUAL(REASON_NONE, failure.reason); + TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location); + TEST_ASSERT_EQUAL(1, call_counter++); + return greentea_case_teardown_handler(source, passed, failed, failure); +} +status_t continue_failure(const Case *const, const failure_t) +{ + TEST_FAIL_MESSAGE("Failure handler should have never been called!"); + return STATUS_CONTINUE; +} + +// Ignoring Teardown Handler ------------------------------------------------------------------------------------------ +void ignore_case() +{ + TEST_ASSERT_EQUAL(2, call_counter++); +} +status_t ignore_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t failure) +{ + TEST_ASSERT_EQUAL(1, passed); + TEST_ASSERT_EQUAL(0, failed); + TEST_ASSERT_EQUAL(REASON_NONE, failure.reason); + TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location); + TEST_ASSERT_EQUAL(3, call_counter++); + greentea_case_teardown_handler(source, passed, failed, failure); + return STATUS_ABORT; +} +status_t ignore_failure(const Case *const source, const failure_t failure) +{ + TEST_ASSERT_EQUAL(4, call_counter++); + TEST_ASSERT_EQUAL(REASON_CASE_TEARDOWN, failure.reason); + TEST_ASSERT_EQUAL(LOCATION_CASE_TEARDOWN, failure.location); + verbose_case_failure_handler(source, failure.ignored()); + return STATUS_IGNORE; +} + +// Aborting Teardown Handler ------------------------------------------------------------------------------------------ +void abort_case() +{ + TEST_ASSERT_EQUAL(5, call_counter++); +} +status_t abort_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t failure) +{ + TEST_ASSERT_EQUAL(1, passed); + TEST_ASSERT_EQUAL(0, failed); + TEST_ASSERT_EQUAL(REASON_NONE, failure.reason); + TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location); + TEST_ASSERT_EQUAL(6, call_counter++); + greentea_case_teardown_handler(source, passed, failed, failure); + return STATUS_ABORT; +} +status_t abort_failure(const Case *const source, const failure_t failure) +{ + TEST_ASSERT_EQUAL(7, call_counter++); + TEST_ASSERT_EQUAL(REASON_CASE_TEARDOWN, failure.reason); + TEST_ASSERT_EQUAL(LOCATION_CASE_TEARDOWN, failure.location); + return verbose_case_failure_handler(source, failure); +} + +// Cases -------------------------------------------------------------------------------------------------------------- +Case cases[] = { + Case("Teardown handler returns CONTINUE", continue_case, continue_case_teardown, continue_failure), + Case("Teardown handler returns ABORT but is IGNORED", ignore_case, ignore_case_teardown, ignore_failure), + Case("Teardown handler returns ABORT", abort_case, abort_case_teardown, abort_failure) +}; + +// Specification: Setup & Teardown ------------------------------------------------------------------------------------ +status_t greentea_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(15, "default_auto"); + + return greentea_test_setup_handler(number_of_cases); +} + +void greentea_teardown(const size_t passed, const size_t failed, const failure_t failure) +{ + TEST_ASSERT_EQUAL(8, call_counter++); + TEST_ASSERT_EQUAL(2, passed); + TEST_ASSERT_EQUAL(1, failed); + TEST_ASSERT_EQUAL(REASON_CASE_TEARDOWN, failure.reason); + TEST_ASSERT_EQUAL(LOCATION_CASE_TEARDOWN, failure.location); + + // pretend to greentea that the test was successful + greentea_test_teardown_handler(3, 0, REASON_NONE); +} + +Specification specification(greentea_setup, cases, greentea_teardown, selftest_handlers); + +int main() +{ + // Run the specification only AFTER setting the custom scheduler(if required). + Harness::run(specification); +} diff --git a/frameworks/utest/TESTS/unit_tests/control_type/main.cpp b/frameworks/utest/TESTS/unit_tests/control_type/main.cpp new file mode 100644 index 0000000000..3103ffaf64 --- /dev/null +++ b/frameworks/utest/TESTS/unit_tests/control_type/main.cpp @@ -0,0 +1,275 @@ + +/* mbed Microcontroller Library + * Copyright (c) 2013-2015 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-drivers/mbed.h" +#include "greentea-client/test_env.h" +#include "utest/utest.h" +#include "unity/unity.h" + +#define ASSERT_CONTROL(value, expected_repeat, expected_timeout) { \ + c = value; \ + TEST_ASSERT_EQUAL_MESSAGE(expected_repeat, c.get_repeat(), "Repeat"); \ + TEST_ASSERT_EQUAL_MESSAGE(expected_timeout, c.get_timeout(), "Timeout"); } + + +using namespace utest::v1; + +void test_constructors() +{ + control_t c; + TEST_ASSERT_EQUAL(REPEAT_UNDECLR, c.get_repeat()); + TEST_ASSERT_EQUAL(TIMEOUT_UNDECLR, c.get_timeout()); + + ASSERT_CONTROL(control_t(REPEAT_ALL), REPEAT_ALL, TIMEOUT_UNDECLR); + + ASSERT_CONTROL(control_t(200), REPEAT_UNDECLR, 200); +} + +void test_constants() +{ + control_t c; + + ASSERT_CONTROL(CaseNext, REPEAT_NONE, TIMEOUT_NONE); + + ASSERT_CONTROL(CaseNoRepeat, REPEAT_NONE, TIMEOUT_UNDECLR); + + ASSERT_CONTROL(CaseRepeatAll, REPEAT_ALL, TIMEOUT_UNDECLR); + + ASSERT_CONTROL(CaseRepeatHandler, REPEAT_HANDLER, TIMEOUT_UNDECLR); + + ASSERT_CONTROL(CaseAwait, REPEAT_UNDECLR, TIMEOUT_FOREVER); + + ASSERT_CONTROL(CaseTimeout(0), REPEAT_UNDECLR, 0); + ASSERT_CONTROL(CaseTimeout(100000), REPEAT_UNDECLR, 100000); + + ASSERT_CONTROL(CaseRepeatAllOnTimeout(0), REPEAT_ALL_ON_TIMEOUT, 0); + ASSERT_CONTROL(CaseRepeatAllOnTimeout(100000), REPEAT_ALL_ON_TIMEOUT, 100000); + + ASSERT_CONTROL(CaseRepeatHandlerOnTimeout(0), REPEAT_HANDLER_ON_TIMEOUT, 0); + ASSERT_CONTROL(CaseRepeatHandlerOnTimeout(100000), REPEAT_HANDLER_ON_TIMEOUT, 100000); +} + +void test_same_group_combinations() +{ + control_t c; + // arbitration within same group should not change anything + ASSERT_CONTROL(CaseNext + CaseNext, REPEAT_NONE, TIMEOUT_NONE); + + ASSERT_CONTROL(CaseNoRepeat + CaseNoRepeat, REPEAT_NONE, TIMEOUT_UNDECLR); + + ASSERT_CONTROL(CaseRepeatAll + CaseRepeatAll, REPEAT_ALL, TIMEOUT_UNDECLR); + + ASSERT_CONTROL(CaseRepeatHandler + CaseRepeatHandler, REPEAT_HANDLER, TIMEOUT_UNDECLR); + + ASSERT_CONTROL(CaseAwait + CaseAwait, REPEAT_UNDECLR, TIMEOUT_FOREVER); + + // same group _and_ same values + ASSERT_CONTROL(CaseTimeout( 0) + CaseTimeout( 0), REPEAT_UNDECLR, 0); + ASSERT_CONTROL(CaseTimeout(100000) + CaseTimeout(100000), REPEAT_UNDECLR, 100000); + + ASSERT_CONTROL(CaseRepeatAllOnTimeout( 0) + CaseRepeatAllOnTimeout( 0), REPEAT_ALL_ON_TIMEOUT, 0); + ASSERT_CONTROL(CaseRepeatAllOnTimeout(100000) + CaseRepeatAllOnTimeout(100000), REPEAT_ALL_ON_TIMEOUT, 100000); + + ASSERT_CONTROL(CaseRepeatHandlerOnTimeout( 0) + CaseRepeatHandlerOnTimeout( 0), REPEAT_HANDLER_ON_TIMEOUT, 0); + ASSERT_CONTROL(CaseRepeatHandlerOnTimeout(100000) + CaseRepeatHandlerOnTimeout(100000), REPEAT_HANDLER_ON_TIMEOUT, 100000); + + // same group but _different_ values + // stricter value should win + ASSERT_CONTROL(CaseTimeout(100) + CaseTimeout( 12), REPEAT_UNDECLR, 12); + ASSERT_CONTROL(CaseTimeout(267) + CaseTimeout(36756), REPEAT_UNDECLR, 267); + + ASSERT_CONTROL(CaseRepeatAllOnTimeout(12145) + CaseRepeatAllOnTimeout( 592), REPEAT_ALL_ON_TIMEOUT, 592); + ASSERT_CONTROL(CaseRepeatAllOnTimeout( 3593) + CaseRepeatAllOnTimeout(294523), REPEAT_ALL_ON_TIMEOUT, 3593); + + ASSERT_CONTROL(CaseRepeatHandlerOnTimeout(124001) + CaseRepeatHandlerOnTimeout(49610), REPEAT_HANDLER_ON_TIMEOUT, 49610); + ASSERT_CONTROL(CaseRepeatHandlerOnTimeout( 47) + CaseRepeatHandlerOnTimeout( 209), REPEAT_HANDLER_ON_TIMEOUT, 47); +} + +void test_different_group_combinations() +{ + // different group and different value + control_t c; + + // Matrix with CaseNext + // CaseNext + CaseNoRepeat => CaseNext + ASSERT_CONTROL(CaseNext + CaseNoRepeat, REPEAT_NONE, TIMEOUT_NONE); + ASSERT_CONTROL(CaseNoRepeat + CaseNext, REPEAT_NONE, TIMEOUT_NONE); + + // CaseNext + CaseRepeatAll => CaseNext + ASSERT_CONTROL(CaseNext + CaseRepeatAll, REPEAT_NONE, TIMEOUT_NONE); + ASSERT_CONTROL(CaseRepeatAll + CaseNext, REPEAT_NONE, TIMEOUT_NONE); + + // CaseNext + CaseRepeatHandler => CaseNext + ASSERT_CONTROL(CaseNext + CaseRepeatHandler, REPEAT_NONE, TIMEOUT_NONE); + ASSERT_CONTROL(CaseRepeatHandler + CaseNext, REPEAT_NONE, TIMEOUT_NONE); + + // CaseNext + CaseNoTimeout => CaseNext + ASSERT_CONTROL(CaseNext + CaseNoTimeout, REPEAT_NONE, TIMEOUT_NONE); + ASSERT_CONTROL(CaseNoTimeout + CaseNext, REPEAT_NONE, TIMEOUT_NONE); + + // CaseNext + CaseAwait => CaseNext + ASSERT_CONTROL(CaseNext + CaseAwait, REPEAT_NONE, TIMEOUT_NONE); + ASSERT_CONTROL(CaseAwait + CaseNext, REPEAT_NONE, TIMEOUT_NONE); + + // CaseNext + CaseTimeout => CaseNext + ASSERT_CONTROL(CaseNext + CaseTimeout(42), REPEAT_NONE, TIMEOUT_NONE); + ASSERT_CONTROL(CaseTimeout(42) + CaseNext, REPEAT_NONE, TIMEOUT_NONE); + + // CaseNext + CaseRepeatAllOnTimeout => CaseNext + ASSERT_CONTROL(CaseNext + CaseRepeatAllOnTimeout(42), REPEAT_NONE, TIMEOUT_NONE); + ASSERT_CONTROL(CaseRepeatAllOnTimeout(42) + CaseNext, REPEAT_NONE, TIMEOUT_NONE); + + // CaseNext + CaseRepeatHandlerOnTimeout => CaseNext + ASSERT_CONTROL(CaseNext + CaseRepeatHandlerOnTimeout(42), REPEAT_NONE, TIMEOUT_NONE); + ASSERT_CONTROL(CaseRepeatHandlerOnTimeout(42) + CaseNext, REPEAT_NONE, TIMEOUT_NONE); + + // Matrix with CaseNoRepeat + // CaseNoRepeat + CaseRepeatHandler => CaseNoRepeat + ASSERT_CONTROL(CaseNoRepeat + CaseRepeatHandler, REPEAT_NONE, TIMEOUT_UNDECLR); + ASSERT_CONTROL(CaseRepeatHandler + CaseNoRepeat, REPEAT_NONE, TIMEOUT_UNDECLR); + + // CaseNoRepeat + CaseNoTimeout => CaseNext + ASSERT_CONTROL(CaseNoRepeat + CaseNoTimeout, REPEAT_NONE, TIMEOUT_NONE); + ASSERT_CONTROL(CaseNoTimeout + CaseNoRepeat, REPEAT_NONE, TIMEOUT_NONE); + + // CaseNoRepeat + CaseAwait => REPEAT_NONE + TIMEOUT_FOREVER + ASSERT_CONTROL(CaseNoRepeat + CaseAwait, REPEAT_NONE, TIMEOUT_FOREVER); + ASSERT_CONTROL(CaseAwait + CaseNoRepeat, REPEAT_NONE, TIMEOUT_FOREVER); + + // CaseNoRepeat + CaseTimeout => REPEAT_NONE + timeout + ASSERT_CONTROL(CaseNoRepeat + CaseTimeout(42), REPEAT_NONE, 42); + ASSERT_CONTROL(CaseTimeout(42) + CaseNoRepeat, REPEAT_NONE, 42); + + // CaseNoRepeat + CaseRepeatAllOnTimeout => REPEAT_NONE + timeout + ASSERT_CONTROL(CaseNoRepeat + CaseRepeatAllOnTimeout(42), REPEAT_NONE, 42); + ASSERT_CONTROL(CaseRepeatAllOnTimeout(42) + CaseNoRepeat, REPEAT_NONE, 42); + + // CaseNoRepeat + CaseRepeatHandlerOnTimeout => REPEAT_NONE + timeout + ASSERT_CONTROL(CaseNoRepeat + CaseRepeatHandlerOnTimeout(42), REPEAT_NONE, 42); + ASSERT_CONTROL(CaseRepeatHandlerOnTimeout(42) + CaseNoRepeat, REPEAT_NONE, 42); + + // Matrix with CaseRepeatAll + // CaseRepeatAll + CaseRepeatHandler => CaseRepeatAll + ASSERT_CONTROL(CaseRepeatAll + CaseRepeatHandler, REPEAT_ALL, TIMEOUT_UNDECLR); + ASSERT_CONTROL(CaseRepeatHandler + CaseRepeatAll, REPEAT_ALL, TIMEOUT_UNDECLR); + + // CaseRepeatAll + CaseNoTimeout => REPEAT_ALL + TIMEOUT_NONE + ASSERT_CONTROL(CaseRepeatAll + CaseNoTimeout, REPEAT_ALL, TIMEOUT_NONE); + ASSERT_CONTROL(CaseNoTimeout + CaseRepeatAll, REPEAT_ALL, TIMEOUT_NONE); + + // CaseRepeatAll + CaseAwait => REPEAT_ALL + TIMEOUT_FOREVER + ASSERT_CONTROL(CaseRepeatAll + CaseAwait, REPEAT_ALL, TIMEOUT_FOREVER); + ASSERT_CONTROL(CaseAwait + CaseRepeatAll, REPEAT_ALL, TIMEOUT_FOREVER); + + // CaseRepeatAll + CaseTimeout => REPEAT_ALL + timeout + ASSERT_CONTROL(CaseRepeatAll + CaseTimeout(42), REPEAT_ALL, 42); + ASSERT_CONTROL(CaseTimeout(42) + CaseRepeatAll, REPEAT_ALL, 42); + + // CaseRepeatAll + CaseRepeatAllOnTimeout => (REPEAT_ALL | REPEAT_ON_TIMEOUT) + timeout + ASSERT_CONTROL(CaseRepeatAll + CaseRepeatAllOnTimeout(42), (REPEAT_ALL | REPEAT_ON_TIMEOUT), 42); + ASSERT_CONTROL(CaseRepeatAllOnTimeout(42) + CaseRepeatAll, (REPEAT_ALL | REPEAT_ON_TIMEOUT), 42); + + // CaseRepeatAll + CaseRepeatHandlerOnTimeout => (REPEAT_ALL | REPEAT_ON_TIMEOUT) + timeout + ASSERT_CONTROL(CaseRepeatAll + CaseRepeatHandlerOnTimeout(42), REPEAT_ALL | REPEAT_ON_TIMEOUT, 42); + ASSERT_CONTROL(CaseRepeatHandlerOnTimeout(42) + CaseRepeatAll, REPEAT_ALL | REPEAT_ON_TIMEOUT, 42); + + // Matrix with CaseRepeatHandler + // CaseRepeatHandler + CaseNoTimeout => REPEAT_HANDLER + TIMEOUT_NONE + ASSERT_CONTROL(CaseRepeatHandler + CaseNoTimeout, REPEAT_HANDLER, TIMEOUT_NONE); + ASSERT_CONTROL(CaseNoTimeout + CaseRepeatHandler, REPEAT_HANDLER, TIMEOUT_NONE); + + // CaseRepeatHandler + CaseAwait => REPEAT_HANDLER + TIMEOUT_FOREVER + ASSERT_CONTROL(CaseRepeatHandler + CaseAwait, REPEAT_HANDLER, TIMEOUT_FOREVER); + ASSERT_CONTROL(CaseAwait + CaseRepeatHandler, REPEAT_HANDLER, TIMEOUT_FOREVER); + + // CaseRepeatHandler + CaseTimeout => REPEAT_HANDLER + timeout + ASSERT_CONTROL(CaseRepeatHandler + CaseTimeout(42), REPEAT_HANDLER, 42); + ASSERT_CONTROL(CaseTimeout(42) + CaseRepeatHandler, REPEAT_HANDLER, 42); + + // CaseRepeatHandler + CaseRepeatAllOnTimeout => (REPEAT_ALL | REPEAT_ON_TIMEOUT) + timeout + ASSERT_CONTROL(CaseRepeatHandler + CaseRepeatAllOnTimeout(42), REPEAT_ALL | REPEAT_ON_TIMEOUT, 42); + ASSERT_CONTROL(CaseRepeatAllOnTimeout(42) + CaseRepeatHandler, REPEAT_ALL | REPEAT_ON_TIMEOUT, 42); + + // CaseRepeatHandler + CaseRepeatHandlerOnTimeout => (REPEAT_HANDLER | REPEAT_ON_TIMEOUT) + timeout + ASSERT_CONTROL(CaseRepeatHandler + CaseRepeatHandlerOnTimeout(42), REPEAT_HANDLER | REPEAT_ON_TIMEOUT, 42); + ASSERT_CONTROL(CaseRepeatHandlerOnTimeout(42) + CaseRepeatHandler, REPEAT_HANDLER | REPEAT_ON_TIMEOUT, 42); + + // Matrix with CaseNoTimeout + // CaseNoTimeout + CaseAwait => CaseNoTimeout + ASSERT_CONTROL(CaseNoTimeout + CaseAwait, REPEAT_UNDECLR, TIMEOUT_NONE); + ASSERT_CONTROL(CaseAwait + CaseNoTimeout, REPEAT_UNDECLR, TIMEOUT_NONE); + + // CaseNoTimeout + CaseTimeout => CaseNoTimeout + ASSERT_CONTROL(CaseNoTimeout + CaseTimeout(42), REPEAT_UNDECLR, TIMEOUT_NONE); + ASSERT_CONTROL(CaseTimeout(42) + CaseNoTimeout, REPEAT_UNDECLR, TIMEOUT_NONE); + + // CaseNoTimeout + CaseRepeatAllOnTimeout => REPEAT_SETUP_TEARDOWN + TIMEOUT_NONE + ASSERT_CONTROL(CaseNoTimeout + CaseRepeatAllOnTimeout(42), REPEAT_SETUP_TEARDOWN, TIMEOUT_NONE); + ASSERT_CONTROL(CaseRepeatAllOnTimeout(42) + CaseNoTimeout, REPEAT_SETUP_TEARDOWN, TIMEOUT_NONE); + + // CaseNoTimeout + CaseRepeatHandlerOnTimeout => REPEAT_CASE_ONLY + TIMEOUT_NONE + ASSERT_CONTROL(CaseNoTimeout + CaseRepeatHandlerOnTimeout(42), REPEAT_CASE_ONLY, TIMEOUT_NONE); + ASSERT_CONTROL(CaseRepeatHandlerOnTimeout(42) + CaseNoTimeout, REPEAT_CASE_ONLY, TIMEOUT_NONE); + + // Matrix with CaseAwait + // CaseAwait + CaseTimeout => CaseTimeout + ASSERT_CONTROL(CaseAwait + CaseTimeout(42), REPEAT_UNDECLR, 42); + ASSERT_CONTROL(CaseTimeout(42) + CaseAwait, REPEAT_UNDECLR, 42); + + // CaseAwait + CaseRepeatAllOnTimeout => CaseRepeatAllOnTimeout + ASSERT_CONTROL(CaseAwait + CaseRepeatAllOnTimeout(42), REPEAT_ALL_ON_TIMEOUT, 42); + ASSERT_CONTROL(CaseRepeatAllOnTimeout(42) + CaseAwait, REPEAT_ALL_ON_TIMEOUT, 42); + + // CaseAwait + CaseRepeatHandlerOnTimeout => CaseRepeatHandlerOnTimeout + ASSERT_CONTROL(CaseAwait + CaseRepeatHandlerOnTimeout(42), REPEAT_HANDLER_ON_TIMEOUT, 42); + ASSERT_CONTROL(CaseRepeatHandlerOnTimeout(42) + CaseAwait, REPEAT_HANDLER_ON_TIMEOUT, 42); + + // Matrix with CaseTimeout + // CaseTimeout + CaseRepeatAllOnTimeout => CaseRepeatAllOnTimeout with lower timeout + ASSERT_CONTROL(CaseTimeout(21) + CaseRepeatAllOnTimeout(42), REPEAT_ALL_ON_TIMEOUT, 21); + ASSERT_CONTROL(CaseRepeatAllOnTimeout(42) + CaseTimeout(21), REPEAT_ALL_ON_TIMEOUT, 21); + + // CaseAwait + CaseRepeatHandlerOnTimeout => CaseRepeatHandlerOnTimeout with lower timeout + ASSERT_CONTROL(CaseTimeout(21) + CaseRepeatHandlerOnTimeout(42), REPEAT_HANDLER_ON_TIMEOUT, 21); + ASSERT_CONTROL(CaseRepeatHandlerOnTimeout(42) + CaseTimeout(21), REPEAT_HANDLER_ON_TIMEOUT, 21); + + // Matrix with CaseRepeatAllOnTimeout + // CaseRepeatAllOnTimeout + CaseRepeatHandlerOnTimeout => CaseRepeatAllOnTimeout with lower timeout + ASSERT_CONTROL(CaseRepeatAllOnTimeout(21) + CaseRepeatHandlerOnTimeout(42), REPEAT_ALL_ON_TIMEOUT, 21); + ASSERT_CONTROL(CaseRepeatHandlerOnTimeout(42) + CaseRepeatAllOnTimeout(21), REPEAT_ALL_ON_TIMEOUT, 21); +} + +Case cases[] = +{ + Case("Testing constructors", test_constructors), + Case("Testing constants", test_constants), + Case("Testing combinations of same group", test_same_group_combinations), + Case("Testing combinations of different group", test_different_group_combinations) +}; + +status_t greentea_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(15, "default_auto"); + + return greentea_test_setup_handler(number_of_cases); +}; +Specification specification(greentea_setup, cases, greentea_continue_handlers); + +int main() +{ + // Run the specification only AFTER setting the custom scheduler(if required). + Harness::run(specification); +} diff --git a/frameworks/utest/TESTS/unit_tests/minimal_async_scheduler/main.cpp b/frameworks/utest/TESTS/unit_tests/minimal_async_scheduler/main.cpp new file mode 100644 index 0000000000..97e23f8b63 --- /dev/null +++ b/frameworks/utest/TESTS/unit_tests/minimal_async_scheduler/main.cpp @@ -0,0 +1,171 @@ + +/* 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. + */ + +// define this to get rid of the minar dependency. +#define YOTTA_CFG_UTEST_USE_CUSTOM_SCHEDULER 1 + +#include "mbed-drivers/mbed.h" +#include "greentea-client/test_env.h" +#include "utest/utest.h" +#include "unity/unity.h" +#include "utest/stack_trace.h" + +#include "ticker_api.h" +#include "us_ticker_api.h" + +using namespace utest::v1; + +// only one callback is active at any given time +volatile utest_v1_harness_callback_t minimal_callback; +volatile utest_v1_harness_callback_t ticker_callback; +static Timeout utest_minimal_object; + +// Scheduler ---------------------------------------------------------------------------------------------------------- +static void ticker_handler() +{ + UTEST_LOG_FUNCTION(); +// printf("\t\t>>> Ticker callback fired for %p.\n", ticker_callback); + minimal_callback = ticker_callback; +} + +static int32_t utest_minimal_init() +{ + UTEST_LOG_FUNCTION(); + minimal_callback = NULL; + ticker_callback = NULL; + return 0; +} +static void *utest_minimal_post(const utest_v1_harness_callback_t callback, timestamp_t delay_ms) +{ + UTEST_LOG_FUNCTION(); + // printf("\t\t>>> Schedule %p with %ums delay => %p.\n", callback, (unsigned int)delay_ms, (void*)1); + timestamp_t delay_us = delay_ms *1000; + + if (delay_ms) { + ticker_callback = callback; + // fire the interrupt in 1000us * delay_ms + utest_minimal_object.attach_us(ticker_handler, delay_us); + } else { + minimal_callback = callback; + } + + // return a bogus handle + return (void*)1; +} +static int32_t utest_minimal_cancel(void *handle) +{ + UTEST_LOG_FUNCTION(); + printf("\t\t>>> Cancel %p => %u\n", handle, (unsigned int)0); + (void) handle; + utest_minimal_object.detach(); + return 0; +} +static int32_t utest_minimal_run() +{ + UTEST_LOG_FUNCTION(); + /* This is the amazing minimal scheduler. + * This is just a busy loop that calls the callbacks in this context. + * THIS LOOP IS BLOCKING. + */ + 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; +} +static const utest_v1_scheduler_t utest_minimal_scheduler = +{ + utest_minimal_init, + utest_minimal_post, + utest_minimal_cancel, + utest_minimal_run +}; + +// Tests -------------------------------------------------------------------------------------------------------------- +int call_counter(0); + +// Basic Test Case ---------------------------------------------------------------------------------------------------- +control_t test_case() +{ + UTEST_LOG_FUNCTION(); + static int counter(0); + TEST_ASSERT_EQUAL(counter++, call_counter++); + printf("Running Test #%d\n", counter); + return CaseNext; +} + +// Async Test Case Failure -------------------------------------------------------------------------------------------- +control_t test_case_async() +{ + UTEST_LOG_FUNCTION(); + static int counter(3); + TEST_ASSERT_EQUAL(counter++, call_counter++); + printf("Running Test #%d\n", counter); + return CaseTimeout(200); +} +status_t test_case_async_failure(const Case *const source, const failure_t reason) +{ + UTEST_LOG_FUNCTION(); + // ignore the timeout, since this is a test + return greentea_case_failure_continue_handler(source, reason.ignored()); +} + +// Cases -------------------------------------------------------------------------------------------------------------- +Case cases[] = { + Case("Minimal Scheduler: Case 1", test_case), + Case("Minimal Scheduler: Case 2", test_case), + Case("Minimal Scheduler: Case 3", test_case), + Case("Minimal Scheduler: Async Case 4 (Failure)", test_case_async, test_case_async_failure) +}; + +// Specification: Setup & Teardown ------------------------------------------------------------------------------------ +status_t greentea_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(15, "default_auto"); + return greentea_test_setup_handler(number_of_cases); +} +void greentea_teardown(const size_t passed, const size_t failed, const failure_t failure) +{ + UTEST_LOG_FUNCTION(); + TEST_ASSERT_EQUAL(4, call_counter++); + TEST_ASSERT_EQUAL(4, passed); + TEST_ASSERT_EQUAL(0, failed); + TEST_ASSERT_EQUAL(REASON_NONE, failure.reason); + TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location); + UTEST_DUMP_TRACE + greentea_test_teardown_handler(passed, failed, failure); +} + +Specification specification(greentea_setup, cases, greentea_teardown, selftest_handlers); + +int main() +{ + // You MUST set the custom scheduler before running the specification. + Harness::set_scheduler(utest_minimal_scheduler); + // Run the specification only AFTER setting the custom scheduler. + Harness::run(specification); +} diff --git a/frameworks/utest/TESTS/unit_tests/minimal_scheduler/main.cpp b/frameworks/utest/TESTS/unit_tests/minimal_scheduler/main.cpp new file mode 100644 index 0000000000..97dfe6b33a --- /dev/null +++ b/frameworks/utest/TESTS/unit_tests/minimal_scheduler/main.cpp @@ -0,0 +1,125 @@ + +/* 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. + */ + +// define this to get rid of the minar dependency. +#define YOTTA_CFG_UTEST_USE_CUSTOM_SCHEDULER 1 + +#include "mbed-drivers/mbed.h" +#include "greentea-client/test_env.h" +#include "utest/utest.h" +#include "unity/unity.h" + +using namespace utest::v1; + +// only one callback is active at any given time +volatile utest_v1_harness_callback_t minimal_callback; + +// Scheduler ---------------------------------------------------------------------------------------------------------- +static int32_t utest_minimal_init() +{ + minimal_callback = NULL; + return 0; +} +static void *utest_minimal_post(const utest_v1_harness_callback_t callback, const uint32_t delay_ms) +{ + minimal_callback = callback; + // this scheduler does not support scheduling of asynchronous callbacks + return (delay_ms ? NULL : (void*)1); +} +static int32_t utest_minimal_cancel(void *handle) +{ + (void) handle; + // this scheduler does not support canceling of asynchronous callbacks + return -1; +} +static int32_t utest_minimal_run() +{ + /* This is the amazing minimal scheduler. + * This is just a busy loop that calls the callbacks in this context. + * THIS LOOP IS BLOCKING. + */ + while(1) + { + // check if a new callback has been set + if (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; +} +static const utest_v1_scheduler_t utest_minimal_scheduler = +{ + utest_minimal_init, + utest_minimal_post, + utest_minimal_cancel, + utest_minimal_run +}; + +// Tests -------------------------------------------------------------------------------------------------------------- +int call_counter(0); + +// Basic Test Case ---------------------------------------------------------------------------------------------------- +control_t test_case() +{ + static int counter(0); + TEST_ASSERT_EQUAL(counter++, call_counter++); + printf("Running Test #%d\n", counter); + return CaseNext; +} + +// Cases -------------------------------------------------------------------------------------------------------------- +Case cases[] = { + Case("Minimal Scheduler: Case 1", test_case), + Case("Minimal Scheduler: Case 2", test_case), + Case("Minimal Scheduler: Case 3", test_case), + Case("Minimal Scheduler: Case 4", test_case), + Case("Minimal Scheduler: Case 5", test_case), + Case("Minimal Scheduler: Case 6", test_case), + Case("Minimal Scheduler: Case 7", test_case), + Case("Minimal Scheduler: Case 8", test_case) +}; + +// Specification: Setup & Teardown ------------------------------------------------------------------------------------ +status_t greentea_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(15, "default_auto"); + return greentea_test_setup_handler(number_of_cases); +} +void greentea_teardown(const size_t passed, const size_t failed, const failure_t failure) +{ + TEST_ASSERT_EQUAL(8, call_counter++); + TEST_ASSERT_EQUAL(8, passed); + TEST_ASSERT_EQUAL(0, failed); + TEST_ASSERT_EQUAL(REASON_NONE, failure.reason); + TEST_ASSERT_EQUAL(LOCATION_NONE, failure.location); + greentea_test_teardown_handler(passed, failed, failure); +} + +Specification specification(greentea_setup, cases, greentea_teardown, selftest_handlers); + +int main() +{ + // You MUST set the custom scheduler before running the specification. + Harness::set_scheduler(utest_minimal_scheduler); + // Run the specification only AFTER setting the custom scheduler. + Harness::run(specification); +} diff --git a/frameworks/utest/TESTS/unit_tests/test_assertion_failure_test_setup/main.cpp b/frameworks/utest/TESTS/unit_tests/test_assertion_failure_test_setup/main.cpp new file mode 100644 index 0000000000..0f14c41860 --- /dev/null +++ b/frameworks/utest/TESTS/unit_tests/test_assertion_failure_test_setup/main.cpp @@ -0,0 +1,83 @@ + +/* mbed Microcontroller Library + * Copyright (c) 2013-2015 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-drivers/mbed.h" +#include "greentea-client/test_env.h" +#include "utest/utest.h" +#include "unity/unity.h" + + +using namespace utest::v1; + +static bool failure_is_in_setup = false; + +void never_call_case() +{ + TEST_FAIL_MESSAGE("Case handler should have never been called!"); +} +Case cases[] = +{ + Case("dummy test", never_call_case) +}; + +// this setup handler fails +status_t failing_setup_handler(const size_t number_of_cases) +{ + GREENTEA_SETUP(5, "default_auto"); + + status_t status = greentea_test_setup_handler(number_of_cases); + + failure_is_in_setup = true; + TEST_FAIL_MESSAGE("Explicit assertion failure in test setup handler!"); + return status; +}; + +void test_failure_handler(const failure_t failure) +{ + if (failure_is_in_setup) { + failure_is_in_setup = false; + TEST_ASSERT_EQUAL(REASON_ASSERTION, failure.reason); + TEST_ASSERT_EQUAL(LOCATION_TEST_SETUP, failure.location); + verbose_test_failure_handler(failure); + + // pretend to greentea that we actally executed one test case + greentea_case_setup_handler(cases, 0); + greentea_case_teardown_handler(cases, 1, 0, REASON_NONE); + + // pretend to greentea that the test was successful + greentea_test_teardown_handler(1, 0, REASON_NONE); + while(1) ; + } + else { + selftest_handlers.test_failure(failure); + } +} + +const handlers_t custom_handlers = { + greentea_abort_handlers.test_setup, + greentea_abort_handlers.test_teardown, + test_failure_handler, + greentea_abort_handlers.case_setup, + greentea_abort_handlers.case_teardown, + greentea_abort_handlers.case_failure +}; + +Specification specification(failing_setup_handler, cases, custom_handlers); + +int main() +{ + Harness::run(specification); +} diff --git a/frameworks/utest/TESTS/unit_tests/test_setup_case_selection_failure/main.cpp b/frameworks/utest/TESTS/unit_tests/test_setup_case_selection_failure/main.cpp new file mode 100644 index 0000000000..e7ed2b065a --- /dev/null +++ b/frameworks/utest/TESTS/unit_tests/test_setup_case_selection_failure/main.cpp @@ -0,0 +1,70 @@ + +/* mbed Microcontroller Library + * Copyright (c) 2013-2015 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-drivers/mbed.h" +#include "greentea-client/test_env.h" +#include "utest/utest.h" +#include "unity/unity.h" + + +using namespace utest::v1; + +void never_call_case() +{ + TEST_FAIL_MESSAGE("Case handler should have never been called!"); +} +Case cases[] = +{ + Case("dummy test", never_call_case), + Case("dummy test 2", never_call_case) +}; + +// this setup handler fails since it sends +status_t failing_setup_handler(const size_t number_of_cases) +{ + GREENTEA_SETUP(5, "default_auto"); + + TEST_ASSERT_EQUAL(2, number_of_cases); + greentea_test_setup_handler(number_of_cases); + return status_t(3); // return an index outside the range of the test cases +}; + +// the teardown handler will then be called with the reason `REASON_TEST_SETUP` +void failing_teardown_handler(const size_t passed, const size_t failed, const failure_t failure) +{ + TEST_ASSERT_EQUAL(0, passed); + TEST_ASSERT_EQUAL(0, failed); + TEST_ASSERT_EQUAL(REASON_CASE_INDEX, failure.reason); + TEST_ASSERT_EQUAL(LOCATION_TEST_SETUP, failure.location); + + verbose_test_teardown_handler(passed, failed, failure); + + // pretend to greentea that we actally executed two test case + greentea_case_setup_handler(cases, 0); + greentea_case_teardown_handler(cases, 1, 0, REASON_NONE); + + greentea_case_setup_handler(cases + 1, 0); + greentea_case_teardown_handler(cases + 1, 1, 0, REASON_NONE); + + greentea_test_teardown_handler(2, 0, REASON_NONE); +}; + +Specification specification(failing_setup_handler, cases, failing_teardown_handler, selftest_handlers); + +int main() +{ + Harness::run(specification); +} diff --git a/frameworks/utest/TESTS/unit_tests/test_setup_failure/main.cpp b/frameworks/utest/TESTS/unit_tests/test_setup_failure/main.cpp new file mode 100644 index 0000000000..bcae024cc5 --- /dev/null +++ b/frameworks/utest/TESTS/unit_tests/test_setup_failure/main.cpp @@ -0,0 +1,70 @@ + +/* mbed Microcontroller Library + * Copyright (c) 2013-2015 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-drivers/mbed.h" +#include "greentea-client/test_env.h" +#include "utest/utest.h" +#include "unity/unity.h" + + +using namespace utest::v1; + +void never_call_case() +{ + TEST_FAIL_MESSAGE("Case handler should have never been called!"); +} +Case cases[] = +{ + Case("dummy test", never_call_case), + Case("dummy test 2", never_call_case) +}; + +// this setup handler fails +status_t failing_setup_handler(const size_t number_of_cases) +{ + GREENTEA_SETUP(5, "default_auto"); + + TEST_ASSERT_EQUAL(2, number_of_cases); + greentea_test_setup_handler(number_of_cases); + return STATUS_ABORT; // aborting test +}; + +// the teardown handler will then be called with the reason `REASON_TEST_SETUP` +void failing_teardown_handler(const size_t passed, const size_t failed, const failure_t failure) +{ + TEST_ASSERT_EQUAL(0, passed); + TEST_ASSERT_EQUAL(0, failed); + TEST_ASSERT_EQUAL(REASON_TEST_SETUP, failure.reason); + TEST_ASSERT_EQUAL(LOCATION_TEST_SETUP, failure.location); + + verbose_test_teardown_handler(passed, failed, failure); + + // pretend to greentea that we actally executed two test case + greentea_case_setup_handler(cases, 0); + greentea_case_teardown_handler(cases, 1, 0, REASON_NONE); + + greentea_case_setup_handler(cases + 1, 0); + greentea_case_teardown_handler(cases + 1, 1, 0, REASON_NONE); + + greentea_test_teardown_handler(2, 0, REASON_NONE); +}; + +Specification specification(failing_setup_handler, cases, failing_teardown_handler, selftest_handlers); + +int main() +{ + Harness::run(specification); +} diff --git a/frameworks/utest/source/default_handlers.cpp b/frameworks/utest/source/default_handlers.cpp index 9ee928df1e..f8774ebd95 100644 --- a/frameworks/utest/source/default_handlers.cpp +++ b/frameworks/utest/source/default_handlers.cpp @@ -37,7 +37,7 @@ const handlers_t utest::v1::verbose_continue_handlers = { // --- SPECIAL HANDLERS --- static void test_failure_handler(const failure_t failure) { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); if (failure.location == LOCATION_TEST_SETUP || failure.location == LOCATION_TEST_TEARDOWN) { verbose_test_failure_handler(failure); printf("{{failure}}\n{{end}}\n"); @@ -48,14 +48,14 @@ static void test_failure_handler(const failure_t failure) { // --- VERBOSE TEST HANDLERS --- utest::v1::status_t utest::v1::verbose_test_setup_handler(const size_t number_of_cases) { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); 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) { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); printf("\n>>> Test cases: %u passed, %u failed", passed, failed); if (failure.reason == REASON_NONE) { printf("\n"); @@ -74,14 +74,14 @@ void utest::v1::verbose_test_failure_handler(const failure_t failure) // --- VERBOSE CASE HANDLERS --- utest::v1::status_t utest::v1::verbose_case_setup_handler(const Case *const source, const size_t index_of_case) { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); printf("\n>>> Running case #%u: '%s'...\n", index_of_case + 1, source->get_description()); return STATUS_CONTINUE; } utest::v1::status_t utest::v1::verbose_case_teardown_handler(const Case *const source, const size_t passed, const size_t failed, const failure_t failure) { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); printf(">>> '%s': %u passed, %u failed", source->get_description(), passed, failed); if (failure.reason == REASON_NONE) { printf("\n"); @@ -93,7 +93,7 @@ utest::v1::status_t utest::v1::verbose_case_teardown_handler(const Case *const s utest::v1::status_t utest::v1::verbose_case_failure_handler(const Case *const /*source*/, const failure_t failure) { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); if (!(failure.reason & REASON_ASSERTION)) { verbose_test_failure_handler(failure); } diff --git a/frameworks/utest/source/greentea_handlers.cpp b/frameworks/utest/source/greentea_handlers.cpp index c1e4bf37a5..815aa2ac8b 100644 --- a/frameworks/utest/source/greentea_handlers.cpp +++ b/frameworks/utest/source/greentea_handlers.cpp @@ -58,7 +58,7 @@ const handlers_t utest::v1::selftest_handlers = { // --- SPECIAL HANDLERS --- static utest::v1::status_t unknown_test_setup_handler(const size_t) { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); 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"); @@ -66,7 +66,7 @@ static utest::v1::status_t unknown_test_setup_handler(const size_t) { } static void selftest_failure_handler(const failure_t failure) { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); if (failure.location == LOCATION_TEST_SETUP || failure.location == LOCATION_TEST_TEARDOWN || failure.reason == REASON_ASSERTION) { verbose_test_failure_handler(failure); } @@ -78,7 +78,7 @@ static void selftest_failure_handler(const failure_t failure) { } static void test_failure_handler(const failure_t failure) { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); if (failure.location == LOCATION_TEST_SETUP || failure.location == LOCATION_TEST_TEARDOWN) { verbose_test_failure_handler(failure); GREENTEA_TESTSUITE_RESULT(false); @@ -89,14 +89,14 @@ static void test_failure_handler(const failure_t failure) { // --- GREENTEA HANDLERS --- utest::v1::status_t utest::v1::greentea_test_setup_handler(const size_t number_of_cases) { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); 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) { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); 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))); @@ -105,14 +105,14 @@ void utest::v1::greentea_test_teardown_handler(const size_t passed, const size_t void utest::v1::greentea_test_failure_handler(const failure_t failure) { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); verbose_test_failure_handler(failure); } // --- GREENTEA CASE HANDLERS --- utest::v1::status_t utest::v1::greentea_case_setup_handler(const Case *const source, const size_t index_of_case) { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); utest::v1::status_t status = verbose_case_setup_handler(source, index_of_case); greentea_send_kv(TEST_ENV_TESTCASE_START, source->get_description()); return status; @@ -120,20 +120,20 @@ utest::v1::status_t utest::v1::greentea_case_setup_handler(const Case *const sou utest::v1::status_t utest::v1::greentea_case_teardown_handler(const Case *const source, const size_t passed, const size_t failed, const failure_t failure) { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); greentea_send_kv(TEST_ENV_TESTCASE_FINISH, source->get_description(), passed, failed); return verbose_case_teardown_handler(source, passed, failed, failure); } utest::v1::status_t utest::v1::greentea_case_failure_abort_handler(const Case *const source, const failure_t failure) { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); utest::v1::status_t status = verbose_case_failure_handler(source, failure); return (status == STATUS_IGNORE) ? STATUS_IGNORE : STATUS_ABORT; } utest::v1::status_t utest::v1::greentea_case_failure_continue_handler(const Case *const source, const failure_t failure) { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); return verbose_case_failure_handler(source, failure); } diff --git a/frameworks/utest/source/harness.cpp b/frameworks/utest/source/harness.cpp index 43b6439bd0..b95274fc7e 100644 --- a/frameworks/utest/source/harness.cpp +++ b/frameworks/utest/source/harness.cpp @@ -55,19 +55,19 @@ namespace } static void die() { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); while(1) ; } static bool is_scheduler_valid(const utest_v1_scheduler_t scheduler) { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); return (scheduler.init && scheduler.post && scheduler.cancel && scheduler.run); } bool Harness::set_scheduler(const utest_v1_scheduler_t scheduler) { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); if (is_scheduler_valid(scheduler)) { ::scheduler = scheduler; return true; @@ -77,13 +77,13 @@ bool Harness::set_scheduler(const utest_v1_scheduler_t scheduler) bool Harness::run(const Specification& specification, size_t) { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); return run(specification); } bool Harness::run(const Specification& specification) { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); // check if a specification is currently running if (is_busy()) return false; @@ -91,13 +91,14 @@ bool Harness::run(const Specification& specification) // 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; @@ -149,7 +150,7 @@ bool Harness::run(const Specification& specification) void Harness::raise_failure(const failure_reason_t reason) { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); // 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; @@ -195,7 +196,7 @@ void Harness::raise_failure(const failure_reason_t reason) void Harness::schedule_next_case() { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); if (!case_timeout_occurred && case_failed_before == case_failed) { case_passed++; } @@ -231,7 +232,7 @@ void Harness::schedule_next_case() void Harness::handle_timeout() { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); { UTEST_ENTER_CRITICAL_SECTION; @@ -249,7 +250,7 @@ void Harness::handle_timeout() void Harness::validate_callback(const control_t control) { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); UTEST_ENTER_CRITICAL_SECTION; case_validation_count++; @@ -269,7 +270,7 @@ void Harness::validate_callback(const control_t control) bool Harness::is_busy() { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); UTEST_ENTER_CRITICAL_SECTION; if (!test_cases) return false; if (!case_current) return false; @@ -281,7 +282,7 @@ bool Harness::is_busy() void Harness::run_next_case() { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); if(case_current < (test_cases + test_length)) { handlers.case_setup = defaults.get_handler(case_current->setup_handler); diff --git a/frameworks/utest/source/shim.cpp b/frameworks/utest/source/shim.cpp index 31adecc409..8630e0aeb4 100644 --- a/frameworks/utest/source/shim.cpp +++ b/frameworks/utest/source/shim.cpp @@ -69,20 +69,20 @@ Timeout utest_timeout_object; static void ticker_handler() { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); //printf("\t\t>>> Ticker callback fired for %p.\n", ticker_callback); minimal_callback = ticker_callback; } static int32_t utest_us_ticker_init() { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); // Ticker scheduler does not require any initialisation so return immediately return 0; } static void *utest_us_ticker_post(const utest_v1_harness_callback_t callback, timestamp_t delay_ms) { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); timestamp_t delay_us = delay_ms *1000; //printf("\t\t>>> Schedule %p with %ums delay => %p.\n", callback, (unsigned int)delay_ms, (void*)1); @@ -103,7 +103,7 @@ static void *utest_us_ticker_post(const utest_v1_harness_callback_t callback, ti } static int32_t utest_us_ticker_cancel(void *handle) { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); //printf("\t\t>>> Cancel %p => %u\n", handle, (unsigned int)0); (void) handle; utest_timeout_object.detach(); @@ -111,7 +111,7 @@ static int32_t utest_us_ticker_cancel(void *handle) } static int32_t utest_us_ticker_run() { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); while(1) { // check if a new callback has been set @@ -138,7 +138,7 @@ static const utest_v1_scheduler_t utest_v1_scheduler = }; utest_v1_scheduler_t utest_v1_get_scheduler() { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); return utest_v1_scheduler; } } diff --git a/frameworks/utest/source/stack_trace.cpp b/frameworks/utest/source/stack_trace.cpp index c44d2260f1..3ff1c874aa 100644 --- a/frameworks/utest/source/stack_trace.cpp +++ b/frameworks/utest/source/stack_trace.cpp @@ -26,6 +26,8 @@ using namespace utest::v1; +std::string utest_trace[UTEST_MAX_BACKTRACE]; + static unsigned trace_index = 0; static unsigned total_calls = 0; @@ -39,11 +41,7 @@ void utest_trace_initialise() } void utest_add_to_trace(char *func_name) -{ - - // Check if we have already used this entry. If so free the previously allocated - // string. - utest_trace[trace_index].clear(); +{ utest_trace[trace_index] = std::string(func_name); trace_index = (trace_index + 1 == UTEST_MAX_BACKTRACE) ? 0 : trace_index + 1; total_calls ++; diff --git a/frameworks/utest/source/unity_handler.cpp b/frameworks/utest/source/unity_handler.cpp index e58d15447b..7a8c67f319 100644 --- a/frameworks/utest/source/unity_handler.cpp +++ b/frameworks/utest/source/unity_handler.cpp @@ -23,13 +23,13 @@ extern "C" void utest_unity_assert_failure() { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); utest::v1::Harness::raise_failure(utest::v1::REASON_ASSERTION); } extern "C" void utest_unity_ignore_failure() { - UTEST_LOG_FUNCTION + UTEST_LOG_FUNCTION(); utest::v1::Harness::raise_failure(utest::v1::failure_reason_t(utest::v1::REASON_ASSERTION | utest::v1::REASON_IGNORE)); } diff --git a/frameworks/utest/utest/stack_trace.h b/frameworks/utest/utest/stack_trace.h index e484c0c990..d8ba213862 100644 --- a/frameworks/utest/utest/stack_trace.h +++ b/frameworks/utest/utest/stack_trace.h @@ -29,13 +29,13 @@ extern void utest_trace_initialise(); extern void utest_add_to_trace(char *func_name); extern void utest_dump_trace(); -#define UTEST_LOG_FUNCTION utest_add_to_trace((char *)__func__); +#define UTEST_LOG_FUNCTION(); utest_add_to_trace((char *)__func__); #define UTEST_TRACE_START utest_trace_initialise(); #define UTEST_DUMP_TRACE utest_dump_trace(); #else -#define UTEST_LOG_FUNCTION +#define UTEST_LOG_FUNCTION(); #define UTEST_TRACE_START #define UTEST_DUMP_TRACE