Browse Source

mqtt: Adds host tests for mqtt client

Euripedes Rocha Filho 4 years ago
parent
commit
f6d23bfee1

+ 131 - 1
components/mqtt/CMakeLists.txt

@@ -4,4 +4,134 @@ idf_component_register(SRCS "esp-mqtt/mqtt_client.c"
                             "esp-mqtt/lib/platform_esp32_idf.c"
                     INCLUDE_DIRS esp-mqtt/include
                     PRIV_INCLUDE_DIRS "esp-mqtt/lib/include"
-                    REQUIRES lwip nghttp mbedtls tcp_transport)
+                    )
+
+if(TEST_BUILD)
+message(STATUS "building MOCKS")
+idf_component_get_property(tcp_transport_dir tcp_transport COMPONENT_DIR)
+idf_component_get_property(esp_hw_support_dir esp_hw_support COMPONENT_DIR)
+idf_component_get_property(esp_event_dir esp_event COMPONENT_DIR)
+idf_component_get_property(log_dir log COMPONENT_DIR)
+idf_component_get_property(freertos_dir freertos COMPONENT_DIR)
+idf_component_get_property(nghttp_dir nghttp COMPONENT_DIR)
+idf_component_get_property(esp_wifi_dir esp_wifi COMPONENT_DIR)
+idf_component_get_property(esp_hw_support_dir esp_hw_support COMPONENT_DIR)
+idf_component_get_property(esp_tls_dir esp-tls COMPONENT_DIR)
+idf_component_get_property(esp_netif_dir esp_netif COMPONENT_DIR)
+idf_component_get_property(esp_common_dir esp_common COMPONENT_DIR)
+idf_component_get_property(esp_rom_dir esp_rom COMPONENT_DIR)
+idf_component_get_property(esp_system_dir esp_system COMPONENT_DIR)
+idf_component_get_property(mbedtls_dir mbedtls COMPONENT_DIR)
+
+ idf_component_get_property(cmock_lib cmock COMPONENT_LIB)
+ set(IDF_PATH $ENV{IDF_PATH})
+ set(CMOCK_DIR "${IDF_PATH}/components/cmock/CMock")
+ set(MOCK_GEN_DIR "${CMAKE_CURRENT_BINARY_DIR}/mocks")
+ set(ENV{UNITY_DIR} "$ENV{IDF_PATH}/components/cmock/CMock")
+ file(MAKE_DIRECTORY ${MOCK_GEN_DIR})
+
+ set(MOCK_OUTPUT
+     "${MOCK_GEN_DIR}/Mockesp_transport.c" "${MOCK_GEN_DIR}/Mockesp_transport.h"
+     "${MOCK_GEN_DIR}/Mockesp_transport_ssl.c" "${MOCK_GEN_DIR}/Mockesp_transport_ssl.h"
+     "${MOCK_GEN_DIR}/Mockesp_transport_ws.c" "${MOCK_GEN_DIR}/Mockesp_transport_ws.h"
+     "${MOCK_GEN_DIR}/Mockesp_transport_tcp.c" "${MOCK_GEN_DIR}/Mockesp_transport_tcp.h"
+     "${MOCK_GEN_DIR}/Mockesp_event.c" "${MOCK_GEN_DIR}/Mockesp_event.h"
+     "${MOCK_GEN_DIR}/Mockesp_mac.c" "${MOCK_GEN_DIR}/Mockesp_mac.h"
+     "${MOCK_GEN_DIR}/Mockesp_random.c" "${MOCK_GEN_DIR}/Mockesp_random.h"
+     "${MOCK_GEN_DIR}/Mockesp_system.c" "${MOCK_GEN_DIR}/Mockesp_system.h"
+     "${MOCK_GEN_DIR}/Mockesp_tls.c" "${MOCK_GEN_DIR}/Mockesp_tls.h"
+     "${MOCK_GEN_DIR}/Mockevent_groups.c" "${MOCK_GEN_DIR}/Mockevent_groups.h"
+     "${MOCK_GEN_DIR}/Mockqueue.c" "${MOCK_GEN_DIR}/Mockqueue.h"
+     "${MOCK_GEN_DIR}/Mocktask.c" "${MOCK_GEN_DIR}/Mocktask.h"
+     "${MOCK_GEN_DIR}/Mockesp_log.c" "${MOCK_GEN_DIR}/Mockesp_log.h"
+     "${MOCK_GEN_DIR}/Mockhttp_parser.c" "${MOCK_GEN_DIR}/Mockhttp_parser.h"
+     )
+
+ set(HEADERS_TO_MOCK
+     ${tcp_transport_dir}/include/esp_transport_tcp.h
+     ${tcp_transport_dir}/include/esp_transport_ws.h
+     ${tcp_transport_dir}/include/esp_transport_ssl.h
+     ${tcp_transport_dir}/include/esp_transport.h
+     ${esp_event_dir}/include/esp_event.h
+     ${esp_hw_support_dir}/include/esp_mac.h
+     ${esp_hw_support_dir}/include/esp_random.h
+     ${esp_system_dir}/include/esp_system.h
+     ${esp_tls_dir}/esp_tls.h
+     ${freertos_dir}/include/freertos/queue.h
+     ${freertos_dir}/include/freertos/task.h
+     ${freertos_dir}/include/freertos/event_groups.h
+     ${log_dir}/include/esp_log.h
+     ${nghttp_dir}/port/include/http_parser.h
+     )
+
+ set(srcs
+     ${MOCK_GEN_DIR}/Mockesp_transport.c
+     ${MOCK_GEN_DIR}/Mockesp_transport_ws.c
+     ${MOCK_GEN_DIR}/Mockesp_transport_ssl.c
+     ${MOCK_GEN_DIR}/Mockesp_transport_tcp.c
+     ${MOCK_GEN_DIR}/Mockesp_transport_tcp.c
+     ${MOCK_GEN_DIR}/Mockesp_event.c
+     ${MOCK_GEN_DIR}/Mockesp_mac.c
+     ${MOCK_GEN_DIR}/Mockesp_random.c
+     ${MOCK_GEN_DIR}/Mockesp_system.c
+     ${MOCK_GEN_DIR}/Mockesp_tls.c
+     ${MOCK_GEN_DIR}/Mockesp_log.c
+     ${MOCK_GEN_DIR}/Mockhttp_parser.c
+     ${MOCK_GEN_DIR}/Mockevent_groups.c
+     ${MOCK_GEN_DIR}/Mockqueue.c
+     ${MOCK_GEN_DIR}/Mocktask.c
+    )
+
+ add_custom_command(
+     OUTPUT ruby_found SYMBOLIC
+     COMMAND "ruby" "-v"
+     COMMENT "Try to find ruby. If this fails, you need to install ruby"
+ )
+
+ add_custom_command(
+     OUTPUT ${MOCK_OUTPUT}
+     DEPENDS ruby_found
+     COMMAND ${CMAKE_COMMAND} -E env "UNITY_DIR=${IDF_PATH}/components/unity/unity"
+         ruby
+         ${CMOCK_DIR}/lib/cmock.rb
+         -o${CMAKE_CURRENT_SOURCE_DIR}/host_test/mocks/config.yaml
+         ${HEADERS_TO_MOCK}
+   )
+
+ add_library(mocks ${srcs})
+ target_include_directories(mocks PUBLIC
+    ${CMAKE_CURRENT_SOURCE_DIR}/host_test/mocks/include
+    ${tcp_transport_dir}/include
+    ${esp_tls_dir}
+    ${freertos_dir}/include
+    ${esp_event_dir}/include
+    ${esp_system_dir}/include
+    ${esp_common_dir}/include
+    ${esp_wifi_dir}/include
+    ${esp_hw_support_dir}/include
+    ${esp_netif_dir}/include
+    ${log_dir}/include
+    ${esp_rom_dir}/include
+    ${mbedtls_dir}/port/include
+    ${nghttp_dir}/port/include
+    ${mbedtls_dir}/mbedtls/include
+    ${freertos_dir}/include/freertos
+    esp-mqtt/lib/include
+    ${MOCK_GEN_DIR}
+    )
+ target_link_libraries(mocks PUBLIC ${cmock_lib})
+ target_compile_definitions(mocks PUBLIC
+     CONFIG_LOG_MAXIMUM_LEVEL=5
+     CONFIG_LOG_DEFAULT_LEVEL=3
+     CONFIG_ESP_TLS_USING_MBEDTLS
+     CONFIG_ESP_TLS_SERVER
+     CONFIG_LOG_TIMESTAMP_SOURCE_RTOS)
+ target_link_options(${COMPONENT_LIB} INTERFACE -fsanitize=address)
+
+ target_link_libraries(${COMPONENT_LIB} PUBLIC mocks)
+
+else()
+    idf_component_get_property(nghttp_lib nghttp COMPONENT_LIB)
+    idf_component_get_property(tcp_transport_lib tcp_transport COMPONENT_LIB)
+    target_link_libraries(${COMPONENT_LIB} PUBLIC ${nghttp_lib} ${tcp_transport_lib})
+endif()

