mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-01 10:40:47 +03:00
Merge branch 'test/esp_timer_api_coverage' into 'master'
test(esp_timer): cover unused public query and absolute-alarm APIs See merge request espressif/esp-idf!52442
This commit is contained in:
@@ -1692,3 +1692,284 @@ TEST_CASE("esp_timer_stop_blocking from timer callback and does not block", "[es
|
||||
vSemaphoreDelete(state.callback_can_finish);
|
||||
vSemaphoreDelete(state.callback_finished);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
volatile int fire_count;
|
||||
volatile int64_t fire_time_us;
|
||||
} timer_observation_t;
|
||||
|
||||
static void record_timer_fire(void* arg)
|
||||
{
|
||||
timer_observation_t* observation = (timer_observation_t*) arg;
|
||||
observation->fire_time_us = esp_timer_get_time();
|
||||
observation->fire_count++;
|
||||
}
|
||||
|
||||
static bool time_is_in_range(uint64_t time_us, uint64_t earliest_us, uint64_t latest_us)
|
||||
{
|
||||
return time_us >= earliest_us && time_us <= latest_us;
|
||||
}
|
||||
|
||||
static bool time_is_within(int64_t actual_us, int64_t expected_us, int64_t tolerance_us)
|
||||
{
|
||||
return actual_us >= expected_us - tolerance_us && actual_us <= expected_us + tolerance_us;
|
||||
}
|
||||
|
||||
TEST_CASE("esp_timer_get_period reports period and rejects invalid arguments", "[esp_timer]")
|
||||
{
|
||||
esp_timer_handle_t timer;
|
||||
const esp_timer_create_args_t args = {
|
||||
.callback = &dummy_cb,
|
||||
.name = "period",
|
||||
};
|
||||
TEST_ESP_OK(esp_timer_create(&args, &timer));
|
||||
|
||||
uint64_t period_us = UINT64_MAX;
|
||||
TEST_ESP_OK(esp_timer_start_once(timer, 400 * 1000));
|
||||
TEST_ESP_OK(esp_timer_get_period(timer, &period_us));
|
||||
TEST_ASSERT_TRUE(period_us == 0);
|
||||
TEST_ESP_OK(esp_timer_stop(timer));
|
||||
|
||||
const uint64_t expected_period_us = 250 * 1000;
|
||||
TEST_ESP_OK(esp_timer_start_periodic(timer, expected_period_us));
|
||||
TEST_ESP_OK(esp_timer_get_period(timer, &period_us));
|
||||
TEST_ASSERT_TRUE(period_us == expected_period_us);
|
||||
TEST_ESP_OK(esp_timer_stop(timer));
|
||||
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_timer_get_period(NULL, &period_us));
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_timer_get_period(timer, NULL));
|
||||
|
||||
TEST_ESP_OK(esp_timer_delete(timer));
|
||||
vTaskDelay(3);
|
||||
}
|
||||
|
||||
TEST_CASE("esp_timer_get_expiry_time returns the one-shot deadline and validates arguments", "[esp_timer]")
|
||||
{
|
||||
esp_timer_handle_t timer;
|
||||
const esp_timer_create_args_t args = {
|
||||
.callback = &dummy_cb,
|
||||
.name = "expiry",
|
||||
};
|
||||
TEST_ESP_OK(esp_timer_create(&args, &timer));
|
||||
|
||||
const uint64_t timeout_us = 500 * 1000;
|
||||
int64_t before_start_us = esp_timer_get_time();
|
||||
TEST_ESP_OK(esp_timer_start_once(timer, timeout_us));
|
||||
int64_t after_start_us = esp_timer_get_time();
|
||||
uint64_t expiry_us = 0;
|
||||
TEST_ESP_OK(esp_timer_get_expiry_time(timer, &expiry_us));
|
||||
TEST_ASSERT_TRUE(time_is_in_range(expiry_us,
|
||||
before_start_us + timeout_us,
|
||||
after_start_us + timeout_us));
|
||||
TEST_ESP_OK(esp_timer_stop(timer));
|
||||
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_timer_get_expiry_time(NULL, &expiry_us));
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_timer_get_expiry_time(timer, NULL));
|
||||
|
||||
TEST_ESP_OK(esp_timer_start_periodic(timer, 200 * 1000));
|
||||
TEST_ESP_ERR(ESP_ERR_NOT_SUPPORTED, esp_timer_get_expiry_time(timer, &expiry_us));
|
||||
TEST_ESP_OK(esp_timer_stop(timer));
|
||||
|
||||
TEST_ESP_OK(esp_timer_delete(timer));
|
||||
vTaskDelay(3);
|
||||
}
|
||||
|
||||
TEST_CASE("absolute one-shot fires at its deadline and start APIs reject past deadlines", "[esp_timer]")
|
||||
{
|
||||
const uint64_t deadline_delay_us = 300 * 1000;
|
||||
const uint64_t expired_deadline_us = 1;
|
||||
volatile int callback_count = 0;
|
||||
esp_timer_handle_t timer;
|
||||
const esp_timer_create_args_t args = {
|
||||
.callback = &test_timer_triggered,
|
||||
.arg = (void*) &callback_count,
|
||||
.name = "once_at",
|
||||
};
|
||||
TEST_ESP_OK(esp_timer_create(&args, &timer));
|
||||
|
||||
uint64_t deadline_us = esp_timer_get_time() + deadline_delay_us;
|
||||
TEST_ESP_OK(esp_timer_start_once_at(timer, deadline_us));
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(80));
|
||||
TEST_ASSERT_EQUAL(0, callback_count);
|
||||
vTaskDelay(pdMS_TO_TICKS(400));
|
||||
TEST_ASSERT_EQUAL(1, callback_count);
|
||||
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_timer_start_once_at(timer, expired_deadline_us));
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_timer_start_periodic_at(timer, 100 * 1000, expired_deadline_us));
|
||||
|
||||
TEST_ESP_OK(esp_timer_delete(timer));
|
||||
vTaskDelay(3);
|
||||
}
|
||||
|
||||
TEST_CASE("esp_timer_restart_at reschedules a one-shot and rejects a past deadline", "[esp_timer]")
|
||||
{
|
||||
const uint64_t initial_timeout_us = 2 * 1000 * 1000;
|
||||
const uint64_t deadline_delay_us = 300 * 1000;
|
||||
const uint64_t expired_deadline_us = 1;
|
||||
volatile int callback_count = 0;
|
||||
esp_timer_handle_t timer;
|
||||
const esp_timer_create_args_t args = {
|
||||
.callback = &test_timer_triggered,
|
||||
.arg = (void*) &callback_count,
|
||||
.name = "restart_at",
|
||||
};
|
||||
TEST_ESP_OK(esp_timer_create(&args, &timer));
|
||||
|
||||
TEST_ESP_OK(esp_timer_start_once(timer, initial_timeout_us));
|
||||
uint64_t deadline_us = esp_timer_get_time() + deadline_delay_us;
|
||||
TEST_ESP_OK(esp_timer_restart_at(timer, 0, deadline_us));
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(80));
|
||||
TEST_ASSERT_EQUAL(0, callback_count);
|
||||
vTaskDelay(pdMS_TO_TICKS(400));
|
||||
TEST_ASSERT_EQUAL(1, callback_count);
|
||||
|
||||
TEST_ESP_OK(esp_timer_start_once(timer, initial_timeout_us));
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_timer_restart_at(timer, 0, expired_deadline_us));
|
||||
TEST_ESP_OK(esp_timer_stop(timer));
|
||||
|
||||
TEST_ESP_OK(esp_timer_delete(timer));
|
||||
vTaskDelay(3);
|
||||
}
|
||||
|
||||
TEST_CASE("wake-up alarm skips timers configured to skip unhandled events", "[esp_timer]")
|
||||
{
|
||||
const uint64_t short_delay_us = 200 * 1000;
|
||||
const uint64_t long_delay_us = 800 * 1000;
|
||||
const int64_t alarm_tolerance_us = 80 * 1000;
|
||||
esp_timer_handle_t non_wake_timer;
|
||||
esp_timer_handle_t wake_timer;
|
||||
const esp_timer_create_args_t non_wake_args = {
|
||||
.callback = &dummy_cb,
|
||||
.name = "non_wake",
|
||||
.skip_unhandled_events = true,
|
||||
};
|
||||
const esp_timer_create_args_t wake_args = {
|
||||
.callback = &dummy_cb,
|
||||
.name = "wake",
|
||||
};
|
||||
TEST_ESP_OK(esp_timer_create(&non_wake_args, &non_wake_timer));
|
||||
TEST_ESP_OK(esp_timer_create(&wake_args, &wake_timer));
|
||||
|
||||
int64_t start_time_us = esp_timer_get_time();
|
||||
TEST_ESP_OK(esp_timer_start_periodic(non_wake_timer, short_delay_us));
|
||||
TEST_ESP_OK(esp_timer_start_once(wake_timer, long_delay_us));
|
||||
TEST_ASSERT_TRUE(time_is_within(esp_timer_get_next_alarm_for_wake_up(),
|
||||
start_time_us + long_delay_us,
|
||||
alarm_tolerance_us));
|
||||
|
||||
TEST_ESP_OK(esp_timer_stop(non_wake_timer));
|
||||
TEST_ESP_OK(esp_timer_stop(wake_timer));
|
||||
|
||||
start_time_us = esp_timer_get_time();
|
||||
TEST_ESP_OK(esp_timer_start_once(wake_timer, short_delay_us));
|
||||
TEST_ESP_OK(esp_timer_start_periodic(non_wake_timer, long_delay_us));
|
||||
TEST_ASSERT_TRUE(time_is_within(esp_timer_get_next_alarm_for_wake_up(),
|
||||
start_time_us + short_delay_us,
|
||||
alarm_tolerance_us));
|
||||
|
||||
TEST_ESP_OK(esp_timer_stop(non_wake_timer));
|
||||
TEST_ESP_OK(esp_timer_stop(wake_timer));
|
||||
TEST_ESP_OK(esp_timer_delete(non_wake_timer));
|
||||
TEST_ESP_OK(esp_timer_delete(wake_timer));
|
||||
vTaskDelay(3);
|
||||
}
|
||||
|
||||
TEST_CASE("stopping the earliest timer rearms the next timer", "[esp_timer]")
|
||||
{
|
||||
const int64_t stopped_timer_delay_us = 300 * 1000;
|
||||
const int64_t remaining_timer_delay_us = 900 * 1000;
|
||||
const int64_t fire_time_tolerance_us = 150 * 1000;
|
||||
timer_observation_t stopped = { 0 };
|
||||
timer_observation_t remaining = { 0 };
|
||||
esp_timer_handle_t stopped_timer;
|
||||
esp_timer_handle_t remaining_timer;
|
||||
const esp_timer_create_args_t stopped_args = {
|
||||
.callback = &record_timer_fire,
|
||||
.arg = &stopped,
|
||||
.name = "stopped_early",
|
||||
};
|
||||
const esp_timer_create_args_t remaining_args = {
|
||||
.callback = &record_timer_fire,
|
||||
.arg = &remaining,
|
||||
.name = "remaining_late",
|
||||
};
|
||||
TEST_ESP_OK(esp_timer_create(&stopped_args, &stopped_timer));
|
||||
TEST_ESP_OK(esp_timer_create(&remaining_args, &remaining_timer));
|
||||
|
||||
int64_t start_time_us = esp_timer_get_time();
|
||||
TEST_ESP_OK(esp_timer_start_once(stopped_timer, stopped_timer_delay_us));
|
||||
TEST_ESP_OK(esp_timer_start_once(remaining_timer, remaining_timer_delay_us));
|
||||
#if !CONFIG_ESP_TASK_WDT_USE_ESP_TIMER
|
||||
uint64_t alarm_before_stop = esp_timer_impl_get_alarm_reg();
|
||||
#endif
|
||||
TEST_ESP_OK(esp_timer_stop(stopped_timer));
|
||||
#if !CONFIG_ESP_TASK_WDT_USE_ESP_TIMER
|
||||
TEST_ASSERT_TRUE(alarm_before_stop != esp_timer_impl_get_alarm_reg());
|
||||
#endif
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
TEST_ASSERT_EQUAL(0, stopped.fire_count);
|
||||
TEST_ASSERT_EQUAL(0, remaining.fire_count);
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(600));
|
||||
TEST_ASSERT_EQUAL(0, stopped.fire_count);
|
||||
TEST_ASSERT_EQUAL(1, remaining.fire_count);
|
||||
TEST_ASSERT_TRUE(time_is_within(remaining.fire_time_us,
|
||||
start_time_us + remaining_timer_delay_us,
|
||||
fire_time_tolerance_us));
|
||||
|
||||
TEST_ESP_OK(esp_timer_delete(stopped_timer));
|
||||
TEST_ESP_OK(esp_timer_delete(remaining_timer));
|
||||
vTaskDelay(3);
|
||||
}
|
||||
|
||||
TEST_CASE("stopping a later timer keeps the earliest timer armed", "[esp_timer]")
|
||||
{
|
||||
const int64_t remaining_timer_delay_us = 300 * 1000;
|
||||
const int64_t stopped_timer_delay_us = 900 * 1000;
|
||||
const int64_t fire_time_tolerance_us = 150 * 1000;
|
||||
timer_observation_t remaining = { 0 };
|
||||
timer_observation_t stopped = { 0 };
|
||||
esp_timer_handle_t remaining_timer;
|
||||
esp_timer_handle_t stopped_timer;
|
||||
const esp_timer_create_args_t remaining_args = {
|
||||
.callback = &record_timer_fire,
|
||||
.arg = &remaining,
|
||||
.name = "remaining_early",
|
||||
};
|
||||
const esp_timer_create_args_t stopped_args = {
|
||||
.callback = &record_timer_fire,
|
||||
.arg = &stopped,
|
||||
.name = "stopped_late",
|
||||
};
|
||||
TEST_ESP_OK(esp_timer_create(&remaining_args, &remaining_timer));
|
||||
TEST_ESP_OK(esp_timer_create(&stopped_args, &stopped_timer));
|
||||
|
||||
int64_t start_time_us = esp_timer_get_time();
|
||||
TEST_ESP_OK(esp_timer_start_once(remaining_timer, remaining_timer_delay_us));
|
||||
TEST_ESP_OK(esp_timer_start_once(stopped_timer, stopped_timer_delay_us));
|
||||
#if !CONFIG_ESP_TASK_WDT_USE_ESP_TIMER
|
||||
uint64_t alarm_before_stop = esp_timer_impl_get_alarm_reg();
|
||||
#endif
|
||||
TEST_ESP_OK(esp_timer_stop(stopped_timer));
|
||||
#if !CONFIG_ESP_TASK_WDT_USE_ESP_TIMER
|
||||
TEST_ASSERT_TRUE(alarm_before_stop == esp_timer_impl_get_alarm_reg());
|
||||
#endif
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
TEST_ASSERT_EQUAL(1, remaining.fire_count);
|
||||
TEST_ASSERT_EQUAL(0, stopped.fire_count);
|
||||
TEST_ASSERT_TRUE(time_is_within(remaining.fire_time_us,
|
||||
start_time_us + remaining_timer_delay_us,
|
||||
fire_time_tolerance_us));
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(600));
|
||||
TEST_ASSERT_EQUAL(1, remaining.fire_count);
|
||||
TEST_ASSERT_EQUAL(0, stopped.fire_count);
|
||||
|
||||
TEST_ESP_OK(esp_timer_delete(remaining_timer));
|
||||
TEST_ESP_OK(esp_timer_delete(stopped_timer));
|
||||
vTaskDelay(3);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user