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
|
||||
- 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:
|
||||
extends: .host_test_template
|
||||
script:
|
||||
|
@@ -1,9 +1,16 @@
|
||||
idf_component_register(SRCS
|
||||
"esp_exception.cpp"
|
||||
"i2c_cxx.cpp"
|
||||
"gpio_cxx.cpp"
|
||||
"esp_event_api.cpp"
|
||||
"esp_event_cxx.cpp"
|
||||
"esp_timer_cxx.cpp"
|
||||
idf_build_get_property(target IDF_TARGET)
|
||||
|
||||
set(srcs "esp_timer_cxx.cpp" "esp_exception.cpp" "gpio_cxx.cpp")
|
||||
set(requires "esp_timer" "driver")
|
||||
|
||||
if(NOT ${target} STREQUAL "linux")
|
||||
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"
|
||||
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 <functional>
|
||||
#include <string>
|
||||
#include "esp_exception.hpp"
|
||||
#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]")
|
||||
{
|
||||
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