[driver]: partial mocking of driver component

* added mocking of spi master and gpio
* mock registering in one function in
  component.cmake
pull/7307/head
Jakob Hasse 2021-01-14 12:11:22 +08:00
rodzic cfb6857f53
commit 79b0256d63
13 zmienionych plików z 303 dodań i 1 usunięć

Wyświetl plik

@ -5,14 +5,18 @@
*/
#pragma once
#include "sdkconfig.h"
#include "esp_err.h"
#include <stdbool.h>
#include "esp_intr_alloc.h"
#if !CONFIG_IDF_TARGET_LINUX
#include <esp_types.h>
#include <esp_bit_defs.h>
#include "esp_attr.h"
#include "esp_intr_alloc.h"
#include "soc/soc_caps.h"
#include "soc/gpio_periph.h"
#endif // !CONFIG_IDF_TARGET_LINUX
#include "hal/gpio_types.h"
// |================================= WARNING ====================================================== |

Wyświetl plik

@ -9,8 +9,10 @@
#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
#ifndef SPI_MOCK
#include "soc/lldesc.h"
#include "soc/spi_periph.h"
#endif
#include "hal/spi_types.h"
#include "sdkconfig.h"

Wyświetl plik

@ -17,6 +17,7 @@
#include "param_test.h"
#include "soc/io_mux_reg.h"
#include "sdkconfig.h"
#include "soc/spi_periph.h"
// All the tests using the header should use this definition as much as possible,
// so that the working host can be changed easily in the future.

5
mocks/README.md 100644
Wyświetl plik

@ -0,0 +1,5 @@
# Mocked Components
All components in this directory mock their respective originals in the [component directory](../components). The components in this directory are for **testing only**. Currently, the main goal is to implement Linux-based host tests with these mocking components. Target-based tests using the mocking components are not possible now but may be possible in the future.
Some components only consist of header files without any CMakeLists.txt file. The headers in these are currently needed by other mocking components to satisfy a minimal set of definitions from dependencies. *They are not a full mock implementation.* These components with header files only may be replaced by an actual mock implementation of the corresponding component in the future.

Wyświetl plik

@ -0,0 +1,22 @@
# NOTE: This kind of mocking currently works on Linux targets only.
# On Espressif chips, too many dependencies are missing at the moment.
# Furthermore, this component can only mock the interfaces of
# spi_master.h and gpio.h.
message(STATUS "building DRIVER MOCKS (only SPI and GPIO driver)")
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}
MOCK_HEADER_FILES
${original_driver_dir}/include/driver/spi_master.h
${original_driver_dir}/include/driver/spi_common.h
${original_driver_dir}/include/driver/gpio.h)
idf_build_set_property(COMPILE_DEFINITIONS "-DSPI_MOCK" APPEND)

Wyświetl plik

@ -0,0 +1,8 @@
:cmock:
:plugins:
- expect
- expect_any_args
- return_thru_ptr
- array
- ignore_arg
- callback

Wyświetl plik

@ -0,0 +1,29 @@
/*
* 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 esp_hw_support component.
* It is a stripped-down copy to support mocking.
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/** Function prototype for interrupt handler function */
typedef void (*intr_handler_t)(void *arg);
/** Interrupt handler associated data structure */
typedef struct intr_handle_data_t intr_handle_data_t;
/** Handle to an interrupt handler */
typedef intr_handle_data_t *intr_handle_t ;
#ifdef __cplusplus
}
#endif

Wyświetl plik

