UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2024 Olaf Wintermann. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "event.h" 30 31 #include "../daemon/event.h" 32 33 typedef struct EVTest { 34 EventHandler *h; 35 pthread_mutex_t mutex; 36 pthread_cond_t cond; 37 void *data1; 38 void *data2; 39 int i1; 40 int i2; 41 } EVTest; 42 43 UCX_TEST(test_evhandler_create) { 44 EventHandlerConfig cfg1 = { .nthreads = 1}; 45 46 EventHandlerConfig cfg4 = { .nthreads = 4}; 47 48 UCX_TEST_BEGIN; 49 50 EVHandler *ev1 = evhandler_create(&cfg1); 51 UCX_TEST_ASSERT(ev1, "evhandler_create (1) failed"); 52 UCX_TEST_ASSERT(ev1->numins == 1, "ev1 wrong number of instances"); 53 54 EVHandler *ev2 = evhandler_create(&cfg4); 55 UCX_TEST_ASSERT(ev2, "evhandler_create (2) failed"); 56 UCX_TEST_ASSERT(ev2->numins == 4, "ev2 wrong number of instances"); 57 58 59 evhandler_shutdown(ev1); 60 evhandler_shutdown(ev2); 61 62 evhandler_wait_and_destroy(ev1); 63 evhandler_wait_and_destroy(ev2); 64 65 UCX_TEST_END; 66 } 67 68 static int test_event_send_fn(EventHandler *h, Event *event) { 69 EVTest *test = event->cookie; 70 test->i1 = 1; 71 test->i2 = h == test->h; 72 73 pthread_mutex_lock(&test->mutex); 74 pthread_cond_signal(&test->cond); 75 pthread_mutex_unlock(&test->mutex); 76 77 return 0; 78 } 79 80 static void testdata_wait_for_completion(EVTest *testdata) { 81 time_t tstart = time(NULL); 82 while(!testdata->i1) { 83 time_t t = time(NULL); 84 if(t - tstart > 10) { 85 break; 86 } 87 88 pthread_mutex_lock(&testdata->mutex); 89 pthread_cond_wait(&testdata->cond, &testdata->mutex); 90 pthread_mutex_unlock(&testdata->mutex); 91 } 92 } 93 94 UCX_TEST(test_event_send) { 95 EventHandlerConfig cfg = { .nthreads = 1}; 96 97 EVHandler *ev = evhandler_create(&cfg); 98 EventHandler *h = ev_instance(ev); 99 100 EVTest testdata; 101 ZERO(&testdata, sizeof(EVTest)); 102 testdata.h = h; 103 pthread_mutex_init(&testdata.mutex, NULL); 104 pthread_cond_init(&testdata.cond, NULL); 105 106 UCX_TEST_BEGIN; 107 108 // test sending a single event 109 // the event signals completion in the testdata object 110 // wait up to 10 seconds for completion (it should be instantly) 111 112 Event evt; 113 ZERO(&evt, sizeof(Event)); 114 evt.fn = test_event_send_fn; 115 evt.cookie = &testdata; 116 117 int ret = event_send(h, &evt); 118 119 // wait for event finish 120 testdata_wait_for_completion(&testdata); 121 122 UCX_TEST_ASSERT(!ret, "event_send failed"); 123 UCX_TEST_ASSERT(testdata.i1, "event callback not called"); 124 UCX_TEST_ASSERT(testdata.i2, "event callback received wrong event handler pointer"); 125 126 UCX_TEST_END; 127 128 pthread_mutex_destroy(&testdata.mutex); 129 pthread_cond_destroy(&testdata.cond); 130 131 evhandler_shutdown(ev); 132 evhandler_wait_and_destroy(ev); 133 } 134 135 #define EV_TEST_NUM_EVENTS 2000 136 137 static int test_event_send_multi_fn_count(EventHandler *h, Event *event) { 138 EVTest *test = event->cookie; 139 140 test->i2++; 141 142 return 0; 143 } 144 145 static int test_event_send_multi_fn_end(EventHandler *h, Event *event) { 146 EVTest *test = event->cookie; 147 test->i1 = 1; 148 149 pthread_mutex_lock(&test->mutex); 150 pthread_cond_signal(&test->cond); 151 pthread_mutex_unlock(&test->mutex); 152 153 return 0; 154 } 155 156 static int test_event_send_multi_fn1(EventHandler *h, Event *event) { 157 EVTest *test = event->cookie; 158 test->i2 = 0; 159 160 for(int i=0;i<EV_TEST_NUM_EVENTS;i++) { 161 Event *newevent = malloc(sizeof(Event)); 162 ZERO(newevent, sizeof(Event)); 163 newevent->fn = test_event_send_multi_fn_count; 164 newevent->finish = ev_free_event; 165 newevent->cookie = test; 166 event_send(h, newevent); 167 } 168 169 Event *finish_event = malloc(sizeof(Event)); 170 ZERO(finish_event, sizeof(Event)); 171 finish_event->fn = test_event_send_multi_fn_end; 172 finish_event->finish = ev_free_event; 173 finish_event->cookie = test; 174 event_send(h, finish_event); 175 176 return 0; 177 } 178 179 UCX_TEST(test_event_send_multi) { 180 EventHandlerConfig cfg = { .nthreads = 1}; 181 182 EVHandler *ev = evhandler_create(&cfg); 183 EventHandler *h = ev_instance(ev); 184 185 EVTest testdata; 186 ZERO(&testdata, sizeof(EVTest)); 187 testdata.h = h; 188 pthread_mutex_init(&testdata.mutex, NULL); 189 pthread_cond_init(&testdata.cond, NULL); 190 191 UCX_TEST_BEGIN; 192 193 // test sending multiple events 194 // the first callback test_event_send_multi_fn1 adds additional 195 // EV_TEST_NUM_EVENTS events to the handler + an additional 196 // finishing event, that notifies completion 197 198 Event evt; 199 ZERO(&evt, sizeof(Event)); 200 evt.fn = test_event_send_multi_fn1; 201 evt.cookie = &testdata; 202 203 int ret = event_send(h, &evt); 204 205 // wait for event finish 206 testdata_wait_for_completion(&testdata); 207 208 UCX_TEST_ASSERT(!ret, "event_send failed"); 209 UCX_TEST_ASSERT(testdata.i1, "event callback not called"); 210 UCX_TEST_ASSERT(testdata.i2 == EV_TEST_NUM_EVENTS, "event callback received wrong event handler pointer"); 211 212 UCX_TEST_END; 213 214 pthread_mutex_destroy(&testdata.mutex); 215 pthread_cond_destroy(&testdata.cond); 216 217 evhandler_shutdown(ev); 218 evhandler_wait_and_destroy(ev); 219 } 220