1 /* 2 * Copyright (c) 2013 Niels Provos and Nick Mathewson 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 3. The name of the author may not be used to endorse or promote products 13 * derived from this software without specific prior written permission. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include "event2/event-config.h" 28 #include "evconfig-private.h" 29 #include "tinytest.h" 30 #include "tinytest_macros.h" 31 #include <stdlib.h> 32 33 #include "event2/event.h" 34 #include "event2/util.h" 35 #include "event-internal.h" 36 #include "defer-internal.h" 37 38 #include "regress.h" 39 #include "regress_thread.h" 40 41 static void 42 timer_callback(evutil_socket_t fd, short what, void *arg) 43 { 44 int *int_arg = arg; 45 *int_arg += 1; 46 (void)fd; 47 (void)what; 48 } 49 static void 50 simple_callback(struct event_callback *evcb, void *arg) 51 { 52 int *int_arg = arg; 53 *int_arg += 1; 54 (void)evcb; 55 } 56 static void 57 event_finalize_callback_1(struct event *ev, void *arg) 58 { 59 int *int_arg = arg; 60 *int_arg += 100; 61 (void)ev; 62 } 63 static void 64 callback_finalize_callback_1(struct event_callback *evcb, void *arg) 65 { 66 int *int_arg = arg; 67 *int_arg += 100; 68 (void)evcb; 69 } 70 71 72 static void 73 test_fin_cb_invoked(void *arg) 74 { 75 struct basic_test_data *data = arg; 76 struct event_base *base = data->base; 77 78 struct event *ev; 79 struct event ev2; 80 struct event_callback evcb; 81 int cb_called = 0; 82 int ev_called = 0; 83 84 const struct timeval ten_sec = {10,0}; 85 86 event_deferred_cb_init_(&evcb, 0, simple_callback, &cb_called); 87 ev = evtimer_new(base, timer_callback, &ev_called); 88 /* Just finalize them; don't bother adding. */ 89 event_free_finalize(0, ev, event_finalize_callback_1); 90 event_callback_finalize_(base, 0, &evcb, callback_finalize_callback_1); 91 92 event_base_dispatch(base); 93 94 tt_int_op(cb_called, ==, 100); 95 tt_int_op(ev_called, ==, 100); 96 97 ev_called = cb_called = 0; 98 event_base_assert_ok_(base); 99 100 /* Now try it when they're active. (actually, don't finalize: make 101 * sure activation can happen! */ 102 ev = evtimer_new(base, timer_callback, &ev_called); 103 event_deferred_cb_init_(&evcb, 0, simple_callback, &cb_called); 104 105 event_active(ev, EV_TIMEOUT, 1); 106 event_callback_activate_(base, &evcb); 107 108 event_base_dispatch(base); 109 tt_int_op(cb_called, ==, 1); 110 tt_int_op(ev_called, ==, 1); 111 112 ev_called = cb_called = 0; 113 event_base_assert_ok_(base); 114 115 /* Great, it worked. Now activate and finalize and make sure only 116 * finalizing happens. */ 117 event_active(ev, EV_TIMEOUT, 1); 118 event_callback_activate_(base, &evcb); 119 event_free_finalize(0, ev, event_finalize_callback_1); 120 event_callback_finalize_(base, 0, &evcb, callback_finalize_callback_1); 121 122 event_base_dispatch(base); 123 tt_int_op(cb_called, ==, 100); 124 tt_int_op(ev_called, ==, 100); 125 126 ev_called = 0; 127 128 event_base_assert_ok_(base); 129 130 /* Okay, now add but don't have it become active, and make sure *that* 131 * works. */ 132 ev = evtimer_new(base, timer_callback, &ev_called); 133 event_add(ev, &ten_sec); 134 event_free_finalize(0, ev, event_finalize_callback_1); 135 136 event_base_dispatch(base); 137 tt_int_op(ev_called, ==, 100); 138 139 ev_called = 0; 140 event_base_assert_ok_(base); 141 142 /* Now try adding and deleting after finalizing. */ 143 ev = evtimer_new(base, timer_callback, &ev_called); 144 evtimer_assign(&ev2, base, timer_callback, &ev_called); 145 event_add(ev, &ten_sec); 146 event_free_finalize(0, ev, event_finalize_callback_1); 147 event_finalize(0, &ev2, event_finalize_callback_1); 148 149 event_add(&ev2, &ten_sec); 150 event_del(ev); 151 event_active(&ev2, EV_TIMEOUT, 1); 152 153 event_base_dispatch(base); 154 tt_int_op(ev_called, ==, 200); 155 156 event_base_assert_ok_(base); 157 158 end: 159 ; 160 } 161 162 #ifndef EVENT__DISABLE_MM_REPLACEMENT 163 static void * 164 tfff_malloc(size_t n) 165 { 166 return malloc(n); 167 } 168 static void *tfff_p1=NULL, *tfff_p2=NULL; 169 static int tfff_p1_freed=0, tfff_p2_freed=0; 170 static void 171 tfff_free(void *p) 172 { 173 if (! p) 174 return; 175 if (p == tfff_p1) 176 ++tfff_p1_freed; 177 if (p == tfff_p2) 178 ++tfff_p2_freed; 179 free(p); 180 } 181 static void * 182 tfff_realloc(void *p, size_t sz) 183 { 184 return realloc(p,sz); 185 } 186 #endif 187 188 static void 189 test_fin_free_finalize(void *arg) 190 { 191 #ifdef EVENT__DISABLE_MM_REPLACEMENT 192 tinytest_set_test_skipped_(); 193 #else 194 struct event_base *base = NULL; 195 struct event *ev, *ev2; 196 int ev_called = 0; 197 int ev2_called = 0; 198 199 (void)arg; 200 201 event_set_mem_functions(tfff_malloc, tfff_realloc, tfff_free); 202 203 base = event_base_new(); 204 tt_assert(base); 205 206 ev = evtimer_new(base, timer_callback, &ev_called); 207 ev2 = evtimer_new(base, timer_callback, &ev2_called); 208 tfff_p1 = ev; 209 tfff_p2 = ev2; 210 event_free_finalize(0, ev, event_finalize_callback_1); 211 event_finalize(0, ev2, event_finalize_callback_1); 212 213 event_base_dispatch(base); 214 215 tt_int_op(ev_called, ==, 100); 216 tt_int_op(ev2_called, ==, 100); 217 218 event_base_assert_ok_(base); 219 tt_int_op(tfff_p1_freed, ==, 1); 220 tt_int_op(tfff_p2_freed, ==, 0); 221 222 event_free(ev2); 223 224 end: 225 if (base) 226 event_base_free(base); 227 #endif 228 } 229 230 /* For test_fin_within_cb */ 231 struct event_and_count { 232 struct event *ev; 233 struct event *ev2; 234 int count; 235 }; 236 static void 237 event_finalize_callback_2(struct event *ev, void *arg) 238 { 239 struct event_and_count *evc = arg; 240 evc->count += 100; 241 event_free(ev); 242 } 243 static void 244 timer_callback_2(evutil_socket_t fd, short what, void *arg) 245 { 246 struct event_and_count *evc = arg; 247 event_finalize(0, evc->ev, event_finalize_callback_2); 248 event_finalize(0, evc->ev2, event_finalize_callback_2); 249 ++ evc->count; 250 (void)fd; 251 (void)what; 252 } 253 254 static void 255 test_fin_within_cb(void *arg) 256 { 257 struct basic_test_data *data = arg; 258 struct event_base *base = data->base; 259 260 struct event_and_count evc1, evc2; 261 evc1.count = evc2.count = 0; 262 evc2.ev2 = evc1.ev = evtimer_new(base, timer_callback_2, &evc1); 263 evc1.ev2 = evc2.ev = evtimer_new(base, timer_callback_2, &evc2); 264 265 /* Activate both. The first one will have its callback run, which 266 * will finalize both of them, preventing the second one's callback 267 * from running. */ 268 event_active(evc1.ev, EV_TIMEOUT, 1); 269 event_active(evc2.ev, EV_TIMEOUT, 1); 270 271 event_base_dispatch(base); 272 tt_int_op(evc1.count, ==, 101); 273 tt_int_op(evc2.count, ==, 100); 274 275 event_base_assert_ok_(base); 276 /* Now try with EV_PERSIST events. */ 277 evc1.count = evc2.count = 0; 278 evc2.ev2 = evc1.ev = event_new(base, -1, EV_PERSIST, timer_callback_2, &evc1); 279 evc1.ev2 = evc2.ev = event_new(base, -1, EV_PERSIST, timer_callback_2, &evc2); 280 281 event_active(evc1.ev, EV_TIMEOUT, 1); 282 event_active(evc2.ev, EV_TIMEOUT, 1); 283 284 event_base_dispatch(base); 285 tt_int_op(evc1.count, ==, 101); 286 tt_int_op(evc2.count, ==, 100); 287 288 event_base_assert_ok_(base); 289 end: 290 ; 291 } 292 293 #if 0 294 static void 295 timer_callback_3(evutil_socket_t *fd, short what, void *arg) 296 { 297 (void)fd; 298 (void)what; 299 300 } 301 static void 302 test_fin_many(void *arg) 303 { 304 struct basic_test_data *data = arg; 305 struct event_base *base = data->base; 306 307 struct event *ev1, *ev2; 308 struct event_callback evcb1, evcb2; 309 int ev1_count = 0, ev2_count = 0; 310 int evcb1_count = 0, evcb2_count = 0; 311 struct event_callback *array[4]; 312 313 int n; 314 315 /* First attempt: call finalize_many with no events running */ 316 ev1 = evtimer_new(base, timer_callback, &ev1_count); 317 ev1 = evtimer_new(base, timer_callback, &ev2_count); 318 event_deferred_cb_init_(&evcb1, 0, simple_callback, &evcb1_called); 319 event_deferred_cb_init_(&evcb2, 0, simple_callback, &evcb2_called); 320 array[0] = &ev1->ev_evcallback; 321 array[1] = &ev2->ev_evcallback; 322 array[2] = &evcb1; 323 array[3] = &evcb2; 324 325 326 327 n = event_callback_finalize_many(base, 4, array, 328 callback_finalize_callback_1); 329 330 } 331 #endif 332 333 334 #define TEST(name, flags) \ 335 { #name, test_fin_##name, (flags), &basic_setup, NULL } 336 337 struct testcase_t finalize_testcases[] = { 338 339 TEST(cb_invoked, TT_FORK|TT_NEED_BASE), 340 TEST(free_finalize, TT_FORK), 341 TEST(within_cb, TT_FORK|TT_NEED_BASE), 342 // TEST(many, TT_FORK|TT_NEED_BASE), 343 344 345 END_OF_TESTCASES 346 }; 347 348