@ -0,0 +1,14 @@
/*
* 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;

Wyświetl plik

@ -0,0 +1,14 @@
/*
* 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

Wyświetl plik

@ -0,0 +1,129 @@
/*
* 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 hal component. It is a stripped-down copy to support mocking.
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
GPIO_NUM_NC = -1, /*!< Use to signal not connected to S/W */
GPIO_NUM_0 = 0, /*!< GPIO0, input and output */
GPIO_NUM_1 = 1, /*!< GPIO1, input and output */
GPIO_NUM_2 = 2, /*!< GPIO2, input and output */
GPIO_NUM_3 = 3, /*!< GPIO3, input and output */
GPIO_NUM_4 = 4, /*!< GPIO4, input and output */
GPIO_NUM_5 = 5, /*!< GPIO5, input and output */
GPIO_NUM_6 = 6, /*!< GPIO6, input and output */
GPIO_NUM_7 = 7, /*!< GPIO7, input and output */
GPIO_NUM_8 = 8, /*!< GPIO8, input and output */
GPIO_NUM_9 = 9, /*!< GPIO9, input and output */
GPIO_NUM_10 = 10, /*!< GPIO10, input and output */
GPIO_NUM_11 = 11, /*!< GPIO11, input and output */
GPIO_NUM_12 = 12, /*!< GPIO12, input and output */
GPIO_NUM_13 = 13, /*!< GPIO13, input and output */
GPIO_NUM_14 = 14, /*!< GPIO14, input and output */
GPIO_NUM_15 = 15, /*!< GPIO15, input and output */
GPIO_NUM_16 = 16, /*!< GPIO16, input and output */
GPIO_NUM_17 = 17, /*!< GPIO17, input and output */
GPIO_NUM_18 = 18, /*!< GPIO18, input and output */
GPIO_NUM_19 = 19, /*!< GPIO19, input and output */
GPIO_NUM_20 = 20, /*!< GPIO20, input and output */
GPIO_NUM_21 = 21, /*!< GPIO21, input and output */
GPIO_NUM_22 = 22, /*!< GPIO22, input and output */
GPIO_NUM_23 = 23, /*!< GPIO23, input and output */
GPIO_NUM_25 = 25, /*!< GPIO25, input and output */
GPIO_NUM_26 = 26, /*!< GPIO26, input and output */
GPIO_NUM_27 = 27, /*!< GPIO27, input and output */
GPIO_NUM_28 = 28, /*!< GPIO28, input and output */
GPIO_NUM_29 = 29, /*!< GPIO29, input and output */
GPIO_NUM_30 = 30, /*!< GPIO30, input and output */
GPIO_NUM_31 = 31, /*!< GPIO31, input and output */
GPIO_NUM_32 = 32, /*!< GPIO32, input and output */
GPIO_NUM_33 = 33, /*!< GPIO33, input and output */
GPIO_NUM_34 = 34, /*!< GPIO34, input mode only */
GPIO_NUM_35 = 35, /*!< GPIO35, input mode only */
GPIO_NUM_36 = 36, /*!< GPIO36, input mode only */
GPIO_NUM_37 = 37, /*!< GPIO37, input mode only */
GPIO_NUM_38 = 38, /*!< GPIO38, input mode only */
GPIO_NUM_39 = 39, /*!< GPIO39, input mode only */
GPIO_NUM_MAX,
/** @endcond */
} gpio_num_t;
typedef enum {
GPIO_INTR_DISABLE = 0, /*!< Disable GPIO interrupt */
GPIO_INTR_POSEDGE = 1, /*!< GPIO interrupt type : rising edge */
GPIO_INTR_NEGEDGE = 2, /*!< GPIO interrupt type : falling edge */
GPIO_INTR_ANYEDGE = 3, /*!< GPIO interrupt type : both rising and falling edge */
GPIO_INTR_LOW_LEVEL = 4, /*!< GPIO interrupt type : input low level trigger */
GPIO_INTR_HIGH_LEVEL = 5, /*!< GPIO interrupt type : input high level trigger */
GPIO_INTR_MAX,
} gpio_int_type_t;
/** @cond */
#define GPIO_MODE_DEF_DISABLE (0)
#define GPIO_MODE_DEF_INPUT (1) ///< bit mask for input
#define GPIO_MODE_DEF_OUTPUT (2) ///< bit mask for output
#define GPIO_MODE_DEF_OD (3) ///< bit mask for OD mode
/** @endcond */
typedef enum {
GPIO_MODE_DISABLE = GPIO_MODE_DEF_DISABLE, /*!< GPIO mode : disable input and output */
GPIO_MODE_INPUT = GPIO_MODE_DEF_INPUT, /*!< GPIO mode : input only */
GPIO_MODE_OUTPUT = GPIO_MODE_DEF_OUTPUT, /*!< GPIO mode : output only mode */
GPIO_MODE_OUTPUT_OD = ((GPIO_MODE_DEF_OUTPUT) | (GPIO_MODE_DEF_OD)), /*!< GPIO mode : output only with open-drain mode */
GPIO_MODE_INPUT_OUTPUT_OD = ((GPIO_MODE_DEF_INPUT) | (GPIO_MODE_DEF_OUTPUT) | (GPIO_MODE_DEF_OD)), /*!< GPIO mode : output and input with open-drain mode*/
GPIO_MODE_INPUT_OUTPUT = ((GPIO_MODE_DEF_INPUT) | (GPIO_MODE_DEF_OUTPUT)), /*!< GPIO mode : output and input mode */
} gpio_mode_t;
typedef enum {
GPIO_PULLUP_DISABLE = 0x0, /*!< Disable GPIO pull-up resistor */
GPIO_PULLUP_ENABLE = 0x1, /*!< Enable GPIO pull-up resistor */
} gpio_pullup_t;
typedef enum {
GPIO_PULLDOWN_DISABLE = 0x0, /*!< Disable GPIO pull-down resistor */
GPIO_PULLDOWN_ENABLE = 0x1, /*!< Enable GPIO pull-down resistor */
} gpio_pulldown_t;
/**
* @brief Configuration parameters of GPIO pad for gpio_config function
*/
typedef struct {
uint64_t pin_bit_mask; /*!< GPIO pin: set with bit mask, each bit maps to a GPIO */
gpio_mode_t mode; /*!< GPIO mode: set input/output mode */
gpio_pullup_t pull_up_en; /*!< GPIO pull-up */
gpio_pulldown_t pull_down_en; /*!< GPIO pull-down */
gpio_int_type_t intr_type; /*!< GPIO interrupt type */
} gpio_config_t;
typedef enum {
GPIO_PULLUP_ONLY, /*!< Pad pull up */
GPIO_PULLDOWN_ONLY, /*!< Pad pull down */
GPIO_PULLUP_PULLDOWN, /*!< Pad pull up + pull down*/
GPIO_FLOATING, /*!< Pad floating */
} gpio_pull_mode_t;
typedef enum {
GPIO_DRIVE_CAP_0 = 0, /*!< Pad drive capability: weak */
GPIO_DRIVE_CAP_1 = 1, /*!< Pad drive capability: stronger */
GPIO_DRIVE_CAP_2 = 2, /*!< Pad drive capability: medium */
GPIO_DRIVE_CAP_DEFAULT = 2, /*!< Pad drive capability: medium */
GPIO_DRIVE_CAP_3 = 3, /*!< Pad drive capability: strongest */
GPIO_DRIVE_CAP_MAX,
} gpio_drive_cap_t;
typedef void (*gpio_isr_t)(void *);
#ifdef __cplusplus
}
#endif