+ 6 - 0
components/mqtt/host_test/CMakeLists.txt

@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 3.5)
+
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+set(COMPONENTS main)
+option(TEST_BUILD "" ON)
+project(host_mqtt_client_test)

+ 27 - 0
components/mqtt/host_test/README.md

@@ -0,0 +1,27 @@
+# Description
+
+This directory contains test code for the mqtt client that runs on host.
+
+Tests are written using [Catch2](https://github.com/catchorg/Catch2) test framework 
+
+# Build
+
+Tests build regularly like an idf project. 
+
+```
+idf.py build
+```
+
+# Run
+
+The build produces an executable in the build folder. 
+
+Just run:
+
+```
+./build/host_mqtt_client_test.elf
+```
+
+The test executable have some options provided by the test framework. 
+
+

+ 3 - 0
components/mqtt/host_test/main/CMakeLists.txt

@@ -0,0 +1,3 @@
+idf_component_register(SRCS  "test_mqtt_client.cpp"
+                       INCLUDE_DIRS "$ENV{IDF_PATH}/tools/catch"
+                       REQUIRES cmock mqtt)

+ 109 - 0
components/mqtt/host_test/main/test_mqtt_client.cpp

@@ -0,0 +1,109 @@
+#define CATCH_CONFIG_MAIN  // This tells the catch header to generate a main
+#include "catch.hpp"
+#include "mqtt_client.h"
+
+extern "C" {
+#include "Mockesp_event.h"
+#include "Mockesp_log.h"
+#include "Mockesp_system.h"
+#include "Mockesp_mac.h"
+#include "Mockesp_transport.h"
+#include "Mockesp_transport_ssl.h"
+#include "Mockesp_transport_tcp.h"
+#include "Mockesp_transport_ws.h"
+#include "Mockevent_groups.h"
+#include "Mockhttp_parser.h"
+#include "Mockqueue.h"
+#include "Mocktask.h"
+
+    /*
+     * The following functions are not directly called but the generation of them
+     * from cmock is broken, so we need to define them here.
+     */
+    BaseType_t xQueueTakeMutexRecursive(QueueHandle_t xMutex,
+                                        TickType_t xTicksToWait)
+    {
+        return 0;
+    }
+    BaseType_t xQueueGiveMutexRecursive(QueueHandle_t xMutex)
+    {
+        return 0;
+    }
+}
+
+struct ClientInitializedFixture {
+    esp_mqtt_client_handle_t client;
+    ClientInitializedFixture()
+    {
+        TEST_PROTECT();
+        int mtx;
+        int transport_list;
+        int transport;
+        int event_group;
+        uint8_t mac[] = {0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55};
+        esp_log_write_Ignore();
+        xQueueCreateMutex_ExpectAnyArgsAndReturn(
+            reinterpret_cast<QueueHandle_t>(&mtx));
+        xEventGroupCreate_IgnoreAndReturn(reinterpret_cast<EventGroupHandle_t>(&event_group));
+        esp_log_timestamp_IgnoreAndReturn(0);
+        esp_transport_list_init_IgnoreAndReturn(reinterpret_cast<esp_transport_list_handle_t>(&transport_list));
+        esp_transport_tcp_init_IgnoreAndReturn(reinterpret_cast<esp_transport_handle_t>(&transport));
+        esp_transport_ssl_init_IgnoreAndReturn(reinterpret_cast<esp_transport_handle_t>(&transport));
+        esp_transport_ws_init_IgnoreAndReturn(reinterpret_cast<esp_transport_handle_t>(&transport));
+        esp_transport_ws_set_subprotocol_IgnoreAndReturn(ESP_OK);
+        esp_transport_list_add_IgnoreAndReturn(ESP_OK);
+        esp_transport_set_default_port_IgnoreAndReturn(ESP_OK);
+        http_parser_parse_url_IgnoreAndReturn(0);
+        http_parser_url_init_ExpectAnyArgs();
+        esp_event_loop_create_IgnoreAndReturn(ESP_OK);
+        esp_read_mac_IgnoreAndReturn(ESP_OK);
+        esp_read_mac_ReturnThruPtr_mac(mac);
+        esp_transport_list_destroy_IgnoreAndReturn(ESP_OK);
+        vEventGroupDelete_Ignore();
+        vQueueDelete_Ignore();
+
+        esp_mqtt_client_config_t config{};
+        client = esp_mqtt_client_init(&config);
+    }
+    ~ClientInitializedFixture()
+    {
+        esp_mqtt_client_destroy(client);
+    }
+};
+TEST_CASE_METHOD(ClientInitializedFixture, "Client set uri")
+{
+    struct http_parser_url ret_uri;
+    SECTION("User set a correct URI") {
+        http_parser_parse_url_StopIgnore();
+        http_parser_parse_url_ExpectAnyArgsAndReturn(0);
+        http_parser_parse_url_ReturnThruPtr_u(&ret_uri);
+        auto res = esp_mqtt_client_set_uri(client, " ");
+        REQUIRE(res == ESP_OK);
+    }
+    SECTION("Incorrect URI from user") {
+        http_parser_parse_url_StopIgnore();
+        http_parser_parse_url_ExpectAnyArgsAndReturn(1);
+        http_parser_parse_url_ReturnThruPtr_u(&ret_uri);
+        auto res = esp_mqtt_client_set_uri(client, " ");
+        REQUIRE(res == ESP_FAIL);
+    }
+}
+TEST_CASE_METHOD(ClientInitializedFixture, "Client Start")
+{
+    SECTION("Successful start") {
+        xTaskCreatePinnedToCore_ExpectAnyArgsAndReturn(pdTRUE);
+        auto res = esp_mqtt_client_start(client);
+        REQUIRE(res == ESP_OK);
+    }
+    SECTION("Failed on initialization") {
+        xTaskCreatePinnedToCore_ExpectAnyArgsAndReturn(pdFALSE);
+        auto res = esp_mqtt_client_start(nullptr);
+        REQUIRE(res == ESP_ERR_INVALID_ARG);
+    }
+    SECTION("Client already started") {}
+    SECTION("Failed to start task") {
+        xTaskCreatePinnedToCore_ExpectAnyArgsAndReturn(pdFALSE);
+        auto res = esp_mqtt_client_start(client);
+        REQUIRE(res == ESP_FAIL);
+    }
+}

+ 23 - 0
components/mqtt/host_test/mocks/config.yaml

@@ -0,0 +1,23 @@
+        :cmock:
+          :plugins:
+            - expect
+            - expect_any_args
+            - return_thru_ptr
+            - ignore
+            - array
+            - callback
+          :includes_h_pre_orig_header:
+            - FreeRTOS.h
+            - net/if.h
+          :strippables:
+            - '(?:__attribute__\s*\(+.*?\)+)'
+            - '(?:vQueueAddToRegistry\s*\(+.*?\)+)'
+            - '(?:vQueueUnregisterQueue\s*\(+.*?\)+)'
+            - '(?:pcQueueGetName\s*\(+.*?\)+)'
+            - '(?:xQueueTakeMutexRecursive\s*\(+.*?\)+)'
+            - '(?:xQueueGiveMutexRecursive\s*\(+.*?\)+)'
+            - '(?:vTaskSetThreadLocalStoragePointerAndDelCallback\s*\(+.*?\)+)'
+            - '(?:esp_log_writev\s*\(+.*?\)+)'
+            - '(?:esp_restart\s*\(+.*?\)+)'
+            - '(?:esp_system_abort\s*\(+.*?\)+)'
+            - PRIVILEGED_FUNCTION

+ 133 - 0
components/mqtt/host_test/mocks/include/freertos/FreeRTOSConfig.h

@@ -0,0 +1,133 @@
+/*
+    FreeRTOS V8.2.0 - Copyright (C) 2015 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_H
+#define FREERTOS_CONFIG_H
+
+#include "esp_attr.h"
+
+/*-----------------------------------------------------------
+ * Application specific definitions.
+ *
+ * These definitions should be adjusted for your particular hardware and
+ * application requirements.
+ *
+ * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
+ * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
+ *
+ * See http://www.freertos.org/a00110.html.
+ *----------------------------------------------------------*/
+
+#define configUSE_PREEMPTION 1
+#define configUSE_IDLE_HOOK 1
+#define configUSE_TICK_HOOK 1
+#define configTICK_RATE_HZ ((TickType_t)1000)
+#define configMINIMAL_STACK_SIZE ((unsigned short)256) /* This can be made smaller if required. */
+#define configTOTAL_HEAP_SIZE ((size_t)(32 * 1024))
+#define configMAX_TASK_NAME_LEN (16)
+#define configUSE_TRACE_FACILITY 1
+#define configUSE_16_BIT_TICKS 1
+#define configIDLE_SHOULD_YIELD 1
+#define configUSE_CO_ROUTINES 1
+#define configUSE_MUTEXES 1
+#define configUSE_COUNTING_SEMAPHORES 1
+#define configUSE_ALTERNATIVE_API 0
+#define configUSE_RECURSIVE_MUTEXES 1
+#define configCHECK_FOR_STACK_OVERFLOW 0 /* Do not use this option on the PC port. */
+#define configUSE_APPLICATION_TASK_TAG 1
+#define configQUEUE_REGISTRY_SIZE 0
+
+#define configMAX_PRIORITIES (10)
+#define configMAX_CO_ROUTINE_PRIORITIES (2)
+
+/* Set the following definitions to 1 to include the API function, or zero
+to exclude the API function. */
+
+#define INCLUDE_vTaskPrioritySet 1
+#define INCLUDE_uxTaskPriorityGet 1
+#define INCLUDE_vTaskDelete 1
+#define INCLUDE_vTaskCleanUpResources 1
+#define INCLUDE_vTaskSuspend 1
+#define INCLUDE_vTaskDelayUntil 1
+#define INCLUDE_vTaskDelay 1
+#define INCLUDE_uxTaskGetStackHighWaterMark 0 /* Do not use this option on the PC port. */
+
+/* This demo makes use of one or more example stats formatting functions.  These
+format the raw data provided by the uxTaskGetSystemState() function in to human
+readable ASCII form.  See the notes in the implementation of vTaskList() within
+FreeRTOS/Source/tasks.c for limitations. */
+#define configUSE_STATS_FORMATTING_FUNCTIONS 1
+
+/* An example "task switched in" hook macro definition. */
+#define traceTASK_SWITCHED_IN() xTaskCallApplicationTaskHook(NULL, (void*)0xabcd)
+
+extern void vMainQueueSendPassed(void);
+#define traceQUEUE_SEND(pxQueue) vMainQueueSendPassed()
+
+#endif /* FREERTOS_CONFIG_H */

+ 199 - 0
components/mqtt/host_test/mocks/include/freertos/portmacro.h

@@ -0,0 +1,199 @@
+/*
+ * FreeRTOS Kernel V10.2.1
+ * Copyright (C) 2019 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * http://www.FreeRTOS.org
+ * http://aws.amazon.com/freertos
+ *
+ * 1 tab == 4 spaces!
+ */
+#ifndef PORTMACRO_H
+#define PORTMACRO_H
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <limits.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef __ASSEMBLER__
+
+/*-----------------------------------------------------------
+ * Port specific definitions.
+ *
+ * The settings in this file configure FreeRTOS correctly for the
+ * given hardware and compiler.
+ *
+ * These settings should not be altered.
+ *-----------------------------------------------------------
+ */
+
+/* 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;
+
+#if (configUSE_16_BIT_TICKS == 1)
+typedef uint16_t TickType_t;
+#define portMAX_DELAY (TickType_t)0xffff
+#else
+typedef uint32_t TickType_t;
+#define portMAX_DELAY (TickType_t)0xffffffffUL
+#endif
+/*------------------------------------------------------*/
+
+/* Architecture specifics. */
+#define portSTACK_GROWTH (-1)
+#define portTICK_PERIOD_MS ((TickType_t)(1000 / configTICK_RATE_HZ))
+#define portBYTE_ALIGNMENT 16
+/*-----------------------------------------------------------*/
+
+#define portCRITICAL_NESTING_IN_TCB 0
+
+/*
+ * Send an interrupt to another core in order to make the task running
+ * on it yield for a higher-priority task.
+ */
+void vPortYieldOtherCore(BaseType_t coreid);
+
+/*
+ Callback to set a watchpoint on the end of the stack. Called every context switch to change the stack
+ watchpoint around.
+ */
+void vPortSetStackWatchpoint(void *pxStackStart);
+
+/*
+ * Returns true if the current core is in ISR context; low prio ISR, med prio ISR or timer tick ISR. High prio ISRs
+ * aren't detected here, but they normally cannot call C code, so that should not be an issue anyway.
+ */
+BaseType_t xPortInIsrContext(void);
+
+/*
+ * This function will be called in High prio ISRs. Returns true if the current core was in ISR context
+ * before calling into high prio ISR context.
+ */
+BaseType_t xPortInterruptedFromISRContext(void);
+
+/* "mux" data structure (spinlock) */
+typedef struct {
+    /* owner field values:
+     * 0                - Uninitialized (invalid)
+     * portMUX_FREE_VAL - Mux is free, can be locked by either CPU
+     * CORE_ID_REGVAL_PRO / CORE_ID_REGVAL_APP - Mux is locked to the particular core
+     *
+     *
+     * Any value other than portMUX_FREE_VAL, CORE_ID_REGVAL_PRO, CORE_ID_REGVAL_APP indicates corruption
+     */
+    uint32_t owner;
+    /* count field:
+     * If mux is unlocked, count should be zero.
+     * If mux is locked, count is non-zero & represents the number of recursive locks on the mux.
+     */
+    uint32_t count;
+#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
+    const char *lastLockedFn;
+    int lastLockedLine;
+#endif
+} portMUX_TYPE;
+
+#define portMUX_FREE_VAL SPINLOCK_FREE
+
+/* Special constants for vPortCPUAcquireMutexTimeout() */
+#define portMUX_NO_TIMEOUT SPINLOCK_WAIT_FOREVER /* When passed for 'timeout_cycles', spin forever if necessary */
+#define portMUX_TRY_LOCK SPINLOCK_NO_WAIT        /* Try to acquire the spinlock a single time only */
+
+// Keep this in sync with the portMUX_TYPE struct definition please.
+#ifndef CONFIG_FREERTOS_PORTMUX_DEBUG
+#define portMUX_INITIALIZER_UNLOCKED                                                                                   \
+    { .owner = portMUX_FREE_VAL, .count = 0, }
+#else
+#define portMUX_INITIALIZER_UNLOCKED                                                                                   \
+    { .owner = portMUX_FREE_VAL, .count = 0, .lastLockedFn = "(never locked)", .lastLockedLine = -1 }
+#endif
+
+/* Scheduler utilities. */
+extern void vPortYield(void);
+extern void vPortYieldFromISR(void);
+
+#define portYIELD() vPortYield()
+#define portYIELD_FROM_ISR() vPortYieldFromISR()
+
+/* Yielding within an API call (when interrupts are off), means the yield should be delayed
+   until interrupts are re-enabled.
+   To do this, we use the "cross-core" interrupt as a trigger to yield on this core when interrupts are re-enabled.This
+   is the same interrupt & code path which is used to trigger a yield between CPUs, although in this case the yield is
+   happening on the same CPU.
+*/
+#define portYIELD_WITHIN_API() portYIELD()
+/*-----------------------------------------------------------*/
+
+/* Critical section management. */
+extern int vPortSetInterruptMask(void);
+extern void vPortClearInterruptMask(int);
+
+void vPortCPUInitializeMutex(portMUX_TYPE *mux);
+void vPortCPUAcquireMutex(portMUX_TYPE *mux);
+bool vPortCPUAcquireMutexTimeout(portMUX_TYPE *mux, int timeout_cycles);
+void vPortCPUReleaseMutex(portMUX_TYPE *mux);
+
+extern void vPortEnterCritical(void);
+extern void vPortExitCritical(void);
+
+extern void esp_vApplicationIdleHook(void);
+extern void esp_vApplicationTickHook(void);
+
+#ifndef CONFIG_FREERTOS_LEGACY_HOOKS
+#define vApplicationIdleHook esp_vApplicationIdleHook
+#define vApplicationTickHook esp_vApplicationTickHook
+#endif /* !CONFIG_FREERTOS_LEGACY_HOOKS */
+
+/* Task function macros as described on the FreeRTOS.org WEB site. */
+#define portTASK_FUNCTION_PROTO(vFunction, pvParameters) void vFunction(void* pvParameters)
+#define portTASK_FUNCTION(vFunction, pvParameters) void vFunction(void* pvParameters)
+
+void vApplicationSleep(TickType_t xExpectedIdleTime);
+#define portSUPPRESS_TICKS_AND_SLEEP(idleTime) vApplicationSleep(idleTime)
+
+#define portNOP() //__asm volatile  ( " nop " )
+
+#define portVALID_TCB_MEM(ptr)   // esp_ptr_byte_accessible(ptr)
+#define portVALID_STACK_MEM(ptr) // esp_ptr_byte_accessible(ptr)
+
+#endif //__ASSEMBLER__
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PORTMACRO_H */

+ 2 - 0
components/mqtt/host_test/mocks/include/machine/endian.h

@@ -0,0 +1,2 @@
+#pragma once
+#include_next <endian.h>

+ 66 - 0
components/mqtt/host_test/mocks/include/sys/queue.h

@@ -0,0 +1,66 @@
+#pragma once
+
+/* Implementation from BSD headers*/
+#define	QMD_SAVELINK(name, link)	void **name = (void *)&(link)
+#define	TRASHIT(x)	do {(x) = (void *)-1;} while (0)
+#define	STAILQ_NEXT(elm, field)	((elm)->field.stqe_next)
+
+#define	STAILQ_FIRST(head)	((head)->stqh_first)
+
+#define	STAILQ_HEAD(name, type)						\
+struct name {								\
+	struct type *stqh_first;/* first element */			\
+	struct type **stqh_last;/* addr of last next element */		\
+}
+
+#define	STAILQ_ENTRY(type)						\
+struct {								\
+	struct type *stqe_next;	/* next element */			\
+}
+
+#define	STAILQ_INSERT_TAIL(head, elm, field) do {			\
+	STAILQ_NEXT((elm), field) = NULL;				\
+	*(head)->stqh_last = (elm);					\
+	(head)->stqh_last = &STAILQ_NEXT((elm), field);			\
+} while (0)
+
+#define	STAILQ_INIT(head) do {						\
+	STAILQ_FIRST((head)) = NULL;					\
+	(head)->stqh_last = &STAILQ_FIRST((head));			\
+} while (0)
+
+#define	STAILQ_FOREACH(var, head, field)				\
+	for((var) = STAILQ_FIRST((head));				\
+	   (var);							\
+	   (var) = STAILQ_NEXT((var), field))
+
+#define	STAILQ_FOREACH_SAFE(var, head, field, tvar)			\
+	for ((var) = STAILQ_FIRST((head));				\
+	    (var) && ((tvar) = STAILQ_NEXT((var), field), 1);		\
+	    (var) = (tvar))
+
+#define STAILQ_REMOVE_AFTER(head, elm, field) do {			\
+	if ((STAILQ_NEXT(elm, field) =					\
+	     STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL)	\
+		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
+} while (0)
+
+#define	STAILQ_REMOVE_HEAD(head, field) do {				\
+	if ((STAILQ_FIRST((head)) =					\
+	     STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL)		\
+		(head)->stqh_last = &STAILQ_FIRST((head));		\
+} while (0)
+
+#define	STAILQ_REMOVE(head, elm, type, field) do {			\
+	QMD_SAVELINK(oldnext, (elm)->field.stqe_next);			\
+	if (STAILQ_FIRST((head)) == (elm)) {				\
+		STAILQ_REMOVE_HEAD((head), field);			\
+	}								\
+	else {								\
+		struct type *curelm = STAILQ_FIRST((head));		\
+		while (STAILQ_NEXT(curelm, field) != (elm))		\
+			curelm = STAILQ_NEXT(curelm, field);		\
+		STAILQ_REMOVE_AFTER(head, curelm, field);		\
+	}								\
+	TRASHIT(*oldnext);						\
+} while (0)

+ 6 - 0
components/mqtt/host_test/sdkconfig.defaults

@@ -0,0 +1,6 @@
+CONFIG_IDF_TARGET="linux"
+CONFIG_COMPILER_CXX_EXCEPTIONS=y
+CONFIG_COMPILER_CXX_RTTI=y
+CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE=0
+CONFIG_COMPILER_STACK_CHECK_NONE=y
+CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=n