diff --git a/components/esp_event/default_event_loop.c b/components/esp_event/default_event_loop.c index 9b5b8e8b63..5ecd69872f 100644 --- a/components/esp_event/default_event_loop.c +++ b/components/esp_event/default_event_loop.c @@ -33,6 +33,24 @@ esp_err_t esp_event_handler_register(esp_event_base_t event_base, int32_t event_ event_handler, event_handler_arg); } +esp_err_t esp_event_handler_instance_register(esp_event_base_t event_base, + int32_t event_id, + esp_event_handler_t event_handler, + void *event_handler_arg, + esp_event_handler_instance_t *context) +{ + if (s_default_loop == NULL) { + return ESP_ERR_INVALID_STATE; + } + + return esp_event_handler_instance_register_with(s_default_loop, + event_base, + event_id, + event_handler, + event_handler_arg, + context); +} + esp_err_t esp_event_handler_unregister(esp_event_base_t event_base, int32_t event_id, esp_event_handler_t event_handler) { @@ -44,6 +62,17 @@ esp_err_t esp_event_handler_unregister(esp_event_base_t event_base, int32_t even event_handler); } +esp_err_t esp_event_handler_instance_unregister(esp_event_base_t event_base, + int32_t event_id, + esp_event_handler_instance_t context) +{ + if (s_default_loop == NULL) { + return ESP_ERR_INVALID_STATE; + } + + return esp_event_handler_instance_unregister_with(s_default_loop, event_base, event_id, context); +} + esp_err_t esp_event_post(esp_event_base_t event_base, int32_t event_id, void* event_data, size_t event_data_size, TickType_t ticks_to_wait) { diff --git a/components/esp_event/esp_event.c b/components/esp_event/esp_event.c index a346d2f348..5b0c3499c8 100644 --- a/components/esp_event/esp_event.c +++ b/components/esp_event/esp_event.c @@ -66,7 +66,7 @@ static int esp_event_dump_prepare(void) esp_event_loop_node_t *loop_node_it; esp_event_base_node_t* base_node_it; esp_event_id_node_t* id_node_it; - esp_event_handler_instance_t* handler_it; + esp_event_handler_node_t* handler_it; // Count the number of items to be printed. This is needed to compute how much memory to reserve. int loops = 0, handlers = 0; @@ -122,9 +122,9 @@ static void esp_event_loop_run_task(void* args) vTaskSuspend(NULL); } -static void handler_execute(esp_event_loop_instance_t* loop, esp_event_handler_instance_t *handler, esp_event_post_instance_t post) +static void handler_execute(esp_event_loop_instance_t* loop, esp_event_handler_node_t *handler, esp_event_post_instance_t post) { - ESP_LOGD(TAG, "running post %s:%d with handler %p on loop %p", post.base, post.id, handler->handler, loop); + ESP_LOGD(TAG, "running post %s:%d with handler %p and context %p on loop %p", post.base, post.id, handler->handler_ctx->handler, &handler->handler_ctx, loop); #ifdef CONFIG_ESP_EVENT_LOOP_PROFILING int64_t start, diff; @@ -142,9 +142,9 @@ static void handler_execute(esp_event_loop_instance_t* loop, esp_event_handler_i } } - (*(handler->handler))(handler->arg, post.base, post.id, data_ptr); + (*(handler->handler_ctx->handler))(handler->handler_ctx->arg, post.base, post.id, data_ptr); #else - (*(handler->handler))(handler->arg, post.base, post.id, post.data); + (*(handler->handler_ctx->handler))(handler->handler_ctx->arg, post.base, post.id, post.data); #endif #ifdef CONFIG_ESP_EVENT_LOOP_PROFILING @@ -159,29 +159,38 @@ static void handler_execute(esp_event_loop_instance_t* loop, esp_event_handler_i #endif } -static esp_err_t handler_instances_add(esp_event_handler_instances_t* handlers, esp_event_handler_t handler, void* handler_arg) +static esp_err_t handler_instances_add(esp_event_handler_nodes_t* handlers, esp_event_handler_t event_handler, void* event_handler_arg, esp_event_handler_instance_context_t **handler_ctx, bool legacy) { - esp_event_handler_instance_t* handler_instance = calloc(1, sizeof(*handler_instance)); + esp_event_handler_node_t *handler_instance = calloc(1, sizeof(*handler_instance)); - if (!handler_instance) { + if (!handler_instance) return ESP_ERR_NO_MEM; + + esp_event_handler_instance_context_t *context = calloc(1, sizeof(*context)); + + if (!context) { + free(handler_instance); return ESP_ERR_NO_MEM; } - handler_instance->handler = handler; - handler_instance->arg = handler_arg; + context->handler = event_handler; + context->arg = event_handler_arg; + handler_instance->handler_ctx = context; if (SLIST_EMPTY(handlers)) { SLIST_INSERT_HEAD(handlers, handler_instance, next); } else { - esp_event_handler_instance_t *it = NULL, *last = NULL; + esp_event_handler_node_t *it = NULL, *last = NULL; SLIST_FOREACH(it, handlers, next) { - if (handler == it->handler) { - it->arg = handler_arg; - ESP_LOGW(TAG, "handler already registered, overwriting"); - free(handler_instance); - return ESP_OK; + if (legacy) { + if(event_handler == it->handler_ctx->handler) { + it->handler_ctx->arg = event_handler_arg; + ESP_LOGW(TAG, "handler already registered, overwriting"); + free(handler_instance); + free(context); + return ESP_OK; + } } last = it; } @@ -189,13 +198,24 @@ static esp_err_t handler_instances_add(esp_event_handler_instances_t* handlers, SLIST_INSERT_AFTER(last, handler_instance, next); } + // If the caller didn't provide the handler instance context, don't set it. + // It will be removed once the event loop is deleted. + if (handler_ctx) { + *handler_ctx = context; + } + return ESP_OK; } -static esp_err_t base_node_add_handler(esp_event_base_node_t* base_node, int32_t id, esp_event_handler_t handler, void* handler_arg) +static esp_err_t base_node_add_handler(esp_event_base_node_t* base_node, + int32_t id, + esp_event_handler_t event_handler, + void *event_handler_arg, + esp_event_handler_instance_context_t **handler_ctx, + bool legacy) { if (id == ESP_EVENT_ANY_ID) { - return handler_instances_add(&(base_node->handlers), handler, handler_arg); + return handler_instances_add(&(base_node->handlers), event_handler, event_handler_arg, handler_ctx, legacy); } else { esp_err_t err = ESP_OK; @@ -220,7 +240,7 @@ static esp_err_t base_node_add_handler(esp_event_base_node_t* base_node, int32_t SLIST_INIT(&(id_node->handlers)); - err = handler_instances_add(&(id_node->handlers), handler, handler_arg); + err = handler_instances_add(&(id_node->handlers), event_handler, event_handler_arg, handler_ctx, legacy); if (err == ESP_OK) { if (!last_id_node) { @@ -236,15 +256,21 @@ static esp_err_t base_node_add_handler(esp_event_base_node_t* base_node, int32_t return err; } else { - return handler_instances_add(&(id_node->handlers), handler, handler_arg); + return handler_instances_add(&(id_node->handlers), event_handler, event_handler_arg, handler_ctx, legacy); } } } -static esp_err_t loop_node_add_handler(esp_event_loop_node_t* loop_node, esp_event_base_t base, int32_t id, esp_event_handler_t handler, void* handler_arg) +static esp_err_t loop_node_add_handler(esp_event_loop_node_t* loop_node, + esp_event_base_t base, + int32_t id, + esp_event_handler_t event_handler, + void *event_handler_arg, + esp_event_handler_instance_context_t **handler_ctx, + bool legacy) { if (base == esp_event_any_base && id == ESP_EVENT_ANY_ID) { - return handler_instances_add(&(loop_node->handlers), handler, handler_arg); + return handler_instances_add(&(loop_node->handlers), event_handler, event_handler_arg, handler_ctx, legacy); } else { esp_err_t err = ESP_OK; @@ -273,7 +299,7 @@ static esp_err_t loop_node_add_handler(esp_event_loop_node_t* loop_node, esp_eve SLIST_INIT(&(base_node->handlers)); SLIST_INIT(&(base_node->id_nodes)); - err = base_node_add_handler(base_node, id, handler, handler_arg); + err = base_node_add_handler(base_node, id, event_handler, event_handler_arg, handler_ctx, legacy); if (err == ESP_OK) { if (!last_base_node) { @@ -288,20 +314,30 @@ static esp_err_t loop_node_add_handler(esp_event_loop_node_t* loop_node, esp_eve return err; } else { - return base_node_add_handler(base_node, id, handler, handler_arg); + return base_node_add_handler(base_node, id, event_handler, event_handler_arg, handler_ctx, legacy); } } } -static esp_err_t handler_instances_remove(esp_event_handler_instances_t* handlers, esp_event_handler_t handler) +static esp_err_t handler_instances_remove(esp_event_handler_nodes_t* handlers, esp_event_handler_instance_context_t* handler_ctx, bool legacy) { - esp_event_handler_instance_t *it, *temp; + esp_event_handler_node_t *it, *temp; SLIST_FOREACH_SAFE(it, handlers, next, temp) { - if (it->handler == handler) { - SLIST_REMOVE(handlers, it, esp_event_handler_instance, next); - free(it); - return ESP_OK; + if (legacy) { + if (it->handler_ctx->handler == handler_ctx->handler) { + SLIST_REMOVE(handlers, it, esp_event_handler_node, next); + free(it->handler_ctx); + free(it); + return ESP_OK; + } + } else { + if (it->handler_ctx == handler_ctx) { + SLIST_REMOVE(handlers, it, esp_event_handler_node, next); + free(it->handler_ctx); + free(it); + return ESP_OK; + } } } @@ -309,16 +345,16 @@ static esp_err_t handler_instances_remove(esp_event_handler_instances_t* handler } -static esp_err_t base_node_remove_handler(esp_event_base_node_t* base_node, int32_t id, esp_event_handler_t handler) +static esp_err_t base_node_remove_handler(esp_event_base_node_t* base_node, int32_t id, esp_event_handler_instance_context_t* handler_ctx, bool legacy) { if (id == ESP_EVENT_ANY_ID) { - return handler_instances_remove(&(base_node->handlers), handler); + return handler_instances_remove(&(base_node->handlers), handler_ctx, legacy); } else { esp_event_id_node_t *it, *temp; SLIST_FOREACH_SAFE(it, &(base_node->id_nodes), next, temp) { if (it->id == id) { - esp_err_t res = handler_instances_remove(&(it->handlers), handler); + esp_err_t res = handler_instances_remove(&(it->handlers), handler_ctx, legacy); if (res == ESP_OK) { if (SLIST_EMPTY(&(it->handlers))) { @@ -334,16 +370,16 @@ static esp_err_t base_node_remove_handler(esp_event_base_node_t* base_node, int3 return ESP_ERR_NOT_FOUND; } -static esp_err_t loop_node_remove_handler(esp_event_loop_node_t* loop_node, esp_event_base_t base, int32_t id, esp_event_handler_t handler) +static esp_err_t loop_node_remove_handler(esp_event_loop_node_t* loop_node, esp_event_base_t base, int32_t id, esp_event_handler_instance_context_t* handler_ctx, bool legacy) { if (base == esp_event_any_base && id == ESP_EVENT_ANY_ID) { - return handler_instances_remove(&(loop_node->handlers), handler); + return handler_instances_remove(&(loop_node->handlers), handler_ctx, legacy); } else { esp_event_base_node_t *it, *temp; SLIST_FOREACH_SAFE(it, &(loop_node->base_nodes), next, temp) { if (it->base == base) { - esp_err_t res = base_node_remove_handler(it, id, handler); + esp_err_t res = base_node_remove_handler(it, id, handler_ctx, legacy); if (res == ESP_OK) { if (SLIST_EMPTY(&(it->handlers)) && SLIST_EMPTY(&(it->id_nodes))) { @@ -359,11 +395,12 @@ static esp_err_t loop_node_remove_handler(esp_event_loop_node_t* loop_node, esp_ return ESP_ERR_NOT_FOUND; } -static void handler_instances_remove_all(esp_event_handler_instances_t* handlers) +static void handler_instances_remove_all(esp_event_handler_nodes_t* handlers) { - esp_event_handler_instance_t *it, *temp; + esp_event_handler_node_t *it, *temp; SLIST_FOREACH_SAFE(it, handlers, next, temp) { - SLIST_REMOVE(handlers, it, esp_event_handler_instance, next); + SLIST_REMOVE(handlers, it, esp_event_handler_node, next); + free(it->handler_ctx); free(it); } } @@ -526,7 +563,7 @@ esp_err_t esp_event_loop_run(esp_event_loop_handle_t event_loop, TickType_t tick bool exec = false; - esp_event_handler_instance_t *handler, *temp_handler; + esp_event_handler_node_t *handler, *temp_handler; esp_event_loop_node_t *loop_node, *temp_node; esp_event_base_node_t *base_node, *temp_base; esp_event_id_node_t *id_node, *temp_id_node; @@ -645,8 +682,9 @@ esp_err_t esp_event_loop_delete(esp_event_loop_handle_t event_loop) return ESP_OK; } -esp_err_t esp_event_handler_register_with(esp_event_loop_handle_t event_loop, esp_event_base_t event_base, - int32_t event_id, esp_event_handler_t event_handler, void* event_handler_arg) +esp_err_t esp_event_handler_register_with_internal(esp_event_loop_handle_t event_loop, esp_event_base_t event_base, + int32_t event_id, esp_event_handler_t event_handler, void* event_handler_arg, + esp_event_handler_instance_context_t** handler_ctx_arg, bool legacy) { assert(event_loop); assert(event_handler); @@ -687,7 +725,7 @@ esp_err_t esp_event_handler_register_with(esp_event_loop_handle_t event_loop, es SLIST_INIT(&(loop_node->handlers)); SLIST_INIT(&(loop_node->base_nodes)); - err = loop_node_add_handler(loop_node, event_base, event_id, event_handler, event_handler_arg); + err = loop_node_add_handler(loop_node, event_base, event_id, event_handler, event_handler_arg, handler_ctx_arg, legacy); if (err == ESP_OK) { if (!last_loop_node) { @@ -701,7 +739,7 @@ esp_err_t esp_event_handler_register_with(esp_event_loop_handle_t event_loop, es } } else { - err = loop_node_add_handler(last_loop_node, event_base, event_id, event_handler, event_handler_arg); + err = loop_node_add_handler(last_loop_node, event_base, event_id, event_handler, event_handler_arg, handler_ctx_arg, legacy); } on_err: @@ -709,11 +747,24 @@ on_err: return err; } -esp_err_t esp_event_handler_unregister_with(esp_event_loop_handle_t event_loop, esp_event_base_t event_base, - int32_t event_id, esp_event_handler_t event_handler) +esp_err_t esp_event_handler_register_with(esp_event_loop_handle_t event_loop, esp_event_base_t event_base, + int32_t event_id, esp_event_handler_t event_handler, void* event_handler_arg) +{ + return esp_event_handler_register_with_internal(event_loop, event_base, event_id, event_handler, event_handler_arg, NULL, true); +} + +esp_err_t esp_event_handler_instance_register_with(esp_event_loop_handle_t event_loop, esp_event_base_t event_base, + int32_t event_id, esp_event_handler_t event_handler, void* event_handler_arg, + esp_event_handler_instance_t* handler_ctx_arg) +{ + return esp_event_handler_register_with_internal(event_loop, event_base, event_id, event_handler, event_handler_arg, (esp_event_handler_instance_context_t**) handler_ctx_arg, false); +} + +esp_err_t esp_event_handler_unregister_with_internal(esp_event_loop_handle_t event_loop, esp_event_base_t event_base, + int32_t event_id, esp_event_handler_instance_context_t* handler_ctx, bool legacy) { assert(event_loop); - assert(event_handler); + assert(handler_ctx); if (event_base == ESP_EVENT_ANY_BASE && event_id != ESP_EVENT_ANY_ID) { ESP_LOGE(TAG, "unregistering to any event base with specific id unsupported"); @@ -731,7 +782,7 @@ esp_err_t esp_event_handler_unregister_with(esp_event_loop_handle_t event_loop, esp_event_loop_node_t *it, *temp; SLIST_FOREACH_SAFE(it, &(loop->loop_nodes), next, temp) { - esp_err_t res = loop_node_remove_handler(it, event_base, event_id, event_handler); + esp_err_t res = loop_node_remove_handler(it, event_base, event_id, handler_ctx, legacy); if (res == ESP_OK && SLIST_EMPTY(&(it->base_nodes)) && SLIST_EMPTY(&(it->handlers))) { SLIST_REMOVE(&(loop->loop_nodes), it, esp_event_loop_node, next); @@ -745,6 +796,24 @@ esp_err_t esp_event_handler_unregister_with(esp_event_loop_handle_t event_loop, return ESP_OK; } +esp_err_t esp_event_handler_unregister_with(esp_event_loop_handle_t event_loop, esp_event_base_t event_base, + int32_t event_id, esp_event_handler_t event_handler) +{ + esp_event_handler_instance_context_t local_handler_ctx; + local_handler_ctx.handler = event_handler; + local_handler_ctx.arg = NULL; + + return esp_event_handler_unregister_with_internal(event_loop, event_base, event_id, &local_handler_ctx, true); +} + +esp_err_t esp_event_handler_instance_unregister_with(esp_event_loop_handle_t event_loop, esp_event_base_t event_base, + int32_t event_id, esp_event_handler_instance_t handler_ctx_arg) +{ + if (!handler_ctx_arg) return ESP_ERR_INVALID_ARG; + + return esp_event_handler_unregister_with_internal(event_loop, event_base, event_id, (esp_event_handler_instance_context_t*) handler_ctx_arg, false); +} + esp_err_t esp_event_post_to(esp_event_loop_handle_t event_loop, esp_event_base_t event_base, int32_t event_id, void* event_data, size_t event_data_size, TickType_t ticks_to_wait) { @@ -879,7 +948,7 @@ esp_err_t esp_event_dump(FILE* file) esp_event_loop_node_t *loop_node_it; esp_event_base_node_t* base_node_it; esp_event_id_node_t* id_node_it; - esp_event_handler_instance_t* handler_it; + esp_event_handler_node_t* handler_it; // Allocate memory for printing int sz = esp_event_dump_prepare(); @@ -904,13 +973,13 @@ esp_err_t esp_event_dump(FILE* file) SLIST_FOREACH(loop_node_it, &(loop_it->loop_nodes), next) { SLIST_FOREACH(handler_it, &(loop_node_it->handlers), next) { - PRINT_DUMP_INFO(dst, sz, HANDLER_DUMP_FORMAT, handler_it->handler, "ESP_EVENT_ANY_BASE", + PRINT_DUMP_INFO(dst, sz, HANDLER_DUMP_FORMAT, handler_it->handler_ctx->handler, "ESP_EVENT_ANY_BASE", "ESP_EVENT_ANY_ID", handler_it->invoked, handler_it->time); } SLIST_FOREACH(base_node_it, &(loop_node_it->base_nodes), next) { SLIST_FOREACH(handler_it, &(base_node_it->handlers), next) { - PRINT_DUMP_INFO(dst, sz, HANDLER_DUMP_FORMAT, handler_it->handler, base_node_it->base , + PRINT_DUMP_INFO(dst, sz, HANDLER_DUMP_FORMAT, handler_it->handler_ctx->handler, base_node_it->base , "ESP_EVENT_ANY_ID", handler_it->invoked, handler_it->time); } @@ -919,7 +988,7 @@ esp_err_t esp_event_dump(FILE* file) memset(id_str_buf, 0, sizeof(id_str_buf)); snprintf(id_str_buf, sizeof(id_str_buf), "%d", id_node_it->id); - PRINT_DUMP_INFO(dst, sz, HANDLER_DUMP_FORMAT, handler_it->handler, base_node_it->base , + PRINT_DUMP_INFO(dst, sz, HANDLER_DUMP_FORMAT, handler_it->handler_ctx->handler, base_node_it->base , id_str_buf, handler_it->invoked, handler_it->time); } } diff --git a/components/esp_event/esp_event_private.c b/components/esp_event/esp_event_private.c index 828e458c6d..42214d2677 100644 --- a/components/esp_event/esp_event_private.c +++ b/components/esp_event/esp_event_private.c @@ -26,11 +26,11 @@ bool esp_event_is_handler_registered(esp_event_loop_handle_t event_loop, esp_eve esp_event_loop_node_t* loop_node; esp_event_base_node_t* base_node; esp_event_id_node_t* id_node; - esp_event_handler_instance_t* handler; + esp_event_handler_node_t* handler; SLIST_FOREACH(loop_node, &(loop->loop_nodes), next) { SLIST_FOREACH(handler, &(loop_node->handlers), next) { - if(event_base == ESP_EVENT_ANY_BASE && event_id == ESP_EVENT_ANY_ID && handler->handler == event_handler) + if(event_base == ESP_EVENT_ANY_BASE && event_id == ESP_EVENT_ANY_ID && handler->handler_ctx->handler == event_handler) { result = true; goto out; @@ -40,7 +40,7 @@ bool esp_event_is_handler_registered(esp_event_loop_handle_t event_loop, esp_eve SLIST_FOREACH(base_node, &(loop_node->base_nodes), next) { if (base_node->base == event_base) { SLIST_FOREACH(handler, &(base_node->handlers), next) { - if(event_id == ESP_EVENT_ANY_ID && handler->handler == event_handler) + if(event_id == ESP_EVENT_ANY_ID && handler->handler_ctx->handler == event_handler) { result = true; goto out; @@ -50,12 +50,12 @@ bool esp_event_is_handler_registered(esp_event_loop_handle_t event_loop, esp_eve SLIST_FOREACH(id_node, &(base_node->id_nodes), next) { if(id_node->id == event_id) { SLIST_FOREACH(handler, &(id_node->handlers), next) { - if(handler->handler == event_handler) + if(handler->handler_ctx->handler == event_handler) { result = true; goto out; } - } + } } } } @@ -65,4 +65,4 @@ bool esp_event_is_handler_registered(esp_event_loop_handle_t event_loop, esp_eve out: xSemaphoreGive(loop->mutex); return result; -} \ No newline at end of file +} diff --git a/components/esp_event/include/esp_event.h b/components/esp_event/include/esp_event.h index 60c51a731b..b5d7b14d78 100644 --- a/components/esp_event/include/esp_event.h +++ b/components/esp_event/include/esp_event.h @@ -32,7 +32,7 @@ extern "C" { /// Configuration for creating event loops typedef struct { int32_t queue_size; /**< size of the event loop queue */ - const char* task_name; /**< name of the event loop task; if NULL, + const char *task_name; /**< name of the event loop task; if NULL, a dedicated task is not created for event loop*/ UBaseType_t task_priority; /**< priority of the event loop task, ignored if task name is NULL */ uint32_t task_stack_size; /**< stack size of the event loop task, ignored if task name is NULL */ @@ -52,7 +52,7 @@ typedef struct { * - ESP_FAIL: Failed to create task loop * - Others: Fail */ -esp_err_t esp_event_loop_create(const esp_event_loop_args_t* event_loop_args, esp_event_loop_handle_t* event_loop); +esp_err_t esp_event_loop_create(const esp_event_loop_args_t *event_loop_args, esp_event_loop_handle_t *event_loop); /** * @brief Delete an existing event loop. @@ -114,7 +114,10 @@ esp_err_t esp_event_loop_delete_default(void); esp_err_t esp_event_loop_run(esp_event_loop_handle_t event_loop, TickType_t ticks_to_run); /** - * @brief Register an event handler to the system event loop. + * @brief Register an event handler to the system event loop (legacy). + * + * @note This function is obsolete and will be deprecated soon, please use esp_event_handler_instance_register() + * instead. * * This function can be used to register a handler for either: (1) specific events, * (2) all events of a certain event base, or (3) all events known by the system event loop. @@ -142,12 +145,15 @@ esp_err_t esp_event_loop_run(esp_event_loop_handle_t event_loop, TickType_t tick * - Others: Fail */ esp_err_t esp_event_handler_register(esp_event_base_t event_base, - int32_t event_id, - esp_event_handler_t event_handler, - void* event_handler_arg); + int32_t event_id, + esp_event_handler_t event_handler, + void *event_handler_arg); /** - * @brief Register an event handler to a specific loop. + * @brief Register an event handler to a specific loop (legacy). + * + * @note This function is obsolete and will be deprecated soon, please use esp_event_handler_instance_register_with() + * instead. * * This function behaves in the same manner as esp_event_handler_register, except the additional * specification of the event loop to register the handler to. @@ -168,13 +174,94 @@ esp_err_t esp_event_handler_register(esp_event_base_t event_base, * - Others: Fail */ esp_err_t esp_event_handler_register_with(esp_event_loop_handle_t event_loop, - esp_event_base_t event_base, - int32_t event_id, - esp_event_handler_t event_handler, - void* event_handler_arg); + esp_event_base_t event_base, + int32_t event_id, + esp_event_handler_t event_handler, + void *event_handler_arg); /** - * @brief Unregister a handler with the system event loop. + * @brief Register an instance of event handler to a specific loop. + * + * This function can be used to register a handler for either: (1) specific events, + * (2) all events of a certain event base, or (3) all events known by the system event loop. + * + * - specific events: specify exact event_base and event_id + * - all events of a certain base: specify exact event_base and use ESP_EVENT_ANY_ID as the event_id + * - all events known by the loop: use ESP_EVENT_ANY_BASE for event_base and ESP_EVENT_ANY_ID as the event_id + * + * Besides the error, the function returns an instance object as output parameter to identify each registration. + * This is necessary to remove (unregister) the registration before the event loop is deleted. + * + * Registering multiple handlers to events, registering a single handler to multiple events as well as registering + * the same handler to the same event multiple times is possible. + * Each registration yields a distinct instance object which identifies it over the registration + * lifetime. + * + * @param[in] event_loop the event loop to register this handler function to + * @param[in] event_base the base id of the event to register the handler for + * @param[in] event_id the id of the event to register the handler for + * @param[in] event_handler the handler function which gets called when the event is dispatched + * @param[in] event_handler_arg data, aside from event data, that is passed to the handler when it is called + * @param[out] instance An event handler instance object related to the registered event handler and data, can be NULL. + * This needs to be kept if the specific callback instance should be unregistered before deleting the whole + * event loop. Registering the same event handler multiple times is possible and yields distinct instance + * objects. The data can be the same for all registrations. + * If no unregistration is needed but the handler should be deleted when the event loop is deleted, + * instance can be NULL. + * + * @note the event loop library does not maintain a copy of event_handler_arg, therefore the user should + * ensure that event_handler_arg still points to a valid location by the time the handler gets called + * + * @return + * - ESP_OK: Success + * - ESP_ERR_NO_MEM: Cannot allocate memory for the handler + * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id or instance is NULL + * - Others: Fail + */ +esp_err_t esp_event_handler_instance_register_with(esp_event_loop_handle_t event_loop, + esp_event_base_t event_base, + int32_t event_id, + esp_event_handler_t event_handler, + void *event_handler_arg, + esp_event_handler_instance_t *instance); + +/** + * @brief Register an instance of event handler to the default loop. + * + * This function does the same as esp_event_handler_instance_register_with, except that it registers the + * handler to the default event loop. + * + * @param[in] event_base the base id of the event to register the handler for + * @param[in] event_id the id of the event to register the handler for + * @param[in] event_handler the handler function which gets called when the event is dispatched + * @param[in] event_handler_arg data, aside from event data, that is passed to the handler when it is called + * @param[out] instance An event handler instance object related to the registered event handler and data, can be NULL. + * This needs to be kept if the specific callback instance should be unregistered before deleting the whole + * event loop. Registering the same event handler multiple times is possible and yields distinct instance + * objects. The data can be the same for all registrations. + * If no unregistration is needed but the handler should be deleted when the event loop is deleted, + * instance can be NULL. + * + * @note the event loop library does not maintain a copy of event_handler_arg, therefore the user should + * ensure that event_handler_arg still points to a valid location by the time the handler gets called + * + * @return + * - ESP_OK: Success + * - ESP_ERR_NO_MEM: Cannot allocate memory for the handler + * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id or instance is NULL + * - Others: Fail + */ +esp_err_t esp_event_handler_instance_register(esp_event_base_t event_base, + int32_t event_id, + esp_event_handler_t event_handler, + void *event_handler_arg, + esp_event_handler_instance_t *instance); + +/** + * @brief Unregister a handler with the system event loop (legacy). + * + * @note This function is obsolete and will be deprecated soon, please use esp_event_handler_instance_unregister() + * instead. * * This function can be used to unregister a handler so that it no longer gets called during dispatch. * Handlers can be unregistered for either: (1) specific events, (2) all events of a certain event base, @@ -194,10 +281,15 @@ esp_err_t esp_event_handler_register_with(esp_event_loop_handle_t event_loop, * @return ESP_ERR_INVALID_ARG invalid combination of event base and event id * @return others fail */ -esp_err_t esp_event_handler_unregister(esp_event_base_t event_base, int32_t event_id, esp_event_handler_t event_handler); +esp_err_t esp_event_handler_unregister(esp_event_base_t event_base, + int32_t event_id, + esp_event_handler_t event_handler); /** - * @brief Unregister a handler with the system event loop. + * @brief Unregister a handler from a specific event loop (legacy). + * + * @note This function is obsolete and will be deprecated soon, please use esp_event_handler_instance_unregister_with() + * instead. * * This function behaves in the same manner as esp_event_handler_unregister, except the additional specification of * the event loop to unregister the handler with. @@ -217,6 +309,53 @@ esp_err_t esp_event_handler_unregister_with(esp_event_loop_handle_t event_loop, int32_t event_id, esp_event_handler_t event_handler); +/** + * @brief Unregister a handler instance from a specific event loop. + * + * This function can be used to unregister a handler so that it no longer gets called during dispatch. + * Handlers can be unregistered for either: (1) specific events, (2) all events of a certain event base, + * or (3) all events known by the system event loop + * + * - specific events: specify exact event_base and event_id + * - all events of a certain base: specify exact event_base and use ESP_EVENT_ANY_ID as the event_id + * - all events known by the loop: use ESP_EVENT_ANY_BASE for event_base and ESP_EVENT_ANY_ID as the event_id + * + * This function ignores unregistration of handler instances that have not been previously registered. + * + * @param[in] event_loop the event loop with which to unregister this handler function + * @param[in] event_base the base of the event with which to unregister the handler + * @param[in] event_id the id of the event with which to unregister the handler + * @param[in] instance the instance object of the registration to be unregistered + * + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id + * - Others: Fail + */ +esp_err_t esp_event_handler_instance_unregister_with(esp_event_loop_handle_t event_loop, + esp_event_base_t event_base, + int32_t event_id, + esp_event_handler_instance_t instance); + +/** + * @brief Unregister a handler from the system event loop. + * + * This function does the same as esp_event_handler_instance_unregister_with, except that it unregisters the + * handler instance from the default event loop. + * + * @param[in] event_base the base of the event with which to unregister the handler + * @param[in] event_id the id of the event with which to unregister the handler + * @param[in] instance the instance object of the registration to be unregistered + * + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id + * - Others: Fail + */ +esp_err_t esp_event_handler_instance_unregister(esp_event_base_t event_base, + int32_t event_id, + esp_event_handler_instance_t instance); + /** * @brief Posts an event to the system default event loop. The event loop library keeps a copy of event_data and manages * the copy's lifetime automatically (allocation + deletion); this ensures that the data the @@ -230,16 +369,16 @@ esp_err_t esp_event_handler_unregister_with(esp_event_loop_handle_t event_loop, * * @return * - ESP_OK: Success - * - ESP_ERR_TIMEOUT: Time to wait for event queue to unblock expired, + * - ESP_ERR_TIMEOUT: Time to wait for event queue to unblock expired, * queue full when posting from ISR * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id * - Others: Fail */ esp_err_t esp_event_post(esp_event_base_t event_base, - int32_t event_id, - void* event_data, - size_t event_data_size, - TickType_t ticks_to_wait); + int32_t event_id, + void *event_data, + size_t event_data_size, + TickType_t ticks_to_wait); /** * @brief Posts an event to the specified event loop. The event loop library keeps a copy of event_data and manages @@ -258,7 +397,7 @@ esp_err_t esp_event_post(esp_event_base_t event_base, * * @return * - ESP_OK: Success - * - ESP_ERR_TIMEOUT: Time to wait for event queue to unblock expired, + * - ESP_ERR_TIMEOUT: Time to wait for event queue to unblock expired, * queue full when posting from ISR * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id * - Others: Fail @@ -266,19 +405,19 @@ esp_err_t esp_event_post(esp_event_base_t event_base, esp_err_t esp_event_post_to(esp_event_loop_handle_t event_loop, esp_event_base_t event_base, int32_t event_id, - void* event_data, + void *event_data, size_t event_data_size, TickType_t ticks_to_wait); #if CONFIG_ESP_EVENT_POST_FROM_ISR /** * @brief Special variant of esp_event_post for posting events from interrupt handlers. - * + * * @param[in] event_base the event base that identifies the event * @param[in] event_id the event id that identifies the event * @param[in] event_data the data, specific to the event occurence, that gets passed to the handler * @param[in] event_data_size the size of the event data; max is 4 bytes - * @param[out] task_unblocked an optional parameter (can be NULL) which indicates that an event task with + * @param[out] task_unblocked an optional parameter (can be NULL) which indicates that an event task with * higher priority than currently running task has been unblocked by the posted event; * a context switch should be requested before the interrupt is existed. * @@ -290,14 +429,14 @@ esp_err_t esp_event_post_to(esp_event_loop_handle_t event_loop, * - ESP_OK: Success * - ESP_FAIL: Event queue for the default event loop full * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id, - * data size of more than 4 bytes + * data size of more than 4 bytes * - Others: Fail */ esp_err_t esp_event_isr_post(esp_event_base_t event_base, - int32_t event_id, - void* event_data, - size_t event_data_size, - BaseType_t* task_unblocked); + int32_t event_id, + void *event_data, + size_t event_data_size, + BaseType_t *task_unblocked); /** * @brief Special variant of esp_event_post_to for posting events from interrupt handlers @@ -307,7 +446,7 @@ esp_err_t esp_event_isr_post(esp_event_base_t event_base, * @param[in] event_id the event id that identifies the event * @param[in] event_data the data, specific to the event occurence, that gets passed to the handler * @param[in] event_data_size the size of the event data - * @param[out] task_unblocked an optional parameter (can be NULL) which indicates that an event task with + * @param[out] task_unblocked an optional parameter (can be NULL) which indicates that an event task with * higher priority than currently running task has been unblocked by the posted event; * a context switch should be requested before the interrupt is existed. * @@ -319,15 +458,15 @@ esp_err_t esp_event_isr_post(esp_event_base_t event_base, * - ESP_OK: Success * - ESP_FAIL: Event queue for the loop full * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id, - * data size of more than 4 bytes + * data size of more than 4 bytes * - Others: Fail */ esp_err_t esp_event_isr_post_to(esp_event_loop_handle_t event_loop, - esp_event_base_t event_base, - int32_t event_id, - void* event_data, - size_t event_data_size, - BaseType_t* task_unblocked); + esp_event_base_t event_base, + int32_t event_id, + void *event_data, + size_t event_data_size, + BaseType_t *task_unblocked); #endif /** @@ -374,7 +513,7 @@ esp_err_t esp_event_isr_post_to(esp_event_loop_handle_t event_loop, * - ESP_ERR_NO_MEM: Cannot allocate memory for event loops list * - Others: Fail */ -esp_err_t esp_event_dump(FILE* file); +esp_err_t esp_event_dump(FILE *file); #ifdef __cplusplus } // extern "C" diff --git a/components/esp_event/include/esp_event_base.h b/components/esp_event/include/esp_event_base.h index 73bc73be85..fc5a1deb02 100644 --- a/components/esp_event/include/esp_event_base.h +++ b/components/esp_event/include/esp_event_base.h @@ -26,11 +26,11 @@ extern "C" { // Event loop library types typedef const char* esp_event_base_t; /**< unique pointer to a subsystem that exposes events */ typedef void* esp_event_loop_handle_t; /**< a number that identifies an event with respect to a base */ -typedef void (*esp_event_handler_t)(void* event_handler_arg, - esp_event_base_t event_base, - int32_t event_id, +typedef void (*esp_event_handler_t)(void* event_handler_arg, + esp_event_base_t event_base, + int32_t event_id, void* event_data); /**< function called when an event is posted to the queue */ - +typedef void* esp_event_handler_instance_t; /**< context identifying an instance of a registered event handler */ // Defines for registering/unregistering event handlers #define ESP_EVENT_ANY_BASE NULL /**< register handler for any event base */ diff --git a/components/esp_event/private_include/esp_event_internal.h b/components/esp_event/private_include/esp_event_internal.h index fb970a8068..02403e0399 100644 --- a/components/esp_event/private_include/esp_event_internal.h +++ b/components/esp_event/private_include/esp_event_internal.h @@ -24,23 +24,27 @@ extern "C" { typedef SLIST_HEAD(base_nodes, base_node) base_nodes_t; -/// Event handler -typedef struct esp_event_handler_instance { +typedef struct esp_event_handler_context { esp_event_handler_t handler; /**< event handler function*/ - void* arg; /**< event handler argument */ + void* arg; +} esp_event_handler_instance_context_t; /**< event handler argument */ + +/// Event handler +typedef struct esp_event_handler_node { + esp_event_handler_instance_context_t* handler_ctx; /**< event handler context*/ #ifdef CONFIG_ESP_EVENT_LOOP_PROFILING uint32_t invoked; /**< number of times this handler has been invoked */ int64_t time; /**< total runtime of this handler across all calls */ #endif - SLIST_ENTRY(esp_event_handler_instance) next; /**< next event handler in the list */ -} esp_event_handler_instance_t; + SLIST_ENTRY(esp_event_handler_node) next; /**< next event handler in the list */ +} esp_event_handler_node_t; -typedef SLIST_HEAD(esp_event_handler_instances, esp_event_handler_instance) esp_event_handler_instances_t; +typedef SLIST_HEAD(esp_event_handler_instances, esp_event_handler_node) esp_event_handler_nodes_t; /// Event typedef struct esp_event_id_node { int32_t id; /**< id number of the event */ - esp_event_handler_instances_t handlers; /**< list of handlers to be executed when + esp_event_handler_nodes_t handlers; /**< list of handlers to be executed when this event is raised */ SLIST_ENTRY(esp_event_id_node) next; /**< pointer to the next event node on the linked list */ } esp_event_id_node_t; @@ -49,7 +53,7 @@ typedef SLIST_HEAD(esp_event_id_nodes, esp_event_id_node) esp_event_id_nodes_t; typedef struct esp_event_base_node { esp_event_base_t base; /**< base identifier of the event */ - esp_event_handler_instances_t handlers; /**< event base level handlers, handlers for + esp_event_handler_nodes_t handlers; /**< event base level handlers, handlers for all events with this base */ esp_event_id_nodes_t id_nodes; /**< list of event ids with this base */ SLIST_ENTRY(esp_event_base_node) next; /**< pointer to the next base node on the linked list */ @@ -58,7 +62,7 @@ typedef struct esp_event_base_node { typedef SLIST_HEAD(esp_event_base_nodes, esp_event_base_node) esp_event_base_nodes_t; typedef struct esp_event_loop_node { - esp_event_handler_instances_t handlers; /** event loop level handlers */ + esp_event_handler_nodes_t handlers; /** event loop level handlers */ esp_event_base_nodes_t base_nodes; /** list of event bases registered to the loop */ SLIST_ENTRY(esp_event_loop_node) next; /** pointer to the next loop node containing event loop level handlers and the rest of diff --git a/components/esp_event/test/test_default_loop.c b/components/esp_event/test/test_default_loop.c new file mode 100644 index 0000000000..586a360224 --- /dev/null +++ b/components/esp_event/test/test_default_loop.c @@ -0,0 +1,157 @@ + +#include +#include + +#include "esp_event.h" +#include "sdkconfig.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_log.h" +#include "driver/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 "sdkconfig.h" +#include "unity.h" + +#include "test_utils.h" + +typedef struct { + void* data; + SemaphoreHandle_t mutex; +} simple_arg_t; + +static const char* TAG = "test_event"; + +ESP_EVENT_DECLARE_BASE(s_default_test_base1); +ESP_EVENT_DECLARE_BASE(s_default_test_base2); + +ESP_EVENT_DEFINE_BASE(s_default_test_base1); +ESP_EVENT_DEFINE_BASE(s_default_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 +}; + +// 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"); + +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); +} + +TEST_CASE("default loop: can create and delete loop", "[event]") +{ + TEST_SETUP(); + + TEST_ESP_OK(esp_event_loop_create_default()); + + TEST_ESP_OK(esp_event_loop_delete_default()); +} + +TEST_CASE("default loop: registering fails on uninitialized default loop", "[event]") +{ + TEST_SETUP(); + + esp_event_handler_instance_t instance; + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, esp_event_handler_instance_register(s_default_test_base1, + TEST_EVENT_BASE1_EV1, + test_event_simple_handler, + NULL, + &instance)); +} + +TEST_CASE("default loop: registering/unregistering event works", "[event]") +{ + TEST_SETUP(); + + int count = 0; + + simple_arg_t arg = { + .data = &count, + .mutex = xSemaphoreCreateMutex() + }; + + TEST_ESP_OK(esp_event_loop_create_default()); + + esp_event_handler_instance_t instance; + TEST_ESP_OK(esp_event_handler_instance_register(s_default_test_base1, + TEST_EVENT_BASE1_EV1, + test_event_simple_handler, + &arg, + &instance)); + TEST_ASSERT(instance); + TEST_ESP_OK(esp_event_post(s_default_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY)); + + vTaskDelay(10); + + TEST_ASSERT_EQUAL(1, count); + + TEST_ESP_OK(esp_event_handler_instance_unregister(s_default_test_base1, + TEST_EVENT_BASE1_EV1, + &instance)); + + vTaskDelay(10); + + TEST_ASSERT_EQUAL(1, count); + + TEST_ESP_OK(esp_event_loop_delete_default()); + + vSemaphoreDelete(arg.mutex); +} + +TEST_CASE("default event loop: registering event handler instance without instance context works", "[event]") { + TEST_SETUP(); + + int count_1 = 0; + + simple_arg_t arg_1 = { + .data = &count_1, + .mutex = xSemaphoreCreateMutex() + }; + + TEST_ESP_OK(esp_event_loop_create_default()); + + TEST_ESP_OK(esp_event_handler_instance_register(ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, test_event_simple_handler, &arg_1, NULL)); + + TEST_ESP_OK(esp_event_post(s_default_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY)); + + vTaskDelay(10); + + TEST_ASSERT_EQUAL(1, count_1); + + TEST_ESP_OK(esp_event_loop_delete_default()); + + vSemaphoreDelete(arg_1.mutex); +} diff --git a/components/esp_event/test/test_event.c b/components/esp_event/test/test_event.c index 25e4a18517..d8d73e42ad 100644 --- a/components/esp_event/test/test_event.c +++ b/components/esp_event/test/test_event.c @@ -75,6 +75,11 @@ typedef struct { 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; @@ -171,7 +176,7 @@ static void test_event_post_task(void* args) xSemaphoreTake(arg->start, portMAX_DELAY); for (int i = 0; i < data->num; i++) { - TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(data->loop, data->base, data->id, NULL, 0, portMAX_DELAY)); + TEST_ESP_OK(esp_event_post_to(data->loop, data->base, data->id, NULL, 0, portMAX_DELAY)); vTaskDelay(1); } @@ -189,9 +194,9 @@ static void test_event_simple_handler_registration_task(void* args) for(int i = 0; i < data->num; i++) { if (data->is_registration) { - TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(data->loop, data->base, data->id, data->handles[i], NULL)); + TEST_ESP_OK(esp_event_handler_register_with(data->loop, data->base, data->id, data->handles[i], NULL)); } else { - TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_unregister_with(data->loop, data->base, data->id, data->handles[i])); + TEST_ESP_OK(esp_event_handler_unregister_with(data->loop, data->base, data->id, data->handles[i])); } vTaskDelay(1); } @@ -212,7 +217,7 @@ static void test_handler_post_w_task(void* event_handler_arg, esp_event_base_t e if (*count <= 2) { if (event_base == s_test_base1 && event_id == TEST_EVENT_BASE1_EV1) { - TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(*loop, s_test_base1, 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)); } else{ xSemaphoreGive((SemaphoreHandle_t) arg->mutex); } @@ -237,7 +242,7 @@ static void test_handler_post_wo_task(void* event_handler_arg, esp_event_base_t if (*count <= 2) { if (event_base == s_test_base1 && event_id == TEST_EVENT_BASE1_EV1) { - TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(*loop, s_test_base1, 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)); } else{ xSemaphoreGive((SemaphoreHandle_t) arg->mutex); } @@ -246,7 +251,7 @@ static void test_handler_post_wo_task(void* event_handler_arg, esp_event_base_t // 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_OK, esp_event_post_to(*loop, s_test_base1, 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_ASSERT_EQUAL(ESP_ERR_TIMEOUT, esp_event_post_to(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY)); } } @@ -260,7 +265,20 @@ static void test_handler_unregister_itself(void* event_handler_arg, esp_event_ba (*unregistered) += (event_base == s_test_base1 ? 0 : 10) + event_id + 1; // Unregister this handler for this event - TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_unregister_with(*loop, event_base, event_id, test_handler_unregister_itself)); + 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) @@ -268,19 +286,19 @@ 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_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(event_loop, portMAX_DELAY)); + 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_ASSERT_EQUAL(ESP_OK, esp_event_loop_create_default()); + TEST_ESP_OK(esp_event_loop_create_default()); } static void test_teardown(void) { - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete_default()); + TEST_ESP_OK(esp_event_loop_delete_default()); } #define TIMER_DIVIDER 16 // Hardware timer clock divider @@ -302,31 +320,31 @@ TEST_CASE("can create and delete event loops", "[event]") esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop1)); + TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop1)); loop_args.task_name = NULL; - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop2)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop3)); + TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop2)); + TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop3)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop3, s_test_base1, TEST_EVENT_BASE1_EV1, (void*) 0x00000001, NULL)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop3, s_test_base1, TEST_EVENT_BASE1_EV2, (void*) 0x00000002, NULL)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop3, s_test_base2, TEST_EVENT_BASE1_EV1, (void*) 0x00000003, NULL)); + 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_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop3, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY)); + TEST_ESP_OK(esp_event_post_to(loop3, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY)); break; case 1: - TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop3, s_test_base2, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY)); + TEST_ESP_OK(esp_event_post_to(loop3, s_test_base2, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY)); break; case 2: - TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop3, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY)); + TEST_ESP_OK(esp_event_post_to(loop3, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY)); break; case 3: - TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop3, s_test_base2, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY)); + TEST_ESP_OK(esp_event_post_to(loop3, s_test_base2, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY)); break; default: break; @@ -335,9 +353,433 @@ TEST_CASE("can create and delete event loops", "[event]") 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_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop1)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop2)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop3)); + 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(); } @@ -361,36 +803,36 @@ TEST_CASE("can register/unregister handlers for all events/all events for a spec esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); loop_args.task_name = NULL; - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop)); + 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_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, test_event_simple_handler, NULL)); - TEST_ASSERT_EQUAL(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, 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_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, 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_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler, &arg)); - TEST_ASSERT_EQUAL(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_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_ASSERT_EQUAL(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_ASSERT_EQUAL(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) + 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_ASSERT_EQUAL(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_ASSERT_EQUAL(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_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_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(10))); + TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10))); TEST_ASSERT_EQUAL(9, count); // 3 + 3 + 2 + 1 - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop)); + TEST_ESP_OK(esp_event_loop_delete(loop)); vSemaphoreDelete(arg.mutex); @@ -407,7 +849,7 @@ TEST_CASE("can unregister handler", "[event]") esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); loop_args.task_name = NULL; - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop)); + TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop)); int count = 0; @@ -416,26 +858,70 @@ TEST_CASE("can unregister handler", "[event]") .mutex = xSemaphoreCreateMutex() }; - TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg)); - TEST_ASSERT_EQUAL(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_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_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY)); - TEST_ASSERT_EQUAL(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_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_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(10))); + TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10))); TEST_ASSERT_EQUAL(2, count); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_unregister_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_simple_handler)); + TEST_ESP_OK(esp_event_handler_unregister_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_simple_handler)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY)); - TEST_ASSERT_EQUAL(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_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_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(10))); + TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10))); TEST_ASSERT_EQUAL(3, count); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop)); + 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); @@ -452,7 +938,7 @@ TEST_CASE("handler can unregister itself", "[event]") esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); loop_args.task_name = NULL; - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop)); + TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop)); int unregistered = 0; @@ -464,35 +950,73 @@ TEST_CASE("handler can unregister itself", "[event]") */ int expected_unregistered = 0; - TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_handler_unregister_itself, &unregistered)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_handler_unregister_itself, &unregistered)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base2, TEST_EVENT_BASE2_EV1, test_handler_unregister_itself, &unregistered)); - TEST_ASSERT_EQUAL(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_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_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, &loop, sizeof(loop), portMAX_DELAY)); - TEST_ASSERT_EQUAL(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, &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_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, &loop, sizeof(loop), portMAX_DELAY)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE2_EV1, &loop, sizeof(loop), portMAX_DELAY)); - TEST_ASSERT_EQUAL(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_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_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE2_EV2, &loop, sizeof(loop), portMAX_DELAY)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(10))); + 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_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, &loop, sizeof(loop), portMAX_DELAY)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, &loop, sizeof(loop), portMAX_DELAY)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE2_EV1, &loop, sizeof(loop), portMAX_DELAY)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE2_EV2, &loop, sizeof(loop), portMAX_DELAY)); - TEST_ASSERT_EQUAL(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_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_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop)); + 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(); } @@ -508,7 +1032,7 @@ TEST_CASE("can exit running loop at approximately the set amount of time", "[eve esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); loop_args.task_name = NULL; - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop)); + TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop)); performance_data_t handler_data = { .performed = 0, @@ -516,7 +1040,7 @@ TEST_CASE("can exit running loop at approximately the set amount of time", "[eve .done = xSemaphoreCreateBinary() }; - TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_performance_handler, &handler_data)); + 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, @@ -545,7 +1069,7 @@ TEST_CASE("can exit running loop at approximately the set amount of time", "[eve // Run the loop for the runtime_ms set amount of time, regardless of whether events // are still being posted to the loop. - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(runtime_ms))); + TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(runtime_ms))); diff = (esp_timer_get_time() - start); @@ -560,7 +1084,7 @@ TEST_CASE("can exit running loop at approximately the set amount of time", "[eve vSemaphoreDelete(handler_data.done); vTaskDelete(post_task); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop)); + TEST_ESP_OK(esp_event_loop_delete(loop)); TEST_TEARDOWN(); } @@ -578,7 +1102,7 @@ TEST_CASE("can register/unregister handlers simultaneously", "[event]") esp_event_loop_handle_t loop; esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop)); + TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop)); ESP_LOGI(TAG, "registering handlers"); @@ -683,7 +1207,39 @@ TEST_CASE("can register/unregister handlers simultaneously", "[event]") free(registration_arg); free(unregistration_arg); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop)); + 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(); } @@ -702,7 +1258,7 @@ TEST_CASE("can post and run events", "[event]") loop_args.task_name = NULL; loop_args.queue_size = TEST_CONFIG_TASKS_TO_SPAWN * TEST_CONFIG_ITEMS_TO_REGISTER; - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop)); + TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop)); int count = 0; @@ -711,7 +1267,7 @@ TEST_CASE("can post and run events", "[event]") .mutex = xSemaphoreCreateMutex() }; - TEST_ASSERT_EQUAL(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_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)); @@ -736,7 +1292,7 @@ TEST_CASE("can post and run events", "[event]") // 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_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(10))); + TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10))); } for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) { @@ -744,7 +1300,7 @@ TEST_CASE("can post and run events", "[event]") } // Execute the rest - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(10))); + 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); @@ -757,7 +1313,85 @@ TEST_CASE("can post and run events", "[event]") free(post_event_data); free(post_event_arg); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop)); + 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); @@ -794,14 +1428,14 @@ static void performance_test(bool dedicated_task) loop_args.task_name = NULL; } - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop)); + 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_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, test_base + base, id, test_event_performance_handler, &data)); + TEST_ESP_OK(esp_event_handler_register_with(loop, test_base + base, id, test_event_performance_handler, &data)); } } @@ -856,7 +1490,7 @@ static void performance_test(bool dedicated_task) int64_t start = esp_timer_get_time(); for (int base = 0; base < bases; base++) { for (int id = 0; id < ids; id++) { - TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, test_base + post_bases[base], post_ids[id], NULL, 0, portMAX_DELAY)); + TEST_ESP_OK(esp_event_post_to(loop, test_base + post_bases[base], post_ids[id], NULL, 0, portMAX_DELAY)); } } @@ -879,7 +1513,7 @@ static void performance_test(bool dedicated_task) ((esp_event_loop_instance_t*) loop)->task = mtask; } - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop)); + TEST_ESP_OK(esp_event_loop_delete(loop)); TEST_TEARDOWN(); @@ -921,15 +1555,15 @@ TEST_CASE("can post to loop from handler - dedicated task", "[event]") .mutex = xSemaphoreCreateBinary() }; - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop_w_task)); + 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_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop_w_task, s_test_base1, TEST_EVENT_BASE1_EV1, test_handler_post_w_task, &arg)); - TEST_ASSERT_EQUAL(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_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_ASSERT_EQUAL(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)); + 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); @@ -938,10 +1572,10 @@ TEST_CASE("can post to loop from handler - dedicated task", "[event]") // Test that other tasks can still post while there is still slots in the queue, while handler is executing count = 100; - TEST_ASSERT_EQUAL(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)); + 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_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop_w_task, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY)); + 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, @@ -951,7 +1585,62 @@ TEST_CASE("can post to loop from handler - dedicated task", "[event]") vTaskDelay(pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop_w_task)); + 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); @@ -977,17 +1666,17 @@ TEST_CASE("can post to loop from handler - no dedicated task", "[event]") loop_args.queue_size = 1; loop_args.task_name = NULL; - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop_wo_task)); + 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_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop_wo_task, s_test_base1, TEST_EVENT_BASE1_EV1, test_handler_post_wo_task, &arg)); - TEST_ASSERT_EQUAL(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_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_ASSERT_EQUAL(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)); + 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); @@ -995,7 +1684,7 @@ TEST_CASE("can post to loop from handler - no dedicated task", "[event]") count = 100; - TEST_ASSERT_EQUAL(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)); + 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)); @@ -1009,7 +1698,68 @@ TEST_CASE("can post to loop from handler - no dedicated task", "[event]") vTaskDelete(mtask); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop_wo_task)); + 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); @@ -1040,17 +1790,17 @@ static void test_event_simple_handler_2(void* handler_arg, esp_event_base_t base 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_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler_1, handler_arg)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler_2, handler_arg)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler_3, handler_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_ASSERT_EQUAL(ESP_OK, esp_event_handler_unregister_with(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler_1)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_unregister_with(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler_2)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_unregister_with(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler_3)); + 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]") @@ -1062,30 +1812,30 @@ TEST_CASE("can register from handler", "[event]") esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); loop_args.task_name = NULL; - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop)); + TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop)); int count = 0; - TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_registration_from_handler_hdlr, &count)); - TEST_ASSERT_EQUAL(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_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_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, &loop, sizeof(&loop), portMAX_DELAY)); - TEST_ASSERT_EQUAL(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_EV1, &loop, sizeof(&loop), portMAX_DELAY)); + TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10))); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY)); - TEST_ASSERT_EQUAL(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_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE2_EV1, &loop, sizeof(&loop), portMAX_DELAY)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(10))); + 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_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY)); - TEST_ASSERT_EQUAL(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_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop)); + TEST_ESP_OK(esp_event_loop_delete(loop)); TEST_TEARDOWN(); } @@ -1095,9 +1845,9 @@ static void test_create_loop_handler(void* handler_args, esp_event_base_t base, esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); if (id == TEST_EVENT_BASE1_EV1) { - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, (esp_event_loop_handle_t*) handler_args)); + TEST_ESP_OK(esp_event_loop_create(&loop_args, (esp_event_loop_handle_t*) handler_args)); } else { - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(*((esp_event_loop_handle_t*) handler_args))); + TEST_ESP_OK(esp_event_loop_delete(*((esp_event_loop_handle_t*) handler_args))); } } @@ -1111,18 +1861,18 @@ TEST_CASE("can create and delete loop from handler", "[event]") esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); loop_args.task_name = NULL; - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop)); + TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_create_loop_handler, &test_loop)); - TEST_ASSERT_EQUAL(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_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_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY)); - TEST_ASSERT_EQUAL(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_EV1, NULL, 0, portMAX_DELAY)); + TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10))); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY)); - TEST_ASSERT_EQUAL(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(ESP_OK, esp_event_loop_delete(loop)); + TEST_ESP_OK(esp_event_loop_delete(loop)); TEST_TEARDOWN(); } @@ -1135,7 +1885,7 @@ TEST_CASE("events are dispatched in the order they are registered", "[event]") esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); loop_args.task_name = NULL; - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop)); + TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop)); int id_arr[7]; @@ -1145,13 +1895,13 @@ TEST_CASE("events are dispatched in the order they are registered", "[event]") int data_arr[12] = {0}; - TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base2, TEST_EVENT_BASE2_EV1, test_event_ordered_dispatch, id_arr + 0)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, test_event_ordered_dispatch, id_arr + 1)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, ESP_EVENT_ANY_ID, test_event_ordered_dispatch, id_arr + 2)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base2, TEST_EVENT_BASE2_EV2, test_event_ordered_dispatch, id_arr + 3)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_ordered_dispatch, id_arr + 4)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base2, ESP_EVENT_ANY_ID, test_event_ordered_dispatch, id_arr + 5)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_ordered_dispatch, id_arr + 6)); + 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); @@ -1162,12 +1912,12 @@ TEST_CASE("events are dispatched in the order they are registered", "[event]") ordered_data_t* dptr = &data; - TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV2, &dptr, sizeof(dptr), portMAX_DELAY)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, &dptr, sizeof(dptr), portMAX_DELAY)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, &dptr, sizeof(dptr), portMAX_DELAY)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV1, &dptr, sizeof(dptr), portMAX_DELAY)); + 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_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(10))); + 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}; @@ -1176,7 +1926,7 @@ TEST_CASE("events are dispatched in the order they are registered", "[event]") TEST_ASSERT_EQUAL(ref_arr[i], data_arr[i]); } - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop)); + TEST_ESP_OK(esp_event_loop_delete(loop)); TEST_TEARDOWN(); } @@ -1190,25 +1940,25 @@ TEST_CASE("can properly prepare event data posted to loop", "[event]") esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); loop_args.task_name = NULL; - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop)); + 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_ASSERT_EQUAL(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_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_ASSERT_EQUAL(ESP_OK, esp_event_isr_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, &sample, sizeof(sample), NULL)); + 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_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop)); + TEST_ESP_OK(esp_event_loop_delete(loop)); TEST_TEARDOWN(); } @@ -1238,7 +1988,7 @@ void IRAM_ATTR test_event_on_timer_alarm(void* para) // 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_ASSERT_EQUAL(ESP_OK, esp_event_isr_post(s_test_base1, TEST_EVENT_BASE1_EV1, &data, sizeof(data), &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(); } @@ -1272,7 +2022,7 @@ TEST_CASE("can post events from interrupt handler", "[event]") TEST_SETUP(); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register(s_test_base1, TEST_EVENT_BASE1_EV1, + TEST_ESP_OK(esp_event_handler_register(s_test_base1, TEST_EVENT_BASE1_EV1, test_handler_post_from_isr, &sem)); xSemaphoreTake(sem, portMAX_DELAY); diff --git a/tools/ci/config/target-test.yml b/tools/ci/config/target-test.yml index 28f8cf9d05..f63b052baf 100644 --- a/tools/ci/config/target-test.yml +++ b/tools/ci/config/target-test.yml @@ -345,7 +345,7 @@ UT_001: UT_002: extends: .unit_test_template - parallel: 10 + parallel: 12 tags: - ESP32_IDF - UT_T1_1