diff --git a/components/driver/test/test_adc.c b/components/driver/test/test_adc.c index 6d674ba6b5..dbbb934cf3 100644 --- a/components/driver/test/test_adc.c +++ b/components/driver/test/test_adc.c @@ -11,6 +11,7 @@ #include "test_utils.h" #include "esp_adc_cal.h" #include "driver/adc_common.h" +#include "esp_cpu.h" __attribute__((unused)) static const char *TAG = "ADC"; diff --git a/components/driver/test/test_gpio.c b/components/driver/test/test_gpio.c index 5f73b2ebb8..af243dc513 100644 --- a/components/driver/test/test_gpio.c +++ b/components/driver/test/test_gpio.c @@ -20,7 +20,7 @@ #include "sdkconfig.h" #include "esp_rom_uart.h" #include "esp_rom_sys.h" -#include "test_utils.h" +#include "unity_test_utils.h" #define WAKE_UP_IGNORE 1 // gpio_wakeup function development is not completed yet, set it deprecated. @@ -457,7 +457,7 @@ TEST_CASE("GPIO interrupt on other CPUs test", "[gpio]") TEST_ASSERT_EQUAL_INT(edge_intr_times, 1); gpio_isr_handler_remove(TEST_GPIO_EXT_OUT_IO); gpio_uninstall_isr_service(); - test_utils_task_delete(gpio_task_handle); + unity_utils_task_delete(gpio_task_handle); } } #endif //!CONFIG_FREERTOS_UNICORE diff --git a/components/esp_wifi/test/test_wifi_init.c b/components/esp_wifi/test/test_wifi_init.c index 2d13fa6022..660a817ac4 100644 --- a/components/esp_wifi/test/test_wifi_init.c +++ b/components/esp_wifi/test/test_wifi_init.c @@ -7,6 +7,7 @@ #include "nvs_flash.h" #include "test_utils.h" #include "freertos/event_groups.h" +#include "unity_test_utils.h" #define GOT_IP_EVENT 0x00000001 #define DISCONNECT_EVENT 0x00000002 @@ -116,7 +117,7 @@ TEST_CASE("wifi driver can start on APP CPU", "[wifi_init]") xSemaphoreTake(sema, portMAX_DELAY); vSemaphoreDelete(sema); sema = NULL; - test_utils_task_delete(th); + unity_utils_task_delete(th); } static void wifi_start_stop_task(void* arg) @@ -169,7 +170,7 @@ TEST_CASE("Calling esp_wifi_stop() with start", "[wifi_init]") xSemaphoreTake(sema, portMAX_DELAY); vSemaphoreDelete(sema); sema = NULL; - test_utils_task_delete(th); + unity_utils_task_delete(th); } static void wifi_stop_task(void* arg) @@ -218,7 +219,7 @@ TEST_CASE("Calling esp_wifi_stop() without start", "[wifi_init]") xSemaphoreTake(sema, portMAX_DELAY); vSemaphoreDelete(sema); sema = NULL; - test_utils_task_delete(th); + unity_utils_task_delete(th); } static void wifi_deinit_task(void* arg) @@ -271,5 +272,5 @@ TEST_CASE("Calling esp_wifi_deinit() without stop", "[wifi_init]") xSemaphoreTake(sema, portMAX_DELAY); vSemaphoreDelete(sema); sema = NULL; - test_utils_task_delete(th); + unity_utils_task_delete(th); } diff --git a/components/sdmmc/test/test_sd.c b/components/sdmmc/test/test_sd.c index 25070abd04..6d49dfec22 100644 --- a/components/sdmmc/test/test_sd.c +++ b/components/sdmmc/test/test_sd.c @@ -24,6 +24,8 @@ #include "esp_heap_caps.h" #include "esp_rom_gpio.h" #include "test_utils.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" #include "soc/gpio_sig_map.h" #include "soc/gpio_reg.h" diff --git a/components/spi_flash/test/test_read_write.c b/components/spi_flash/test/test_read_write.c index e0028c0cd1..590a38b429 100644 --- a/components/spi_flash/test/test_read_write.c +++ b/components/spi_flash/test/test_read_write.c @@ -17,6 +17,7 @@ #include #include "../cache_utils.h" #include "soc/timer_periph.h" +#include "esp_attr.h" #include "esp_heap_caps.h" #include "esp_rom_spiflash.h" #if CONFIG_IDF_TARGET_ESP32 diff --git a/components/tcp_transport/test/test_transport_fixtures.c b/components/tcp_transport/test/test_transport_fixtures.c index 1ad70ddbd7..c1bfad87d8 100644 --- a/components/tcp_transport/test/test_transport_fixtures.c +++ b/components/tcp_transport/test/test_transport_fixtures.c @@ -8,6 +8,7 @@ #include "lwip/sockets.h" #include "freertos/event_groups.h" #include "tcp_transport_fixtures.h" +#include "unity_test_utils.h" // This is a private API of the tcp transport, but needed for socket operation tests int esp_transport_get_socket(esp_transport_handle_t t); @@ -228,8 +229,8 @@ static void connect_test_teardown(tcp_connect_test_t t) vTaskSuspend(t->tcp_connect_task); vTaskSuspend(t->listener_task); vEventGroupDelete(t->tcp_connect_done); - test_utils_task_delete(t->tcp_connect_task); - test_utils_task_delete(t->listener_task); + unity_utils_task_delete(t->tcp_connect_task); + unity_utils_task_delete(t->listener_task); free(t); } diff --git a/components/unity/CMakeLists.txt b/components/unity/CMakeLists.txt index 14184db294..14a33632cd 100644 --- a/components/unity/CMakeLists.txt +++ b/components/unity/CMakeLists.txt @@ -15,6 +15,7 @@ endif() if(CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER) list(APPEND srcs "unity_runner.c") + list(APPEND srcs "unity_utils_freertos.c") endif() if(CONFIG_UNITY_ENABLE_FIXTURE) diff --git a/components/unity/include/unity_test_utils.h b/components/unity/include/unity_test_utils.h new file mode 100644 index 0000000000..f508ecaa5f --- /dev/null +++ b/components/unity/include/unity_test_utils.h @@ -0,0 +1,26 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Delete task ensuring dynamic memory (for stack, tcb etc.) gets freed up immediately + * + * @param[in] thandle Handle of task to be deleted (should not be NULL or self handle) + */ +void unity_utils_task_delete(TaskHandle_t thandle); + +#ifdef __cplusplus +} +#endif diff --git a/components/unity/unity_utils_freertos.c b/components/unity/unity_utils_freertos.c new file mode 100644 index 0000000000..a9616e46b2 --- /dev/null +++ b/components/unity/unity_utils_freertos.c @@ -0,0 +1,69 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "unity.h" +#include "unity_test_utils.h" +#include "freertos/semphr.h" +#include "sdkconfig.h" +#if !CONFIG_FREERTOS_UNICORE +#include "esp_ipc.h" +#include "esp_freertos_hooks.h" +#endif + +#if !CONFIG_FREERTOS_UNICORE +static SemaphoreHandle_t test_sem; + +static bool idle_hook_func(void) +{ + if (test_sem) { + xSemaphoreGive(test_sem); + } + return true; +} + +static void task_delete_func(void *arg) +{ + vTaskDelete(arg); +} +#endif // !CONFIG_FREERTOS_UNICORE + +void unity_utils_task_delete(TaskHandle_t thandle) +{ + /* Self deletion can not free up associated task dynamic memory immediately, + * hence not recommended for test scenarios */ + TEST_ASSERT_NOT_NULL_MESSAGE(thandle, "unity_utils_task_delete: handle is NULL"); + TEST_ASSERT_NOT_EQUAL_MESSAGE(thandle, xTaskGetCurrentTaskHandle(), "unity_utils_task_delete: handle is of currently executing task"); + +#if CONFIG_FREERTOS_UNICORE + vTaskDelete(thandle); +#else // CONFIG_FREERTOS_UNICORE + const BaseType_t tsk_affinity = xTaskGetAffinity(thandle); + const BaseType_t core_id = xPortGetCoreID(); + + printf("Task_affinity: 0x%x, current_core: %d\n", tsk_affinity, core_id); + + if (tsk_affinity == tskNO_AFFINITY) { + /* For no affinity case, we wait for idle hook to trigger on different core */ + esp_err_t ret = esp_register_freertos_idle_hook_for_cpu(idle_hook_func, !core_id); + TEST_ASSERT_EQUAL_MESSAGE(ret, ESP_OK, "unity_utils_task_delete: failed to register idle hook"); + vTaskDelete(thandle); + test_sem = xSemaphoreCreateBinary(); + TEST_ASSERT_NOT_NULL_MESSAGE(test_sem, "unity_utils_task_delete: failed to create semaphore"); + xSemaphoreTake(test_sem, portMAX_DELAY); + esp_deregister_freertos_idle_hook_for_cpu(idle_hook_func, !core_id); + vSemaphoreDelete(test_sem); + test_sem = NULL; + } else if (tsk_affinity != core_id) { + /* Task affinity and current core are differnt, schedule IPC call (to delete task) + * on core where task is pinned to */ + esp_ipc_call_blocking(tsk_affinity, task_delete_func, thandle); + } else { + /* Task affinity and current core are same, so we can safely proceed for deletion */ + vTaskDelete(thandle); + } +#endif // !CONFIG_FREERTOS_UNICORE +} diff --git a/tools/unit-test-app/components/test_utils/include/test_utils.h b/tools/unit-test-app/components/test_utils/include/test_utils.h index a739eb1fd8..6526c88d1b 100644 --- a/tools/unit-test-app/components/test_utils/include/test_utils.h +++ b/tools/unit-test-app/components/test_utils/include/test_utils.h @@ -11,8 +11,6 @@ #include #include #include "sdkconfig.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" #include "unity.h" #include "soc/soc_caps.h" /* include performance pass standards header file */ @@ -237,14 +235,6 @@ test_utils_exhaust_memory_rec test_utils_exhaust_memory(uint32_t caps, size_t li */ void test_utils_free_exhausted_memory(test_utils_exhaust_memory_rec rec); - -/** - * @brief Delete task ensuring dynamic memory (for stack, tcb etc.) gets freed up immediately - * - * @param[in] thandle Handle of task to be deleted (should not be NULL or self handle) - */ -void test_utils_task_delete(TaskHandle_t thandle); - #ifdef __cplusplus } #endif diff --git a/tools/unit-test-app/components/test_utils/test_utils.c b/tools/unit-test-app/components/test_utils/test_utils.c index c2d4763403..e09a07c2f8 100644 --- a/tools/unit-test-app/components/test_utils/test_utils.c +++ b/tools/unit-test-app/components/test_utils/test_utils.c @@ -13,10 +13,6 @@ #include "lwip/sockets.h" #include "sdkconfig.h" #include "memory_checks.h" -#if !CONFIG_FREERTOS_UNICORE -#include "esp_ipc.h" -#include "esp_freertos_hooks.h" -#endif const esp_partition_t *get_test_data_partition(void) { @@ -147,57 +143,3 @@ void test_utils_free_exhausted_memory(test_utils_exhaust_memory_rec rec) } free(rec); } - -#if !CONFIG_FREERTOS_UNICORE -static SemaphoreHandle_t test_sem; - -static bool test_idle_hook_func(void) -{ - if (test_sem) { - xSemaphoreGive(test_sem); - } - return true; -} - -static void test_task_delete_func(void *arg) -{ - vTaskDelete(arg); -} -#endif // !CONFIG_FREERTOS_UNICORE - -void test_utils_task_delete(TaskHandle_t thandle) -{ - /* Self deletion can not free up associated task dynamic memory immediately, - * hence not recommended for test scenarios */ - TEST_ASSERT_NOT_NULL_MESSAGE(thandle, "test_utils_task_delete: handle is NULL"); - TEST_ASSERT_NOT_EQUAL_MESSAGE(thandle, xTaskGetCurrentTaskHandle(), "test_utils_task_delete: handle is of currently executing task"); - -#if CONFIG_FREERTOS_UNICORE - vTaskDelete(thandle); -#else // CONFIG_FREERTOS_UNICORE - const BaseType_t tsk_affinity = xTaskGetAffinity(thandle); - const BaseType_t core_id = xPortGetCoreID(); - - printf("Task_affinity: 0x%x, current_core: %d\n", tsk_affinity, core_id); - - if (tsk_affinity == tskNO_AFFINITY) { - /* For no affinity case, we wait for idle hook to trigger on different core */ - esp_err_t ret = esp_register_freertos_idle_hook_for_cpu(test_idle_hook_func, !core_id); - TEST_ASSERT_EQUAL_MESSAGE(ret, ESP_OK, "test_utils_task_delete: failed to register idle hook"); - vTaskDelete(thandle); - test_sem = xSemaphoreCreateBinary(); - TEST_ASSERT_NOT_NULL_MESSAGE(test_sem, "test_utils_task_delete: failed to create semaphore"); - xSemaphoreTake(test_sem, portMAX_DELAY); - esp_deregister_freertos_idle_hook_for_cpu(test_idle_hook_func, !core_id); - vSemaphoreDelete(test_sem); - test_sem = NULL; - } else if (tsk_affinity != core_id) { - /* Task affinity and current core are differnt, schedule IPC call (to delete task) - * on core where task is pinned to */ - esp_ipc_call_blocking(tsk_affinity, test_task_delete_func, thandle); - } else { - /* Task affinity and current core are same, so we can safely proceed for deletion */ - vTaskDelete(thandle); - } -#endif // !CONFIG_FREERTOS_UNICORE -}