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 41static void 42timer_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} 49static void 50simple_callback(struct event_callback *evcb, void *arg) 51{ 52 int *int_arg = arg; 53 *int_arg += 1; 54 (void)evcb; 55} 56static void 57event_finalize_callback_1(struct event *ev, void *arg) 58{ 59 int *int_arg = arg; 60 *int_arg += 100; 61 (void)ev; 62} 63static void 64callback_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 72static void 73test_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 158end: 159 ; 160} 161 162#ifndef EVENT__DISABLE_MM_REPLACEMENT 163static void * 164tfff_malloc(size_t n) 165{ 166 return malloc(n); 167} 168static void *tfff_p1=NULL, *tfff_p2=NULL; 169static int tfff_p1_freed=0, tfff_p2_freed=0; 170static void 171tfff_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} 181static void * 182tfff_realloc(void *p, size_t sz) 183{ 184 return realloc(p,sz); 185} 186#endif 187 188static void 189test_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 224end: 225 if (base) 226 event_base_free(base); 227#endif 228} 229 230/* For test_fin_within_cb */ 231struct event_and_count { 232 struct event *ev; 233 struct event *ev2; 234 int count; 235}; 236static void 237event_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} 243static void 244timer_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 254static void 255test_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); 289end: 290 ; 291} 292 293#if 0 294static void 295timer_callback_3(evutil_socket_t *fd, short what, void *arg) 296{ 297 (void)fd; 298 (void)what; 299 300} 301static void 302test_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 337struct 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