1 #include <stdbool.h>
2 #include <string.h>
3 
4 #include "esp_event.h"
5 #include "sdkconfig.h"
6 
7 #include "freertos/FreeRTOS.h"
8 #include "freertos/task.h"
9 #include "esp_log.h"
10 #include "driver/periph_ctrl.h"
11 #include "driver/timer.h"
12 
13 #include "esp_event.h"
14 #include "esp_event_private.h"
15 #include "esp_event_internal.h"
16 
17 #include "esp_heap_caps.h"
18 #include "esp_timer.h"
19 
20 #include "sdkconfig.h"
21 #include "unity.h"
22 
23 #include "test_utils.h"
24 
25 static const char* TAG = "test_event";
26 
27 #define TEST_CONFIG_ITEMS_TO_REGISTER        5
28 #define TEST_CONFIG_TASKS_TO_SPAWN           2
29 
30 #define TEST_CONFIG_WAIT_MULTIPLIER          5
31 
32 // The initial logging "initializing test" is to ensure mutex allocation is not counted against memory not being freed
33 // during teardown.
34 #define TEST_SETUP() \
35         ESP_LOGI(TAG, "initializing test"); \
36         size_t free_mem_before = heap_caps_get_free_size(MALLOC_CAP_DEFAULT); \
37         test_setup(); \
38         s_test_core_id = xPortGetCoreID(); \
39         s_test_priority = uxTaskPriorityGet(NULL);
40 
41 #define TEST_TEARDOWN() \
42         test_teardown(); \
43         vTaskDelay(pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER)); \
44         TEST_ASSERT_EQUAL(free_mem_before, heap_caps_get_free_size(MALLOC_CAP_DEFAULT));
45 
46 typedef struct {
47     void* data;
48     SemaphoreHandle_t start;
49     SemaphoreHandle_t done;
50 } task_arg_t;
51 
52 typedef struct {
53     esp_event_base_t base;
54     int32_t id;
55     esp_event_handler_t* handles;
56     int32_t num;
57     esp_event_loop_handle_t loop;
58     bool is_registration;
59 } handler_registration_data_t;
60 
61 typedef struct {
62     esp_event_base_t base;
63     int32_t id;
64     esp_event_loop_handle_t loop;
65     int32_t num;
66 } post_event_data_t;
67 
68 typedef struct {
69     int performed;
70     int expected;
71     SemaphoreHandle_t done;
72 } performance_data_t;
73 
74 typedef struct {
75     void* data;
76     SemaphoreHandle_t mutex;
77 } simple_arg_t;
78 
79 typedef struct {
80     esp_event_handler_instance_t *context;
81     void* data;
82 } instance_unregister_data_t;
83 
84 typedef struct {
85     int *arr;
86     int index;
87 } ordered_data_t;
88 
89 static BaseType_t s_test_core_id;
90 static UBaseType_t s_test_priority;
91 
92 ESP_EVENT_DECLARE_BASE(s_test_base1);
93 ESP_EVENT_DECLARE_BASE(s_test_base2);
94 
95 ESP_EVENT_DEFINE_BASE(s_test_base1);
96 ESP_EVENT_DEFINE_BASE(s_test_base2);
97 
98 enum {
99     TEST_EVENT_BASE1_EV1,
100     TEST_EVENT_BASE1_EV2,
101     TEST_EVENT_BASE1_MAX
102 };
103 
104 enum {
105     TEST_EVENT_BASE2_EV1,
106     TEST_EVENT_BASE2_EV2,
107     TEST_EVENT_BASE2_MAX
108 };
109 
test_event_get_core(void)110 static BaseType_t test_event_get_core(void)
111 {
112     static int calls = 0;
113 
114     if (portNUM_PROCESSORS > 1) {
115         return (s_test_core_id + calls++) % portNUM_PROCESSORS;
116     } else {
117         return s_test_core_id;
118     }
119 }
120 
test_event_get_default_loop_args(void)121 static esp_event_loop_args_t test_event_get_default_loop_args(void)
122 {
123     esp_event_loop_args_t loop_config = {
124         .queue_size = CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE,
125         .task_name = "loop",
126         .task_priority = s_test_priority,
127         .task_stack_size = 2048,
128         .task_core_id = test_event_get_core()
129     };
130 
131     return loop_config;
132 }
133 
test_event_simple_handler(void * event_handler_arg,esp_event_base_t event_base,int32_t event_id,void * event_data)134 static void test_event_simple_handler(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
135 {
136     if (!event_handler_arg) {
137         return;
138     }
139     simple_arg_t* arg = (simple_arg_t*) event_handler_arg;
140     xSemaphoreTake(arg->mutex, portMAX_DELAY);
141 
142     int* count = (int*) arg->data;
143 
144     if (event_data == NULL) {
145         (*count)++;
146     } else {
147         (*count) += *((int*) event_data);
148     }
149 
150     xSemaphoreGive(arg->mutex);
151 }
152 
test_event_ordered_dispatch(void * event_handler_arg,esp_event_base_t event_base,int32_t event_id,void * event_data)153 static void test_event_ordered_dispatch(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
154 {
155     int *arg = (int*) event_handler_arg;
156     ordered_data_t *data = *((ordered_data_t**) (event_data));
157 
158     data->arr[data->index++] = *arg;
159 }
160 
test_event_performance_handler(void * event_handler_arg,esp_event_base_t event_base,int32_t event_id,void * event_data)161 static void test_event_performance_handler(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
162 {
163     performance_data_t* data = (performance_data_t*) event_handler_arg;
164 
165     data->performed++;
166 
167     if (data->performed >= data->expected) {
168         xSemaphoreGive(data->done);
169     }
170 }
171 
test_event_post_task(void * args)172 static void test_event_post_task(void* args)
173 {
174     task_arg_t* arg = (task_arg_t*) args;
175     post_event_data_t* data = arg->data;
176 
177     xSemaphoreTake(arg->start, portMAX_DELAY);
178 
179     for (int i = 0; i < data->num; i++) {
180         TEST_ESP_OK(esp_event_post_to(data->loop, data->base, data->id, NULL, 0, portMAX_DELAY));
181         vTaskDelay(1);
182     }
183 
184     xSemaphoreGive(arg->done);
185 
186     vTaskDelete(NULL);
187 }
188 
test_event_simple_handler_registration_task(void * args)189 static void test_event_simple_handler_registration_task(void* args)
190 {
191     task_arg_t* arg = (task_arg_t*) args;
192     handler_registration_data_t* data = (handler_registration_data_t*) arg->data;
193 
194     xSemaphoreTake(arg->start, portMAX_DELAY);
195 
196     for(int i = 0; i < data->num; i++) {
197         if (data->is_registration) {
198             TEST_ESP_OK(esp_event_handler_register_with(data->loop, data->base, data->id, data->handles[i], NULL));
199         } else {
200             TEST_ESP_OK(esp_event_handler_unregister_with(data->loop, data->base, data->id, data->handles[i]));
201         }
202         vTaskDelay(1);
203     }
204 
205     xSemaphoreGive(arg->done);
206 
207     vTaskDelete(NULL);
208 }
209 
test_handler_post_w_task(void * event_handler_arg,esp_event_base_t event_base,int32_t event_id,void * event_data)210 static void test_handler_post_w_task(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
211 {
212     simple_arg_t* arg = (simple_arg_t*) event_handler_arg;
213 
214     esp_event_loop_handle_t* loop = (esp_event_loop_handle_t*) event_data;
215     int* count = (int*) arg->data;
216 
217     (*count)++;
218 
219     if (*count <= 2) {
220         if (event_base == s_test_base1 && event_id == TEST_EVENT_BASE1_EV1) {
221             TEST_ESP_OK(esp_event_post_to(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
222         } else{
223             xSemaphoreGive((SemaphoreHandle_t) arg->mutex);
224         }
225     } else {
226         // Test that once the queue is full and the handler attempts to post to the same loop,
227         // posting does not block indefinitely.
228         if (event_base == s_test_base1 && event_id == TEST_EVENT_BASE1_EV1) {
229             xSemaphoreTake((SemaphoreHandle_t) arg->mutex, portMAX_DELAY);
230             TEST_ASSERT_EQUAL(ESP_ERR_TIMEOUT, esp_event_post_to(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
231         }
232     }
233 }
234 
test_handler_post_wo_task(void * event_handler_arg,esp_event_base_t event_base,int32_t event_id,void * event_data)235 static void test_handler_post_wo_task(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
236 {
237     simple_arg_t* arg = (simple_arg_t*) event_handler_arg;
238 
239     esp_event_loop_handle_t* loop = (esp_event_loop_handle_t*) event_data;
240     int* count = (int*) arg->data;
241 
242     (*count)++;
243 
244     if (*count <= 2) {
245         if (event_base == s_test_base1 && event_id == TEST_EVENT_BASE1_EV1) {
246             TEST_ESP_OK(esp_event_post_to(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
247         } else{
248             xSemaphoreGive((SemaphoreHandle_t) arg->mutex);
249         }
250     } else {
251         // Test that once the queue is full and the handler attempts to post to the same loop,
252         // posting does not block indefinitely.
253         if (event_base == s_test_base1 && event_id == TEST_EVENT_BASE1_EV1) {
254             xSemaphoreTake((SemaphoreHandle_t) arg->mutex, portMAX_DELAY);
255             TEST_ESP_OK(esp_event_post_to(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
256             TEST_ASSERT_EQUAL(ESP_ERR_TIMEOUT, esp_event_post_to(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
257         }
258     }
259 }
260 
test_handler_unregister_itself(void * event_handler_arg,esp_event_base_t event_base,int32_t event_id,void * event_data)261 static void test_handler_unregister_itself(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
262 {
263     esp_event_loop_handle_t* loop = (esp_event_loop_handle_t*) event_data;
264     int* unregistered = (int*) event_handler_arg;
265 
266     (*unregistered) += (event_base == s_test_base1 ? 0 : 10) + event_id + 1;
267 
268     // Unregister this handler for this event
269     TEST_ESP_OK(esp_event_handler_unregister_with(*loop, event_base, event_id, test_handler_unregister_itself));
270 }
271 
test_handler_instance_unregister_itself(void * event_handler_arg,esp_event_base_t event_base,int32_t event_id,void * event_data)272 static void test_handler_instance_unregister_itself(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
273 {
274     esp_event_loop_handle_t* loop = (esp_event_loop_handle_t*) event_data;
275     instance_unregister_data_t *unregister_data = (instance_unregister_data_t*) event_handler_arg;
276     esp_event_handler_instance_t *context = (esp_event_handler_instance_t*) unregister_data->context;
277     int *count = (int*) unregister_data->data;
278 
279     (*count)++;
280 
281     // Unregister this handler for this event
282     TEST_ESP_OK(esp_event_handler_instance_unregister_with(*loop, event_base, event_id, *context));
283 }
284 
test_post_from_handler_loop_task(void * args)285 static void test_post_from_handler_loop_task(void* args)
286 {
287     esp_event_loop_handle_t event_loop = (esp_event_loop_handle_t) args;
288 
289     while(1) {
290         TEST_ESP_OK(esp_event_loop_run(event_loop, portMAX_DELAY));
291     }
292 }
293 
test_setup(void)294 static void test_setup(void)
295 {
296     TEST_ASSERT_TRUE(TEST_CONFIG_TASKS_TO_SPAWN >= 2);
297     TEST_ESP_OK(esp_event_loop_create_default());
298 }
299 
test_teardown(void)300 static void test_teardown(void)
301 {
302     TEST_ESP_OK(esp_event_loop_delete_default());
303 }
304 
305 #define TIMER_DIVIDER         16  //  Hardware timer clock divider
306 #define TIMER_SCALE           (TIMER_BASE_CLK / TIMER_DIVIDER)  // convert counter value to seconds
307 #define TIMER_INTERVAL0_SEC   (2.0) // sample test interval for the first timer
308 
309 TEST_CASE("can create and delete event loops", "[event]")
310 {
311     /* this test aims to verify that:
312     *  - creating loops with and without a task succeeds
313     *  - event queue can accomodate the set queue size, and drops the post when exceeded
314     *  - deleting loops with unconsumed posts and unregistered handlers (when unregistration is enabled) does not leak memory */
315 
316     TEST_SETUP();
317 
318     esp_event_loop_handle_t loop1; // with dedicated task
319     esp_event_loop_handle_t loop2; // without dedicated task
320     esp_event_loop_handle_t loop3; // with leftover post and handlers
321 
322     esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
323 
324     TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop1));
325 
326     loop_args.task_name = NULL;
327     TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop2));
328     TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop3));
329 
330     TEST_ESP_OK(esp_event_handler_register_with(loop3, s_test_base1, TEST_EVENT_BASE1_EV1, (void*) 0x00000001, NULL));
331     TEST_ESP_OK(esp_event_handler_register_with(loop3, s_test_base1, TEST_EVENT_BASE1_EV2, (void*) 0x00000002, NULL));
332     TEST_ESP_OK(esp_event_handler_register_with(loop3, s_test_base2, TEST_EVENT_BASE1_EV1, (void*) 0x00000003, NULL));
333 
334     for (int i = 0; i < loop_args.queue_size; i++) {
335         int mod = i % 4;
336 
337         switch(mod) {
338             case 0:
339                 TEST_ESP_OK(esp_event_post_to(loop3, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
340             break;
341             case 1:
342                 TEST_ESP_OK(esp_event_post_to(loop3, s_test_base2, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
343             break;
344             case 2:
345                 TEST_ESP_OK(esp_event_post_to(loop3, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
346             break;
347             case 3:
348                 TEST_ESP_OK(esp_event_post_to(loop3, s_test_base2, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
349             break;
350             default:
351             break;
352         }
353     }
354 
355     TEST_ASSERT_EQUAL(ESP_ERR_TIMEOUT, esp_event_post_to(loop3, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, pdMS_TO_TICKS(10)));
356 
357     TEST_ESP_OK(esp_event_loop_delete(loop1));
358     TEST_ESP_OK(esp_event_loop_delete(loop2));
359     TEST_ESP_OK(esp_event_loop_delete(loop3));
360 
361     TEST_TEARDOWN();
362 }
363 
364 TEST_CASE("registering event handler instance without instance context works", "[event]") {
365     TEST_SETUP();
366 
367     esp_event_loop_handle_t loop;
368 
369     int count_1 = 0;
370 
371     simple_arg_t arg_1 = {
372         .data = &count_1,
373         .mutex = xSemaphoreCreateMutex()
374     };
375 
376     esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
377 
378     loop_args.task_name = NULL;
379     TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
380 
381     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));
382 
383     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
384 
385     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
386 
387     TEST_ASSERT_EQUAL(1, count_1);
388 
389     TEST_ESP_OK(esp_event_loop_delete(loop));
390 
391     vSemaphoreDelete(arg_1.mutex);
392 
393     TEST_TEARDOWN();
394 }
395 
396 TEST_CASE("registering event twice with same handler yields updated handler arg", "[event]") {
397     TEST_SETUP();
398 
399     esp_event_loop_handle_t loop;
400 
401     int count = 0;
402 
403     simple_arg_t arg = {
404         .data = &count,
405         .mutex = xSemaphoreCreateMutex()
406     };
407 
408     esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
409 
410     loop_args.task_name = NULL;
411     TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
412 
413     /* Register the handler twice to the same base and id but with a different argument (expects to return ESP_OK and log a warning)
414      * This aims to verify: 1) Handler's argument to be updated
415      *                      2) Registration not to leak memory
416      */
417     TEST_ESP_OK(esp_event_handler_register_with(loop, ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, test_event_simple_handler, NULL));
418     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
419     // exec loop, no handler data: count stays 0
420     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
421     TEST_ASSERT_EQUAL(0, count);
422 
423     // overriding the former registration of the same event
424     TEST_ESP_OK(esp_event_handler_register_with(loop, ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, test_event_simple_handler, &arg));
425     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
426     // exec loop, registered handler data exists: count increases
427     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
428     TEST_ASSERT_EQUAL(1, count);
429 
430     TEST_ESP_OK(esp_event_loop_delete(loop));
431 
432     vSemaphoreDelete(arg.mutex);
433 
434     TEST_TEARDOWN();
435 }
436 
437 TEST_CASE("registering event handler instance twice works", "[event]") {
438     TEST_SETUP();
439 
440     esp_event_loop_handle_t loop;
441 
442     int count_1 = 0;
443     int count_2 = 0;
444 
445     simple_arg_t arg_1 = {
446         .data = &count_1,
447         .mutex = xSemaphoreCreateMutex()
448     };
449 
450     simple_arg_t arg_2 = {
451         .data = &count_2,
452         .mutex = xSemaphoreCreateMutex()
453     };
454 
455     esp_event_handler_instance_t ctx_1;
456     esp_event_handler_instance_t ctx_2;
457 
458     esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
459 
460     loop_args.task_name = NULL;
461     TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
462 
463     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));
464     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));
465 
466     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
467 
468     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
469 
470     TEST_ASSERT_EQUAL(1, count_1);
471     TEST_ASSERT_EQUAL(1, count_2);
472 
473     TEST_ESP_OK(esp_event_loop_delete(loop));
474 
475     vSemaphoreDelete(arg_1.mutex);
476     vSemaphoreDelete(arg_2.mutex);
477 
478     TEST_TEARDOWN();
479 }
480 
481 TEST_CASE("registering with ANY_BASE but specific ID fails", "[event]") {
482     TEST_SETUP();
483 
484     esp_event_loop_handle_t loop;
485 
486     int count = 0;
487 
488     simple_arg_t arg = {
489         .data = &count,
490         .mutex = xSemaphoreCreateMutex()
491     };
492 
493     esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
494 
495     loop_args.task_name = NULL;
496     TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
497 
498     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));
499     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
500 
501     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
502 
503     TEST_ASSERT_EQUAL(0, count);
504 
505     TEST_ESP_OK(esp_event_loop_delete(loop));
506 
507     vSemaphoreDelete(arg.mutex);
508 
509     TEST_TEARDOWN();
510 }
511 
512 TEST_CASE("registering instance with ANY_BASE but specific ID fails", "[event]") {
513     TEST_SETUP();
514 
515     esp_event_loop_handle_t loop;
516 
517     int count = 0;
518     esp_event_handler_instance_t ctx;
519 
520     simple_arg_t arg = {
521         .data = &count,
522         .mutex = xSemaphoreCreateMutex()
523     };
524 
525     esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
526 
527     loop_args.task_name = NULL;
528     TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
529 
530     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));
531     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
532 
533     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
534 
535     TEST_ASSERT_EQUAL(0, count);
536 
537     TEST_ESP_OK(esp_event_loop_delete(loop));
538 
539     vSemaphoreDelete(arg.mutex);
540 
541     TEST_TEARDOWN();
542 }
543 
544 TEST_CASE("Check registering ANY_ID", "[event]") {
545     TEST_SETUP();
546 
547     esp_event_loop_handle_t loop;
548 
549     int count = 0;
550 
551     simple_arg_t arg = {
552         .data = &count,
553         .mutex = xSemaphoreCreateMutex()
554     };
555 
556     esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
557 
558     loop_args.task_name = NULL;
559     TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
560 
561     TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base1, ESP_EVENT_ANY_ID, test_event_simple_handler, &arg));
562 
563     // handler shouldn't be triggered with different base
564     TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
565     TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
566     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
567     TEST_ASSERT_EQUAL(0, count);
568 
569     // for all events with correct base, it should be triggered
570     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
571     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
572     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
573     TEST_ASSERT_EQUAL(2, count);
574 
575     TEST_ESP_OK(esp_event_loop_delete(loop));
576 
577     vSemaphoreDelete(arg.mutex);
578 
579     TEST_TEARDOWN();
580 }
581 
582 TEST_CASE("Check registering instance with ANY_ID", "[event]") {
583     TEST_SETUP();
584 
585     esp_event_loop_handle_t loop;
586 
587     int count = 0;
588 
589     simple_arg_t arg = {
590         .data = &count,
591         .mutex = xSemaphoreCreateMutex()
592     };
593 
594     esp_event_handler_instance_t ctx;
595 
596     esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
597 
598     loop_args.task_name = NULL;
599     TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
600 
601     TEST_ESP_OK(esp_event_handler_instance_register_with(loop, s_test_base1, ESP_EVENT_ANY_ID, test_event_simple_handler, &arg, &ctx));
602 
603     // handler shouldn't be triggered with different base
604     TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
605     TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
606     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
607     TEST_ASSERT_EQUAL(0, count);
608 
609     // for all events with correct base, it should be triggered
610     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
611     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
612     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
613     TEST_ASSERT_EQUAL(2, count);
614 
615     TEST_ESP_OK(esp_event_loop_delete(loop));
616 
617     vSemaphoreDelete(arg.mutex);
618 
619     TEST_TEARDOWN();
620 }
621 
622 TEST_CASE("Check registering specific event", "[event]") {
623     TEST_SETUP();
624 
625     esp_event_loop_handle_t loop;
626 
627     int count = 0;
628 
629     simple_arg_t arg = {
630         .data = &count,
631         .mutex = xSemaphoreCreateMutex()
632     };
633 
634     esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
635 
636     loop_args.task_name = NULL;
637     TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
638 
639     TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg));
640 
641     // handler should not be triggered with different base
642     TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
643     TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
644     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
645     TEST_ASSERT_EQUAL(0, count);
646 
647     // for incorrect id, it should not be triggered
648     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
649     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
650     TEST_ASSERT_EQUAL(0, count);
651 
652     // for correct event and base, it should be triggered
653     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
654     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
655     TEST_ASSERT_EQUAL(1, count);
656 
657     TEST_ESP_OK(esp_event_loop_delete(loop));
658 
659     vSemaphoreDelete(arg.mutex);
660 
661     TEST_TEARDOWN();
662 }
663 
664 TEST_CASE("Check registering instance with specific event", "[event]") {
665     TEST_SETUP();
666 
667     esp_event_loop_handle_t loop;
668 
669     int count = 0;
670 
671     simple_arg_t arg = {
672         .data = &count,
673         .mutex = xSemaphoreCreateMutex()
674     };
675 
676     esp_event_handler_instance_t ctx;
677 
678     esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
679 
680     loop_args.task_name = NULL;
681     TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
682 
683     TEST_ESP_OK(esp_event_handler_instance_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg, &ctx));
684 
685     // handler should not be triggered with different base
686     TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
687     TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
688     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
689     TEST_ASSERT_EQUAL(0, count);
690 
691     // for incorrect id, it should not be triggered
692     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
693     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
694     TEST_ASSERT_EQUAL(0, count);
695 
696     // for correct event and base, it should be triggered
697     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
698     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
699     TEST_ASSERT_EQUAL(1, count);
700 
701     TEST_ESP_OK(esp_event_loop_delete(loop));
702 
703     vSemaphoreDelete(arg.mutex);
704 
705     TEST_TEARDOWN();
706 }
707 
708 TEST_CASE("Specific event is not called when no correct events are posted", "[event]") {
709     TEST_SETUP();
710 
711     esp_event_loop_handle_t loop;
712 
713     int count = 0;
714 
715     simple_arg_t arg = {
716         .data = &count,
717         .mutex = xSemaphoreCreateMutex()
718     };
719 
720     esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
721 
722     loop_args.task_name = NULL;
723     TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
724 
725     TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg));
726 
727     // handler should not be triggered by any of these postings
728     TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
729     TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
730     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
731     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
732     TEST_ASSERT_EQUAL(0, count);
733 
734     // Post unknown events.
735     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_MAX, NULL, 0, portMAX_DELAY));
736     TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE2_MAX, NULL, 0, portMAX_DELAY));
737     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
738     TEST_ASSERT_EQUAL(0, count);
739 
740     TEST_ESP_OK(esp_event_loop_delete(loop));
741 
742     vSemaphoreDelete(arg.mutex);
743 
744     TEST_TEARDOWN();
745 }
746 
747 TEST_CASE("Specific event instance is not called when no correct events are posted", "[event]") {
748     TEST_SETUP();
749 
750     esp_event_loop_handle_t loop;
751 
752     int count = 0;
753 
754     simple_arg_t arg = {
755         .data = &count,
756         .mutex = xSemaphoreCreateMutex()
757     };
758 
759     esp_event_handler_instance_t ctx;
760 
761     esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
762 
763     loop_args.task_name = NULL;
764     TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
765 
766     TEST_ESP_OK(esp_event_handler_instance_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg, &ctx));
767 
768     // handler should not be triggered by any of these postings
769     TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
770     TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
771     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
772     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
773     TEST_ASSERT_EQUAL(0, count);
774 
775     // Post unknown events.
776     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_MAX, NULL, 0, portMAX_DELAY));
777     TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE2_MAX, NULL, 0, portMAX_DELAY));
778     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
779     TEST_ASSERT_EQUAL(0, count);
780 
781     TEST_ESP_OK(esp_event_loop_delete(loop));
782 
783     vSemaphoreDelete(arg.mutex);
784 
785     TEST_TEARDOWN();
786 }
787 
788 TEST_CASE("can register/unregister handlers for all events/all events for a specific base", "[event]")
789 {
790     /* this test aims to verify that handlers can be registered to be called on all events
791      * or for all events with specific bases */
792 
793     TEST_SETUP();
794 
795     esp_event_loop_handle_t loop;
796 
797     int count = 0;
798 
799     simple_arg_t arg = {
800         .data = &count,
801         .mutex = xSemaphoreCreateMutex()
802     };
803 
804     esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
805 
806     loop_args.task_name = NULL;
807     TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
808 
809     /* Register the handler twice to the same base and id but with a different argument (expects to return ESP_OK and log a warning)
810      * This aims to verify: 1) Handler's argument to be updated
811      *                      2) Registration not to leak memory
812      */
813     TEST_ESP_OK(esp_event_handler_register_with(loop, ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, test_event_simple_handler, NULL));
814     TEST_ESP_OK(esp_event_handler_register_with(loop, ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, test_event_simple_handler, &arg));
815 
816     TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base1, ESP_EVENT_ANY_ID, test_event_simple_handler, &arg));
817     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));
818     TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg));
819     TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler, &arg));
820     TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base2, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg));
821 
822     TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_event_post_to(loop, ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, NULL, 0, portMAX_DELAY));
823     TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_event_post_to(loop, s_test_base1, ESP_EVENT_ANY_ID, NULL, 0, portMAX_DELAY));
824     TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_event_post_to(loop, ESP_EVENT_ANY_BASE, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
825     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)
826     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)
827 
828     // Post unknown events. Respective loop level and base level handlers should still execute.
829     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)
830     TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE2_MAX, NULL, 0, portMAX_DELAY)); // exec loop level (+1)
831 
832     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
833 
834     TEST_ASSERT_EQUAL(9, count); // 3 + 3 + 2 + 1
835 
836     TEST_ESP_OK(esp_event_loop_delete(loop));
837 
838     vSemaphoreDelete(arg.mutex);
839 
840     TEST_TEARDOWN();
841 }
842 
843 TEST_CASE("can unregister handler", "[event]")
844 {
845     /* this test aims to verify that unregistered handlers no longer execute when events are raised */
846 
847     TEST_SETUP();
848 
849     esp_event_loop_handle_t loop;
850     esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
851 
852     loop_args.task_name = NULL;
853     TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
854 
855     int count = 0;
856 
857     simple_arg_t arg = {
858         .data = &count,
859         .mutex = xSemaphoreCreateMutex()
860     };
861 
862     TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg));
863     TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base2, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg));
864 
865     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
866     TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
867 
868     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
869 
870     TEST_ASSERT_EQUAL(2, count);
871 
872     TEST_ESP_OK(esp_event_handler_unregister_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_simple_handler));
873 
874     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
875     TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
876 
877     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
878 
879     TEST_ASSERT_EQUAL(3, count);
880 
881     TEST_ESP_OK(esp_event_loop_delete(loop));
882 
883     vSemaphoreDelete(arg.mutex);
884 
885     TEST_TEARDOWN();
886 }
887 
888 TEST_CASE("can unregister handler instance", "[event]")
889 {
890     /* this test aims to verify that unregistered handlers no longer execute when events are raised */
891 
892     TEST_SETUP();
893 
894     esp_event_loop_handle_t loop;
895     esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
896 
897     loop_args.task_name = NULL;
898     TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
899 
900     int count = 0;
901 
902     simple_arg_t arg = {
903         .data = &count,
904         .mutex = xSemaphoreCreateMutex()
905     };
906 
907     esp_event_handler_instance_t ctx;
908 
909     TEST_ESP_OK(esp_event_handler_instance_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg, &ctx));
910 
911     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
912 
913     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
914 
915     TEST_ASSERT_EQUAL(1, count);
916 
917     TEST_ESP_OK(esp_event_handler_instance_unregister_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, ctx));
918 
919     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
920 
921     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
922 
923     TEST_ASSERT_EQUAL(1, count);
924 
925     TEST_ESP_OK(esp_event_loop_delete(loop));
926 
927     vSemaphoreDelete(arg.mutex);
928 
929     TEST_TEARDOWN();
930 }
931 
932 TEST_CASE("handler can unregister itself", "[event]")
933 {
934     /* this test aims to verify that handlers can unregister themselves */
935 
936     TEST_SETUP();
937 
938     esp_event_loop_handle_t loop;
939     esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
940 
941     loop_args.task_name = NULL;
942     TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
943 
944     int unregistered = 0;
945 
946     /*
947      * s_test_base1, ev1 = 1
948      * s_test_base1, ev2 = 2
949      * s_test_base2, ev1 = 11
950      * s_test_base2, ev2 = 12
951      */
952     int expected_unregistered = 0;
953 
954     TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_handler_unregister_itself, &unregistered));
955     TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_handler_unregister_itself, &unregistered));
956     TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base2, TEST_EVENT_BASE2_EV1, test_handler_unregister_itself, &unregistered));
957     TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base2, TEST_EVENT_BASE2_EV2, test_handler_unregister_itself, &unregistered));
958 
959     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, &loop, sizeof(loop), portMAX_DELAY));
960     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
961     expected_unregistered =  2;  // base1, ev2
962     TEST_ASSERT_EQUAL(expected_unregistered, unregistered);
963 
964     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, &loop, sizeof(loop), portMAX_DELAY));
965     TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE2_EV1, &loop, sizeof(loop), portMAX_DELAY));
966     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
967     expected_unregistered +=  1 + 11; // base1, ev1 +  base2, ev1
968     TEST_ASSERT_EQUAL(expected_unregistered, unregistered);
969 
970     TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE2_EV2, &loop, sizeof(loop), portMAX_DELAY));
971     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
972     expected_unregistered += 12; //  base2, ev2
973     TEST_ASSERT_EQUAL(expected_unregistered, unregistered);
974 
975     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, &loop, sizeof(loop), portMAX_DELAY));
976     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, &loop, sizeof(loop), portMAX_DELAY));
977     TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE2_EV1, &loop, sizeof(loop), portMAX_DELAY));
978     TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE2_EV2, &loop, sizeof(loop), portMAX_DELAY));
979     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
980     TEST_ASSERT_EQUAL(expected_unregistered, unregistered); // all handlers unregistered
981 
982     TEST_ESP_OK(esp_event_loop_delete(loop));
983 
984     TEST_TEARDOWN();
985 }
986 
987 TEST_CASE("handler instance can unregister itself", "[event]")
988 {
989     /* this test aims to verify that handlers can unregister themselves */
990 
991     TEST_SETUP();
992 
993     esp_event_loop_handle_t loop;
994     esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
995 
996     loop_args.task_name = NULL;
997     TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
998 
999     esp_event_handler_instance_t ctx;
1000 
1001     int count = 0;
1002 
1003     instance_unregister_data_t instance_data = {
1004         .context = &ctx,
1005         .data = &count
1006     };
1007 
1008     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));
1009 
1010     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, &loop, sizeof(loop), portMAX_DELAY));
1011     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
1012     TEST_ASSERT_EQUAL(1, count);
1013 
1014     vTaskDelay(1000);
1015 
1016     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, &loop, sizeof(loop), portMAX_DELAY));
1017     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
1018     TEST_ASSERT_EQUAL(1, count);
1019 
1020     TEST_ESP_OK(esp_event_loop_delete(loop));
1021 
1022     TEST_TEARDOWN();
1023 }
1024 
1025 TEST_CASE("can exit running loop at approximately the set amount of time", "[event]")
1026 {
1027     /* this test aims to verify that running loop does not block indefinitely in cases where
1028      * events are posted frequently */
1029 
1030     TEST_SETUP();
1031 
1032     esp_event_loop_handle_t loop;
1033     esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
1034 
1035     loop_args.task_name = NULL;
1036     TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
1037 
1038     performance_data_t handler_data = {
1039         .performed = 0,
1040         .expected = INT32_MAX,
1041         .done = xSemaphoreCreateBinary()
1042     };
1043 
1044     TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_performance_handler, &handler_data));
1045 
1046     post_event_data_t post_event_data = {
1047         .base = s_test_base1,
1048         .id = TEST_EVENT_BASE1_EV1,
1049         .loop = loop,
1050         .num  = INT32_MAX
1051     };
1052 
1053     task_arg_t post_event_arg = {
1054         .data = &post_event_data,
1055         .done = xSemaphoreCreateBinary(),
1056         .start = xSemaphoreCreateBinary()
1057     };
1058 
1059     TaskHandle_t post_task;
1060 
1061     xTaskCreatePinnedToCore(test_event_post_task, "post", 2048, &post_event_arg, s_test_priority, &post_task, test_event_get_core());
1062 
1063     int runtime_ms = 10;
1064     int runtime_us = runtime_ms * 1000;
1065 
1066     int64_t start, diff;
1067     start = esp_timer_get_time();
1068 
1069     xSemaphoreGive(post_event_arg.start);
1070 
1071     // Run the loop for the runtime_ms set amount of time, regardless of whether events
1072     // are still being posted to the loop.
1073     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(runtime_ms)));
1074 
1075     diff = (esp_timer_get_time() - start);
1076 
1077     // Threshold is 25 percent.
1078     TEST_ASSERT(diff < runtime_us * 1.25f);
1079 
1080     // Verify that the post task still continues
1081     TEST_ASSERT_NOT_EQUAL(pdTRUE, xSemaphoreTake(post_event_arg.done, pdMS_TO_TICKS(10)));
1082 
1083     vSemaphoreDelete(post_event_arg.done);
1084     vSemaphoreDelete(post_event_arg.start);
1085     vSemaphoreDelete(handler_data.done);
1086     vTaskDelete(post_task);
1087 
1088     TEST_ESP_OK(esp_event_loop_delete(loop));
1089 
1090     TEST_TEARDOWN();
1091 }
1092 
1093 TEST_CASE("can register/unregister handlers simultaneously", "[event]")
1094 {
1095     /* this test aims to verify that the event handlers list remains consistent despite
1096      * simultaneous access by differenct tasks */
1097 
1098     TEST_SETUP();
1099 
1100     const char* base = "base";
1101     int32_t id = 0;
1102 
1103     esp_event_loop_handle_t loop;
1104     esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
1105 
1106     TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
1107 
1108     ESP_LOGI(TAG, "registering handlers");
1109 
1110     handler_registration_data_t* registration_data = calloc(TEST_CONFIG_TASKS_TO_SPAWN, sizeof(*registration_data));
1111     task_arg_t* registration_arg = calloc(TEST_CONFIG_TASKS_TO_SPAWN, sizeof(*registration_arg));
1112 
1113     for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) {
1114         registration_data[i].base = base;
1115         registration_data[i].id = id;
1116         registration_data[i].loop = loop;
1117         registration_data[i].handles = calloc(TEST_CONFIG_ITEMS_TO_REGISTER, sizeof(esp_event_handler_t));
1118         registration_data[i].num = TEST_CONFIG_ITEMS_TO_REGISTER;
1119         registration_data[i].is_registration = true;
1120 
1121         for (int j = 0; j < TEST_CONFIG_ITEMS_TO_REGISTER; j++) {
1122             registration_data[i].handles[j] = (void*) (i * TEST_CONFIG_ITEMS_TO_REGISTER) + (j + TEST_CONFIG_ITEMS_TO_REGISTER);
1123         }
1124 
1125         registration_arg[i].start = xSemaphoreCreateBinary();
1126         registration_arg[i].done = xSemaphoreCreateBinary();
1127         registration_arg[i].data = &registration_data[i];
1128 
1129         xTaskCreatePinnedToCore(test_event_simple_handler_registration_task, "register", 2048, &registration_arg[i], s_test_priority, NULL, test_event_get_core());
1130     }
1131 
1132     // Give the semaphores to the spawned registration task
1133     for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) {
1134         xSemaphoreGive(registration_arg[i].start);
1135     }
1136 
1137     // Take the same semaphores in order to proceed
1138     for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) {
1139         xSemaphoreTake(registration_arg[i].done, portMAX_DELAY);
1140     }
1141 
1142     ESP_LOGI(TAG, "checking consistency of handlers list");
1143 
1144     // Check consistency of events list
1145     for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) {
1146         for (int j = 0; j < TEST_CONFIG_ITEMS_TO_REGISTER; j++) {
1147             TEST_ASSERT_TRUE(esp_event_is_handler_registered(loop, base, id, registration_data[i].handles[j]));
1148         }
1149     }
1150 
1151     ESP_LOGI(TAG, "unregistering handlers");
1152 
1153     /* Test if tasks can unregister simultaneously */
1154 
1155     // Unregister registered events
1156     handler_registration_data_t* unregistration_data = calloc(TEST_CONFIG_TASKS_TO_SPAWN, sizeof(*unregistration_data));
1157     task_arg_t* unregistration_arg = calloc(TEST_CONFIG_TASKS_TO_SPAWN, sizeof(*unregistration_arg));
1158 
1159     for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) {
1160         unregistration_data[i].base = base;
1161         unregistration_data[i].id = id;
1162         unregistration_data[i].loop = loop;
1163         unregistration_data[i].handles = calloc(TEST_CONFIG_ITEMS_TO_REGISTER, sizeof(esp_event_handler_t));
1164         unregistration_data[i].num = TEST_CONFIG_ITEMS_TO_REGISTER;
1165         unregistration_data[i].is_registration = false;
1166 
1167         memcpy(unregistration_data[i].handles, registration_data[i].handles, TEST_CONFIG_ITEMS_TO_REGISTER * sizeof(esp_event_handler_t));
1168 
1169         unregistration_arg[i].data = &unregistration_data[i];
1170         unregistration_arg[i].start = xSemaphoreCreateBinary();
1171         unregistration_arg[i].done = xSemaphoreCreateBinary();
1172 
1173         xTaskCreatePinnedToCore(test_event_simple_handler_registration_task, "unregister", 2048, &unregistration_arg[i], s_test_priority, NULL, test_event_get_core());
1174     }
1175 
1176     // Give the semaphores to the spawned unregistration task
1177     for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) {
1178         xSemaphoreGive(unregistration_arg[i].start);
1179     }
1180 
1181     // Take the same semaphores in order to proceed
1182     for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) {
1183         xSemaphoreTake(unregistration_arg[i].done, portMAX_DELAY);
1184     }
1185 
1186     ESP_LOGI(TAG, "checking consistency of handlers list");
1187 
1188     // Check consistency of events list
1189     for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) {
1190         for (int j = 0; j < TEST_CONFIG_ITEMS_TO_REGISTER; j++) {
1191             TEST_ASSERT_FALSE(esp_event_is_handler_registered(loop, base, id, registration_data[i].handles[j]));
1192         }
1193     }
1194 
1195     // Do cleanup
1196     for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) {
1197         free(registration_data[i].handles);
1198         vSemaphoreDelete(registration_arg[i].start);
1199         vSemaphoreDelete(registration_arg[i].done);
1200 
1201         free(unregistration_data[i].handles);
1202         vSemaphoreDelete(unregistration_arg[i].start);
1203         vSemaphoreDelete(unregistration_arg[i].done);
1204     }
1205 
1206     free(registration_data);
1207     free(unregistration_data);
1208     free(registration_arg);
1209     free(unregistration_arg);
1210 
1211     TEST_ESP_OK(esp_event_loop_delete(loop));
1212 
1213     TEST_TEARDOWN();
1214 }
1215 
1216 TEST_CASE("posting ANY_EVENT or ANY_ID fails", "[event]") {
1217     TEST_SETUP();
1218 
1219     esp_event_loop_handle_t loop;
1220 
1221     int count = 0;
1222 
1223     simple_arg_t arg = {
1224         .data = &count,
1225         .mutex = xSemaphoreCreateMutex()
1226     };
1227 
1228     esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
1229 
1230     loop_args.task_name = NULL;
1231     TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
1232 
1233     TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_event_post_to(loop, ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, NULL, 0, portMAX_DELAY));
1234     TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_event_post_to(loop, s_test_base1, ESP_EVENT_ANY_ID, NULL, 0, portMAX_DELAY));
1235     TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_event_post_to(loop, ESP_EVENT_ANY_BASE, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
1236 
1237     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
1238 
1239     TEST_ASSERT_EQUAL(0, count);
1240 
1241     TEST_ESP_OK(esp_event_loop_delete(loop));
1242 
1243     vSemaphoreDelete(arg.mutex);
1244 
1245     TEST_TEARDOWN();
1246 }
1247 
1248 TEST_CASE("can post and run events", "[event]")
1249 {
1250     /* this test aims to verify that:
1251      *  - multiple tasks can post to the queue simultaneously
1252      *  - handlers recieve the appropriate handler arg and associated event data */
1253 
1254     TEST_SETUP();
1255 
1256     esp_event_loop_handle_t loop;
1257 
1258     esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
1259 
1260     loop_args.task_name = NULL;
1261     loop_args.queue_size = TEST_CONFIG_TASKS_TO_SPAWN * TEST_CONFIG_ITEMS_TO_REGISTER;
1262     TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
1263 
1264     int count = 0;
1265 
1266     simple_arg_t arg = {
1267         .data = &count,
1268         .mutex = xSemaphoreCreateMutex()
1269     };
1270 
1271     TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg));
1272 
1273     post_event_data_t* post_event_data = calloc(TEST_CONFIG_TASKS_TO_SPAWN, sizeof(*post_event_data));
1274     task_arg_t* post_event_arg = calloc(TEST_CONFIG_TASKS_TO_SPAWN, sizeof(*post_event_arg));
1275 
1276     for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++)
1277     {
1278         post_event_data[i].base = s_test_base1;
1279         post_event_data[i].id = TEST_EVENT_BASE1_EV1;
1280         post_event_data[i].loop = loop;
1281         post_event_data[i].num = TEST_CONFIG_ITEMS_TO_REGISTER;
1282 
1283         post_event_arg[i].data = &post_event_data[i];
1284         post_event_arg[i].start = xSemaphoreCreateBinary();
1285         post_event_arg[i].done = xSemaphoreCreateBinary();
1286 
1287         xTaskCreatePinnedToCore(test_event_post_task, "post", 2048, &post_event_arg[i], s_test_priority, NULL, test_event_get_core());
1288     }
1289 
1290     for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) {
1291         xSemaphoreGive(post_event_arg[i].start);
1292     }
1293 
1294     // Execute some events as they are posted
1295     for (int i = 0; i < (TEST_CONFIG_TASKS_TO_SPAWN * TEST_CONFIG_ITEMS_TO_REGISTER) / 2; i++) {
1296         TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
1297     }
1298 
1299     for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) {
1300         xSemaphoreTake(post_event_arg[i].done, portMAX_DELAY);
1301     }
1302 
1303     // Execute the rest
1304     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
1305 
1306     TEST_ASSERT_EQUAL(TEST_CONFIG_TASKS_TO_SPAWN * TEST_CONFIG_ITEMS_TO_REGISTER, count);
1307 
1308     // Cleanup
1309     for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) {
1310         vSemaphoreDelete(post_event_arg[i].start);
1311         vSemaphoreDelete(post_event_arg[i].done);
1312     }
1313 
1314     free(post_event_data);
1315     free(post_event_arg);
1316 
1317     TEST_ESP_OK(esp_event_loop_delete(loop));
1318 
1319     vSemaphoreDelete(arg.mutex);
1320 
1321     TEST_TEARDOWN();
1322 }
1323 
1324 TEST_CASE("can post and run events with instances", "[event]")
1325 {
1326     /* this test aims to verify that:
1327      *  - multiple tasks can post to the queue simultaneously
1328      *  - handlers recieve the appropriate handler arg and associated event data */
1329 
1330     TEST_SETUP();
1331 
1332     esp_event_loop_handle_t loop;
1333 
1334     esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
1335 
1336     loop_args.task_name = NULL;
1337     loop_args.queue_size = TEST_CONFIG_TASKS_TO_SPAWN * TEST_CONFIG_ITEMS_TO_REGISTER;
1338     TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
1339 
1340     int count = 0;
1341 
1342     simple_arg_t arg = {
1343         .data = &count,
1344         .mutex = xSemaphoreCreateMutex()
1345     };
1346 
1347     esp_event_handler_instance_t ctx;
1348 
1349     TEST_ESP_OK(esp_event_handler_instance_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg, &ctx));
1350 
1351     post_event_data_t* post_event_data = calloc(TEST_CONFIG_TASKS_TO_SPAWN, sizeof(*post_event_data));
1352     task_arg_t* post_event_arg = calloc(TEST_CONFIG_TASKS_TO_SPAWN, sizeof(*post_event_arg));
1353 
1354     for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++)
1355     {
1356         post_event_data[i].base = s_test_base1;
1357         post_event_data[i].id = TEST_EVENT_BASE1_EV1;
1358         post_event_data[i].loop = loop;
1359         post_event_data[i].num = TEST_CONFIG_ITEMS_TO_REGISTER;
1360 
1361         post_event_arg[i].data = &post_event_data[i];
1362         post_event_arg[i].start = xSemaphoreCreateBinary();
1363         post_event_arg[i].done = xSemaphoreCreateBinary();
1364 
1365         xTaskCreatePinnedToCore(test_event_post_task, "post", 2048, &post_event_arg[i], s_test_priority, NULL, test_event_get_core());
1366     }
1367 
1368     for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) {
1369         xSemaphoreGive(post_event_arg[i].start);
1370     }
1371 
1372     // Execute some events as they are posted
1373     for (int i = 0; i < (TEST_CONFIG_TASKS_TO_SPAWN * TEST_CONFIG_ITEMS_TO_REGISTER) / 2; i++) {
1374         TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
1375     }
1376 
1377     for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) {
1378         xSemaphoreTake(post_event_arg[i].done, portMAX_DELAY);
1379     }
1380 
1381     // Execute the rest
1382     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
1383 
1384     TEST_ASSERT_EQUAL(TEST_CONFIG_TASKS_TO_SPAWN * TEST_CONFIG_ITEMS_TO_REGISTER, count);
1385 
1386     // Cleanup
1387     for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) {
1388         vSemaphoreDelete(post_event_arg[i].start);
1389         vSemaphoreDelete(post_event_arg[i].done);
1390     }
1391 
1392     free(post_event_data);
1393     free(post_event_arg);
1394 
1395     TEST_ESP_OK(esp_event_loop_delete(loop));
1396 
1397     vSemaphoreDelete(arg.mutex);
1398 
1399     TEST_TEARDOWN();
1400 }
1401 
loop_run_task(void * args)1402 static void loop_run_task(void* args)
1403 {
1404     esp_event_loop_handle_t event_loop = (esp_event_loop_handle_t) args;
1405 
1406     while(1) {
1407         esp_event_loop_run(event_loop, portMAX_DELAY);
1408     }
1409 }
1410 
performance_test(bool dedicated_task)1411 static void performance_test(bool dedicated_task)
1412 {
1413     // rand() seems to do a one-time allocation. Call it here so that the memory it allocates
1414     // is not counted as a leak.
1415     unsigned int _rand __attribute__((unused)) = rand();
1416 
1417     TEST_SETUP();
1418 
1419     const char test_base[] = "qwertyuiopasdfghjklzxvbnmmnbvcxz";
1420 
1421     #define TEST_CONFIG_BASES  (sizeof(test_base) - 1)
1422     #define TEST_CONFIG_IDS    (TEST_CONFIG_BASES / 2)
1423 
1424     // Create loop
1425     esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
1426     esp_event_loop_handle_t loop;
1427 
1428     if (!dedicated_task) {
1429         loop_args.task_name = NULL;
1430     }
1431 
1432     TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
1433 
1434     performance_data_t data;
1435 
1436     // Register the handlers
1437     for (int base = 0; base < TEST_CONFIG_BASES; base++) {
1438         for (int id = 0; id < TEST_CONFIG_IDS; id++) {
1439             TEST_ESP_OK(esp_event_handler_register_with(loop, test_base + base, id, test_event_performance_handler, &data));
1440         }
1441     }
1442 
1443     TaskHandle_t mtask = NULL;
1444 
1445     if (!dedicated_task) {
1446         xTaskCreate(loop_run_task, "loop_run", loop_args.task_stack_size, (void*) loop, loop_args.task_priority, &mtask);
1447     }
1448 
1449     // Perform performance test
1450     float running_sum = 0;
1451     float running_count = 0;
1452 
1453     for (int bases = 1; bases <= TEST_CONFIG_BASES; bases *= 2) {
1454         for (int ids = 1; ids <= TEST_CONFIG_IDS; ids *= 2) {
1455 
1456             data.performed = 0;
1457             data.expected = bases * ids;
1458             data.done = xSemaphoreCreateBinary();
1459 
1460             // Generate randomized list of posts
1461             int post_bases[TEST_CONFIG_BASES];
1462             int post_ids[TEST_CONFIG_IDS];
1463 
1464             for (int i = 0; i < bases; i++) {
1465                 post_bases[i] = i;
1466             }
1467 
1468             for (int i = 0; i < ids; i++) {
1469                 post_ids[i] = i;
1470             }
1471 
1472             for (int i = 0; i < bases; i++) {
1473                 int rand_a  = rand() % bases;
1474                 int rand_b  = rand() % bases;
1475 
1476                 int temp = post_bases[rand_a];
1477                 post_bases[rand_a]= post_bases[rand_b];
1478                 post_bases[rand_b] = temp;
1479             }
1480 
1481             for (int i = 0; i < ids; i++) {
1482                 int rand_a  = rand() % ids;
1483                 int rand_b  = rand() % ids;
1484 
1485                 int temp = post_ids[rand_a];
1486                 post_ids[rand_a]= post_ids[rand_b];
1487                 post_ids[rand_b] = temp;
1488             }
1489 
1490             // Post the events
1491             int64_t start = esp_timer_get_time();
1492             for (int base = 0; base < bases; base++) {
1493                 for (int id = 0; id < ids; id++) {
1494                     TEST_ESP_OK(esp_event_post_to(loop, test_base + post_bases[base], post_ids[id], NULL, 0, portMAX_DELAY));
1495                 }
1496             }
1497 
1498             xSemaphoreTake(data.done, portMAX_DELAY);
1499             int64_t elapsed = esp_timer_get_time() - start;
1500 
1501             // Record data
1502             TEST_ASSERT_EQUAL(data.expected, data.performed);
1503 
1504             running_count++;
1505             running_sum += data.performed / (elapsed / (1000000.0));
1506 
1507             vSemaphoreDelete(data.done);
1508         }
1509     }
1510 
1511     int average = (int) (running_sum / (running_count));
1512 
1513     if (!dedicated_task) {
1514         ((esp_event_loop_instance_t*) loop)->task = mtask;
1515     }
1516 
1517     TEST_ESP_OK(esp_event_loop_delete(loop));
1518 
1519     TEST_TEARDOWN();
1520 
1521 #ifdef CONFIG_ESP_EVENT_LOOP_PROFILING
1522     ESP_LOGI(TAG, "events dispatched/second with profiling enabled: %d", average);
1523     // Enabling profiling will slow down event dispatch, so the set threshold
1524     // is not valid when it is enabled.
1525 #else
1526 #ifndef CONFIG_SPIRAM
1527     TEST_PERFORMANCE_GREATER_THAN(EVENT_DISPATCH, "%d", average);
1528 #else
1529     TEST_PERFORMANCE_GREATER_THAN(EVENT_DISPATCH_PSRAM, "%d", average);
1530 #endif // CONFIG_SPIRAM
1531 #endif // CONFIG_ESP_EVENT_LOOP_PROFILING
1532 }
1533 
1534 TEST_CASE("performance test - dedicated task", "[event]")
1535 {
1536     performance_test(true);
1537 }
1538 
1539 TEST_CASE("performance test - no dedicated task", "[event]")
1540 {
1541     performance_test(false);
1542 }
1543 
1544 TEST_CASE("can post to loop from handler - dedicated task", "[event]")
1545 {
1546     TEST_SETUP();
1547 
1548     esp_event_loop_handle_t loop_w_task;
1549 
1550     esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
1551 
1552     int count;
1553 
1554     simple_arg_t arg = {
1555         .data = &count,
1556         .mutex = xSemaphoreCreateBinary()
1557     };
1558 
1559     TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop_w_task));
1560 
1561     count = 0;
1562 
1563     // Test that a handler can post to a different loop while there is still slots on the queue
1564     TEST_ESP_OK(esp_event_handler_register_with(loop_w_task, s_test_base1, TEST_EVENT_BASE1_EV1, test_handler_post_w_task, &arg));
1565     TEST_ESP_OK(esp_event_handler_register_with(loop_w_task, s_test_base1, TEST_EVENT_BASE1_EV2, test_handler_post_w_task, &arg));
1566 
1567     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));
1568 
1569     xSemaphoreTake(arg.mutex, portMAX_DELAY);
1570 
1571     TEST_ASSERT_EQUAL(2, count);
1572 
1573     // Test that other tasks can still post while  there is still slots in the queue, while handler is executing
1574     count = 100;
1575 
1576     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));
1577 
1578     for (int i = 0; i < loop_args.queue_size; i++) {
1579         TEST_ESP_OK(esp_event_post_to(loop_w_task, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
1580     }
1581 
1582     TEST_ASSERT_EQUAL(ESP_ERR_TIMEOUT, esp_event_post_to(loop_w_task, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0,
1583                          pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER)));
1584 
1585     xSemaphoreGive(arg.mutex);
1586 
1587     vTaskDelay(pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER));
1588 
1589     TEST_ESP_OK(esp_event_loop_delete(loop_w_task));
1590 
1591     vSemaphoreDelete(arg.mutex);
1592 
1593     TEST_TEARDOWN();
1594 }
1595 
1596 TEST_CASE("can post to loop from handler instance - dedicated task", "[event]")
1597 {
1598     TEST_SETUP();
1599 
1600     esp_event_loop_handle_t loop_w_task;
1601 
1602     esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
1603 
1604     int count;
1605 
1606     simple_arg_t arg = {
1607         .data = &count,
1608         .mutex = xSemaphoreCreateBinary()
1609     };
1610 
1611     TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop_w_task));
1612 
1613     count = 0;
1614 
1615     esp_event_handler_instance_t ctx_1;
1616     esp_event_handler_instance_t ctx_2;
1617 
1618     // Test that a handler can post to a different loop while there is still slots on the queue
1619     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));
1620     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));
1621 
1622     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));
1623 
1624     xSemaphoreTake(arg.mutex, portMAX_DELAY);
1625 
1626     TEST_ASSERT_EQUAL(2, count);
1627 
1628     // Test that other tasks can still post while  there is still slots in the queue, while handler is executing
1629     count = 100;
1630 
1631     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));
1632 
1633     for (int i = 0; i < loop_args.queue_size; i++) {
1634         TEST_ESP_OK(esp_event_post_to(loop_w_task, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
1635     }
1636 
1637     TEST_ASSERT_EQUAL(ESP_ERR_TIMEOUT, esp_event_post_to(loop_w_task, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0,
1638                          pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER)));
1639 
1640     xSemaphoreGive(arg.mutex);
1641 
1642     vTaskDelay(pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER));
1643 
1644     TEST_ESP_OK(esp_event_loop_delete(loop_w_task));
1645 
1646     vSemaphoreDelete(arg.mutex);
1647 
1648     TEST_TEARDOWN();
1649 }
1650 
1651 TEST_CASE("can post to loop from handler - no dedicated task", "[event]")
1652 {
1653     TEST_SETUP();
1654 
1655     esp_event_loop_handle_t loop_wo_task;
1656 
1657     esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
1658 
1659     int count;
1660 
1661     simple_arg_t arg = {
1662         .data = &count,
1663         .mutex = xSemaphoreCreateBinary()
1664     };
1665 
1666     count = 0;
1667 
1668     loop_args.queue_size = 1;
1669     loop_args.task_name = NULL;
1670     TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop_wo_task));
1671 
1672     TaskHandle_t mtask;
1673 
1674     xTaskCreate(test_post_from_handler_loop_task, "task", 2584, (void*) loop_wo_task, s_test_priority, &mtask);
1675 
1676     // Test that a handler can post to a different loop while there is still slots on the queue
1677     TEST_ESP_OK(esp_event_handler_register_with(loop_wo_task, s_test_base1, TEST_EVENT_BASE1_EV1, test_handler_post_wo_task, &arg));
1678     TEST_ESP_OK(esp_event_handler_register_with(loop_wo_task, s_test_base1, TEST_EVENT_BASE1_EV2, test_handler_post_wo_task, &arg));
1679 
1680     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));
1681 
1682     xSemaphoreTake(arg.mutex, portMAX_DELAY);
1683 
1684     TEST_ASSERT_EQUAL(2, count);
1685 
1686     count = 100;
1687 
1688     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));
1689 
1690     vTaskDelay(pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER));
1691 
1692     // For loop without tasks, posting is more restrictive. Posting should wait until execution of handler finishes
1693     TEST_ASSERT_EQUAL(ESP_ERR_TIMEOUT, esp_event_post_to(loop_wo_task, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0,
1694                          pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER)));
1695 
1696     xSemaphoreGive(arg.mutex);
1697 
1698     vTaskDelay(pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER));
1699 
1700     vTaskDelete(mtask);
1701 
1702     TEST_ESP_OK(esp_event_loop_delete(loop_wo_task));
1703 
1704     vSemaphoreDelete(arg.mutex);
1705 
1706     TEST_TEARDOWN();
1707 }
1708 
1709 TEST_CASE("can post to loop from handler instance - no dedicated task", "[event]")
1710 {
1711     TEST_SETUP();
1712 
1713     esp_event_loop_handle_t loop_wo_task;
1714 
1715     esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
1716 
1717     int count;
1718 
1719     simple_arg_t arg = {
1720         .data = &count,
1721         .mutex = xSemaphoreCreateBinary()
1722     };
1723 
1724     count = 0;
1725 
1726     esp_event_handler_instance_t ctx_1;
1727     esp_event_handler_instance_t ctx_2;
1728 
1729     loop_args.queue_size = 1;
1730     loop_args.task_name = NULL;
1731     TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop_wo_task));
1732 
1733     TaskHandle_t mtask;
1734 
1735     xTaskCreate(test_post_from_handler_loop_task, "task", 2584, (void*) loop_wo_task, s_test_priority, &mtask);
1736 
1737     // Test that a handler can post to a different loop while there is still slots on the queue
1738     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));
1739     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));
1740 
1741     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));
1742 
1743     xSemaphoreTake(arg.mutex, portMAX_DELAY);
1744 
1745     TEST_ASSERT_EQUAL(2, count);
1746 
1747     count = 100;
1748 
1749     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));
1750 
1751     vTaskDelay(pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER));
1752 
1753     // For loop without tasks, posting is more restrictive. Posting should wait until execution of handler finishes
1754     TEST_ASSERT_EQUAL(ESP_ERR_TIMEOUT, esp_event_post_to(loop_wo_task, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0,
1755                          pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER)));
1756 
1757     xSemaphoreGive(arg.mutex);
1758 
1759     vTaskDelay(pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER));
1760 
1761     vTaskDelete(mtask);
1762 
1763     TEST_ESP_OK(esp_event_loop_delete(loop_wo_task));
1764 
1765     vSemaphoreDelete(arg.mutex);
1766 
1767     TEST_TEARDOWN();
1768 }
1769 
test_event_simple_handler_template(void * handler_arg,esp_event_base_t base,int32_t id,void * event_arg)1770 static void test_event_simple_handler_template(void* handler_arg, esp_event_base_t base, int32_t id, void* event_arg)
1771 {
1772     int* count = (int*) handler_arg;
1773     (*count)++;
1774 }
1775 
test_event_simple_handler_1(void * handler_arg,esp_event_base_t base,int32_t id,void * event_arg)1776 static void test_event_simple_handler_1(void* handler_arg, esp_event_base_t base, int32_t id, void* event_arg)
1777 {
1778     test_event_simple_handler_template(handler_arg, base, id, event_arg);
1779 }
1780 
test_event_simple_handler_3(void * handler_arg,esp_event_base_t base,int32_t id,void * event_arg)1781 static void test_event_simple_handler_3(void* handler_arg, esp_event_base_t base, int32_t id, void* event_arg)
1782 {
1783     test_event_simple_handler_template(handler_arg, base, id, event_arg);
1784 }
1785 
test_event_simple_handler_2(void * handler_arg,esp_event_base_t base,int32_t id,void * event_arg)1786 static void test_event_simple_handler_2(void* handler_arg, esp_event_base_t base, int32_t id, void* event_arg)
1787 {
1788     test_event_simple_handler_template(handler_arg, base, id, event_arg);
1789 }
1790 
test_registration_from_handler_hdlr(void * handler_arg,esp_event_base_t base,int32_t id,void * event_arg)1791 static void test_registration_from_handler_hdlr(void* handler_arg, esp_event_base_t base, int32_t id, void* event_arg)
1792 {
1793     esp_event_loop_handle_t* loop = (esp_event_loop_handle_t*) event_arg;
1794     TEST_ESP_OK(esp_event_handler_register_with(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler_1, handler_arg));
1795     TEST_ESP_OK(esp_event_handler_register_with(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler_2, handler_arg));
1796     TEST_ESP_OK(esp_event_handler_register_with(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler_3, handler_arg));
1797 }
1798 
test_unregistration_from_handler_hdlr(void * handler_arg,esp_event_base_t base,int32_t id,void * event_arg)1799 static void test_unregistration_from_handler_hdlr(void* handler_arg, esp_event_base_t base, int32_t id, void* event_arg)
1800 {
1801     esp_event_loop_handle_t* loop = (esp_event_loop_handle_t*) event_arg;
1802     TEST_ESP_OK(esp_event_handler_unregister_with(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler_1));
1803     TEST_ESP_OK(esp_event_handler_unregister_with(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler_2));
1804     TEST_ESP_OK(esp_event_handler_unregister_with(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler_3));
1805 }
1806 
1807 TEST_CASE("can register from handler", "[event]")
1808 {
1809     TEST_SETUP();
1810 
1811     esp_event_loop_handle_t loop;
1812 
1813     esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
1814 
1815     loop_args.task_name = NULL;
1816     TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
1817 
1818     int count = 0;
1819 
1820     TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_registration_from_handler_hdlr, &count));
1821     TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base2, TEST_EVENT_BASE2_EV1, test_unregistration_from_handler_hdlr, &count));
1822 
1823     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, &loop, sizeof(&loop), portMAX_DELAY));
1824     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
1825 
1826     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
1827     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
1828 
1829     TEST_ASSERT_EQUAL(3, count);
1830 
1831     TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE2_EV1, &loop, sizeof(&loop), portMAX_DELAY));
1832     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
1833 
1834     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
1835     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
1836 
1837     TEST_ASSERT_EQUAL(3, count);
1838 
1839     TEST_ESP_OK(esp_event_loop_delete(loop));
1840 
1841     TEST_TEARDOWN();
1842 }
1843 
test_create_loop_handler(void * handler_args,esp_event_base_t base,int32_t id,void * event_data)1844 static void test_create_loop_handler(void* handler_args, esp_event_base_t base, int32_t id, void* event_data)
1845 {
1846     esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
1847 
1848     if (id == TEST_EVENT_BASE1_EV1) {
1849         TEST_ESP_OK(esp_event_loop_create(&loop_args, (esp_event_loop_handle_t*) handler_args));
1850     } else {
1851         TEST_ESP_OK(esp_event_loop_delete(*((esp_event_loop_handle_t*) handler_args)));
1852     }
1853 }
1854 
1855 TEST_CASE("can create and delete loop from handler", "[event]")
1856 {
1857     TEST_SETUP();
1858 
1859     esp_event_loop_handle_t loop;
1860     esp_event_loop_handle_t test_loop;
1861 
1862     esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
1863 
1864     loop_args.task_name = NULL;
1865     TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
1866 
1867     TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_create_loop_handler, &test_loop));
1868     TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_create_loop_handler, &test_loop));
1869 
1870     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
1871     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
1872 
1873     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY));
1874     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
1875 
1876     TEST_ESP_OK(esp_event_loop_delete(loop));
1877 
1878     TEST_TEARDOWN();
1879 }
1880 
1881 TEST_CASE("events are dispatched in the order they are registered", "[event]")
1882 {
1883     TEST_SETUP();
1884 
1885     esp_event_loop_handle_t loop;
1886     esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
1887 
1888     loop_args.task_name = NULL;
1889     TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
1890 
1891     int id_arr[7];
1892 
1893     for (int i = 0; i < 7; i++) {
1894         id_arr[i] = i;
1895     }
1896 
1897     int data_arr[12] = {0};
1898 
1899     TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base2, TEST_EVENT_BASE2_EV1, test_event_ordered_dispatch, id_arr + 0));
1900     TEST_ESP_OK(esp_event_handler_register_with(loop, ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, test_event_ordered_dispatch, id_arr + 1));
1901     TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base1, ESP_EVENT_ANY_ID, test_event_ordered_dispatch, id_arr + 2));
1902     TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base2, TEST_EVENT_BASE2_EV2, test_event_ordered_dispatch, id_arr + 3));
1903     TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_ordered_dispatch, id_arr + 4));
1904     TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base2, ESP_EVENT_ANY_ID, test_event_ordered_dispatch, id_arr + 5));
1905     TEST_ESP_OK(esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_ordered_dispatch, id_arr + 6));
1906 
1907     esp_event_dump(stdout);
1908 
1909     ordered_data_t data = {
1910         .arr = data_arr,
1911         .index = 0
1912     };
1913 
1914     ordered_data_t* dptr = &data;
1915 
1916     TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV2, &dptr, sizeof(dptr), portMAX_DELAY));
1917     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, &dptr, sizeof(dptr), portMAX_DELAY));
1918     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, &dptr, sizeof(dptr), portMAX_DELAY));
1919     TEST_ESP_OK(esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV1, &dptr, sizeof(dptr), portMAX_DELAY));
1920 
1921     TEST_ESP_OK(esp_event_loop_run(loop, pdMS_TO_TICKS(10)));
1922 
1923     // Expected data executing the posts above
1924     int ref_arr[12] = {1, 3, 5, 1, 2, 4, 1, 2, 6, 0, 1, 5};
1925 
1926     for (int i = 0; i < 12; i++) {
1927         TEST_ASSERT_EQUAL(ref_arr[i], data_arr[i]);
1928     }
1929 
1930     TEST_ESP_OK(esp_event_loop_delete(loop));
1931 
1932     TEST_TEARDOWN();
1933 }
1934 
1935 #if CONFIG_ESP_EVENT_POST_FROM_ISR
1936 TEST_CASE("can properly prepare event data posted to loop", "[event]")
1937 {
1938     TEST_SETUP();
1939 
1940     esp_event_loop_handle_t loop;
1941     esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
1942 
1943     loop_args.task_name = NULL;
1944     TEST_ESP_OK(esp_event_loop_create(&loop_args, &loop));
1945 
1946     esp_event_post_instance_t post;
1947     esp_event_loop_instance_t* loop_def = (esp_event_loop_instance_t*) loop;
1948 
1949     TEST_ESP_OK(esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
1950     TEST_ASSERT_EQUAL(pdTRUE, xQueueReceive(loop_def->queue, &post, portMAX_DELAY));
1951     TEST_ASSERT_EQUAL(false, post.data_set);
1952     TEST_ASSERT_EQUAL(false, post.data_allocated);
1953     TEST_ASSERT_EQUAL(NULL, post.data.ptr);
1954 
1955     int sample = 0;
1956     TEST_ESP_OK(esp_event_isr_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, &sample, sizeof(sample), NULL));
1957     TEST_ASSERT_EQUAL(pdTRUE, xQueueReceive(loop_def->queue, &post, portMAX_DELAY));
1958     TEST_ASSERT_EQUAL(true, post.data_set);
1959     TEST_ASSERT_EQUAL(false, post.data_allocated);
1960     TEST_ASSERT_EQUAL(false, post.data.val);
1961 
1962     TEST_ESP_OK(esp_event_loop_delete(loop));
1963 
1964     TEST_TEARDOWN();
1965 }
1966 
test_handler_post_from_isr(void * event_handler_arg,esp_event_base_t event_base,int32_t event_id,void * event_data)1967 static void test_handler_post_from_isr(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
1968 {
1969     SemaphoreHandle_t *sem = (SemaphoreHandle_t*) event_handler_arg;
1970     // Event data is just the address value (maybe have been truncated due to casting).
1971     int *data = (int*) event_data;
1972     TEST_ASSERT_EQUAL(*data, (int) (*sem));
1973     xSemaphoreGive(*sem);
1974 }
1975 
test_event_on_timer_alarm(void * para)1976 void IRAM_ATTR test_event_on_timer_alarm(void* para)
1977 {
1978     /* Retrieve the interrupt status and the counter value
1979        from the timer that reported the interrupt */
1980     uint64_t timer_counter_value =
1981         timer_group_get_counter_value_in_isr(TIMER_GROUP_0, TIMER_0);
1982     timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_0);
1983     timer_counter_value += (uint64_t) (TIMER_INTERVAL0_SEC * TIMER_SCALE);
1984     timer_group_set_alarm_value_in_isr(TIMER_GROUP_0, TIMER_0, timer_counter_value);
1985 
1986     int data = (int) para;
1987     // Posting events with data more than 4 bytes should fail.
1988     TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_event_isr_post(s_test_base1, TEST_EVENT_BASE1_EV1, &data, 5, NULL));
1989     // This should succeedd, as data is int-sized. The handler for the event checks that the passed event data
1990     // is correct.
1991     BaseType_t task_unblocked;
1992     TEST_ESP_OK(esp_event_isr_post(s_test_base1, TEST_EVENT_BASE1_EV1, &data, sizeof(data), &task_unblocked));
1993     if (task_unblocked == pdTRUE) {
1994         portYIELD_FROM_ISR();
1995     }
1996 }
1997 
1998 TEST_CASE("can post events from interrupt handler", "[event]")
1999 {
2000     SemaphoreHandle_t sem = xSemaphoreCreateBinary();
2001 
2002     /* Select and initialize basic parameters of the timer */
2003     timer_config_t config;
2004     config.divider = TIMER_DIVIDER;
2005     config.counter_dir = TIMER_COUNT_UP;
2006     config.counter_en = TIMER_PAUSE;
2007     config.alarm_en = TIMER_ALARM_EN;
2008     config.intr_type = TIMER_INTR_LEVEL;
2009     config.auto_reload = false;
2010     timer_init(TIMER_GROUP_0, TIMER_0, &config);
2011 
2012     /* Timer's counter will initially start from value below.
2013        Also, if auto_reload is set, this value will be automatically reload on alarm */
2014     timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0x00000000ULL);
2015 
2016     /* Configure the alarm value and the interrupt on alarm. */
2017     timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, TIMER_INTERVAL0_SEC * TIMER_SCALE);
2018     timer_enable_intr(TIMER_GROUP_0, TIMER_0);
2019     timer_isr_register(TIMER_GROUP_0, TIMER_0, test_event_on_timer_alarm,
2020         (void *) sem, ESP_INTR_FLAG_IRAM, NULL);
2021 
2022     timer_start(TIMER_GROUP_0, TIMER_0);
2023 
2024     TEST_SETUP();
2025 
2026     TEST_ESP_OK(esp_event_handler_register(s_test_base1, TEST_EVENT_BASE1_EV1,
2027                                                         test_handler_post_from_isr, &sem));
2028 
2029     xSemaphoreTake(sem, portMAX_DELAY);
2030 
2031     TEST_TEARDOWN();
2032 }
2033 
2034 #endif // CONFIG_ESP_EVENT_POST_FROM_ISR
2035