mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-03 20:54:32 +02:00
Merge branch 'feature/esp_timer_mock' into 'master'
[esp_timer]: created mock override component See merge request espressif/esp-idf!14526
This commit is contained in:
@@ -356,6 +356,13 @@ test_esp_event:
|
|||||||
- idf.py build
|
- idf.py build
|
||||||
- build/test_esp_event_host.elf
|
- build/test_esp_event_host.elf
|
||||||
|
|
||||||
|
test_esp_timer_cxx:
|
||||||
|
extends: .host_test_template
|
||||||
|
script:
|
||||||
|
- cd ${IDF_PATH}/examples/cxx/experimental/experimental_cpp_component/host_test/esp_timer
|
||||||
|
- idf.py build
|
||||||
|
- build/test_esp_timer_cxx_host.elf
|
||||||
|
|
||||||
test_eh_frame_parser:
|
test_eh_frame_parser:
|
||||||
extends: .host_test_template
|
extends: .host_test_template
|
||||||
script:
|
script:
|
||||||
|
@@ -1,9 +1,16 @@
|
|||||||
idf_component_register(SRCS
|
idf_build_get_property(target IDF_TARGET)
|
||||||
"esp_exception.cpp"
|
|
||||||
"i2c_cxx.cpp"
|
set(srcs "esp_timer_cxx.cpp" "esp_exception.cpp" "gpio_cxx.cpp")
|
||||||
"gpio_cxx.cpp"
|
set(requires "esp_timer" "driver")
|
||||||
"esp_event_api.cpp"
|
|
||||||
"esp_event_cxx.cpp"
|
if(NOT ${target} STREQUAL "linux")
|
||||||
"esp_timer_cxx.cpp"
|
list(APPEND srcs
|
||||||
|
"i2c_cxx.cpp"
|
||||||
|
"esp_event_api.cpp"
|
||||||
|
"esp_event_cxx.cpp")
|
||||||
|
list(APPEND requires "esp_event")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
idf_component_register(SRCS ${srcs}
|
||||||
INCLUDE_DIRS "include"
|
INCLUDE_DIRS "include"
|
||||||
REQUIRES driver esp_event esp_timer)
|
REQUIRES ${requires})
|
||||||
|
@@ -0,0 +1,10 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
|
||||||
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
|
set(COMPONENTS main)
|
||||||
|
|
||||||
|
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/mocks/esp_timer/")
|
||||||
|
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/mocks/driver/")
|
||||||
|
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/mocks/freertos/")
|
||||||
|
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/examples/cxx/experimental/experimental_cpp_component/")
|
||||||
|
project(test_esp_timer_cxx_host)
|
@@ -0,0 +1,36 @@
|
|||||||
|
| Supported Targets | Linux |
|
||||||
|
| ----------------- | ----- |
|
||||||
|
|
||||||
|
# C++ ESPTimer test on Linux target
|
||||||
|
|
||||||
|
This unit test tests basic functionality of the `ESPTimer` class. The test does not use mocks. Instead, it runs the whole implementation of the component on the Linux host. The test framework is CATCH.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
* A Linux system
|
||||||
|
* The usual IDF requirements for Linux system, as described in the [Getting Started Guides](../../../../docs/en/get-started/index.rst).
|
||||||
|
* The host's gcc/g++
|
||||||
|
|
||||||
|
This application has been tested on Ubuntu 20.04 with `gcc` version *9.3.0*.
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
First, make sure that the target is set to Linux. Run `idf.py --preview set-target linux` if you are not sure. Then do a normal IDF build: `idf.py build`.
|
||||||
|
|
||||||
|
## Run
|
||||||
|
|
||||||
|
IDF monitor doesn't work yet for Linux. You have to run the app manually:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
build/test_esp_timer_cxx_host.elf
|
||||||
|
```
|
||||||
|
|
||||||
|
## Example Output
|
||||||
|
|
||||||
|
Ideally, all tests pass, which is indicated by "All tests passed" in the last line:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ build/test_esp_timer_cxx_host.elf
|
||||||
|
===============================================================================
|
||||||
|
All tests passed (9 assertions in 11 test cases)
|
||||||
|
```
|
@@ -0,0 +1,5 @@
|
|||||||
|
idf_component_register(SRCS "esp_timer_test.cpp"
|
||||||
|
INCLUDE_DIRS
|
||||||
|
"."
|
||||||
|
$ENV{IDF_PATH}/tools/catch
|
||||||
|
REQUIRES cmock esp_timer experimental_cpp_component)
|
@@ -0,0 +1,196 @@
|
|||||||
|
/* ESP Timer C++ unit tests
|
||||||
|
|
||||||
|
This example 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 <stdio.h>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include "esp_err.h"
|
||||||
|
#include "esp_timer_cxx.hpp"
|
||||||
|
|
||||||
|
#include "catch.hpp"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "Mockesp_timer.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: IDF-2693, function definition just to satisfy linker, mock esp_common instead
|
||||||
|
const char *esp_err_to_name(esp_err_t code) {
|
||||||
|
return "test";
|
||||||
|
}
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace idf;
|
||||||
|
using namespace idf::esp_timer;
|
||||||
|
|
||||||
|
struct FixtureException : std::exception {
|
||||||
|
const char *what() const noexcept override {
|
||||||
|
return "CMock failed";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TimerCreationFixture {
|
||||||
|
TimerCreationFixture(bool expect_stop = false) : out_handle(reinterpret_cast<esp_timer_handle_t>(1))
|
||||||
|
{
|
||||||
|
if (!TEST_PROTECT()) {
|
||||||
|
throw FixtureException();
|
||||||
|
}
|
||||||
|
esp_timer_create_ExpectAnyArgsAndReturn(ESP_OK);
|
||||||
|
esp_timer_create_ReturnThruPtr_out_handle(&out_handle);
|
||||||
|
if (expect_stop) {
|
||||||
|
esp_timer_stop_ExpectAndReturn(out_handle, ESP_OK); // implementation may always call stop
|
||||||
|
} else {
|
||||||
|
esp_timer_stop_IgnoreAndReturn(ESP_OK); // implementation may always call stop
|
||||||
|
}
|
||||||
|
esp_timer_delete_ExpectAndReturn(out_handle, ESP_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~TimerCreationFixture()
|
||||||
|
{
|
||||||
|
Mockesp_timer_Verify();
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_timer_handle_t out_handle;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void (*trigger_timer_callback)(void *data) = nullptr;
|
||||||
|
|
||||||
|
esp_err_t cmock_timer_create_callback(const esp_timer_create_args_t* create_args, esp_timer_handle_t* out_handle, int cmock_num_calls)
|
||||||
|
{
|
||||||
|
trigger_timer_callback = create_args->callback;
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TimerCallbackFixture : public TimerCreationFixture {
|
||||||
|
TimerCallbackFixture(bool expect_stop = false) : TimerCreationFixture(expect_stop)
|
||||||
|
{
|
||||||
|
esp_timer_create_AddCallback(cmock_timer_create_callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
~TimerCallbackFixture()
|
||||||
|
{
|
||||||
|
trigger_timer_callback = nullptr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_CASE("get_time works")
|
||||||
|
{
|
||||||
|
esp_timer_get_time_ExpectAndReturn(static_cast<uint64_t>(0xfeeddeadbeef));
|
||||||
|
|
||||||
|
CHECK(get_time() == std::chrono::microseconds(0xfeeddeadbeef));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("get_next_alarm works")
|
||||||
|
{
|
||||||
|
esp_timer_get_next_alarm_ExpectAndReturn(static_cast<uint64_t>(47u));
|
||||||
|
|
||||||
|
CHECK(get_next_alarm() == std::chrono::microseconds(47u));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("ESPTimer null function")
|
||||||
|
{
|
||||||
|
CHECK_THROWS_AS(ESPTimer(nullptr), ESPException&);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("ESPTimer empty std::function")
|
||||||
|
{
|
||||||
|
function<void()> nothing;
|
||||||
|
CHECK_THROWS_AS(ESPTimer(nothing, "test"), ESPException&);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("ESPTimer initializes and deletes itself")
|
||||||
|
{
|
||||||
|
TimerCreationFixture fix;
|
||||||
|
|
||||||
|
function<void()> timer_cb = [&]() { };
|
||||||
|
|
||||||
|
ESPTimer(timer_cb, "test");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("ESPTimer start throws on invalid state failure")
|
||||||
|
{
|
||||||
|
TimerCreationFixture fix;
|
||||||
|
esp_timer_start_once_ExpectAndReturn(fix.out_handle, 5000, ESP_ERR_INVALID_STATE);
|
||||||
|
|
||||||
|
function<void()> timer_cb = [&]() { };
|
||||||
|
|
||||||
|
ESPTimer timer(timer_cb);
|
||||||
|
|
||||||
|
CHECK_THROWS_AS(timer.start(chrono::microseconds(5000)), ESPException&);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("ESPTimer start periodically throws on invalid state failure")
|
||||||
|
{
|
||||||
|
TimerCreationFixture fix;
|
||||||
|
esp_timer_start_periodic_ExpectAndReturn(fix.out_handle, 5000, ESP_ERR_INVALID_STATE);
|
||||||
|
|
||||||
|
function<void()> timer_cb = [&]() { };
|
||||||
|
|
||||||
|
ESPTimer timer(timer_cb);
|
||||||
|
|
||||||
|
CHECK_THROWS_AS(timer.start_periodic(chrono::microseconds(5000)), ESPException&);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("ESPTimer stopp throws on invaid state failure")
|
||||||
|
{
|
||||||
|
TimerCreationFixture fix;
|
||||||
|
|
||||||
|
// Overriding stop part of the fixture
|
||||||
|
esp_timer_stop_StopIgnore();
|
||||||
|
esp_timer_stop_IgnoreAndReturn(ESP_ERR_INVALID_STATE);
|
||||||
|
|
||||||
|
function<void()> timer_cb = [&]() { };
|
||||||
|
|
||||||
|
ESPTimer timer(timer_cb);
|
||||||
|
|
||||||
|
CHECK_THROWS_AS(timer.stop(), ESPException&);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("ESPTimer stops in destructor")
|
||||||
|
{
|
||||||
|
TimerCreationFixture fix(true);
|
||||||
|
esp_timer_start_once_ExpectAndReturn(fix.out_handle, 5000, ESP_OK);
|
||||||
|
|
||||||
|
function<void()> timer_cb = [&]() { };
|
||||||
|
|
||||||
|
ESPTimer timer(timer_cb);
|
||||||
|
|
||||||
|
timer.start(chrono::microseconds(5000));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("ESPTimer stops correctly")
|
||||||
|
{
|
||||||
|
TimerCreationFixture fix(true);
|
||||||
|
esp_timer_start_once_ExpectAndReturn(fix.out_handle, 5000, ESP_OK);
|
||||||
|
|
||||||
|
// Additional stop needed because stop is called in ESPTimer::stop and ~ESPTimer.
|
||||||
|
esp_timer_stop_ExpectAndReturn(fix.out_handle, ESP_OK);
|
||||||
|
|
||||||
|
function<void()> timer_cb = [&]() { };
|
||||||
|
|
||||||
|
ESPTimer timer(timer_cb);
|
||||||
|
|
||||||
|
timer.start(chrono::microseconds(5000));
|
||||||
|
|
||||||
|
timer.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("ESPTimer callback works")
|
||||||
|
{
|
||||||
|
TimerCallbackFixture fix;
|
||||||
|
int flag = 0;
|
||||||
|
|
||||||
|
function<void()> timer_cb = [&]() { flag = 47; };
|
||||||
|
|
||||||
|
ESPTimer timer(timer_cb);
|
||||||
|
|
||||||
|
trigger_timer_callback(&timer);
|
||||||
|
|
||||||
|
REQUIRE(trigger_timer_callback != nullptr);
|
||||||
|
CHECK(flag == 47);
|
||||||
|
}
|
@@ -0,0 +1,3 @@
|
|||||||
|
CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=n
|
||||||
|
CONFIG_IDF_TARGET="linux"
|
||||||
|
CONFIG_CXX_EXCEPTIONS=y
|
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <string>
|
||||||
#include "esp_exception.hpp"
|
#include "esp_exception.hpp"
|
||||||
#include "esp_timer.h"
|
#include "esp_timer.h"
|
||||||
|
|
||||||
|
@@ -44,82 +44,6 @@ struct RefClock {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_CASE("ESPTimer null function", "[ESPTimer]")
|
|
||||||
{
|
|
||||||
TEST_THROW(ESPTimer(nullptr), ESPException);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("ESPTimer empty std::function", "[ESPTimer]")
|
|
||||||
{
|
|
||||||
function<void()> nothing;
|
|
||||||
TEST_THROW(ESPTimer(nothing, "test"), ESPException);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("ESPTimer starting twice throws", "[ESPTimer]")
|
|
||||||
{
|
|
||||||
function<void()> timer_cb = [&]() { };
|
|
||||||
|
|
||||||
ESPTimer timer(timer_cb);
|
|
||||||
|
|
||||||
timer.start(chrono::microseconds(5000));
|
|
||||||
|
|
||||||
TEST_THROW(timer.start(chrono::microseconds(5000)), ESPException);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("ESPTimer periodically starting twice throws", "[ESPTimer]")
|
|
||||||
{
|
|
||||||
function<void()> timer_cb = [&]() { };
|
|
||||||
|
|
||||||
ESPTimer timer(timer_cb);
|
|
||||||
|
|
||||||
timer.start_periodic(chrono::microseconds(5000));
|
|
||||||
|
|
||||||
TEST_THROW(timer.start_periodic(chrono::microseconds(5000)), ESPException);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("ESPTimer stopping non-started timer throws", "[ESPTimer]")
|
|
||||||
{
|
|
||||||
function<void()> timer_cb = [&]() { };
|
|
||||||
|
|
||||||
ESPTimer timer(timer_cb);
|
|
||||||
|
|
||||||
TEST_THROW(timer.stop(), ESPException);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("ESPTimer calls callback", "[ESPTimer]")
|
|
||||||
{
|
|
||||||
bool called = false;
|
|
||||||
|
|
||||||
function<void()> timer_cb = [&]() {
|
|
||||||
called = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
ESPTimer timer(timer_cb);
|
|
||||||
|
|
||||||
timer.start(chrono::microseconds(5000));
|
|
||||||
|
|
||||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
|
||||||
|
|
||||||
TEST_ASSERT(called);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("ESPTimer periodically calls callback", "[ESPTimer]")
|
|
||||||
{
|
|
||||||
size_t called = 0;
|
|
||||||
|
|
||||||
function<void()> timer_cb = [&]() {
|
|
||||||
called++;
|
|
||||||
};
|
|
||||||
|
|
||||||
ESPTimer timer(timer_cb);
|
|
||||||
|
|
||||||
timer.start_periodic(chrono::microseconds(2000));
|
|
||||||
|
|
||||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
|
||||||
|
|
||||||
TEST_ASSERT(called >= 4u);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("ESPTimer produces correct delay", "[ESPTimer]")
|
TEST_CASE("ESPTimer produces correct delay", "[ESPTimer]")
|
||||||
{
|
{
|
||||||
int64_t t_end;
|
int64_t t_end;
|
||||||
|
9
tools/mocks/esp_timer/CMakeLists.txt
Normal file
9
tools/mocks/esp_timer/CMakeLists.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# 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 ESP TIMER MOCKS")
|
||||||
|
|
||||||
|
idf_component_get_property(original_esp_timer_dir esp_timer COMPONENT_OVERRIDEN_DIR)
|
||||||
|
|
||||||
|
idf_component_mock(INCLUDE_DIRS "${original_esp_timer_dir}/include"
|
||||||
|
REQUIRES esp_common
|
||||||
|
MOCK_HEADER_FILES ${original_esp_timer_dir}/include/esp_timer.h)
|
9
tools/mocks/esp_timer/mock/mock_config.yaml
Normal file
9
tools/mocks/esp_timer/mock/mock_config.yaml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
:cmock:
|
||||||
|
:plugins:
|
||||||
|
- expect
|
||||||
|
- expect_any_args
|
||||||
|
- return_thru_ptr
|
||||||
|
- array
|
||||||
|
- ignore
|
||||||
|
- ignore_arg
|
||||||
|
- callback
|
Reference in New Issue
Block a user