Closed ljden closed 1 year ago
Hi @ljden
There is a misunderstanding here. The hal component does not have a mock (yet) in IDF. You can see that $ENV{IDF_PATH}/tools/mocks/hal/
does not contain any CMakeLists.txt file. Hence, adding this path doesn't do anything $ENV{IDF_PATH}/tools/mocks/driver/
, in contrast, does have a CMakeLists.txt file that is creating the mock.
To mock the RMT API provided in rmt_encoder.h
, you basically (more on that below) only need to mock it using the driver mock. The driver mock currently doesn't mock the RMT API, but it should be doable by adding the rmt_encoder.h
to the driver mock's CMakeLists.txt. However, all driver files in IDF pull some of their types in from the HAL layer. And this is where the $ENV{IDF_PATH}/tools/mocks/hal/
directory becomes important: it provides some simple stubs mimicking the actual hal/xxx_types.h
headers. They are used from all other "real" mocks, e.g. the driver mock. The stubs in $ENV{IDF_PATH}/tools/mocks/hal/
are a shortcut to avoid the actual work of mocking the HAL component. These stubs usually only contain the minimal amount of types to enable compilation of the corresponding driver header.
These aspects are more or less also described in the Programming Guide section about Mocks.
Please also check the Component Linux/Mock Support Overview where you can see which components are (at least partially) mocked.
@ljden Something like this should work:
Ah I missed those docs as they are not in the v5.0 stable docs, thanks for the links and details. I will apply the supplied patch and see how it goes. Thanks
That seems to get closer, still got issues:
-- Build files have been written to: /home/vbox/led_manager/host_test/build
[1/45] Try to find ruby. If this fails, you need to install rubyruby 3.0.2p107 (2021-07-07 revision 0db68f0233) [x86_64-linux-gnu]
[26/44] Try to find ruby. If this fails, you need to install rubyruby 3.0.2p107 (2021-07-07 revision 0db68f0233) [x86_64-linux-gnu]
[32/43] Building C object esp-idf/led_manager/CMakeFiles/__idf_led_manager.dir/led_strip_encoder.c.oFAILED: esp-idf/led_manager/CMakeFiles/__idf_led_manager.dir/led_strip_encoder.c.o
/usr/bin/cc -DUNITY_INCLUDE_CONFIG_H -I/home/vbox/led_manager/host_test/build/config -I/home/vbox/led_manager/include -I/home/vbox/esp/esp-idf/tools/mocks/freertos/include -I/home/vbox/esp/esp-idf/components/freertos/FreeRTOS-Kernel/include -I/home/vbox/esp/esp-idf/components/freertos/esp_additions/include -I/home/vbox/esp/esp-idf/components/freertos/esp_additions/include/freertos -I/home/vbox/esp/esp-idf/components/freertos/FreeRTOS-Kernel/include/freertos -I/home/vbox/esp/esp-idf/components/freertos/FreeRTOS-Kernel/portable/linux/include -I/home/vbox/led_manager/host_test/build/esp-idf/freertos/mocks -I/home/vbox/esp/esp-idf/components/log/include -I/home/vbox/esp/esp-idf/components/esp_rom/include -I/home/vbox/esp/esp-idf/components/esp_rom/include/linux -I/home/vbox/esp/esp-idf/tools/mocks/soc/include -I/home/vbox/esp/esp-idf/components/esp_common/include -I/home/vbox/esp/esp-idf/components/cmock/CMock/src -I/home/vbox/esp/esp-idf/components/unity/include -I/home/vbox/esp/esp-idf/components/unity/unity/src -I/home/vbox/led_manager/host_test/managed_components/component_base/include -I/home/vbox/esp/esp-idf/components/esp_event/include -I/home/vbox/esp/esp-idf/components/linux/include -I/home/vbox/esp/esp-idf/components/driver/include -I/home/vbox/esp/esp-idf/components/driver/include/driver -I/home/vbox/esp/esp-idf/tools/mocks/hal/include -I/home/vbox/esp/esp-idf/tools/mocks/esp_hw_support/include -I/home/vbox/led_manager/host_test/build/esp-idf/driver/mocks -ffunction-sections -fdata-sections -Wall -Werror=all -Wno-error=unused-function -Wno-error=unused-variable -Wno-error=deprecated-declarations -Wextra -Wno-unused-parameter -Wno-sign-compare -Wno-enum-conversion -gdwarf-4 -ggdb -Og -fmacro-prefix-map=/home/vbox/led_manager/host_test=. -fmacro-prefix-map=/home/vbox/esp/esp-idf=/IDF -fstrict-volatile-bitfields -Wno-error=unused-but-set-variable -fno-jump-tables -fno-tree-switch-conversion -std=gnu17 -Wno-old-style-declaration -D_GNU_SOURCE -DIDF_VER=\"v5.0-161-g76804f3d42-dirty\" -DconfigTICK_RATE_HZ=1000 -DCONFIG_FREERTOS_HZ=1000 -DESP_PLATFORM -DSPI_MOCK -MD -MT esp-idf/led_manager/CMakeFiles/__idf_led_manager.dir/led_strip_encoder.c.o -MF esp-idf/led_manager/CMakeFiles/__idf_led_manager.dir/led_strip_encoder.c.o.d -o esp-idf/led_manager/CMakeFiles/__idf_led_manager.dir/led_strip_encoder.c.o -c /home/vbox/led_manager/led_strip_encoder.c
/home/vbox/led_manager/led_strip_encoder.c: In function ‘rmt_encode_led_strip’:
/home/vbox/led_manager/led_strip_encoder.c:22:44: error: implicit declaration of function ‘__containerof’ [-Werror=implicit-function-declaration]
22 | rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
| ^~~~~~~~~~~~~
/home/vbox/led_manager/led_strip_encoder.c:22:67: error: expected expression before ‘rmt_led_strip_encoder_t’
22 | rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
| ^~~~~~~~~~~~~~~~~~~~~~~
/home/vbox/led_manager/led_strip_encoder.c: In function ‘rmt_del_led_strip_encoder’:
/home/vbox/led_manager/led_strip_encoder.c:58:67: error: expected expression before ‘rmt_led_strip_encoder_t’
58 | rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
| ^~~~~~~~~~~~~~~~~~~~~~~
/home/vbox/led_manager/led_strip_encoder.c: In function ‘rmt_led_strip_encoder_reset’:
/home/vbox/led_manager/led_strip_encoder.c:67:67: error: expected expression before ‘rmt_led_strip_encoder_t’
67 | rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
| ^~~~~~~~~~~~~~~~~~~~~~~
cc1: some warnings being treated as errors
[33/43] Building CXX object esp-idf/led_manager/CMakeFiles/__idf_led_manager.dir/SerialLed.cpp.oFAILED: esp-idf/led_manager/CMakeFiles/__idf_led_manager.dir/SerialLed.cpp.o
/usr/bin/c++ -DUNITY_INCLUDE_CONFIG_H -I/home/vbox/led_manager/host_test/build/config -I/home/vbox/led_manager/include -I/home/vbox/esp/esp-idf/tools/mocks/freertos/include -I/home/vbox/esp/esp-idf/components/freertos/FreeRTOS-Kernel/include -I/home/vbox/esp/esp-idf/components/freertos/esp_additions/include -I/home/vbox/esp/esp-idf/components/freertos/esp_additions/include/freertos -I/home/vbox/esp/esp-idf/components/freertos/FreeRTOS-Kernel/include/freertos -I/home/vbox/esp/esp-idf/components/freertos/FreeRTOS-Kernel/portable/linux/include -I/home/vbox/led_manager/host_test/build/esp-idf/freertos/mocks -I/home/vbox/esp/esp-idf/components/log/include -I/home/vbox/esp/esp-idf/components/esp_rom/include -I/home/vbox/esp/esp-idf/components/esp_rom/include/linux -I/home/vbox/esp/esp-idf/tools/mocks/soc/include -I/home/vbox/esp/esp-idf/components/esp_common/include -I/home/vbox/esp/esp-idf/components/cmock/CMock/src -I/home/vbox/esp/esp-idf/components/unity/include -I/home/vbox/esp/esp-idf/components/unity/unity/src -I/home/vbox/led_manager/host_test/managed_components/component_base/include -I/home/vbox/esp/esp-idf/components/esp_event/include -I/home/vbox/esp/esp-idf/components/linux/include -I/home/vbox/esp/esp-idf/components/driver/include -I/home/vbox/esp/esp-idf/components/driver/include/driver -I/home/vbox/esp/esp-idf/tools/mocks/hal/include -I/home/vbox/esp/esp-idf/tools/mocks/esp_hw_support/include -I/home/vbox/led_manager/host_test/build/esp-idf/driver/mocks -ffunction-sections -fdata-sections -Wall -Werror=all -Wno-error=unused-function -Wno-error=unused-variable -Wno-error=deprecated-declarations -Wextra -Wno-unused-parameter -Wno-sign-compare -Wno-enum-conversion -gdwarf-4 -ggdb -Og -fmacro-prefix-map=/home/vbox/led_manager/host_test=. -fmacro-prefix-map=/home/vbox/esp/esp-idf=/IDF -fstrict-volatile-bitfields -Wno-error=unused-but-set-variable -fno-jump-tables -fno-tree-switch-conversion -std=gnu++20 -fexceptions -fno-rtti -D_GNU_SOURCE -DIDF_VER=\"v5.0-161-g76804f3d42-dirty\" -DconfigTICK_RATE_HZ=1000 -DCONFIG_FREERTOS_HZ=1000 -DESP_PLATFORM -DSPI_MOCK -std=gnu++20 -MD -MT esp-idf/led_manager/CMakeFiles/__idf_led_manager.dir/SerialLed.cpp.o -MF esp-idf/led_manager/CMakeFiles/__idf_led_manager.dir/SerialLed.cpp.o.d -o esp-idf/led_manager/CMakeFiles/__idf_led_manager.dir/SerialLed.cpp.o -c /home/vbox/led_manager/SerialLed.cpp
In file included from /home/vbox/led_manager/include/SerialLed.hpp:32,
from /home/vbox/led_manager/SerialLed.cpp:29:
/home/vbox/esp/esp-idf/components/driver/include/driver/rmt_tx.h:34:5: error: ‘rmt_clock_source_t’ does not name a type
34 | rmt_clock_source_t clk_src; /*!< Clock source of RMT TX channel, channels in the same group must use the same clock source */
| ^~~~~~~~~~~~~~~~~~
/home/vbox/led_manager/SerialLed.cpp: In constructor ‘cad::SerialLed::SerialLed()’:
/home/vbox/led_manager/SerialLed.cpp:141:20: error: ‘RMT_CLK_SRC_DEFAULT’ was not declared in this scope
141 | .clk_src = RMT_CLK_SRC_DEFAULT, // select source clock
| ^~~~~~~~~~~~~~~~~~~
/home/vbox/led_manager/SerialLed.cpp:151:5: error: ‘const rmt_tx_channel_config_t’ has no non-static data member named ‘clk_src’
151 | };
| ^
seems like I'm missing the rmt_clock_source_t
typedef
vbox@vbox:~/esp/esp-idf$ head -n 24 components/hal/include/hal/rmt_types.h| tail
/**
* @brief RMT group clock source
* @note User should select the clock source based on the power and resolution requirement
*/
#if SOC_RMT_SUPPORTED
typedef soc_periph_rmt_clk_src_t rmt_clock_source_t;
#else
typedef int rmt_clock_source_t;
#endif
the RMT_CLK_SRC_DEFAULT
from components/soc/esp32/include/soc/clk_tree_defs.h
or equivelant
vbox@vbox:~/esp/esp-idf/components/soc/esp32$ grep -rn "RMT_CLK_SRC_DEFAULT"
include/soc/clk_tree_defs.h:183: RMT_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB, /*!< Select APB as the default choice */
and __containerof()
from <sys/cdefs.h>
How would you recommend I go about adding these? Cheers
@ljden For the hal type, you can add it in the tools/mocks/hal/include/hal/rmt_types.h
from the patch. You can create a header file in a similar way inside tools/mocks/
for the soc
component and the definition you need. For the container_of macro, you could conditionally include <sys/cdefs.h>
if CONFIG_IDF_TARGET_LINUX
is defined.
Besides, I'm planning to create an MR that will add rmt mocking to version 5.1.
Thanks, I'll give that a go. Just a note - as far as I can tell, when CONFIG_IDF_TARGET_LINUX
is defined, the <sys/cdefs.h>
won't actually have a __contanerof()
definition. I'm going to try pulling out the bare minimum for __containerof()
and put it in a priv_includes
file for inclusion when CONFIG_IDF_TARGET_LINUX
is defined.
We're sticking with v5.0
and cherry-picking necessary commits so I'll keep an eye out for it. Thanks for the help
Minimum file to get __containerof()
compiling, not sure if it is correct when compiled for linux but it's not directly being tested yet
/* Macro to test version of GCC. Returns 0 for non-GCC or too old GCC. */
#ifndef __GNUC_PREREQ
# if defined __GNUC__ && defined __GNUC_MINOR__
# define __GNUC_PREREQ(maj, min) \
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
# else
# define __GNUC_PREREQ(maj, min) 0
# endif
#endif /* __GNUC_PREREQ */
/* Version with trailing underscores for BSD compatibility. */
#define __GNUC_PREREQ__(ma, mi) __GNUC_PREREQ(ma, mi)
#include <stddef.h>
#define __offsetof(type, field) offsetof(type, field)
typedef unsigned long __uintptr_t;
#ifndef __DEQUALIFY
#define __DEQUALIFY(type, var) ((type)(__uintptr_t)(const volatile void *)(var))
#endif
/*
* Given the pointer x to the member m of the struct s, return
* a pointer to the containing structure. When using GCC, we first
* assign pointer x to a local variable, to check that its type is
* compatible with member m.
*/
#if __GNUC_PREREQ__(3, 1)
#define __containerof(x, s, m) ({ \
const volatile __typeof(((s *)0)->m) *__x = (x); \
__DEQUALIFY(s *, (const volatile char *)__x - __offsetof(s, m));\
})
#else
#define __containerof(x, s, m) \
__DEQUALIFY(s *, (const volatile char *)(x) - __offsetof(s, m))
#endif
On Ubuntu 22.04, it's in the libbsd headers: /usr/include/bsd/sys/cdefs.h
. That file actually has __container_of
.
If that doesn't work for you, we have a helper header for __container_of on linux on master branch already, but not on v5.0.
Hmm, when I included sys/cdefs.h
it didn't compile and when I checked which file it was using it was an x86_64 not bsd. Good to know the files there, I will use that copy instead
@ljden We are currently working on a mock solution for RMT which should solve your problem.
@ljden The code has been merged, you should be able to mock the rmt driver now on IDF master branch.
Thanks for that. We are using v5.0 branch so won't be directly using the fix. Could you link the PR or relevant commits?
@ljden It should be 6382fc3d6b2f2111ab497916b4af251e50d0afad.
@ljden We'll close this issue, then.
Answers checklist.
IDF version.
v5.0
Operating System used.
Linux
How did you build your project?
Command line with idf.py
If you are using Windows, please specify command line type.
None
What is the expected behavior?
I am trying to write host tests for a led manager, which needs to mock hal.
What is the actual behavior?
Steps to reproduce.
copy led_strip_encoder.h/c into component under test and use code add driver and hal mocks to host test cmakelists
Build or installation Logs.
More Information.
No response