mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
16677b0d3c
peripheral enable/disable usually should be managed by driver itself, so make it as espressif private APIs, not recommended for user to use it in application code. However, if user want to re-write the driver or ports to other platform, this is still possible by including the header in this way: "esp_private/peripheral_ctrl.h"
2036 lines
71 KiB
C
2036 lines
71 KiB
C
#include <stdbool.h>
|
|
#include <string.h>
|
|
|
|
#include "esp_event.h"
|
|
#include "sdkconfig.h"
|
|
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
#include "esp_log.h"
|
|
#include "esp_private/periph_ctrl.h"
|
|
#include "driver/timer.h"
|
|
|
|
#include "esp_event.h"
|
|
#include "esp_event_private.h"
|
|
#include "esp_event_internal.h"
|
|
|
|
#include "esp_heap_caps.h"
|
|
#include "esp_timer.h"
|
|
|
|
#include "sdkconfig.h"
|
|
#include "unity.h"
|
|
|
|
#include "test_utils.h"
|
|
|
|
static const char* TAG = "test_event";
|
|
|
|
#define TEST_CONFIG_ITEMS_TO_REGISTER 5
|
|
#define TEST_CONFIG_TASKS_TO_SPAWN 2
|
|
|
|
#define TEST_CONFIG_WAIT_MULTIPLIER 5
|
|
|
|
// The initial logging "initializing test" is to ensure mutex allocation is not counted against memory not being freed
|
|
// during teardown.
|
|
#define TEST_SETUP() \
|
|
ESP_LOGI(TAG, "initializing test"); \
|
|
size_t free_mem_before = heap_caps_get_free_size(MALLOC_CAP_DEFAULT); \
|
|
test_setup(); \
|
|
s_test_core_id = xPortGetCoreID(); \
|
|
s_test_priority = uxTaskPriorityGet(NULL);
|
|
|
|
#define TEST_TEARDOWN() \
|
|
test_teardown(); \
|
|
vTaskDelay(pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER)); \
|
|
TEST_ASSERT_EQUAL(free_mem_before, heap_caps_get_free_size(MALLOC_CAP_DEFAULT));
|
|
|
|
typedef struct {
|
|
void* data;
|
|
SemaphoreHandle_t start;
|
|
SemaphoreHandle_t done;
|
|
} task_arg_t;
|
|
|
|
typedef struct {
|
|
esp_event_base_t base;
|
|
int32_t id;
|
|
esp_event_handler_t* handles;
|
|
int32_t num;
|
|
esp_event_loop_handle_t loop;
|
|
bool is_registration;
|
|
} handler_registration_data_t;
|
|
|
|
typedef struct {
|
|
esp_event_base_t base;
|
|
int32_t id;
|
|
esp_event_loop_handle_t loop;
|
|
int32_t num;
|
|
} post_event_data_t;
|
|
|
|
typedef struct {
|
|
int performed;
|
|
int expected;
|
|
SemaphoreHandle_t done;
|
|
} performance_data_t;
|
|
|
|
typedef struct {
|
|
void* data;
|
|
SemaphoreHandle_t mutex;
|
|
} simple_arg_t;
|
|
|
|
typedef struct {
|
|
esp_event_handler_instance_t *context;
|
|
void* data;
|
|
} instance_unregister_data_t;
|
|
|
|
typedef struct {
|
|
int *arr;
|
|
int index;
|
|
} ordered_data_t;
|
|
|
|
static BaseType_t s_test_core_id;
|
|
static UBaseType_t s_test_priority;
|
|
|
|
ESP_EVENT_DECLARE_BASE(s_test_base1);
|
|
ESP_EVENT_DECLARE_BASE(s_test_base2);
|
|
|
|
ESP_EVENT_DEFINE_BASE(s_test_base1);
|
|
ESP_EVENT_DEFINE_BASE(s_test_base2);
|
|
|
|
enum {
|
|
TEST_EVENT_BASE1_EV1,
|
|
TEST_EVENT_BASE1_EV2,
|
|
TEST_EVENT_BASE1_MAX
|
|
};
|
|
|
|
enum {
|
|
TEST_EVENT_BASE2_EV1,
|
|
TEST_EVENT_BASE2_EV2,
|
|
TEST_EVENT_BASE2_MAX
|
|
};
|
|
|
|
static BaseType_t test_event_get_core(void)
|
|
{
|
|
static int calls = 0;
|
|
|
|
if (portNUM_PROCESSORS > 1) {
|
|
return (s_test_core_id + calls++) % portNUM_PROCESSORS;
|
|
} else {
|
|
return s_test_core_id;
|
|
}
|
|
}
|
|
|
|
static esp_event_loop_args_t test_event_get_default_loop_args(void)
|
|
{
|
|
esp_event_loop_args_t loop_config = {
|
|
.queue_size = CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE,
|
|
.task_name = "loop",
|
|
.task_priority = s_test_priority,
|
|
.task_stack_size = 2048,
|
|
.task_core_id = test_event_get_core()
|
|
};
|
|
|
|
return loop_config;
|
|
}
|
|
|
|
static void test_event_simple_handler(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
|
|
{
|
|
if (!event_handler_arg) {
|
|
return;
|
|
}
|
|
simple_arg_t* arg = (simple_arg_t*) event_handler_arg;
|
|
xSemaphoreTake(arg->mutex, portMAX_DELAY);
|
|
|
|
int* count = (int*) arg->data;
|
|
|
|
if (event_data == NULL) {
|
|
(*count)++;
|
|
} else {
|
|
(*count) += *((int*) event_data);
|
|
}
|
|
|
|
xSemaphoreGive(arg->mutex);
|
|
}
|
|
|
|
static void test_event_ordered_dispatch(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
|
|
{
|
|
int *arg = (int*) event_handler_arg;
|
|
ordered_data_t *data = *((ordered_data_t**) (event_data));
|
|
|
|
data->arr[data->index++] = *arg;
|
|
}
|
|
|
|
static void test_event_performance_handler(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
|
|
{
|
|
performance_data_t* data = (performance_data_t*) event_handler_arg;
|
|
|
|
data->performed++;
|
|
|
|
if (data->performed >= data->expected) {
|
|
xSemaphoreGive(data->done);
|
|
}
|
|
}
|
|
|
|
static void test_event_post_task(void* args)
|
|
{
|
|
task_arg_t* arg = (task_arg_t*) args;
|
|
post_event_data_t* data = arg->data;
|
|
|
|
xSemaphoreTake(arg->start, portMAX_DELAY);
|
|
|
|
for (int i = 0; i < data->num; i++) {
|
|
TEST_ESP_OK(esp_event_post_to(data->loop, data->base, data->id, NULL, 0, portMAX_DELAY));
|
|
vTaskDelay(1);
|
|
}
|
|
|
|
xSemaphoreGive(arg->done);
|
|
|
|
vTaskDelete(NULL);
|
|
}
|
|
|
|
static void test_event_simple_handler_registration_task(void* args)
|
|
{
|
|
task_arg_t* arg = (task_arg_t*) args;
|
|
handler_registration_data_t* data = (handler_registration_data_t*) arg->data;
|
|
|
|
xSemaphoreTake(arg->start, portMAX_DELAY);
|
|
|
|
for(int i = 0; i < data->num; i++) {
|
|
if (data->is_registration) {
|
|
TEST_ESP_OK(esp_event_handler_register_with(data->loop, data->base, data->id, data->handles[i], NULL));
|
|
} else {
|
|
TEST_ESP_OK(esp_event_handler_unregister_with(data->loop, data->base, data->id, data->handles[i]));
|
|
}
|
|
vTaskDelay(1);
|
|
}
|
|
|
|
xSemaphoreGive(arg->done);
|
|
|
|
vTaskDelete(NULL);
|
|
}
|
|
|
|
static void test_handler_post_w_task(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
|
|
{
|
|
simple_arg_t* arg = (simple_arg_t*) event_handler_arg;
|
|
|
|
esp_event_loop_handle_t* loop = (esp_event_loop_handle_t*) event_data;
|
|
int* count = (int*) arg->data;
|
|
|
|
(*count)++;
|
|
|
|
if (*count <= 2) {
|
|
if (event_base == s_test_base1 && event_id == TEST_EVENT_BASE1_EV1) {
|
|
TEST_ESP_OK(esp_event_post_to(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
|
|
} else{
|
|
xSemaphoreGive((SemaphoreHandle_t) arg->mutex);
|
|
}
|
|
} else {
|
|
// Test that once the queue is full and the handler attempts to post to the same loop,
|
|
// posting does not block indefinitely.
|
|
if (event_base == s_test_base1 && event_id == TEST_EVENT_BASE1_EV1) {
|
|
xSemaphoreTake((SemaphoreHandle_t) arg->mutex, portMAX_DELAY);
|
|
TEST_ASSERT_EQUAL(ESP_ERR_TIMEOUT, esp_event_post_to(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
|
|
}
|
|
}
|
|
}
|
|
|
|
static void test_handler_post_wo_task(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
|
|
{
|
|
simple_arg_t* arg = (simple_arg_t*) event_handler_arg;
|
|
|
|
esp_event_loop_handle_t* loop = (esp_event_loop_handle_t*) event_data;
|
|
int* count = (int*) arg->data;
|
|
|
|
(*count)++;
|
|
|
|
if (*count <= 2) {
|
|
if (event_base == s_test_base1 && event_id == TEST_EVENT_BASE1_EV1) {
|
|
TEST_ESP_OK(esp_event_post_to(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
|
|
} else{
|
|
xSemaphoreGive((SemaphoreHandle_t) arg->mutex);
|
|
}
|
|
} else {
|
|
// Test that once the queue is full and the handler attempts to post to the same loop,
|
|
// posting does not block indefinitely.
|
|
if (event_base == s_test_base1 && event_id == TEST_EVENT_BASE1_EV1) {
|
|
xSemaphoreTake((SemaphoreHandle_t) arg->mutex, portMAX_DELAY);
|
|
TEST_ESP_OK(esp_event_post_to(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
|
|
TEST_ASSERT_EQUAL(ESP_ERR_TIMEOUT, esp_event_post_to(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
|
|
}
|
|
}
|
|
}
|
|
|
|
static void test_handler_unregister_itself(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
|
|
{
|
|
esp_event_loop_handle_t* loop = (esp_event_loop_handle_t*) event_data;
|
|
int* unregistered = (int*) event_handler_arg;
|
|
|
|
(*unregistered) += (event_base == s_test_base1 ? 0 : 10) + event_id + 1;
|
|
|
|
// Unregister this handler for this event
|
|
TEST_ESP_OK(esp_event_handler_unregister_with(*loop, event_base, event_id, test_handler_unregister_itself));
|
|
}
|
|
|
|
static void test_handler_instance_unregister_itself(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
|
|
{
|
|
esp_event_loop_handle_t* loop = (esp_event_loop_handle_t*) event_data;
|
|
instance_unregister_data_t *unregister_data = (instance_unregister_data_t*) event_handler_arg;
|
|
esp_event_handler_instance_t *context = (esp_event_handler_instance_t*) unregister_data->context;
|
|
int *count = (int*) unregister_data->data;
|
|
|
|
(*count)++;
|
|
|
|
// Unregister this handler for this event
|
|
TEST_ESP_OK(esp_event_handler_instance_unregister_with(*loop, event_base, event_id, *context));
|
|
}
|
|
|
|
static void test_post_from_handler_loop_task(void* args)
|
|
{
|
|
esp_event_loop_handle_t event_loop = (esp_event_loop_handle_t) args;
|
|
|
|
while(1) {
|
|
TEST_ESP_OK(esp_event_loop_run(event_loop, portMAX_DELAY));
|
|
}
|
|
}
|
|
|
|
static void test_setup(void)
|
|
{
|
|
TEST_ASSERT_TRUE(TEST_CONFIG_TASKS_TO_SPAWN >= 2);
|
|
TEST_ESP_OK(esp_event_loop_create_default());
|
|
}
|
|
|
|
static void test_teardown(void)
|
|
{
|
|
TEST_ESP_OK(esp_event_loop_delete_default());
|
|
}
|
|
|
|
#define TIMER_DIVIDER 16 // Hardware timer clock divider
|
|
#define TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER) // convert counter value to seconds
|
|
#define TIMER_INTERVAL0_SEC (2.0) // sample test interval for the first timer
|
|
|
|
TEST_CASE("can create and delete event loops", "[event]")
|
|
{
|
|
/* this test aims to verify that:
|
|
* - creating loops with and without a task succeeds
|
|
* - event queue can accomodate the set queue size, and drops the post when exceeded
|
|
* - deleting loops with unconsumed posts and unregistered handlers (when unregistration is enabled) does not leak memory */
|
|
|
|
TEST_SETUP();
|
|
|
|
esp_event_loop_handle_t loop1; // with dedicated task
|
|
esp_event_loop_handle_t loop2; // without dedicated task
|
|
esp_event_loop_handle_t loop3; // with leftover post and handlers
|
|
|
|
esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
|
|
|
|
TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop1));
|
|
|
|
loop_args.task_name = NULL;
|
|
TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop2));
|
|
TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop3));
|
|
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop3, s_test_base1, TEST_EVENT_BASE1_EV1, (void*) 0x00000001, NULL));
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop3, s_test_base1, TEST_EVENT_BASE1_EV2, (void*) 0x00000002, NULL));
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop3, s_test_base2, TEST_EVENT_BASE1_EV1, (void*) 0x00000003, NULL));
|
|
|
|
for (int i = 0; i < loop_args.queue_size; i++) {
|
|
int mod = i % 4;
|
|
|
|
switch(mod) {
|
|
case 0:
|
|
TEST_ESP_OK(esp_event_post_to(loop3, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
|
|
break;
|
|
case 1:
|
|
TEST_ESP_OK(esp_event_post_to(loop3, s_test_base2, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
|
|
break;
|
|
case 2:
|
|
TEST_ESP_OK(esp_event_post_to(loop3, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
|
|
break;
|
|
case 3:
|
|
TEST_ESP_OK(esp_event_post_to(loop3, s_test_base2, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
TEST_ASSERT_EQUAL(ESP_ERR_TIMEOUT, esp_event_post_to(loop3, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, pdMS_TO_TICKS(10)));
|
|
|
|
TEST_ESP_OK(esp_event_loop_delete(loop1));
|
|
TEST_ESP_OK(esp_event_loop_delete(loop2));
|
|
TEST_ESP_OK(esp_event_loop_delete(loop3));
|
|
|
|
TEST_TEARDOWN();
|
|
}
|
|
|
|
TEST_CASE("registering event handler instance without instance context works", "[event]") {
|
|
TEST_SETUP();
|
|
|
|
esp_event_loop_handle_t loop;
|
|
|
|
int count_1 = 0;
|
|
|
|
simple_arg_t arg_1 = {
|
|
.data = &count_1,
|
|
.mutex = xSemaphoreCreateMutex()
|
|
};
|
|
|
|
esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
|
|
|
|
loop_args.task_name = NULL;
|
|
TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
|
|
|
|
TEST_ESP_OK(esp_event_handler_instance_register_with(loop, ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, test_event_simple_handler, &arg_1, NULL));
|
|
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
|
|
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
|
|
TEST_ASSERT_EQUAL(1, count_1);
|
|
|
|
TEST_ESP_OK(esp_event_loop_delete(loop));
|
|
|
|
vSemaphoreDelete(arg_1.mutex);
|
|
|
|
TEST_TEARDOWN();
|
|
}
|
|
|
|
TEST_CASE("registering event twice with same handler yields updated handler arg", "[event]") {
|
|
TEST_SETUP();
|
|
|
|
esp_event_loop_handle_t loop;
|
|
|
|
int count = 0;
|
|
|
|
simple_arg_t arg = {
|
|
.data = &count,
|
|
.mutex = xSemaphoreCreateMutex()
|
|
};
|
|
|
|
esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
|
|
|
|
loop_args.task_name = NULL;
|
|
TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
|
|
|
|
/* Register the handler twice to the same base and id but with a different argument (expects to return ESP_OK and log a warning)
|
|
* This aims to verify: 1) Handler's argument to be updated
|
|
* 2) Registration not to leak memory
|
|
*/
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop, ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, test_event_simple_handler, NULL));
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
|
|
// exec loop, no handler data: count stays 0
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
TEST_ASSERT_EQUAL(0, count);
|
|
|
|
// overriding the former registration of the same event
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop, ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, test_event_simple_handler, &arg));
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
|
|
// exec loop, registered handler data exists: count increases
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
TEST_ASSERT_EQUAL(1, count);
|
|
|
|
TEST_ESP_OK(esp_event_loop_delete(loop));
|
|
|
|
vSemaphoreDelete(arg.mutex);
|
|
|
|
TEST_TEARDOWN();
|
|
}
|
|
|
|
TEST_CASE("registering event handler instance twice works", "[event]") {
|
|
TEST_SETUP();
|
|
|
|
esp_event_loop_handle_t loop;
|
|
|
|
int count_1 = 0;
|
|
int count_2 = 0;
|
|
|
|
simple_arg_t arg_1 = {
|
|
.data = &count_1,
|
|
.mutex = xSemaphoreCreateMutex()
|
|
};
|
|
|
|
simple_arg_t arg_2 = {
|
|
.data = &count_2,
|
|
.mutex = xSemaphoreCreateMutex()
|
|
};
|
|
|
|
esp_event_handler_instance_t ctx_1;
|
|
esp_event_handler_instance_t ctx_2;
|
|
|
|
esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
|
|
|
|
loop_args.task_name = NULL;
|
|
TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
|
|
|
|
TEST_ESP_OK(esp_event_handler_instance_register_with(loop, ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, test_event_simple_handler, &arg_1, &ctx_1));
|
|
TEST_ESP_OK(esp_event_handler_instance_register_with(loop, ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, test_event_simple_handler, &arg_2, &ctx_2));
|
|
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
|
|
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
|
|
TEST_ASSERT_EQUAL(1, count_1);
|
|
TEST_ASSERT_EQUAL(1, count_2);
|
|
|
|
TEST_ESP_OK(esp_event_loop_delete(loop));
|
|
|
|
vSemaphoreDelete(arg_1.mutex);
|
|
vSemaphoreDelete(arg_2.mutex);
|
|
|
|
TEST_TEARDOWN();
|
|
}
|
|
|
|
TEST_CASE("registering with ANY_BASE but specific ID fails", "[event]") {
|
|
TEST_SETUP();
|
|
|
|
esp_event_loop_handle_t loop;
|
|
|
|
int count = 0;
|
|
|
|
simple_arg_t arg = {
|
|
.data = &count,
|
|
.mutex = xSemaphoreCreateMutex()
|
|
};
|
|
|
|
esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
|
|
|
|
loop_args.task_name = NULL;
|
|
TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
|
|
|
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_event_handler_register_with(loop, ESP_EVENT_ANY_BASE, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg));
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
|
|
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
|
|
TEST_ASSERT_EQUAL(0, count);
|
|
|
|
TEST_ESP_OK(esp_event_loop_delete(loop));
|
|
|
|
vSemaphoreDelete(arg.mutex);
|
|
|
|
TEST_TEARDOWN();
|
|
}
|
|
|
|
TEST_CASE("registering instance with ANY_BASE but specific ID fails", "[event]") {
|
|
TEST_SETUP();
|
|
|
|
esp_event_loop_handle_t loop;
|
|
|
|
int count = 0;
|
|
esp_event_handler_instance_t ctx;
|
|
|
|
simple_arg_t arg = {
|
|
.data = &count,
|
|
.mutex = xSemaphoreCreateMutex()
|
|
};
|
|
|
|
esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
|
|
|
|
loop_args.task_name = NULL;
|
|
TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
|
|
|
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_event_handler_instance_register_with(loop, ESP_EVENT_ANY_BASE, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg, &ctx));
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
|
|
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
|
|
TEST_ASSERT_EQUAL(0, count);
|
|
|
|
TEST_ESP_OK(esp_event_loop_delete(loop));
|
|
|
|
vSemaphoreDelete(arg.mutex);
|
|
|
|
TEST_TEARDOWN();
|
|
}
|
|
|
|
TEST_CASE("Check registering ANY_ID", "[event]") {
|
|
TEST_SETUP();
|
|
|
|
esp_event_loop_handle_t loop;
|
|
|
|
int count = 0;
|
|
|
|
simple_arg_t arg = {
|
|
.data = &count,
|
|
.mutex = xSemaphoreCreateMutex()
|
|
};
|
|
|
|
esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
|
|
|
|
loop_args.task_name = NULL;
|
|
TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
|
|
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base1, ESP_EVENT_ANY_ID, test_event_simple_handler, &arg));
|
|
|
|
// handler shouldn't be triggered with different base
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
TEST_ASSERT_EQUAL(0, count);
|
|
|
|
// for all events with correct base, it should be triggered
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
TEST_ASSERT_EQUAL(2, count);
|
|
|
|
TEST_ESP_OK(esp_event_loop_delete(loop));
|
|
|
|
vSemaphoreDelete(arg.mutex);
|
|
|
|
TEST_TEARDOWN();
|
|
}
|
|
|
|
TEST_CASE("Check registering instance with ANY_ID", "[event]") {
|
|
TEST_SETUP();
|
|
|
|
esp_event_loop_handle_t loop;
|
|
|
|
int count = 0;
|
|
|
|
simple_arg_t arg = {
|
|
.data = &count,
|
|
.mutex = xSemaphoreCreateMutex()
|
|
};
|
|
|
|
esp_event_handler_instance_t ctx;
|
|
|
|
esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
|
|
|
|
loop_args.task_name = NULL;
|
|
TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
|
|
|
|
TEST_ESP_OK(esp_event_handler_instance_register_with(loop, s_test_base1, ESP_EVENT_ANY_ID, test_event_simple_handler, &arg, &ctx));
|
|
|
|
// handler shouldn't be triggered with different base
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
TEST_ASSERT_EQUAL(0, count);
|
|
|
|
// for all events with correct base, it should be triggered
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
TEST_ASSERT_EQUAL(2, count);
|
|
|
|
TEST_ESP_OK(esp_event_loop_delete(loop));
|
|
|
|
vSemaphoreDelete(arg.mutex);
|
|
|
|
TEST_TEARDOWN();
|
|
}
|
|
|
|
TEST_CASE("Check registering specific event", "[event]") {
|
|
TEST_SETUP();
|
|
|
|
esp_event_loop_handle_t loop;
|
|
|
|
int count = 0;
|
|
|
|
simple_arg_t arg = {
|
|
.data = &count,
|
|
.mutex = xSemaphoreCreateMutex()
|
|
};
|
|
|
|
esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
|
|
|
|
loop_args.task_name = NULL;
|
|
TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
|
|
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg));
|
|
|
|
// handler should not be triggered with different base
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
TEST_ASSERT_EQUAL(0, count);
|
|
|
|
// for incorrect id, it should not be triggered
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
TEST_ASSERT_EQUAL(0, count);
|
|
|
|
// for correct event and base, it should be triggered
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
TEST_ASSERT_EQUAL(1, count);
|
|
|
|
TEST_ESP_OK(esp_event_loop_delete(loop));
|
|
|
|
vSemaphoreDelete(arg.mutex);
|
|
|
|
TEST_TEARDOWN();
|
|
}
|
|
|
|
TEST_CASE("Check registering instance with specific event", "[event]") {
|
|
TEST_SETUP();
|
|
|
|
esp_event_loop_handle_t loop;
|
|
|
|
int count = 0;
|
|
|
|
simple_arg_t arg = {
|
|
.data = &count,
|
|
.mutex = xSemaphoreCreateMutex()
|
|
};
|
|
|
|
esp_event_handler_instance_t ctx;
|
|
|
|
esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
|
|
|
|
loop_args.task_name = NULL;
|
|
TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
|
|
|
|
TEST_ESP_OK(esp_event_handler_instance_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg, &ctx));
|
|
|
|
// handler should not be triggered with different base
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
TEST_ASSERT_EQUAL(0, count);
|
|
|
|
// for incorrect id, it should not be triggered
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
TEST_ASSERT_EQUAL(0, count);
|
|
|
|
// for correct event and base, it should be triggered
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
TEST_ASSERT_EQUAL(1, count);
|
|
|
|
TEST_ESP_OK(esp_event_loop_delete(loop));
|
|
|
|
vSemaphoreDelete(arg.mutex);
|
|
|
|
TEST_TEARDOWN();
|
|
}
|
|
|
|
TEST_CASE("Specific event is not called when no correct events are posted", "[event]") {
|
|
TEST_SETUP();
|
|
|
|
esp_event_loop_handle_t loop;
|
|
|
|
int count = 0;
|
|
|
|
simple_arg_t arg = {
|
|
.data = &count,
|
|
.mutex = xSemaphoreCreateMutex()
|
|
};
|
|
|
|
esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
|
|
|
|
loop_args.task_name = NULL;
|
|
TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
|
|
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg));
|
|
|
|
// handler should not be triggered by any of these postings
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
TEST_ASSERT_EQUAL(0, count);
|
|
|
|
// Post unknown events.
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_MAX, NULL, 0, portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE2_MAX, NULL, 0, portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
TEST_ASSERT_EQUAL(0, count);
|
|
|
|
TEST_ESP_OK(esp_event_loop_delete(loop));
|
|
|
|
vSemaphoreDelete(arg.mutex);
|
|
|
|
TEST_TEARDOWN();
|
|
}
|
|
|
|
TEST_CASE("Specific event instance is not called when no correct events are posted", "[event]") {
|
|
TEST_SETUP();
|
|
|
|
esp_event_loop_handle_t loop;
|
|
|
|
int count = 0;
|
|
|
|
simple_arg_t arg = {
|
|
.data = &count,
|
|
.mutex = xSemaphoreCreateMutex()
|
|
};
|
|
|
|
esp_event_handler_instance_t ctx;
|
|
|
|
esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
|
|
|
|
loop_args.task_name = NULL;
|
|
TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
|
|
|
|
TEST_ESP_OK(esp_event_handler_instance_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg, &ctx));
|
|
|
|
// handler should not be triggered by any of these postings
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
TEST_ASSERT_EQUAL(0, count);
|
|
|
|
// Post unknown events.
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_MAX, NULL, 0, portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE2_MAX, NULL, 0, portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
TEST_ASSERT_EQUAL(0, count);
|
|
|
|
TEST_ESP_OK(esp_event_loop_delete(loop));
|
|
|
|
vSemaphoreDelete(arg.mutex);
|
|
|
|
TEST_TEARDOWN();
|
|
}
|
|
|
|
TEST_CASE("can register/unregister handlers for all events/all events for a specific base", "[event]")
|
|
{
|
|
/* this test aims to verify that handlers can be registered to be called on all events
|
|
* or for all events with specific bases */
|
|
|
|
TEST_SETUP();
|
|
|
|
esp_event_loop_handle_t loop;
|
|
|
|
int count = 0;
|
|
|
|
simple_arg_t arg = {
|
|
.data = &count,
|
|
.mutex = xSemaphoreCreateMutex()
|
|
};
|
|
|
|
esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
|
|
|
|
loop_args.task_name = NULL;
|
|
TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
|
|
|
|
/* Register the handler twice to the same base and id but with a different argument (expects to return ESP_OK and log a warning)
|
|
* This aims to verify: 1) Handler's argument to be updated
|
|
* 2) Registration not to leak memory
|
|
*/
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop, ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, test_event_simple_handler, NULL));
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop, ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, test_event_simple_handler, &arg));
|
|
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base1, ESP_EVENT_ANY_ID, test_event_simple_handler, &arg));
|
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_event_handler_register_with(loop, ESP_EVENT_ANY_BASE, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg));
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg));
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler, &arg));
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base2, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg));
|
|
|
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_event_post_to(loop, ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, NULL, 0, portMAX_DELAY));
|
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_event_post_to(loop, s_test_base1, ESP_EVENT_ANY_ID, NULL, 0, portMAX_DELAY));
|
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_event_post_to(loop, ESP_EVENT_ANY_BASE, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY)); // exec loop, base and id level (+3)
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY)); // exec loop, base and id level (+3)
|
|
|
|
// Post unknown events. Respective loop level and base level handlers should still execute.
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_MAX, NULL, 0, portMAX_DELAY)); // exec loop and base level (+2)
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE2_MAX, NULL, 0, portMAX_DELAY)); // exec loop level (+1)
|
|
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
|
|
TEST_ASSERT_EQUAL(9, count); // 3 + 3 + 2 + 1
|
|
|
|
TEST_ESP_OK(esp_event_loop_delete(loop));
|
|
|
|
vSemaphoreDelete(arg.mutex);
|
|
|
|
TEST_TEARDOWN();
|
|
}
|
|
|
|
TEST_CASE("can unregister handler", "[event]")
|
|
{
|
|
/* this test aims to verify that unregistered handlers no longer execute when events are raised */
|
|
|
|
TEST_SETUP();
|
|
|
|
esp_event_loop_handle_t loop;
|
|
esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
|
|
|
|
loop_args.task_name = NULL;
|
|
TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
|
|
|
|
int count = 0;
|
|
|
|
simple_arg_t arg = {
|
|
.data = &count,
|
|
.mutex = xSemaphoreCreateMutex()
|
|
};
|
|
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg));
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base2, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg));
|
|
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
|
|
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
|
|
TEST_ASSERT_EQUAL(2, count);
|
|
|
|
TEST_ESP_OK(esp_event_handler_unregister_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_simple_handler));
|
|
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
|
|
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
|
|
TEST_ASSERT_EQUAL(3, count);
|
|
|
|
TEST_ESP_OK(esp_event_loop_delete(loop));
|
|
|
|
vSemaphoreDelete(arg.mutex);
|
|
|
|
TEST_TEARDOWN();
|
|
}
|
|
|
|
TEST_CASE("can unregister handler instance", "[event]")
|
|
{
|
|
/* this test aims to verify that unregistered handlers no longer execute when events are raised */
|
|
|
|
TEST_SETUP();
|
|
|
|
esp_event_loop_handle_t loop;
|
|
esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
|
|
|
|
loop_args.task_name = NULL;
|
|
TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
|
|
|
|
int count = 0;
|
|
|
|
simple_arg_t arg = {
|
|
.data = &count,
|
|
.mutex = xSemaphoreCreateMutex()
|
|
};
|
|
|
|
esp_event_handler_instance_t ctx;
|
|
|
|
TEST_ESP_OK(esp_event_handler_instance_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg, &ctx));
|
|
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
|
|
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
|
|
TEST_ASSERT_EQUAL(1, count);
|
|
|
|
TEST_ESP_OK(esp_event_handler_instance_unregister_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, ctx));
|
|
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
|
|
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
|
|
TEST_ASSERT_EQUAL(1, count);
|
|
|
|
TEST_ESP_OK(esp_event_loop_delete(loop));
|
|
|
|
vSemaphoreDelete(arg.mutex);
|
|
|
|
TEST_TEARDOWN();
|
|
}
|
|
|
|
TEST_CASE("handler can unregister itself", "[event]")
|
|
{
|
|
/* this test aims to verify that handlers can unregister themselves */
|
|
|
|
TEST_SETUP();
|
|
|
|
esp_event_loop_handle_t loop;
|
|
esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
|
|
|
|
loop_args.task_name = NULL;
|
|
TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
|
|
|
|
int unregistered = 0;
|
|
|
|
/*
|
|
* s_test_base1, ev1 = 1
|
|
* s_test_base1, ev2 = 2
|
|
* s_test_base2, ev1 = 11
|
|
* s_test_base2, ev2 = 12
|
|
*/
|
|
int expected_unregistered = 0;
|
|
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_handler_unregister_itself, &unregistered));
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_handler_unregister_itself, &unregistered));
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base2, TEST_EVENT_BASE2_EV1, test_handler_unregister_itself, &unregistered));
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base2, TEST_EVENT_BASE2_EV2, test_handler_unregister_itself, &unregistered));
|
|
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, &loop, sizeof(loop), portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
expected_unregistered = 2; // base1, ev2
|
|
TEST_ASSERT_EQUAL(expected_unregistered, unregistered);
|
|
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, &loop, sizeof(loop), portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE2_EV1, &loop, sizeof(loop), portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
expected_unregistered += 1 + 11; // base1, ev1 + base2, ev1
|
|
TEST_ASSERT_EQUAL(expected_unregistered, unregistered);
|
|
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE2_EV2, &loop, sizeof(loop), portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
expected_unregistered += 12; // base2, ev2
|
|
TEST_ASSERT_EQUAL(expected_unregistered, unregistered);
|
|
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, &loop, sizeof(loop), portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, &loop, sizeof(loop), portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE2_EV1, &loop, sizeof(loop), portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE2_EV2, &loop, sizeof(loop), portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
TEST_ASSERT_EQUAL(expected_unregistered, unregistered); // all handlers unregistered
|
|
|
|
TEST_ESP_OK(esp_event_loop_delete(loop));
|
|
|
|
TEST_TEARDOWN();
|
|
}
|
|
|
|
TEST_CASE("handler instance can unregister itself", "[event]")
|
|
{
|
|
/* this test aims to verify that handlers can unregister themselves */
|
|
|
|
TEST_SETUP();
|
|
|
|
esp_event_loop_handle_t loop;
|
|
esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
|
|
|
|
loop_args.task_name = NULL;
|
|
TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
|
|
|
|
esp_event_handler_instance_t ctx;
|
|
|
|
int count = 0;
|
|
|
|
instance_unregister_data_t instance_data = {
|
|
.context = &ctx,
|
|
.data = &count
|
|
};
|
|
|
|
TEST_ESP_OK(esp_event_handler_instance_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_handler_instance_unregister_itself, &instance_data, &ctx));
|
|
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, &loop, sizeof(loop), portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
TEST_ASSERT_EQUAL(1, count);
|
|
|
|
vTaskDelay(1000);
|
|
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, &loop, sizeof(loop), portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
TEST_ASSERT_EQUAL(1, count);
|
|
|
|
TEST_ESP_OK(esp_event_loop_delete(loop));
|
|
|
|
TEST_TEARDOWN();
|
|
}
|
|
|
|
TEST_CASE("can exit running loop at approximately the set amount of time", "[event]")
|
|
{
|
|
/* this test aims to verify that running loop does not block indefinitely in cases where
|
|
* events are posted frequently */
|
|
|
|
TEST_SETUP();
|
|
|
|
esp_event_loop_handle_t loop;
|
|
esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
|
|
|
|
loop_args.task_name = NULL;
|
|
TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
|
|
|
|
performance_data_t handler_data = {
|
|
.performed = 0,
|
|
.expected = INT32_MAX,
|
|
.done = xSemaphoreCreateBinary()
|
|
};
|
|
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_performance_handler, &handler_data));
|
|
|
|
post_event_data_t post_event_data = {
|
|
.base = s_test_base1,
|
|
.id = TEST_EVENT_BASE1_EV1,
|
|
.loop = loop,
|
|
.num = INT32_MAX
|
|
};
|
|
|
|
task_arg_t post_event_arg = {
|
|
.data = &post_event_data,
|
|
.done = xSemaphoreCreateBinary(),
|
|
.start = xSemaphoreCreateBinary()
|
|
};
|
|
|
|
TaskHandle_t post_task;
|
|
|
|
xTaskCreatePinnedToCore(test_event_post_task, "post", 2048, &post_event_arg, s_test_priority, &post_task, test_event_get_core());
|
|
|
|
int runtime_ms = 10;
|
|
int runtime_us = runtime_ms * 1000;
|
|
|
|
int64_t start, diff;
|
|
start = esp_timer_get_time();
|
|
|
|
xSemaphoreGive(post_event_arg.start);
|
|
|
|
// Run the loop for the runtime_ms set amount of time, regardless of whether events
|
|
// are still being posted to the loop.
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(runtime_ms)));
|
|
|
|
diff = (esp_timer_get_time() - start);
|
|
|
|
// Threshold is 25 percent.
|
|
TEST_ASSERT(diff < runtime_us * 1.25f);
|
|
|
|
// Verify that the post task still continues
|
|
TEST_ASSERT_NOT_EQUAL(pdTRUE, xSemaphoreTake(post_event_arg.done, pdMS_TO_TICKS(10)));
|
|
|
|
vSemaphoreDelete(post_event_arg.done);
|
|
vSemaphoreDelete(post_event_arg.start);
|
|
vSemaphoreDelete(handler_data.done);
|
|
vTaskDelete(post_task);
|
|
|
|
TEST_ESP_OK(esp_event_loop_delete(loop));
|
|
|
|
TEST_TEARDOWN();
|
|
}
|
|
|
|
TEST_CASE("can register/unregister handlers simultaneously", "[event]")
|
|
{
|
|
/* this test aims to verify that the event handlers list remains consistent despite
|
|
* simultaneous access by differenct tasks */
|
|
|
|
TEST_SETUP();
|
|
|
|
const char* base = "base";
|
|
int32_t id = 0;
|
|
|
|
esp_event_loop_handle_t loop;
|
|
esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
|
|
|
|
TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
|
|
|
|
ESP_LOGI(TAG, "registering handlers");
|
|
|
|
handler_registration_data_t* registration_data = calloc(TEST_CONFIG_TASKS_TO_SPAWN, sizeof(*registration_data));
|
|
task_arg_t* registration_arg = calloc(TEST_CONFIG_TASKS_TO_SPAWN, sizeof(*registration_arg));
|
|
|
|
for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) {
|
|
registration_data[i].base = base;
|
|
registration_data[i].id = id;
|
|
registration_data[i].loop = loop;
|
|
registration_data[i].handles = calloc(TEST_CONFIG_ITEMS_TO_REGISTER, sizeof(esp_event_handler_t));
|
|
registration_data[i].num = TEST_CONFIG_ITEMS_TO_REGISTER;
|
|
registration_data[i].is_registration = true;
|
|
|
|
for (int j = 0; j < TEST_CONFIG_ITEMS_TO_REGISTER; j++) {
|
|
registration_data[i].handles[j] = (void*) (i * TEST_CONFIG_ITEMS_TO_REGISTER) + (j + TEST_CONFIG_ITEMS_TO_REGISTER);
|
|
}
|
|
|
|
registration_arg[i].start = xSemaphoreCreateBinary();
|
|
registration_arg[i].done = xSemaphoreCreateBinary();
|
|
registration_arg[i].data = ®istration_data[i];
|
|
|
|
xTaskCreatePinnedToCore(test_event_simple_handler_registration_task, "register", 2048, ®istration_arg[i], s_test_priority, NULL, test_event_get_core());
|
|
}
|
|
|
|
// Give the semaphores to the spawned registration task
|
|
for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) {
|
|
xSemaphoreGive(registration_arg[i].start);
|
|
}
|
|
|
|
// Take the same semaphores in order to proceed
|
|
for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) {
|
|
xSemaphoreTake(registration_arg[i].done, portMAX_DELAY);
|
|
}
|
|
|
|
ESP_LOGI(TAG, "checking consistency of handlers list");
|
|
|
|
// Check consistency of events list
|
|
for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) {
|
|
for (int j = 0; j < TEST_CONFIG_ITEMS_TO_REGISTER; j++) {
|
|
TEST_ASSERT_TRUE(esp_event_is_handler_registered(loop, base, id, registration_data[i].handles[j]));
|
|
}
|
|
}
|
|
|
|
ESP_LOGI(TAG, "unregistering handlers");
|
|
|
|
/* Test if tasks can unregister simultaneously */
|
|
|
|
// Unregister registered events
|
|
handler_registration_data_t* unregistration_data = calloc(TEST_CONFIG_TASKS_TO_SPAWN, sizeof(*unregistration_data));
|
|
task_arg_t* unregistration_arg = calloc(TEST_CONFIG_TASKS_TO_SPAWN, sizeof(*unregistration_arg));
|
|
|
|
for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) {
|
|
unregistration_data[i].base = base;
|
|
unregistration_data[i].id = id;
|
|
unregistration_data[i].loop = loop;
|
|
unregistration_data[i].handles = calloc(TEST_CONFIG_ITEMS_TO_REGISTER, sizeof(esp_event_handler_t));
|
|
unregistration_data[i].num = TEST_CONFIG_ITEMS_TO_REGISTER;
|
|
unregistration_data[i].is_registration = false;
|
|
|
|
memcpy(unregistration_data[i].handles, registration_data[i].handles, TEST_CONFIG_ITEMS_TO_REGISTER * sizeof(esp_event_handler_t));
|
|
|
|
unregistration_arg[i].data = &unregistration_data[i];
|
|
unregistration_arg[i].start = xSemaphoreCreateBinary();
|
|
unregistration_arg[i].done = xSemaphoreCreateBinary();
|
|
|
|
xTaskCreatePinnedToCore(test_event_simple_handler_registration_task, "unregister", 2048, &unregistration_arg[i], s_test_priority, NULL, test_event_get_core());
|
|
}
|
|
|
|
// Give the semaphores to the spawned unregistration task
|
|
for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) {
|
|
xSemaphoreGive(unregistration_arg[i].start);
|
|
}
|
|
|
|
// Take the same semaphores in order to proceed
|
|
for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) {
|
|
xSemaphoreTake(unregistration_arg[i].done, portMAX_DELAY);
|
|
}
|
|
|
|
ESP_LOGI(TAG, "checking consistency of handlers list");
|
|
|
|
// Check consistency of events list
|
|
for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) {
|
|
for (int j = 0; j < TEST_CONFIG_ITEMS_TO_REGISTER; j++) {
|
|
TEST_ASSERT_FALSE(esp_event_is_handler_registered(loop, base, id, registration_data[i].handles[j]));
|
|
}
|
|
}
|
|
|
|
// Do cleanup
|
|
for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) {
|
|
free(registration_data[i].handles);
|
|
vSemaphoreDelete(registration_arg[i].start);
|
|
vSemaphoreDelete(registration_arg[i].done);
|
|
|
|
free(unregistration_data[i].handles);
|
|
vSemaphoreDelete(unregistration_arg[i].start);
|
|
vSemaphoreDelete(unregistration_arg[i].done);
|
|
}
|
|
|
|
free(registration_data);
|
|
free(unregistration_data);
|
|
free(registration_arg);
|
|
free(unregistration_arg);
|
|
|
|
TEST_ESP_OK(esp_event_loop_delete(loop));
|
|
|
|
TEST_TEARDOWN();
|
|
}
|
|
|
|
TEST_CASE("posting ANY_EVENT or ANY_ID fails", "[event]") {
|
|
TEST_SETUP();
|
|
|
|
esp_event_loop_handle_t loop;
|
|
|
|
int count = 0;
|
|
|
|
simple_arg_t arg = {
|
|
.data = &count,
|
|
.mutex = xSemaphoreCreateMutex()
|
|
};
|
|
|
|
esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
|
|
|
|
loop_args.task_name = NULL;
|
|
TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
|
|
|
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_event_post_to(loop, ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, NULL, 0, portMAX_DELAY));
|
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_event_post_to(loop, s_test_base1, ESP_EVENT_ANY_ID, NULL, 0, portMAX_DELAY));
|
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_event_post_to(loop, ESP_EVENT_ANY_BASE, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
|
|
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
|
|
TEST_ASSERT_EQUAL(0, count);
|
|
|
|
TEST_ESP_OK(esp_event_loop_delete(loop));
|
|
|
|
vSemaphoreDelete(arg.mutex);
|
|
|
|
TEST_TEARDOWN();
|
|
}
|
|
|
|
TEST_CASE("can post and run events", "[event]")
|
|
{
|
|
/* this test aims to verify that:
|
|
* - multiple tasks can post to the queue simultaneously
|
|
* - handlers recieve the appropriate handler arg and associated event data */
|
|
|
|
TEST_SETUP();
|
|
|
|
esp_event_loop_handle_t loop;
|
|
|
|
esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
|
|
|
|
loop_args.task_name = NULL;
|
|
loop_args.queue_size = TEST_CONFIG_TASKS_TO_SPAWN * TEST_CONFIG_ITEMS_TO_REGISTER;
|
|
TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
|
|
|
|
int count = 0;
|
|
|
|
simple_arg_t arg = {
|
|
.data = &count,
|
|
.mutex = xSemaphoreCreateMutex()
|
|
};
|
|
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg));
|
|
|
|
post_event_data_t* post_event_data = calloc(TEST_CONFIG_TASKS_TO_SPAWN, sizeof(*post_event_data));
|
|
task_arg_t* post_event_arg = calloc(TEST_CONFIG_TASKS_TO_SPAWN, sizeof(*post_event_arg));
|
|
|
|
for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++)
|
|
{
|
|
post_event_data[i].base = s_test_base1;
|
|
post_event_data[i].id = TEST_EVENT_BASE1_EV1;
|
|
post_event_data[i].loop = loop;
|
|
post_event_data[i].num = TEST_CONFIG_ITEMS_TO_REGISTER;
|
|
|
|
post_event_arg[i].data = &post_event_data[i];
|
|
post_event_arg[i].start = xSemaphoreCreateBinary();
|
|
post_event_arg[i].done = xSemaphoreCreateBinary();
|
|
|
|
xTaskCreatePinnedToCore(test_event_post_task, "post", 2048, &post_event_arg[i], s_test_priority, NULL, test_event_get_core());
|
|
}
|
|
|
|
for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) {
|
|
xSemaphoreGive(post_event_arg[i].start);
|
|
}
|
|
|
|
// Execute some events as they are posted
|
|
for (int i = 0; i < (TEST_CONFIG_TASKS_TO_SPAWN * TEST_CONFIG_ITEMS_TO_REGISTER) / 2; i++) {
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
}
|
|
|
|
for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) {
|
|
xSemaphoreTake(post_event_arg[i].done, portMAX_DELAY);
|
|
}
|
|
|
|
// Execute the rest
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
|
|
TEST_ASSERT_EQUAL(TEST_CONFIG_TASKS_TO_SPAWN * TEST_CONFIG_ITEMS_TO_REGISTER, count);
|
|
|
|
// Cleanup
|
|
for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) {
|
|
vSemaphoreDelete(post_event_arg[i].start);
|
|
vSemaphoreDelete(post_event_arg[i].done);
|
|
}
|
|
|
|
free(post_event_data);
|
|
free(post_event_arg);
|
|
|
|
TEST_ESP_OK(esp_event_loop_delete(loop));
|
|
|
|
vSemaphoreDelete(arg.mutex);
|
|
|
|
TEST_TEARDOWN();
|
|
}
|
|
|
|
TEST_CASE("can post and run events with instances", "[event]")
|
|
{
|
|
/* this test aims to verify that:
|
|
* - multiple tasks can post to the queue simultaneously
|
|
* - handlers recieve the appropriate handler arg and associated event data */
|
|
|
|
TEST_SETUP();
|
|
|
|
esp_event_loop_handle_t loop;
|
|
|
|
esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
|
|
|
|
loop_args.task_name = NULL;
|
|
loop_args.queue_size = TEST_CONFIG_TASKS_TO_SPAWN * TEST_CONFIG_ITEMS_TO_REGISTER;
|
|
TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
|
|
|
|
int count = 0;
|
|
|
|
simple_arg_t arg = {
|
|
.data = &count,
|
|
.mutex = xSemaphoreCreateMutex()
|
|
};
|
|
|
|
esp_event_handler_instance_t ctx;
|
|
|
|
TEST_ESP_OK(esp_event_handler_instance_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg, &ctx));
|
|
|
|
post_event_data_t* post_event_data = calloc(TEST_CONFIG_TASKS_TO_SPAWN, sizeof(*post_event_data));
|
|
task_arg_t* post_event_arg = calloc(TEST_CONFIG_TASKS_TO_SPAWN, sizeof(*post_event_arg));
|
|
|
|
for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++)
|
|
{
|
|
post_event_data[i].base = s_test_base1;
|
|
post_event_data[i].id = TEST_EVENT_BASE1_EV1;
|
|
post_event_data[i].loop = loop;
|
|
post_event_data[i].num = TEST_CONFIG_ITEMS_TO_REGISTER;
|
|
|
|
post_event_arg[i].data = &post_event_data[i];
|
|
post_event_arg[i].start = xSemaphoreCreateBinary();
|
|
post_event_arg[i].done = xSemaphoreCreateBinary();
|
|
|
|
xTaskCreatePinnedToCore(test_event_post_task, "post", 2048, &post_event_arg[i], s_test_priority, NULL, test_event_get_core());
|
|
}
|
|
|
|
for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) {
|
|
xSemaphoreGive(post_event_arg[i].start);
|
|
}
|
|
|
|
// Execute some events as they are posted
|
|
for (int i = 0; i < (TEST_CONFIG_TASKS_TO_SPAWN * TEST_CONFIG_ITEMS_TO_REGISTER) / 2; i++) {
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
}
|
|
|
|
for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) {
|
|
xSemaphoreTake(post_event_arg[i].done, portMAX_DELAY);
|
|
}
|
|
|
|
// Execute the rest
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
|
|
TEST_ASSERT_EQUAL(TEST_CONFIG_TASKS_TO_SPAWN * TEST_CONFIG_ITEMS_TO_REGISTER, count);
|
|
|
|
// Cleanup
|
|
for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) {
|
|
vSemaphoreDelete(post_event_arg[i].start);
|
|
vSemaphoreDelete(post_event_arg[i].done);
|
|
}
|
|
|
|
free(post_event_data);
|
|
free(post_event_arg);
|
|
|
|
TEST_ESP_OK(esp_event_loop_delete(loop));
|
|
|
|
vSemaphoreDelete(arg.mutex);
|
|
|
|
TEST_TEARDOWN();
|
|
}
|
|
|
|
static void loop_run_task(void* args)
|
|
{
|
|
esp_event_loop_handle_t event_loop = (esp_event_loop_handle_t) args;
|
|
|
|
while(1) {
|
|
esp_event_loop_run(event_loop, portMAX_DELAY);
|
|
}
|
|
}
|
|
|
|
static void performance_test(bool dedicated_task)
|
|
{
|
|
// rand() seems to do a one-time allocation. Call it here so that the memory it allocates
|
|
// is not counted as a leak.
|
|
unsigned int _rand __attribute__((unused)) = rand();
|
|
|
|
TEST_SETUP();
|
|
|
|
const char test_base[] = "qwertyuiopasdfghjklzxvbnmmnbvcxz";
|
|
|
|
#define TEST_CONFIG_BASES (sizeof(test_base) - 1)
|
|
#define TEST_CONFIG_IDS (TEST_CONFIG_BASES / 2)
|
|
|
|
// Create loop
|
|
esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
|
|
esp_event_loop_handle_t loop;
|
|
|
|
if (!dedicated_task) {
|
|
loop_args.task_name = NULL;
|
|
}
|
|
|
|
TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
|
|
|
|
performance_data_t data;
|
|
|
|
// Register the handlers
|
|
for (int base = 0; base < TEST_CONFIG_BASES; base++) {
|
|
for (int id = 0; id < TEST_CONFIG_IDS; id++) {
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop, test_base + base, id, test_event_performance_handler, &data));
|
|
}
|
|
}
|
|
|
|
TaskHandle_t mtask = NULL;
|
|
|
|
if (!dedicated_task) {
|
|
xTaskCreate(loop_run_task, "loop_run", loop_args.task_stack_size, (void*) loop, loop_args.task_priority, &mtask);
|
|
}
|
|
|
|
// Perform performance test
|
|
float running_sum = 0;
|
|
float running_count = 0;
|
|
|
|
for (int bases = 1; bases <= TEST_CONFIG_BASES; bases *= 2) {
|
|
for (int ids = 1; ids <= TEST_CONFIG_IDS; ids *= 2) {
|
|
|
|
data.performed = 0;
|
|
data.expected = bases * ids;
|
|
data.done = xSemaphoreCreateBinary();
|
|
|
|
// Generate randomized list of posts
|
|
int post_bases[TEST_CONFIG_BASES];
|
|
int post_ids[TEST_CONFIG_IDS];
|
|
|
|
for (int i = 0; i < bases; i++) {
|
|
post_bases[i] = i;
|
|
}
|
|
|
|
for (int i = 0; i < ids; i++) {
|
|
post_ids[i] = i;
|
|
}
|
|
|
|
for (int i = 0; i < bases; i++) {
|
|
int rand_a = rand() % bases;
|
|
int rand_b = rand() % bases;
|
|
|
|
int temp = post_bases[rand_a];
|
|
post_bases[rand_a]= post_bases[rand_b];
|
|
post_bases[rand_b] = temp;
|
|
}
|
|
|
|
for (int i = 0; i < ids; i++) {
|
|
int rand_a = rand() % ids;
|
|
int rand_b = rand() % ids;
|
|
|
|
int temp = post_ids[rand_a];
|
|
post_ids[rand_a]= post_ids[rand_b];
|
|
post_ids[rand_b] = temp;
|
|
}
|
|
|
|
// Post the events
|
|
int64_t start = esp_timer_get_time();
|
|
for (int base = 0; base < bases; base++) {
|
|
for (int id = 0; id < ids; id++) {
|
|
TEST_ESP_OK(esp_event_post_to(loop, test_base + post_bases[base], post_ids[id], NULL, 0, portMAX_DELAY));
|
|
}
|
|
}
|
|
|
|
xSemaphoreTake(data.done, portMAX_DELAY);
|
|
int64_t elapsed = esp_timer_get_time() - start;
|
|
|
|
// Record data
|
|
TEST_ASSERT_EQUAL(data.expected, data.performed);
|
|
|
|
running_count++;
|
|
running_sum += data.performed / (elapsed / (1000000.0));
|
|
|
|
vSemaphoreDelete(data.done);
|
|
}
|
|
}
|
|
|
|
int average = (int) (running_sum / (running_count));
|
|
|
|
if (!dedicated_task) {
|
|
((esp_event_loop_instance_t*) loop)->task = mtask;
|
|
}
|
|
|
|
TEST_ESP_OK(esp_event_loop_delete(loop));
|
|
|
|
TEST_TEARDOWN();
|
|
|
|
#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING
|
|
ESP_LOGI(TAG, "events dispatched/second with profiling enabled: %d", average);
|
|
// Enabling profiling will slow down event dispatch, so the set threshold
|
|
// is not valid when it is enabled.
|
|
#else
|
|
#ifndef CONFIG_SPIRAM
|
|
TEST_PERFORMANCE_GREATER_THAN(EVENT_DISPATCH, "%d", average);
|
|
#else
|
|
TEST_PERFORMANCE_GREATER_THAN(EVENT_DISPATCH_PSRAM, "%d", average);
|
|
#endif // CONFIG_SPIRAM
|
|
#endif // CONFIG_ESP_EVENT_LOOP_PROFILING
|
|
}
|
|
|
|
TEST_CASE("performance test - dedicated task", "[event]")
|
|
{
|
|
performance_test(true);
|
|
}
|
|
|
|
TEST_CASE("performance test - no dedicated task", "[event]")
|
|
{
|
|
performance_test(false);
|
|
}
|
|
|
|
TEST_CASE("can post to loop from handler - dedicated task", "[event]")
|
|
{
|
|
TEST_SETUP();
|
|
|
|
esp_event_loop_handle_t loop_w_task;
|
|
|
|
esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
|
|
|
|
int count;
|
|
|
|
simple_arg_t arg = {
|
|
.data = &count,
|
|
.mutex = xSemaphoreCreateBinary()
|
|
};
|
|
|
|
TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop_w_task));
|
|
|
|
count = 0;
|
|
|
|
// Test that a handler can post to a different loop while there is still slots on the queue
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop_w_task, s_test_base1, TEST_EVENT_BASE1_EV1, test_handler_post_w_task, &arg));
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop_w_task, s_test_base1, TEST_EVENT_BASE1_EV2, test_handler_post_w_task, &arg));
|
|
|
|
TEST_ESP_OK(esp_event_post_to(loop_w_task, s_test_base1, TEST_EVENT_BASE1_EV1, &loop_w_task, sizeof(&loop_w_task), portMAX_DELAY));
|
|
|
|
xSemaphoreTake(arg.mutex, portMAX_DELAY);
|
|
|
|
TEST_ASSERT_EQUAL(2, count);
|
|
|
|
// Test that other tasks can still post while there is still slots in the queue, while handler is executing
|
|
count = 100;
|
|
|
|
TEST_ESP_OK(esp_event_post_to(loop_w_task, s_test_base1, TEST_EVENT_BASE1_EV1, &loop_w_task, sizeof(&loop_w_task), portMAX_DELAY));
|
|
|
|
for (int i = 0; i < loop_args.queue_size; i++) {
|
|
TEST_ESP_OK(esp_event_post_to(loop_w_task, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
|
|
}
|
|
|
|
TEST_ASSERT_EQUAL(ESP_ERR_TIMEOUT, esp_event_post_to(loop_w_task, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0,
|
|
pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER)));
|
|
|
|
xSemaphoreGive(arg.mutex);
|
|
|
|
vTaskDelay(pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER));
|
|
|
|
TEST_ESP_OK(esp_event_loop_delete(loop_w_task));
|
|
|
|
vSemaphoreDelete(arg.mutex);
|
|
|
|
TEST_TEARDOWN();
|
|
}
|
|
|
|
TEST_CASE("can post to loop from handler instance - dedicated task", "[event]")
|
|
{
|
|
TEST_SETUP();
|
|
|
|
esp_event_loop_handle_t loop_w_task;
|
|
|
|
esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
|
|
|
|
int count;
|
|
|
|
simple_arg_t arg = {
|
|
.data = &count,
|
|
.mutex = xSemaphoreCreateBinary()
|
|
};
|
|
|
|
TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop_w_task));
|
|
|
|
count = 0;
|
|
|
|
esp_event_handler_instance_t ctx_1;
|
|
esp_event_handler_instance_t ctx_2;
|
|
|
|
// Test that a handler can post to a different loop while there is still slots on the queue
|
|
TEST_ESP_OK(esp_event_handler_instance_register_with(loop_w_task, s_test_base1, TEST_EVENT_BASE1_EV1, test_handler_post_w_task, &arg, &ctx_1));
|
|
TEST_ESP_OK(esp_event_handler_instance_register_with(loop_w_task, s_test_base1, TEST_EVENT_BASE1_EV2, test_handler_post_w_task, &arg, &ctx_2));
|
|
|
|
TEST_ESP_OK(esp_event_post_to(loop_w_task, s_test_base1, TEST_EVENT_BASE1_EV1, &loop_w_task, sizeof(&loop_w_task), portMAX_DELAY));
|
|
|
|
xSemaphoreTake(arg.mutex, portMAX_DELAY);
|
|
|
|
TEST_ASSERT_EQUAL(2, count);
|
|
|
|
// Test that other tasks can still post while there is still slots in the queue, while handler is executing
|
|
count = 100;
|
|
|
|
TEST_ESP_OK(esp_event_post_to(loop_w_task, s_test_base1, TEST_EVENT_BASE1_EV1, &loop_w_task, sizeof(&loop_w_task), portMAX_DELAY));
|
|
|
|
for (int i = 0; i < loop_args.queue_size; i++) {
|
|
TEST_ESP_OK(esp_event_post_to(loop_w_task, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
|
|
}
|
|
|
|
TEST_ASSERT_EQUAL(ESP_ERR_TIMEOUT, esp_event_post_to(loop_w_task, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0,
|
|
pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER)));
|
|
|
|
xSemaphoreGive(arg.mutex);
|
|
|
|
vTaskDelay(pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER));
|
|
|
|
TEST_ESP_OK(esp_event_loop_delete(loop_w_task));
|
|
|
|
vSemaphoreDelete(arg.mutex);
|
|
|
|
TEST_TEARDOWN();
|
|
}
|
|
|
|
TEST_CASE("can post to loop from handler - no dedicated task", "[event]")
|
|
{
|
|
TEST_SETUP();
|
|
|
|
esp_event_loop_handle_t loop_wo_task;
|
|
|
|
esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
|
|
|
|
int count;
|
|
|
|
simple_arg_t arg = {
|
|
.data = &count,
|
|
.mutex = xSemaphoreCreateBinary()
|
|
};
|
|
|
|
count = 0;
|
|
|
|
loop_args.queue_size = 1;
|
|
loop_args.task_name = NULL;
|
|
TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop_wo_task));
|
|
|
|
TaskHandle_t mtask;
|
|
|
|
xTaskCreate(test_post_from_handler_loop_task, "task", 2584, (void*) loop_wo_task, s_test_priority, &mtask);
|
|
|
|
// Test that a handler can post to a different loop while there is still slots on the queue
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop_wo_task, s_test_base1, TEST_EVENT_BASE1_EV1, test_handler_post_wo_task, &arg));
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop_wo_task, s_test_base1, TEST_EVENT_BASE1_EV2, test_handler_post_wo_task, &arg));
|
|
|
|
TEST_ESP_OK(esp_event_post_to(loop_wo_task, s_test_base1, TEST_EVENT_BASE1_EV1, &loop_wo_task, sizeof(&loop_wo_task), portMAX_DELAY));
|
|
|
|
xSemaphoreTake(arg.mutex, portMAX_DELAY);
|
|
|
|
TEST_ASSERT_EQUAL(2, count);
|
|
|
|
count = 100;
|
|
|
|
TEST_ESP_OK(esp_event_post_to(loop_wo_task, s_test_base1, TEST_EVENT_BASE1_EV1, &loop_wo_task, sizeof(&loop_wo_task), portMAX_DELAY));
|
|
|
|
vTaskDelay(pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER));
|
|
|
|
// For loop without tasks, posting is more restrictive. Posting should wait until execution of handler finishes
|
|
TEST_ASSERT_EQUAL(ESP_ERR_TIMEOUT, esp_event_post_to(loop_wo_task, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0,
|
|
pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER)));
|
|
|
|
xSemaphoreGive(arg.mutex);
|
|
|
|
vTaskDelay(pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER));
|
|
|
|
vTaskDelete(mtask);
|
|
|
|
TEST_ESP_OK(esp_event_loop_delete(loop_wo_task));
|
|
|
|
vSemaphoreDelete(arg.mutex);
|
|
|
|
TEST_TEARDOWN();
|
|
}
|
|
|
|
TEST_CASE("can post to loop from handler instance - no dedicated task", "[event]")
|
|
{
|
|
TEST_SETUP();
|
|
|
|
esp_event_loop_handle_t loop_wo_task;
|
|
|
|
esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
|
|
|
|
int count;
|
|
|
|
simple_arg_t arg = {
|
|
.data = &count,
|
|
.mutex = xSemaphoreCreateBinary()
|
|
};
|
|
|
|
count = 0;
|
|
|
|
esp_event_handler_instance_t ctx_1;
|
|
esp_event_handler_instance_t ctx_2;
|
|
|
|
loop_args.queue_size = 1;
|
|
loop_args.task_name = NULL;
|
|
TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop_wo_task));
|
|
|
|
TaskHandle_t mtask;
|
|
|
|
xTaskCreate(test_post_from_handler_loop_task, "task", 2584, (void*) loop_wo_task, s_test_priority, &mtask);
|
|
|
|
// Test that a handler can post to a different loop while there is still slots on the queue
|
|
TEST_ESP_OK(esp_event_handler_instance_register_with(loop_wo_task, s_test_base1, TEST_EVENT_BASE1_EV1, test_handler_post_wo_task, &arg, &ctx_1));
|
|
TEST_ESP_OK(esp_event_handler_instance_register_with(loop_wo_task, s_test_base1, TEST_EVENT_BASE1_EV2, test_handler_post_wo_task, &arg, &ctx_2));
|
|
|
|
TEST_ESP_OK(esp_event_post_to(loop_wo_task, s_test_base1, TEST_EVENT_BASE1_EV1, &loop_wo_task, sizeof(&loop_wo_task), portMAX_DELAY));
|
|
|
|
xSemaphoreTake(arg.mutex, portMAX_DELAY);
|
|
|
|
TEST_ASSERT_EQUAL(2, count);
|
|
|
|
count = 100;
|
|
|
|
TEST_ESP_OK(esp_event_post_to(loop_wo_task, s_test_base1, TEST_EVENT_BASE1_EV1, &loop_wo_task, sizeof(&loop_wo_task), portMAX_DELAY));
|
|
|
|
vTaskDelay(pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER));
|
|
|
|
// For loop without tasks, posting is more restrictive. Posting should wait until execution of handler finishes
|
|
TEST_ASSERT_EQUAL(ESP_ERR_TIMEOUT, esp_event_post_to(loop_wo_task, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0,
|
|
pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER)));
|
|
|
|
xSemaphoreGive(arg.mutex);
|
|
|
|
vTaskDelay(pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER));
|
|
|
|
vTaskDelete(mtask);
|
|
|
|
TEST_ESP_OK(esp_event_loop_delete(loop_wo_task));
|
|
|
|
vSemaphoreDelete(arg.mutex);
|
|
|
|
TEST_TEARDOWN();
|
|
}
|
|
|
|
static void test_event_simple_handler_template(void* handler_arg, esp_event_base_t base, int32_t id, void* event_arg)
|
|
{
|
|
int* count = (int*) handler_arg;
|
|
(*count)++;
|
|
}
|
|
|
|
static void test_event_simple_handler_1(void* handler_arg, esp_event_base_t base, int32_t id, void* event_arg)
|
|
{
|
|
test_event_simple_handler_template(handler_arg, base, id, event_arg);
|
|
}
|
|
|
|
static void test_event_simple_handler_3(void* handler_arg, esp_event_base_t base, int32_t id, void* event_arg)
|
|
{
|
|
test_event_simple_handler_template(handler_arg, base, id, event_arg);
|
|
}
|
|
|
|
static void test_event_simple_handler_2(void* handler_arg, esp_event_base_t base, int32_t id, void* event_arg)
|
|
{
|
|
test_event_simple_handler_template(handler_arg, base, id, event_arg);
|
|
}
|
|
|
|
static void test_registration_from_handler_hdlr(void* handler_arg, esp_event_base_t base, int32_t id, void* event_arg)
|
|
{
|
|
esp_event_loop_handle_t* loop = (esp_event_loop_handle_t*) event_arg;
|
|
TEST_ESP_OK(esp_event_handler_register_with(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler_1, handler_arg));
|
|
TEST_ESP_OK(esp_event_handler_register_with(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler_2, handler_arg));
|
|
TEST_ESP_OK(esp_event_handler_register_with(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler_3, handler_arg));
|
|
}
|
|
|
|
static void test_unregistration_from_handler_hdlr(void* handler_arg, esp_event_base_t base, int32_t id, void* event_arg)
|
|
{
|
|
esp_event_loop_handle_t* loop = (esp_event_loop_handle_t*) event_arg;
|
|
TEST_ESP_OK(esp_event_handler_unregister_with(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler_1));
|
|
TEST_ESP_OK(esp_event_handler_unregister_with(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler_2));
|
|
TEST_ESP_OK(esp_event_handler_unregister_with(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler_3));
|
|
}
|
|
|
|
TEST_CASE("can register from handler", "[event]")
|
|
{
|
|
TEST_SETUP();
|
|
|
|
esp_event_loop_handle_t loop;
|
|
|
|
esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
|
|
|
|
loop_args.task_name = NULL;
|
|
TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
|
|
|
|
int count = 0;
|
|
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_registration_from_handler_hdlr, &count));
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base2, TEST_EVENT_BASE2_EV1, test_unregistration_from_handler_hdlr, &count));
|
|
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, &loop, sizeof(&loop), portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
|
|
TEST_ASSERT_EQUAL(3, count);
|
|
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE2_EV1, &loop, sizeof(&loop), portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
|
|
TEST_ASSERT_EQUAL(3, count);
|
|
|
|
TEST_ESP_OK(esp_event_loop_delete(loop));
|
|
|
|
TEST_TEARDOWN();
|
|
}
|
|
|
|
static void test_create_loop_handler(void* handler_args, esp_event_base_t base, int32_t id, void* event_data)
|
|
{
|
|
esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
|
|
|
|
if (id == TEST_EVENT_BASE1_EV1) {
|
|
TEST_ESP_OK(esp_event_loop_create(&loop_args, (esp_event_loop_handle_t*) handler_args));
|
|
} else {
|
|
TEST_ESP_OK(esp_event_loop_delete(*((esp_event_loop_handle_t*) handler_args)));
|
|
}
|
|
}
|
|
|
|
TEST_CASE("can create and delete loop from handler", "[event]")
|
|
{
|
|
TEST_SETUP();
|
|
|
|
esp_event_loop_handle_t loop;
|
|
esp_event_loop_handle_t test_loop;
|
|
|
|
esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
|
|
|
|
loop_args.task_name = NULL;
|
|
TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
|
|
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_create_loop_handler, &test_loop));
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_create_loop_handler, &test_loop));
|
|
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
|
|
TEST_ESP_OK(esp_event_loop_delete(loop));
|
|
|
|
TEST_TEARDOWN();
|
|
}
|
|
|
|
TEST_CASE("events are dispatched in the order they are registered", "[event]")
|
|
{
|
|
TEST_SETUP();
|
|
|
|
esp_event_loop_handle_t loop;
|
|
esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
|
|
|
|
loop_args.task_name = NULL;
|
|
TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
|
|
|
|
int id_arr[7];
|
|
|
|
for (int i = 0; i < 7; i++) {
|
|
id_arr[i] = i;
|
|
}
|
|
|
|
int data_arr[12] = {0};
|
|
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base2, TEST_EVENT_BASE2_EV1, test_event_ordered_dispatch, id_arr + 0));
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop, ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, test_event_ordered_dispatch, id_arr + 1));
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base1, ESP_EVENT_ANY_ID, test_event_ordered_dispatch, id_arr + 2));
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base2, TEST_EVENT_BASE2_EV2, test_event_ordered_dispatch, id_arr + 3));
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_ordered_dispatch, id_arr + 4));
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base2, ESP_EVENT_ANY_ID, test_event_ordered_dispatch, id_arr + 5));
|
|
TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_ordered_dispatch, id_arr + 6));
|
|
|
|
esp_event_dump(stdout);
|
|
|
|
ordered_data_t data = {
|
|
.arr = data_arr,
|
|
.index = 0
|
|
};
|
|
|
|
ordered_data_t* dptr = &data;
|
|
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV2, &dptr, sizeof(dptr), portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, &dptr, sizeof(dptr), portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, &dptr, sizeof(dptr), portMAX_DELAY));
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV1, &dptr, sizeof(dptr), portMAX_DELAY));
|
|
|
|
TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
|
|
|
|
// Expected data executing the posts above
|
|
int ref_arr[12] = {1, 3, 5, 1, 2, 4, 1, 2, 6, 0, 1, 5};
|
|
|
|
for (int i = 0; i < 12; i++) {
|
|
TEST_ASSERT_EQUAL(ref_arr[i], data_arr[i]);
|
|
}
|
|
|
|
TEST_ESP_OK(esp_event_loop_delete(loop));
|
|
|
|
TEST_TEARDOWN();
|
|
}
|
|
|
|
#if CONFIG_ESP_EVENT_POST_FROM_ISR
|
|
TEST_CASE("can properly prepare event data posted to loop", "[event]")
|
|
{
|
|
TEST_SETUP();
|
|
|
|
esp_event_loop_handle_t loop;
|
|
esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
|
|
|
|
loop_args.task_name = NULL;
|
|
TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
|
|
|
|
esp_event_post_instance_t post;
|
|
esp_event_loop_instance_t* loop_def = (esp_event_loop_instance_t*) loop;
|
|
|
|
TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
|
|
TEST_ASSERT_EQUAL(pdTRUE, xQueueReceive(loop_def->queue, &post, portMAX_DELAY));
|
|
TEST_ASSERT_EQUAL(false, post.data_set);
|
|
TEST_ASSERT_EQUAL(false, post.data_allocated);
|
|
TEST_ASSERT_EQUAL(NULL, post.data.ptr);
|
|
|
|
int sample = 0;
|
|
TEST_ESP_OK(esp_event_isr_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, &sample, sizeof(sample), NULL));
|
|
TEST_ASSERT_EQUAL(pdTRUE, xQueueReceive(loop_def->queue, &post, portMAX_DELAY));
|
|
TEST_ASSERT_EQUAL(true, post.data_set);
|
|
TEST_ASSERT_EQUAL(false, post.data_allocated);
|
|
TEST_ASSERT_EQUAL(false, post.data.val);
|
|
|
|
TEST_ESP_OK(esp_event_loop_delete(loop));
|
|
|
|
TEST_TEARDOWN();
|
|
}
|
|
|
|
static void test_handler_post_from_isr(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
|
|
{
|
|
SemaphoreHandle_t *sem = (SemaphoreHandle_t*) event_handler_arg;
|
|
// Event data is just the address value (maybe have been truncated due to casting).
|
|
int *data = (int*) event_data;
|
|
TEST_ASSERT_EQUAL(*data, (int) (*sem));
|
|
xSemaphoreGive(*sem);
|
|
}
|
|
|
|
void IRAM_ATTR test_event_on_timer_alarm(void* para)
|
|
{
|
|
/* Retrieve the interrupt status and the counter value
|
|
from the timer that reported the interrupt */
|
|
uint64_t timer_counter_value =
|
|
timer_group_get_counter_value_in_isr(TIMER_GROUP_0, TIMER_0);
|
|
timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_0);
|
|
timer_counter_value += (uint64_t) (TIMER_INTERVAL0_SEC * TIMER_SCALE);
|
|
timer_group_set_alarm_value_in_isr(TIMER_GROUP_0, TIMER_0, timer_counter_value);
|
|
|
|
int data = (int) para;
|
|
// Posting events with data more than 4 bytes should fail.
|
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_event_isr_post(s_test_base1, TEST_EVENT_BASE1_EV1, &data, 5, NULL));
|
|
// This should succeedd, as data is int-sized. The handler for the event checks that the passed event data
|
|
// is correct.
|
|
BaseType_t task_unblocked;
|
|
TEST_ESP_OK(esp_event_isr_post(s_test_base1, TEST_EVENT_BASE1_EV1, &data, sizeof(data), &task_unblocked));
|
|
if (task_unblocked == pdTRUE) {
|
|
portYIELD_FROM_ISR();
|
|
}
|
|
}
|
|
|
|
TEST_CASE("can post events from interrupt handler", "[event]")
|
|
{
|
|
SemaphoreHandle_t sem = xSemaphoreCreateBinary();
|
|
|
|
/* Select and initialize basic parameters of the timer */
|
|
timer_config_t config = {
|
|
.divider = TIMER_DIVIDER,
|
|
.counter_dir = TIMER_COUNT_UP,
|
|
.counter_en = TIMER_PAUSE,
|
|
.alarm_en = TIMER_ALARM_EN,
|
|
.intr_type = TIMER_INTR_LEVEL,
|
|
.auto_reload = false,
|
|
};
|
|
timer_init(TIMER_GROUP_0, TIMER_0, &config);
|
|
|
|
/* Timer's counter will initially start from value below.
|
|
Also, if auto_reload is set, this value will be automatically reload on alarm */
|
|
timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0x00000000ULL);
|
|
|
|
/* Configure the alarm value and the interrupt on alarm. */
|
|
timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, TIMER_INTERVAL0_SEC * TIMER_SCALE);
|
|
timer_enable_intr(TIMER_GROUP_0, TIMER_0);
|
|
timer_isr_register(TIMER_GROUP_0, TIMER_0, test_event_on_timer_alarm,
|
|
(void *) sem, ESP_INTR_FLAG_IRAM, NULL);
|
|
|
|
timer_start(TIMER_GROUP_0, TIMER_0);
|
|
|
|
TEST_SETUP();
|
|
|
|
TEST_ESP_OK(esp_event_handler_register(s_test_base1, TEST_EVENT_BASE1_EV1,
|
|
test_handler_post_from_isr, &sem));
|
|
|
|
xSemaphoreTake(sem, portMAX_DELAY);
|
|
|
|
TEST_TEARDOWN();
|
|
}
|
|
|
|
#endif // CONFIG_ESP_EVENT_POST_FROM_ISR
|