From c9984faaef995b577e193fc6fcdc95953488fb75 Mon Sep 17 00:00:00 2001 From: Jakob Hasse Date: Wed, 21 Jul 2021 12:07:53 +0800 Subject: [PATCH] [mocks]: freertos mock [esp_event]: added preliminary host-based tests --- .gitlab/ci/host-test.yml | 7 + components/esp_event/CMakeLists.txt | 32 ++-- components/esp_event/default_event_loop.c | 3 +- .../esp_event_unit_test/CMakeLists.txt | 8 + .../esp_event_unit_test/main/CMakeLists.txt | 3 + .../main/esp_event_test.cpp | 152 ++++++++++++++++++ .../esp_event_unit_test/sdkconfig.defaults | 4 + components/esp_event/host_test/fixtures.hpp | 148 +++++++++++++++++ components/esp_event/include/esp_event.h | 3 + .../private_include/esp_event_internal.h | 2 + .../private_include/esp_event_private.h | 1 + components/esp_event/test/test_event.c | 8 - .../include/freertos/FreeRTOSConfig.h | 6 +- .../linux/include/freertos/FreeRTOSConfig.h | 75 +++++++++ .../port/linux/include/freertos/portmacro.h | 32 ++++ components/linux/CMakeLists.txt | 7 + components/linux/include/sys/queue.h | 1 + .../host_test/gpio/CMakeLists.txt | 6 + mocks/driver/CMakeLists.txt | 2 +- mocks/esp_system/include/esp_task.h | 56 +++++++ mocks/freertos/CMakeLists.txt | 16 ++ mocks/freertos/Kconfig | 13 ++ mocks/freertos/include/freertos/FreeRTOS.h | 14 -- mocks/freertos/include/freertos/portmacro.h | 14 -- mocks/freertos/mock/mock_config.yaml | 18 +++ 25 files changed, 582 insertions(+), 49 deletions(-) create mode 100644 components/esp_event/host_test/esp_event_unit_test/CMakeLists.txt create mode 100644 components/esp_event/host_test/esp_event_unit_test/main/CMakeLists.txt create mode 100644 components/esp_event/host_test/esp_event_unit_test/main/esp_event_test.cpp create mode 100644 components/esp_event/host_test/esp_event_unit_test/sdkconfig.defaults create mode 100644 components/esp_event/host_test/fixtures.hpp create mode 100644 components/freertos/port/linux/include/freertos/FreeRTOSConfig.h create mode 100644 components/freertos/port/linux/include/freertos/portmacro.h create mode 100644 components/linux/CMakeLists.txt create mode 100644 components/linux/include/sys/queue.h create mode 100644 mocks/esp_system/include/esp_task.h create mode 100644 mocks/freertos/CMakeLists.txt create mode 100644 mocks/freertos/Kconfig delete mode 100644 mocks/freertos/include/freertos/FreeRTOS.h delete mode 100644 mocks/freertos/include/freertos/portmacro.h create mode 100644 mocks/freertos/mock/mock_config.yaml diff --git a/.gitlab/ci/host-test.yml b/.gitlab/ci/host-test.yml index e238d79ee3..37747ac21b 100644 --- a/.gitlab/ci/host-test.yml +++ b/.gitlab/ci/host-test.yml @@ -349,6 +349,13 @@ test_log: - idf.py build - build/test_log_host.elf +test_esp_event: + extends: .host_test_template + script: + - cd ${IDF_PATH}/components/esp_event/host_test/esp_event_unit_test + - idf.py build + - build/test_esp_event_host.elf + test_eh_frame_parser: extends: .host_test_template script: diff --git a/components/esp_event/CMakeLists.txt b/components/esp_event/CMakeLists.txt index 6384b8fe3c..c93a52a74a 100644 --- a/components/esp_event/CMakeLists.txt +++ b/components/esp_event/CMakeLists.txt @@ -1,17 +1,29 @@ -if(IDF_TARGET STREQUAL "esp32") - set(priv_requires esp_eth esp_timer) +idf_build_get_property(target IDF_TARGET) +set(priv_include_dirs "private_include") +set(priv_requires "") +set(requires "log" "esp_common" "freertos") +set(srcs "default_event_loop.c" + "esp_event.c" + "esp_event_private.c") + +if(${target} STREQUAL "linux") + list(APPEND requires "linux") + # Temporary fix until esp_system is available for linux, too + list(APPEND priv_include_dirs "$ENV{IDF_PATH}/mocks/esp_system/include") else() - set(priv_requires esp_timer) + list(APPEND requires "esp_netif") + list(APPEND srcs "event_loop_legacy.c" "event_send.c") + if(${target} STREQUAL "esp32") + list(APPEND priv_requires esp_eth esp_timer) + else() + list(APPEND priv_requires esp_timer) + endif() endif() -idf_component_register(SRCS "default_event_loop.c" - "esp_event.c" - "esp_event_private.c" - "event_loop_legacy.c" - "event_send.c" +idf_component_register(SRCS ${srcs} INCLUDE_DIRS "include" - PRIV_INCLUDE_DIRS "private_include" - REQUIRES log esp_netif + PRIV_INCLUDE_DIRS ${priv_include_dirs} + REQUIRES ${requires} PRIV_REQUIRES ${priv_requires} LDFRAGMENTS linker.lf) diff --git a/components/esp_event/default_event_loop.c b/components/esp_event/default_event_loop.c index 93b37d2803..506cf8e56c 100644 --- a/components/esp_event/default_event_loop.c +++ b/components/esp_event/default_event_loop.c @@ -142,8 +142,9 @@ esp_err_t esp_event_loop_delete_default(void) return ESP_OK; } - +#if !CONFIG_IDF_TARGET_LINUX /* Include the code to forward legacy system_event_t events to the this default * event loop. */ #include "event_send_compat.inc" +#endif diff --git a/components/esp_event/host_test/esp_event_unit_test/CMakeLists.txt b/components/esp_event/host_test/esp_event_unit_test/CMakeLists.txt new file mode 100644 index 0000000000..1cc112f31f --- /dev/null +++ b/components/esp_event/host_test/esp_event_unit_test/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +set(COMPONENTS main) + +idf_build_set_property(COMPILE_DEFINITIONS "-DNO_DEBUG_STORAGE" APPEND) +list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/mocks/freertos/") +project(test_esp_event_host) diff --git a/components/esp_event/host_test/esp_event_unit_test/main/CMakeLists.txt b/components/esp_event/host_test/esp_event_unit_test/main/CMakeLists.txt new file mode 100644 index 0000000000..e118569643 --- /dev/null +++ b/components/esp_event/host_test/esp_event_unit_test/main/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "esp_event_test.cpp" + INCLUDE_DIRS "../../" $ENV{IDF_PATH}/tools/catch + REQUIRES esp_event cmock) diff --git a/components/esp_event/host_test/esp_event_unit_test/main/esp_event_test.cpp b/components/esp_event/host_test/esp_event_unit_test/main/esp_event_test.cpp new file mode 100644 index 0000000000..16c2c590c5 --- /dev/null +++ b/components/esp_event/host_test/esp_event_unit_test/main/esp_event_test.cpp @@ -0,0 +1,152 @@ +/* ESP Event Host-Based Test + + This code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#define CATCH_CONFIG_MAIN + +#include +#include "esp_event.h" + +#include "catch.hpp" + +#include "fixtures.hpp" + +extern "C" { +#include "Mocktask.h" +#include "Mockqueue.h" +} + + +namespace { + +const uint32_t QUEUE_SIZE = 32; + +static UBaseType_t s_test_priority; + +static esp_event_loop_args_t test_event_get_default_loop_args(void) +{ + esp_event_loop_args_t loop_config = { + .queue_size = QUEUE_SIZE, // TODO: CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE from esp_system should be used + .task_name = "loop", + .task_priority = s_test_priority, + .task_stack_size = 2048, + .task_core_id = 0 + }; + + return loop_config; +} + +void dummy_handler(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { } + +} + +// TODO: IDF-2693, function definition just to satisfy linker, implement esp_common instead +const char *esp_err_to_name(esp_err_t code) { + return "test"; +} + +TEST_CASE("create an event loop with any NULL argument fails") +{ + MockQueue queue(CreateAnd::IGNORE); + MockMutex sem(CreateAnd::IGNORE); + MockTask task(CreateAnd::IGNORE); + esp_event_loop_handle_t loop; // with dedicated task + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + CHECK(ESP_ERR_INVALID_ARG == esp_event_loop_create(NULL, &loop)); + CHECK(ESP_ERR_INVALID_ARG == esp_event_loop_create(&loop_args, NULL)); +} + +TEST_CASE("test esp_event_loop_create create_queue_fails(void)") +{ + MockQueue queue(CreateAnd::FAIL); + MockMutex sem(CreateAnd::IGNORE); + MockTask task(CreateAnd::IGNORE); + esp_event_loop_handle_t loop; + + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + + CHECK(ESP_ERR_NO_MEM == esp_event_loop_create(&loop_args, &loop)); +} + +TEST_CASE("test esp_event_loop_create create_mutex_fails(void)") +{ + MockQueue queue(CreateAnd::IGNORE); + MockMutex sem(CreateAnd::FAIL); + MockTask task(CreateAnd::IGNORE); + esp_event_loop_handle_t loop; + + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + + CHECK(ESP_ERR_NO_MEM == esp_event_loop_create(&loop_args, &loop)); +} + +TEST_CASE("test esp_event_loop_create create_task_fails(void)") +{ + MockQueue queue(CreateAnd::IGNORE); + MockMutex sem(CreateAnd::IGNORE); + MockTask task(CreateAnd::FAIL); + esp_event_loop_handle_t loop; + + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + + CHECK(ESP_FAIL == esp_event_loop_create(&loop_args, &loop)); +} + +TEST_CASE("test esp_event_loop_create no_task(void)") +{ + MockQueue queue(CreateAnd::IGNORE); + MockMutex sem(CreateAnd::IGNORE); + xQueueTakeMutexRecursive_IgnoreAndReturn(0); + xQueueGiveMutexRecursive_IgnoreAndReturn(0); + xQueueReceive_IgnoreAndReturn(0); + esp_event_loop_handle_t loop = nullptr; + + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + loop_args.task_name = nullptr; + + CHECK(ESP_OK == esp_event_loop_create(&loop_args, &loop)); + CHECK(loop != nullptr); + + CHECK(ESP_OK == esp_event_loop_delete(loop)); + + xQueueReceive_StopIgnore(); + xQueueTakeMutexRecursive_StopIgnore(); + xQueueGiveMutexRecursive_StopIgnore(); +} + +TEST_CASE("test esp_event_loop_create with_task(void)") +{ + MockQueue queue(CreateAnd::IGNORE); + MockMutex sem(CreateAnd::IGNORE); + MockTask task(CreateAnd::SUCCEED); + xQueueTakeMutexRecursive_IgnoreAndReturn(0); + xQueueGiveMutexRecursive_IgnoreAndReturn(0); + xQueueReceive_IgnoreAndReturn(0); + esp_event_loop_handle_t loop = nullptr; + + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + loop_args.task_name = "test"; + + CHECK(ESP_OK == esp_event_loop_create(&loop_args, &loop)); + CHECK(loop != nullptr); + + CHECK(ESP_OK == esp_event_loop_delete(loop)); + + xQueueReceive_StopIgnore(); + xQueueTakeMutexRecursive_StopIgnore(); + xQueueGiveMutexRecursive_StopIgnore(); +} + +TEST_CASE("registering with ANY_BASE but specific ID fails") { + esp_event_loop_handle_t loop = reinterpret_cast(1); + CHECK(esp_event_handler_register_with(loop, + ESP_EVENT_ANY_BASE, + 47, + dummy_handler, + nullptr) == ESP_ERR_INVALID_ARG); +} diff --git a/components/esp_event/host_test/esp_event_unit_test/sdkconfig.defaults b/components/esp_event/host_test/esp_event_unit_test/sdkconfig.defaults new file mode 100644 index 0000000000..c3180f3309 --- /dev/null +++ b/components/esp_event/host_test/esp_event_unit_test/sdkconfig.defaults @@ -0,0 +1,4 @@ +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=n +CONFIG_IDF_TARGET="linux" +CONFIG_CXX_EXCEPTIONS=y +CONFIG_LOG_DEFAULT_LEVEL_NONE=y diff --git a/components/esp_event/host_test/fixtures.hpp b/components/esp_event/host_test/fixtures.hpp new file mode 100644 index 0000000000..1a8c4ed7b8 --- /dev/null +++ b/components/esp_event/host_test/fixtures.hpp @@ -0,0 +1,148 @@ +/* ESP Event Fixtures + + This code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include "esp_event.h" + +#include "catch.hpp" + +extern "C" { +#include "Mocktask.h" +#include "Mockqueue.h" +} + +/** + * Exception which is thrown if there is some internal cmock error which results in a + * longjump to the location of a TEST_PROTECT() call. + * + * @note This is a temporary solution until there is a better integration of CATCH into CMock. + * Note also that usually there will be a segfault when cmock fails a second time. + * This means paying attention to the first error message is crucial for removing errors. + */ +class CMockException : public std::exception { +public: + virtual ~CMockException() { } + + /** + * @return A reminder to look at the actual cmock log. + */ + virtual const char *what() const noexcept + { + return "CMock encountered an error. Look at the CMock log"; + } +}; + +/** + * Helper macro for setting up a test protect call for CMock. + * + * This macro should be used at the beginning of any test cases + * which use generated CMock mock functions. + * This is necessary because CMock uses longjmp which screws up C++ stacks and + * also the CATCH mechanisms. + * + * @note This is a temporary solution until there is a better integration of CATCH into CMock. + * Note also that usually there will be a segfault when cmock fails a second time. + * This means paying attention to the first error message is crucial for removing errors. + */ +#define CMOCK_SETUP() \ + do { \ + if (!TEST_PROTECT()) { \ + throw CMockException(); \ + } \ + } \ + while (0) + +struct CMockFix { + CMockFix() + { + CMOCK_SETUP(); + } + + ~CMockFix() + { + Mocktask_Verify(); + Mockqueue_Verify(); + } +}; + +enum class CreateAnd { + FAIL, + SUCCEED, + IGNORE +}; + +struct MockQueue : public CMockFix { + MockQueue (CreateAnd flags) : queue(reinterpret_cast(0xdeadbeef)) + { + if (flags == CreateAnd::FAIL) { + xQueueGenericCreate_ExpectAnyArgsAndReturn(nullptr); + } else if (flags == CreateAnd::IGNORE) { + xQueueGenericCreate_IgnoreAndReturn(queue); + vQueueDelete_Ignore(); + } else { + xQueueGenericCreate_ExpectAnyArgsAndReturn(queue); + vQueueDelete_Expect(queue); + } + } + + ~MockQueue() + { + xQueueGenericCreate_StopIgnore(); + vQueueDelete_StopIgnore(); + } + + QueueHandle_t queue; +}; + +struct MockMutex : public CMockFix { + MockMutex (CreateAnd flags) : sem(reinterpret_cast(0xdeadbeef)) + { + if (flags == CreateAnd::FAIL) { + xQueueCreateMutex_ExpectAnyArgsAndReturn(nullptr); + } else if (flags == CreateAnd::IGNORE) { + xQueueCreateMutex_IgnoreAndReturn(sem); + vQueueDelete_Ignore(); + } else { + xQueueCreateMutex_ExpectAnyArgsAndReturn(sem); + vQueueDelete_Expect(sem); + } + } + + ~MockMutex() + { + xQueueCreateMutex_StopIgnore(); + vQueueDelete_StopIgnore(); + } + + QueueHandle_t sem; +}; + +struct MockTask : public CMockFix { + MockTask (CreateAnd flags) : task((void*) 1) + { + if (flags == CreateAnd::FAIL) { + xTaskCreatePinnedToCore_ExpectAnyArgsAndReturn(pdFALSE); + } else if (flags == CreateAnd::IGNORE) { + xTaskCreatePinnedToCore_IgnoreAndReturn(pdTRUE); + xTaskCreatePinnedToCore_ReturnThruPtr_pvCreatedTask(&task); + vTaskDelete_Ignore(); + } else { + xTaskCreatePinnedToCore_ExpectAnyArgsAndReturn(pdTRUE); + xTaskCreatePinnedToCore_ReturnThruPtr_pvCreatedTask(&task); + vTaskDelete_Expect(task); + } + } + + ~MockTask() + { + xTaskCreatePinnedToCore_StopIgnore(); + vTaskDelete_StopIgnore(); + } + + TaskHandle_t task; +}; diff --git a/components/esp_event/include/esp_event.h b/components/esp_event/include/esp_event.h index 2d39422db5..2c069b0c68 100644 --- a/components/esp_event/include/esp_event.h +++ b/components/esp_event/include/esp_event.h @@ -23,7 +23,10 @@ #include "freertos/semphr.h" #include "esp_event_base.h" +// Legacy event loop not implemented on Linux target +#if !CONFIG_IDF_TARGET_LINUX #include "esp_event_legacy.h" +#endif #ifdef __cplusplus extern "C" { diff --git a/components/esp_event/private_include/esp_event_internal.h b/components/esp_event/private_include/esp_event_internal.h index 02403e0399..dd403f6d7c 100644 --- a/components/esp_event/private_include/esp_event_internal.h +++ b/components/esp_event/private_include/esp_event_internal.h @@ -15,6 +15,8 @@ #ifndef ESP_EVENT_INTERNAL_H_ #define ESP_EVENT_INTERNAL_H_ +#include "sys/queue.h" +#include #include "esp_event.h" #include "stdatomic.h" diff --git a/components/esp_event/private_include/esp_event_private.h b/components/esp_event/private_include/esp_event_private.h index fc434876a9..64ccf133c5 100644 --- a/components/esp_event/private_include/esp_event_private.h +++ b/components/esp_event/private_include/esp_event_private.h @@ -15,6 +15,7 @@ #ifndef ESP_EVENT_PRIVATE_H_ #define ESP_EVENT_PRIVATE_H_ +#include #include "esp_event.h" #ifdef __cplusplus diff --git a/components/esp_event/test/test_event.c b/components/esp_event/test/test_event.c index 1e1625e596..605cbc3381 100644 --- a/components/esp_event/test/test_event.c +++ b/components/esp_event/test/test_event.c @@ -306,14 +306,6 @@ static void test_teardown(void) #define TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER) // convert counter value to seconds #define TIMER_INTERVAL0_SEC (2.0) // sample test interval for the first timer -TEST_CASE("create and event loop with any NULL argument fails", "[event]") -{ - esp_event_loop_handle_t loop; // with dedicated task - esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); - TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_event_loop_create(NULL, &loop)); - TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_event_loop_create(&loop_args, NULL)); -} - TEST_CASE("can create and delete event loops", "[event]") { /* this test aims to verify that: diff --git a/components/freertos/include/freertos/FreeRTOSConfig.h b/components/freertos/include/freertos/FreeRTOSConfig.h index c64cb980d8..15f97a9676 100644 --- a/components/freertos/include/freertos/FreeRTOSConfig.h +++ b/components/freertos/include/freertos/FreeRTOSConfig.h @@ -74,7 +74,9 @@ // The arch-specific FreeRTOSConfig.h in port//include. #include_next "freertos/FreeRTOSConfig.h" -#if !(defined(FREERTOS_CONFIG_XTENSA_H) || defined(FREERTOS_CONFIG_RISCV_H)) +#if !(defined(FREERTOS_CONFIG_XTENSA_H) \ + || defined(FREERTOS_CONFIG_RISCV_H) \ + || defined(FREERTOS_CONFIG_LINUX_H)) #error "Needs architecture-speific FreeRTOSConfig.h!" #endif @@ -244,7 +246,9 @@ kept at 1. */ #define configKERNEL_INTERRUPT_PRIORITY 1 +#if !CONFIG_IDF_TARGET_LINUX #define configUSE_NEWLIB_REENTRANT 1 +#endif #define configSUPPORT_DYNAMIC_ALLOCATION 1 #define configSUPPORT_STATIC_ALLOCATION 1 diff --git a/components/freertos/port/linux/include/freertos/FreeRTOSConfig.h b/components/freertos/port/linux/include/freertos/FreeRTOSConfig.h new file mode 100644 index 0000000000..273593d86a --- /dev/null +++ b/components/freertos/port/linux/include/freertos/FreeRTOSConfig.h @@ -0,0 +1,75 @@ +/* + FreeRTOS V10 - Copyright (C) 2021 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef FREERTOS_CONFIG_LINUX_H +#define FREERTOS_CONFIG_LINUX_H + +// This file is included in the common FreeRTOSConfig.h. + +#endif // FREERTOS_CONFIG_LINUX_H diff --git a/components/freertos/port/linux/include/freertos/portmacro.h b/components/freertos/port/linux/include/freertos/portmacro.h new file mode 100644 index 0000000000..720f128c80 --- /dev/null +++ b/components/freertos/port/linux/include/freertos/portmacro.h @@ -0,0 +1,32 @@ +#pragma once + +#include "esp_attr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define portBYTE_ALIGNMENT 16 + +/* Type definitions. */ +#define portCHAR uint8_t +#define portFLOAT float +#define portDOUBLE double +#define portLONG int32_t +#define portSHORT int16_t +#define portSTACK_TYPE uint8_t +#define portBASE_TYPE int +// interrupt module will mask interrupt with priority less than threshold +#define RVHAL_EXCM_LEVEL 4 + +typedef portSTACK_TYPE StackType_t; +typedef portBASE_TYPE BaseType_t; +typedef unsigned portBASE_TYPE UBaseType_t; +typedef uint32_t TickType_t; +#define portMAX_DELAY ( TickType_t ) 0xffffffffUL + +typedef int portMUX_TYPE; + +#ifdef __cplusplus +} +#endif diff --git a/components/linux/CMakeLists.txt b/components/linux/CMakeLists.txt new file mode 100644 index 0000000000..b7d2bd46a7 --- /dev/null +++ b/components/linux/CMakeLists.txt @@ -0,0 +1,7 @@ +idf_build_get_property(target IDF_TARGET) +if(NOT "${target}" STREQUAL "linux") + return() +endif() + +idf_component_register(INCLUDE_DIRS include + REQUIRED_IDF_TARGETS linux) diff --git a/components/linux/include/sys/queue.h b/components/linux/include/sys/queue.h new file mode 100644 index 0000000000..9787d9d5f8 --- /dev/null +++ b/components/linux/include/sys/queue.h @@ -0,0 +1 @@ +#include "bsd/sys/queue.h" diff --git a/examples/cxx/experimental/experimental_cpp_component/host_test/gpio/CMakeLists.txt b/examples/cxx/experimental/experimental_cpp_component/host_test/gpio/CMakeLists.txt index e918d84f04..beee51b886 100644 --- a/examples/cxx/experimental/experimental_cpp_component/host_test/gpio/CMakeLists.txt +++ b/examples/cxx/experimental/experimental_cpp_component/host_test/gpio/CMakeLists.txt @@ -4,6 +4,12 @@ include($ENV{IDF_PATH}/tools/cmake/project.cmake) set(COMPONENTS main) idf_build_set_property(COMPILE_DEFINITIONS "-DNO_DEBUG_STORAGE" APPEND) + +# Overriding components which should be mocked list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/mocks/driver/") +list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/mocks/freertos/") + +# Including experimental component here because it's outside IDF's main component directory list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/examples/cxx/experimental/experimental_cpp_component/") + project(test_gpio_cxx_host) diff --git a/mocks/driver/CMakeLists.txt b/mocks/driver/CMakeLists.txt index 67abbc9392..c672cf5aac 100644 --- a/mocks/driver/CMakeLists.txt +++ b/mocks/driver/CMakeLists.txt @@ -9,11 +9,11 @@ idf_component_get_property(original_driver_dir driver COMPONENT_OVERRIDEN_DIR) set(include_dirs "${original_driver_dir}/include" "${original_driver_dir}/include/driver" - "${CMAKE_CURRENT_SOURCE_DIR}/../freertos/include" "${CMAKE_CURRENT_SOURCE_DIR}/../hal/include" "${CMAKE_CURRENT_SOURCE_DIR}/../esp_hw_support/include") idf_component_mock(INCLUDE_DIRS ${include_dirs} + REQUIRES freertos MOCK_HEADER_FILES ${original_driver_dir}/include/driver/spi_master.h ${original_driver_dir}/include/driver/spi_common.h diff --git a/mocks/esp_system/include/esp_task.h b/mocks/esp_system/include/esp_task.h new file mode 100644 index 0000000000..b96a2c5bc8 --- /dev/null +++ b/mocks/esp_system/include/esp_task.h @@ -0,0 +1,56 @@ +// Copyright 2015-2016 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. +// 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. + +/* Notes: + * 1. Put all task priority and stack size definition in this file + * 2. If the task priority is less than 10, use ESP_TASK_PRIO_MIN + X style, + * otherwise use ESP_TASK_PRIO_MAX - X style + * 3. If this is a daemon task, the macro prefix is ESP_TASKD_, otherwise + * it's ESP_TASK_ + * 4. If the configMAX_PRIORITIES is modified, please make all priority are + * greater than 0 + * 5. Make sure esp_task.h is consistent between wifi lib and idf + * 6. If changing system task priorities, please check the values documented in /api-guides/performance/speed.rst + * are up to date + */ + +#ifndef _ESP_TASK_H_ +#define _ESP_TASK_H_ + +#include "sdkconfig.h" + +#define ESP_TASK_PRIO_MAX (configMAX_PRIORITIES) +#define ESP_TASK_PRIO_MIN (0) + +/* Temporary define until system is properly buildable on Linux */ +#define CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE 10 + +/* Bt contoller Task */ +/* controller */ +#define ESP_TASK_BT_CONTROLLER_PRIO (ESP_TASK_PRIO_MAX - 2) +#ifdef CONFIG_NEWLIB_NANO_FORMAT +#define TASK_EXTRA_STACK_SIZE (0) +#else +#define TASK_EXTRA_STACK_SIZE (512) +#endif + +#define BT_TASK_EXTRA_STACK_SIZE TASK_EXTRA_STACK_SIZE +#define ESP_TASK_BT_CONTROLLER_STACK (3584 + TASK_EXTRA_STACK_SIZE) + + +/* idf task */ +#define ESP_TASKD_EVENT_PRIO (ESP_TASK_PRIO_MAX - 5) +#define ESP_TASKD_EVENT_STACK (2048) + +#endif diff --git a/mocks/freertos/CMakeLists.txt b/mocks/freertos/CMakeLists.txt new file mode 100644 index 0000000000..6daa7e539b --- /dev/null +++ b/mocks/freertos/CMakeLists.txt @@ -0,0 +1,16 @@ +# NOTE: This kind of mocking currently works on Linux targets only. +# On Espressif chips, too many dependencies are missing at the moment. +message(STATUS "building FREERTOS MOCKS (only task and queue)") + +idf_component_get_property(original_freertos_dir freertos COMPONENT_OVERRIDEN_DIR) + +set(include_dirs + "${original_freertos_dir}/include" + "${original_freertos_dir}/include/freertos" # this is due to the way includes are generated in CMock + "${original_freertos_dir}/port/linux/include") + +idf_component_mock(INCLUDE_DIRS ${include_dirs} + REQUIRES esp_common + MOCK_HEADER_FILES + ${original_freertos_dir}/include/freertos/task.h + ${original_freertos_dir}/include/freertos/queue.h) diff --git a/mocks/freertos/Kconfig b/mocks/freertos/Kconfig new file mode 100644 index 0000000000..ddb265003a --- /dev/null +++ b/mocks/freertos/Kconfig @@ -0,0 +1,13 @@ +menu "FreeRTOS" + config FREERTOS_MAX_TASK_NAME_LEN + int "Maximum task name length" + range 1 256 + default 16 + help + Changes the maximum task name length. Each task allocated will + include this many bytes for a task name. Using a shorter value + saves a small amount of RAM, a longer value allows more complex + names. + + For most uses, the default of 16 is OK. +endmenu diff --git a/mocks/freertos/include/freertos/FreeRTOS.h b/mocks/freertos/include/freertos/FreeRTOS.h deleted file mode 100644 index 2b2df0a8a9..0000000000 --- a/mocks/freertos/include/freertos/FreeRTOS.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * NOTE: this is not the original header file from the freertos component. - * It is a stripped-down copy to support mocking. - */ - -#pragma once - -typedef uint32_t TickType_t; diff --git a/mocks/freertos/include/freertos/portmacro.h b/mocks/freertos/include/freertos/portmacro.h deleted file mode 100644 index d88f752b06..0000000000 --- a/mocks/freertos/include/freertos/portmacro.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * NOTE: this is not the original header file from the freertos component. - * It is a stripped-down copy to support mocking. - */ - -#pragma once - -#define portMAX_DELAY ( uint32_t ) 0xffffffff diff --git a/mocks/freertos/mock/mock_config.yaml b/mocks/freertos/mock/mock_config.yaml new file mode 100644 index 0000000000..8dc8ea9764 --- /dev/null +++ b/mocks/freertos/mock/mock_config.yaml @@ -0,0 +1,18 @@ + :cmock: + :includes_h_pre_orig_header: + - FreeRTOS.h + :plugins: + - expect + - expect_any_args + - return_thru_ptr + - array + - ignore + - ignore_arg + - callback + :strippables: + - '(?:__attribute__\s*\(+.*?\)+)' + - '(?:vQueueAddToRegistry\s*\(+.*?\)+)' + - '(?:vQueueUnregisterQueue\s*\(+.*?\)+)' + - '(?:pcQueueGetName\s*\(+.*?\)+)' + - '(?:vTaskSetThreadLocalStoragePointerAndDelCallback\s*\(+.*?\)+)' + - PRIVILEGED_FUNCTION