Wyświetl plik

@ -0,0 +1,22 @@
/*
* 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 hal component. It is a stripped-down copy to support mocking.
*/
#pragma once
/**
* @brief Enum with the three SPI peripherals that are software-accessible in it
*/
typedef enum {
// SPI_HOST (SPI1_HOST) is not supported by the SPI Master and SPI Slave driver on ESP32-S2
SPI1_HOST=0, ///< SPI1
SPI2_HOST=1, ///< SPI2
SPI3_HOST=2, ///< SPI3
SPI_HOST_MAX=3, ///< invalid host value
} spi_host_device_t;

Wyświetl plik

@ -517,6 +517,53 @@ function(idf_component_register)
__component_set_properties()
endfunction()
# idf_component_mock
#
# @brief Create mock component with CMock and register it to IDF build system.
#
# @param[in, optional] INCLUDE_DIRS (multivalue) list include directories which belong to the header files
# provided in MOCK_HEADER_FILES. If any other include directories are necessary, they need
# to be passed here, too.
# @param[in, optional] MOCK_HEADER_FILES (multivalue) list of header files from which the mocks shall be generated.
# @param[in, optional] REQUIRES (multivalue) any other components required by the mock component.
#
function(idf_component_mock)
set(options)
set(single_value)
set(multi_value MOCK_HEADER_FILES INCLUDE_DIRS)
cmake_parse_arguments(_ "${options}" "${single_value}" "${multi_value}" ${ARGN})
list(APPEND __REQUIRES "cmock")
set(MOCK_GENERATED_HEADERS "")
set(MOCK_GENERATED_SRCS "")
set(MOCK_FILES "")
set(IDF_PATH $ENV{IDF_PATH})
set(CMOCK_DIR "${IDF_PATH}/components/cmock/CMock")
set(MOCK_GEN_DIR "${CMAKE_CURRENT_BINARY_DIR}")
list(APPEND __INCLUDE_DIRS "${MOCK_GEN_DIR}/mocks")
foreach(header_file ${__MOCK_HEADER_FILES})
get_filename_component(file_without_dir ${header_file} NAME_WE)
list(APPEND MOCK_GENERATED_HEADERS "${MOCK_GEN_DIR}/mocks/Mock${file_without_dir}.h")
list(APPEND MOCK_GENERATED_SRCS "${MOCK_GEN_DIR}/mocks/Mock${file_without_dir}.c")
endforeach()
file(MAKE_DIRECTORY "${MOCK_GEN_DIR}/mocks")
idf_component_register(SRCS "${MOCK_GENERATED_SRCS}"
INCLUDE_DIRS ${__INCLUDE_DIRS}
REQUIRES ${__REQUIRES})
execute_process(COMMAND ${CMAKE_COMMAND} -E env "UNITY_DIR=${IDF_PATH}/components/unity/unity"
ruby
${CMOCK_DIR}/lib/cmock.rb
-o${CMAKE_CURRENT_SOURCE_DIR}/mock/mock_config.yaml
${__MOCK_HEADER_FILES}
WORKING_DIRECTORY ${MOCK_GEN_DIR}
RESULT_VARIABLE cmock_result)
endfunction()
#
# Deprecated functions
#

Wyświetl plik

@ -56,6 +56,11 @@ endfunction()
macro(require_idf_targets)
endmacro()
macro(idf_component_mock)
idf_component_register(REQUIRES cmock)
return()
endmacro()
macro(idf_component_register)
set(options)
set(single_value KCONFIG KCONFIG_PROJBUILD)