diff --git a/.gitlab/ci/target-test.yml b/.gitlab/ci/target-test.yml index d861b83c15..ca779b5807 100644 --- a/.gitlab/ci/target-test.yml +++ b/.gitlab/ci/target-test.yml @@ -395,12 +395,34 @@ test_app_test_esp32_generic: - .component_ut_template - .rules:test:component_ut-esp32 +.component_ut_esp32s2_template: + extends: + - .component_ut_template + - .rules:test:component_ut-esp32s2 + +.component_ut_esp32c3_template: + extends: + - .component_ut_template + - .rules:test:component_ut-esp32c3 + component_ut_test_001: extends: .component_ut_esp32_template tags: - ESP32 - COMPONENT_UT_GENERIC +component_ut_test_esp32s2: + extends: .component_ut_esp32s2_template + tags: + - ESP32S2 + - COMPONENT_UT_GENERIC + +component_ut_test_esp32c3: + extends: .component_ut_esp32c3_template + tags: + - ESP32C3 + - COMPONENT_UT_GENERIC + .unit_test_template: extends: .target_test_job_template variables: diff --git a/components/newlib/stdatomic.c b/components/newlib/stdatomic.c index a58b203ccd..993fcd1ac2 100644 --- a/components/newlib/stdatomic.c +++ b/components/newlib/stdatomic.c @@ -1,4 +1,4 @@ -// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -17,61 +17,78 @@ #include "sdkconfig.h" #include #include +#include "soc/soc_caps.h" +#include "freertos/FreeRTOS.h" #ifdef __XTENSA__ - #include "xtensa/config/core-isa.h" -#include "xtensa/xtruntime.h" - -// This allows nested interrupts disabling and restoring via local registers or stack. -// They can be called from interrupts too. -// WARNING: Only applies to current CPU. -#define _ATOMIC_ENTER_CRITICAL(void) ({ \ - unsigned state = XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL); \ - atomic_benchmark_intr_disable(); \ - state; \ -}) - -#define _ATOMIC_EXIT_CRITICAL(state) do { \ - atomic_benchmark_intr_restore(state); \ - XTOS_RESTORE_JUST_INTLEVEL(state); \ - } while (0) #ifndef XCHAL_HAVE_S32C1I #error "XCHAL_HAVE_S32C1I not defined, include correct header!" #endif -#define NO_ATOMICS_SUPPORT (XCHAL_HAVE_S32C1I == 0) +#define HAS_ATOMICS_32 (XCHAL_HAVE_S32C1I == 1) +// no 64-bit atomics on Xtensa +#define HAS_ATOMICS_64 0 + #else // RISCV -#include "freertos/portmacro.h" - -// This allows nested interrupts disabling and restoring via local registers or stack. -// They can be called from interrupts too. -// WARNING: Only applies to current CPU. -#define _ATOMIC_ENTER_CRITICAL(void) ({ \ - unsigned state = portENTER_CRITICAL_NESTED(); \ - atomic_benchmark_intr_disable(); \ - state; \ -}) - -#define _ATOMIC_EXIT_CRITICAL(state) do { \ - atomic_benchmark_intr_restore(state); \ - portEXIT_CRITICAL_NESTED(state); \ - } while (0) - -#ifndef __riscv_atomic // GCC toolchain will define this pre-processor if "A" extension is supported +// GCC toolchain will define this pre-processor if "A" extension is supported +#ifndef __riscv_atomic #define __riscv_atomic 0 #endif -#define NO_ATOMICS_SUPPORT (__riscv_atomic == 0) +#define HAS_ATOMICS_32 (__riscv_atomic == 1) +#define HAS_ATOMICS_64 ((__riscv_atomic == 1) && (__riscv_xlen == 64)) +#endif // (__XTENSA__, __riscv) -#endif +#if SOC_CPU_CORES_NUM == 1 +// Single core SoC: atomics can be implemented using portENTER_CRITICAL_NESTED +// and portEXIT_CRITICAL_NESTED, which disable and enable interrupts. +#define _ATOMIC_ENTER_CRITICAL() ({ \ + unsigned state = portENTER_CRITICAL_NESTED(); \ + state; \ +}) -//reserved to measure atomic operation time -#define atomic_benchmark_intr_disable() -#define atomic_benchmark_intr_restore(STATE) +#define _ATOMIC_EXIT_CRITICAL(state) do { \ + portEXIT_CRITICAL_NESTED(state); \ + } while (0) + +#else // SOC_CPU_CORES_NUM + +_Static_assert(HAS_ATOMICS_32, "32-bit atomics should be supported if SOC_CPU_CORES_NUM > 1"); +// Only need to implement 64-bit atomics here. Use a single global portMUX_TYPE spinlock +// to emulate the atomics. +static portMUX_TYPE s_atomic_lock = portMUX_INITIALIZER_UNLOCKED; + +// Return value is not used but kept for compatibility with the single-core version above. +#define _ATOMIC_ENTER_CRITICAL() ({ \ + portENTER_CRITICAL_SAFE(&s_atomic_lock); \ + 0; \ +}) + +#define _ATOMIC_EXIT_CRITICAL(state) do { \ + (void) (state); \ + portEXIT_CRITICAL_SAFE(&s_atomic_lock); \ +} while(0) + +#endif // SOC_CPU_CORES_NUM + +#define ATOMIC_LOAD(n, type) type __atomic_load_ ## n (const type* mem, int memorder) \ +{ \ + unsigned state = _ATOMIC_ENTER_CRITICAL(); \ + type ret = *mem; \ + _ATOMIC_EXIT_CRITICAL(state); \ + return ret; \ +} + +#define ATOMIC_STORE(n, type) void __atomic_store_ ## n (type* mem, type val, int memorder) \ +{ \ + unsigned state = _ATOMIC_ENTER_CRITICAL(); \ + *mem = val; \ + _ATOMIC_EXIT_CRITICAL(state); \ +} #define ATOMIC_EXCHANGE(n, type) type __atomic_exchange_ ## n (type* mem, type val, int memorder) \ { \ @@ -82,7 +99,7 @@ return ret; \ } -#define CMP_EXCHANGE(n, type) bool __atomic_compare_exchange_ ## n (type* mem, type* expect, type desired, int success, int failure) \ +#define CMP_EXCHANGE(n, type) bool __atomic_compare_exchange_ ## n (type* mem, type* expect, type desired, bool weak, int success, int failure) \ { \ bool ret = false; \ unsigned state = _ATOMIC_ENTER_CRITICAL(); \ @@ -141,12 +158,12 @@ return ret; \ } -#define SYNC_FETCH_OP(op, n, type) type __sync_fetch_and_ ## op ##_ ## n (type* ptr, type value, ...) \ +#define SYNC_FETCH_OP(op, n, type) type __sync_fetch_and_ ## op ##_ ## n (type* ptr, type value) \ { \ return __atomic_fetch_ ## op ##_ ## n (ptr, value, __ATOMIC_SEQ_CST); \ } -#define SYNC_BOOL_CMP_EXCHANGE(n, type) bool __sync_bool_compare_and_swap_ ## n (type *ptr, type oldval, type newval, ...) \ +#define SYNC_BOOL_CMP_EXCHANGE(n, type) bool __sync_bool_compare_and_swap_ ## n (type *ptr, type oldval, type newval) \ { \ bool ret = false; \ unsigned state = _ATOMIC_ENTER_CRITICAL(); \ @@ -158,7 +175,7 @@ return ret; \ } -#define SYNC_VAL_CMP_EXCHANGE(n, type) type __sync_val_compare_and_swap_ ## n (type *ptr, type oldval, type newval, ...) \ +#define SYNC_VAL_CMP_EXCHANGE(n, type) type __sync_val_compare_and_swap_ ## n (type *ptr, type oldval, type newval) \ { \ unsigned state = _ATOMIC_ENTER_CRITICAL(); \ type ret = *ptr; \ @@ -169,78 +186,98 @@ return ret; \ } -#pragma GCC diagnostic ignored "-Wbuiltin-declaration-mismatch" - -#if NO_ATOMICS_SUPPORT +#if !HAS_ATOMICS_32 ATOMIC_EXCHANGE(1, uint8_t) ATOMIC_EXCHANGE(2, uint16_t) ATOMIC_EXCHANGE(4, uint32_t) -ATOMIC_EXCHANGE(8, uint64_t) CMP_EXCHANGE(1, uint8_t) CMP_EXCHANGE(2, uint16_t) CMP_EXCHANGE(4, uint32_t) -CMP_EXCHANGE(8, uint64_t) FETCH_ADD(1, uint8_t) FETCH_ADD(2, uint16_t) FETCH_ADD(4, uint32_t) -FETCH_ADD(8, uint64_t) FETCH_SUB(1, uint8_t) FETCH_SUB(2, uint16_t) FETCH_SUB(4, uint32_t) -FETCH_SUB(8, uint64_t) FETCH_AND(1, uint8_t) FETCH_AND(2, uint16_t) FETCH_AND(4, uint32_t) -FETCH_AND(8, uint64_t) FETCH_OR(1, uint8_t) FETCH_OR(2, uint16_t) FETCH_OR(4, uint32_t) -FETCH_OR(8, uint64_t) FETCH_XOR(1, uint8_t) FETCH_XOR(2, uint16_t) FETCH_XOR(4, uint32_t) -FETCH_XOR(8, uint64_t) SYNC_FETCH_OP(add, 1, uint8_t) SYNC_FETCH_OP(add, 2, uint16_t) SYNC_FETCH_OP(add, 4, uint32_t) -SYNC_FETCH_OP(add, 8, uint64_t) SYNC_FETCH_OP(sub, 1, uint8_t) SYNC_FETCH_OP(sub, 2, uint16_t) SYNC_FETCH_OP(sub, 4, uint32_t) -SYNC_FETCH_OP(sub, 8, uint64_t) SYNC_FETCH_OP(and, 1, uint8_t) SYNC_FETCH_OP(and, 2, uint16_t) SYNC_FETCH_OP(and, 4, uint32_t) -SYNC_FETCH_OP(and, 8, uint64_t) SYNC_FETCH_OP(or, 1, uint8_t) SYNC_FETCH_OP(or, 2, uint16_t) SYNC_FETCH_OP(or, 4, uint32_t) -SYNC_FETCH_OP(or, 8, uint64_t) SYNC_FETCH_OP(xor, 1, uint8_t) SYNC_FETCH_OP(xor, 2, uint16_t) SYNC_FETCH_OP(xor, 4, uint32_t) -SYNC_FETCH_OP(xor, 8, uint64_t) SYNC_BOOL_CMP_EXCHANGE(1, uint8_t) SYNC_BOOL_CMP_EXCHANGE(2, uint16_t) SYNC_BOOL_CMP_EXCHANGE(4, uint32_t) -SYNC_BOOL_CMP_EXCHANGE(8, uint64_t) SYNC_VAL_CMP_EXCHANGE(1, uint8_t) SYNC_VAL_CMP_EXCHANGE(2, uint16_t) SYNC_VAL_CMP_EXCHANGE(4, uint32_t) + +#endif // !HAS_ATOMICS_32 + +#if !HAS_ATOMICS_64 + +ATOMIC_LOAD(8, uint64_t) + +ATOMIC_STORE(8, uint64_t) + +ATOMIC_EXCHANGE(8, uint64_t) + +CMP_EXCHANGE(8, uint64_t) + +FETCH_ADD(8, uint64_t) + +FETCH_SUB(8, uint64_t) + +FETCH_AND(8, uint64_t) + +FETCH_OR(8, uint64_t) + +FETCH_XOR(8, uint64_t) + +SYNC_FETCH_OP(add, 8, uint64_t) + +SYNC_FETCH_OP(sub, 8, uint64_t) + +SYNC_FETCH_OP(and, 8, uint64_t) + +SYNC_FETCH_OP(or, 8, uint64_t) + +SYNC_FETCH_OP(xor, 8, uint64_t) + +SYNC_BOOL_CMP_EXCHANGE(8, uint64_t) + SYNC_VAL_CMP_EXCHANGE(8, uint64_t) -#endif +#endif // !HAS_ATOMICS_64 diff --git a/components/newlib/test_apps/CMakeLists.txt b/components/newlib/test_apps/CMakeLists.txt new file mode 100644 index 0000000000..c529187100 --- /dev/null +++ b/components/newlib/test_apps/CMakeLists.txt @@ -0,0 +1,8 @@ +# This is the project CMakeLists.txt file for the test subproject +cmake_minimum_required(VERSION 3.5) + +set(EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/unit-test-app/components") +set(COMPONENTS main) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(newlib_test) diff --git a/components/newlib/test_apps/app_test.py b/components/newlib/test_apps/app_test.py new file mode 100644 index 0000000000..e9ed329db6 --- /dev/null +++ b/components/newlib/test_apps/app_test.py @@ -0,0 +1,19 @@ +import tiny_test_fw # noqa: F401 # pylint: disable=unused-import +import ttfw_idf + +try: + import typing # noqa: F401 # pylint: disable=unused-import +except ImportError: + pass + + +@ttfw_idf.idf_component_unit_test(env_tag='COMPONENT_UT_GENERIC', target=['esp32', 'esp32s2', 'esp32c3']) +def test_component_ut_newlib(env, _): # type: (tiny_test_fw.Env, typing.Any) -> None + dut = env.get_dut('newlib', 'components/newlib/test_apps') + dut.start_app() + stdout = dut.expect('Tests finished, rc=0', full_stdout=True) + ttfw_idf.ComponentUTResult.parse_result(stdout) + + +if __name__ == '__main__': + test_component_ut_newlib() diff --git a/components/newlib/test_apps/main/CMakeLists.txt b/components/newlib/test_apps/main/CMakeLists.txt new file mode 100644 index 0000000000..3eb45e8ff9 --- /dev/null +++ b/components/newlib/test_apps/main/CMakeLists.txt @@ -0,0 +1,5 @@ +idf_component_register(SRCS + "test_newlib_main.c" + "test_stdatomic.c" + REQUIRES test_utils + PRIV_REQUIRES unity) diff --git a/components/newlib/test_apps/main/test_newlib_main.c b/components/newlib/test_apps/main/test_newlib_main.c new file mode 100644 index 0000000000..1197d8f82d --- /dev/null +++ b/components/newlib/test_apps/main/test_newlib_main.c @@ -0,0 +1,12 @@ +#include "unity.h" +#include "unity_fixture.h" + +static void run_all_tests(void) +{ + RUN_TEST_GROUP(stdatomic); +} + +void app_main(void) +{ + UNITY_MAIN_FUNC(run_all_tests); +} diff --git a/components/newlib/test_apps/main/test_stdatomic.c b/components/newlib/test_apps/main/test_stdatomic.c new file mode 100644 index 0000000000..92df464052 --- /dev/null +++ b/components/newlib/test_apps/main/test_stdatomic.c @@ -0,0 +1,131 @@ +#include +#include +#include +#include +#include +#include +#include +#include "unity.h" +#include "unity_fixture.h" + +/* non-static to prevent optimization */ +atomic_ullong g_atomic64; +atomic_uint g_atomic32; +atomic_ushort g_atomic16; +atomic_uchar g_atomic8; + + +TEST_GROUP(stdatomic); + +TEST_SETUP(stdatomic) +{ +} + +TEST_TEAR_DOWN(stdatomic) +{ +} + +TEST(stdatomic, test_64bit_atomics) +{ + unsigned long long x64 = 0; + g_atomic64 = 0; // calls atomic_store + + x64 += atomic_fetch_or (&g_atomic64, 0x1111111111111111ULL); + x64 += atomic_fetch_xor(&g_atomic64, 0x3333333333333333ULL); + x64 += atomic_fetch_and(&g_atomic64, 0xf0f0f0f0f0f0f0f0ULL); + x64 += atomic_fetch_sub(&g_atomic64, 0x0f0f0f0f0f0f0f0fULL); + x64 += atomic_fetch_add(&g_atomic64, 0x2222222222222222ULL); + + TEST_ASSERT_EQUAL_HEX64(0x6464646464646464ULL, x64); + TEST_ASSERT_EQUAL_HEX64(0x3333333333333333ULL, g_atomic64); // calls atomic_load +} + +TEST(stdatomic, test_32bit_atomics) +{ + unsigned int x32 = 0; + g_atomic32 = 0; + + x32 += atomic_fetch_or (&g_atomic32, 0x11111111U); + x32 += atomic_fetch_xor(&g_atomic32, 0x33333333U); + x32 += atomic_fetch_and(&g_atomic32, 0xf0f0f0f0U); + x32 += atomic_fetch_sub(&g_atomic32, 0x0f0f0f0fU); + x32 += atomic_fetch_add(&g_atomic32, 0x22222222U); + + TEST_ASSERT_EQUAL_HEX32(0x64646464, x32); + TEST_ASSERT_EQUAL_HEX32(0x33333333, g_atomic32); +} + +TEST(stdatomic, test_16bit_atomics) +{ + unsigned int x16 = 0; + g_atomic16 = 0; + + x16 += atomic_fetch_or (&g_atomic16, 0x1111); + x16 += atomic_fetch_xor(&g_atomic16, 0x3333); + x16 += atomic_fetch_and(&g_atomic16, 0xf0f0); + x16 += atomic_fetch_sub(&g_atomic16, 0x0f0f); + x16 += atomic_fetch_add(&g_atomic16, 0x2222); + + TEST_ASSERT_EQUAL_HEX16(0x6464, x16); + TEST_ASSERT_EQUAL_HEX16(0x3333, g_atomic16); +} + +TEST(stdatomic, test_8bit_atomics) +{ + unsigned int x8 = 0; + g_atomic8 = 0; + + x8 += atomic_fetch_or (&g_atomic8, 0x11); + x8 += atomic_fetch_xor(&g_atomic8, 0x33); + x8 += atomic_fetch_and(&g_atomic8, 0xf0); + x8 += atomic_fetch_sub(&g_atomic8, 0x0f); + x8 += atomic_fetch_add(&g_atomic8, 0x22); + + TEST_ASSERT_EQUAL_HEX8(0x64, x8); + TEST_ASSERT_EQUAL_HEX16(0x33, g_atomic8); +} + +static void *exclusion_test_task(void *arg); + +TEST(stdatomic, test_exclusion) +{ + /* Check 64-bit atomics for exclusion. + * Only atomic_fetch_add/sub are checked, since all 64-bit atomics use the + * same locking implementation. + */ + g_atomic64 = 0; + pthread_t thread1; + pthread_t thread2; + pthread_create(&thread1, NULL, exclusion_test_task, (void*) 1); + pthread_create(&thread2, NULL, exclusion_test_task, (void*) 0); + pthread_join(thread1, NULL); + pthread_join(thread2, NULL); + + TEST_ASSERT_EQUAL(0, g_atomic64); +} + +/* Two threads run in parallel, incrementing and decrementing + * a single 64-bit variable. In the end the variable should + * have the same value as at the start. + */ +static void* exclusion_test_task(void *varg) +{ + int arg = (int) varg; + for (int i = 0; i < 1000000; ++i) { + if (arg == 0) { + atomic_fetch_add(&g_atomic64, 1ULL); + } else { + atomic_fetch_sub(&g_atomic64, 1ULL); + } + } + return NULL; +} + +TEST_GROUP_RUNNER(stdatomic) +{ + RUN_TEST_CASE(stdatomic, test_64bit_atomics) + RUN_TEST_CASE(stdatomic, test_32bit_atomics) + RUN_TEST_CASE(stdatomic, test_16bit_atomics) + RUN_TEST_CASE(stdatomic, test_8bit_atomics) + RUN_TEST_CASE(stdatomic, test_exclusion) +} diff --git a/components/newlib/test_apps/sdkconfig.defaults b/components/newlib/test_apps/sdkconfig.defaults new file mode 100644 index 0000000000..61bf4b9395 --- /dev/null +++ b/components/newlib/test_apps/sdkconfig.defaults @@ -0,0 +1,3 @@ +CONFIG_UNITY_ENABLE_FIXTURE=y +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=n +CONFIG_UNITY_ENABLE_64BIT=y diff --git a/components/unity/Kconfig b/components/unity/Kconfig index 4a8779fc92..72952c1e53 100644 --- a/components/unity/Kconfig +++ b/components/unity/Kconfig @@ -13,6 +13,14 @@ menu "Unity unit testing library" help If not set, assertions on double arguments will not be available. + config UNITY_ENABLE_64BIT + bool "Support for 64-bit integer types" + default n + help + If not set, assertions on 64-bit integer types will always fail. + If this feature is enabled, take care not to pass pointers (which are 32 bit) + to UNITY_ASSERT_EQUAL, as that will cause pointer-to-int-cast warnings. + config UNITY_ENABLE_COLOR bool "Colorize test output" default n diff --git a/components/unity/include/unity_config.h b/components/unity/include/unity_config.h index 8ebd88f293..32f9719008 100644 --- a/components/unity/include/unity_config.h +++ b/components/unity/include/unity_config.h @@ -21,13 +21,16 @@ #define UNITY_EXCLUDE_DOUBLE #endif //CONFIG_UNITY_ENABLE_DOUBLE +#ifdef CONFIG_UNITY_ENABLE_64BIT +#define UNITY_SUPPORT_64 +#endif + #ifdef CONFIG_UNITY_ENABLE_COLOR #define UNITY_OUTPUT_COLOR #endif #define UNITY_EXCLUDE_TIME_H - void unity_flush(void); void unity_putc(int c); void unity_gets(char* dst, size_t len); diff --git a/components/unity/include/unity_fixture_extras.h b/components/unity/include/unity_fixture_extras.h index 2eeaec2e3a..c6ad8ba46d 100644 --- a/components/unity/include/unity_fixture_extras.h +++ b/components/unity/include/unity_fixture_extras.h @@ -1,25 +1,78 @@ -/* IDF-specific additions to "Unity Fixture" */ +// Copyright 2016-2021 Espressif Systems (Shanghai) Co. Ltd. +// +// 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. + +/* IDF-specific additions to "Unity Fixture". + * This file doesn't need to be included directly, it gets included into unity.h + * through unity_config.h. + */ + #pragma once -#ifndef CONFIG_IDF_TARGET +#include "sdkconfig.h" -/* A shorthand for running one test group from the main function */ -#define UNITY_MAIN(group_) do { \ +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(CONFIG_IDF_TARGET) || defined(CONFIG_IDF_TARGET_LINUX) +#define UNITY_MAYBE_EXIT(rc) do { exit(rc); } while(0) +#else +#define UNITY_MAYBE_EXIT(rc) do { (void) rc; } while(0) +#endif + +/* A shorthand for running all tests called from one function "func_", from the app_main function. + * Use this when there is more than one test group. + * + * Example: + * + * #include "unity.h" + * #include "unity_fixture.h" + * + * static_void run_all_tests(void) { + * RUN_TEST_GROUP(group1); // test group defined in another file, e.g. test_group1.c + * RUN_TEST_GROUP(group2); // test group defined in another file, e.g. test_group2.c + * } + * + * void app_main(void) { + * UNITY_MAIN_FUNC(run_all_tests); + * } + */ +#define UNITY_MAIN_FUNC(func_) do { \ const char* argv[] = { "test", "-v" }; \ const int argc = sizeof(argv)/sizeof(argv[0]); \ - int rc = UnityMain(argc, argv, TEST_ ## group_ ## _GROUP_RUNNER); \ + int rc = UnityMain(argc, argv, func_); \ printf("\nTests finished, rc=%d\n", rc); \ - exit(rc); \ + UNITY_MAYBE_EXIT(rc); \ } while(0) -#else // CONFIG_IDF_TARGET +/* A shorthand for running one test group from the app_main function, when there is only + * one test group and it is defined in the same file. + * + * Example: + * + * #include "unity.h" + * #include "unity_fixture.h" + * + * TEST_GROUP(my_feature); + * // also define TEST_SETUP, TEST_TEARDOWN, TESTs, TEST_GROUP_RUNNER + * + * void app_main(void) { + * UNITY_MAIN(my_feature); + * } + */ +#define UNITY_MAIN(group_) UNITY_MAIN_FUNC(TEST_ ## group_ ## _GROUP_RUNNER) -/* A shorthand for running one test group from the main function */ -#define UNITY_MAIN(group_) do { \ - const char* argv[] = { "test", "-v" }; \ - const int argc = sizeof(argv)/sizeof(argv[0]); \ - int rc = UnityMain(argc, argv, TEST_ ## group_ ## _GROUP_RUNNER); \ - printf("\nTests finished, rc=%d\n", rc); \ -} while(0) - -#endif // CONFIG_IDF_TARGET +#ifdef __cplusplus +} +#endif diff --git a/tools/ci/check_public_headers_exceptions.txt b/tools/ci/check_public_headers_exceptions.txt index 20861b1a5a..23d779deb4 100644 --- a/tools/ci/check_public_headers_exceptions.txt +++ b/tools/ci/check_public_headers_exceptions.txt @@ -82,7 +82,6 @@ components/spiffs/include/spiffs_config.h components/unity/unity/src/unity_internals.h components/unity/unity/extras/ -components/unity/include/unity_fixture_extras.h components/unity/include/unity_config.h components/unity/include/unity_test_runner.h