--- a/src/server/test/event.c Fri Aug 16 16:59:05 2024 +0200 +++ b/src/server/test/event.c Fri Aug 16 18:09:05 2024 +0200 @@ -55,8 +55,12 @@ UCX_TEST_ASSERT(ev2, "evhandler_create (2) failed"); UCX_TEST_ASSERT(ev2->numins == 4, "ev2 wrong number of instances"); - evhandler_close(ev1); - evhandler_close(ev2); + + evhandler_shutdown(ev1); + evhandler_shutdown(ev2); + + evhandler_wait_and_destroy(ev1); + evhandler_wait_and_destroy(ev2); UCX_TEST_END; } @@ -73,6 +77,20 @@ return 0; } +static void testdata_wait_for_completion(EVTest *testdata) { + time_t tstart = time(NULL); + while(!testdata->i1) { + time_t t = time(NULL); + if(t - tstart > 10) { + break; + } + + pthread_mutex_lock(&testdata->mutex); + pthread_cond_wait(&testdata->cond, &testdata->mutex); + pthread_mutex_unlock(&testdata->mutex); + } +} + UCX_TEST(test_event_send) { EventHandlerConfig cfg = { .nthreads = 1}; @@ -87,6 +105,10 @@ UCX_TEST_BEGIN; + // test sending a single event + // the event signals completion in the testdata object + // wait up to 10 seconds for completion (it should be instantly) + Event evt; ZERO(&evt, sizeof(Event)); evt.fn = test_event_send_fn; @@ -95,17 +117,7 @@ int ret = event_send(h, &evt); // wait for event finish - time_t tstart = time(NULL); - while(!testdata.i1) { - time_t t = time(NULL); - if(t - tstart > 10) { - break; - } - - pthread_mutex_lock(&testdata.mutex); - pthread_cond_wait(&testdata.cond, &testdata.mutex); - pthread_mutex_unlock(&testdata.mutex); - } + testdata_wait_for_completion(&testdata); UCX_TEST_ASSERT(!ret, "event_send failed"); UCX_TEST_ASSERT(testdata.i1, "event callback not called"); @@ -116,5 +128,92 @@ pthread_mutex_destroy(&testdata.mutex); pthread_cond_destroy(&testdata.cond); - evhandler_close(ev); + evhandler_shutdown(ev); + evhandler_wait_and_destroy(ev); +} + +#define EV_TEST_NUM_EVENTS 2000 + +static int test_event_send_multi_fn_count(EventHandler *h, Event *event) { + EVTest *test = event->cookie; + + test->i2++; + + return 0; +} + +static int test_event_send_multi_fn_end(EventHandler *h, Event *event) { + EVTest *test = event->cookie; + test->i1 = 1; + + pthread_mutex_lock(&test->mutex); + pthread_cond_signal(&test->cond); + pthread_mutex_unlock(&test->mutex); + + return 0; } + +static int test_event_send_multi_fn1(EventHandler *h, Event *event) { + EVTest *test = event->cookie; + test->i2 = 0; + + for(int i=0;i<EV_TEST_NUM_EVENTS;i++) { + Event *newevent = malloc(sizeof(Event)); + ZERO(newevent, sizeof(Event)); + newevent->fn = test_event_send_multi_fn_count; + newevent->finish = ev_free_event; + newevent->cookie = test; + event_send(h, newevent); + } + + Event *finish_event = malloc(sizeof(Event)); + ZERO(finish_event, sizeof(Event)); + finish_event->fn = test_event_send_multi_fn_end; + finish_event->finish = ev_free_event; + finish_event->cookie = test; + event_send(h, finish_event); + + return 0; +} + +UCX_TEST(test_event_send_multi) { + EventHandlerConfig cfg = { .nthreads = 1}; + + EVHandler *ev = evhandler_create(&cfg); + EventHandler *h = ev_instance(ev); + + EVTest testdata; + ZERO(&testdata, sizeof(EVTest)); + testdata.h = h; + pthread_mutex_init(&testdata.mutex, NULL); + pthread_cond_init(&testdata.cond, NULL); + + UCX_TEST_BEGIN; + + // test sending multiple events + // the first callback test_event_send_multi_fn1 adds additional + // EV_TEST_NUM_EVENTS events to the handler + an additional + // finishing event, that notifies completion + + Event evt; + ZERO(&evt, sizeof(Event)); + evt.fn = test_event_send_multi_fn1; + evt.cookie = &testdata; + + int ret = event_send(h, &evt); + + // wait for event finish + testdata_wait_for_completion(&testdata); + + UCX_TEST_ASSERT(!ret, "event_send failed"); + UCX_TEST_ASSERT(testdata.i1, "event callback not called"); + UCX_TEST_ASSERT(testdata.i2 == EV_TEST_NUM_EVENTS, "event callback received wrong event handler pointer"); + + UCX_TEST_END; + + pthread_mutex_destroy(&testdata.mutex); + pthread_cond_destroy(&testdata.cond); + + evhandler_shutdown(ev); + evhandler_wait_and_destroy(ev); +}