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 "tinytest.h" 29 #include "tinytest_macros.h" 30 #include <stdlib.h> 31 32 #include "event2/event.h" 33 #include "event2/util.h" 34 #include "event-internal.h" 35 #include "defer-internal.h" 36 37 #include "regress.h" 38 #include "regress_thread.h" 39 40 static void 41 timer_callback(evutil_socket_t fd, short what, void *arg) 42 { 43 int *int_arg = arg; 44 *int_arg += 1; 45 (void)fd; 46 (void)what; 47 } 48 static void 49 simple_callback(struct event_callback *evcb, void *arg) 50 { 51 int *int_arg = arg; 52 *int_arg += 1; 53 (void)evcb; 54 } 55 static void 56 event_finalize_callback_1(struct event *ev, void *arg) 57 { 58 int *int_arg = arg; 59 *int_arg += 100; 60 (void)ev; 61 } 62 static void 63 callback_finalize_callback_1(struct event_callback *evcb, void *arg) 64 { 65 int *int_arg = arg; 66 *int_arg += 100; 67 (void)evcb; 68 } 69 70 71 static void 72 test_fin_cb_invoked(void *arg) 73 { 74 struct basic_test_data *data = arg; 75 struct event_base *base = data->base; 76 77 struct event *ev; 78 struct event ev2; 79 struct event_callback evcb; 80 int cb_called = 0; 81 int ev_called = 0; 82 83 const struct timeval ten_sec = {10,0}; 84 85 event_deferred_cb_init_(&evcb, 0, simple_callback, &cb_called); 86 ev = evtimer_new(base, timer_callback, &ev_called); 87 /* Just finalize them; don't bother adding. */ 88 event_free_finalize(0, ev, event_finalize_callback_1); 89 event_callback_finalize_(base, 0, &evcb, callback_finalize_callback_1); 90 91 event_base_dispatch(base); 92 93 tt_int_op(cb_called, ==, 100); 94 tt_int_op(ev_called, ==, 100); 95 96 ev_called = cb_called = 0; 97 event_base_assert_ok_(base); 98 99 /* Now try it when they're active. (actually, don't finalize: make 100 * sure activation can happen! */ 101 ev = evtimer_new(base, timer_callback, &ev_called); 102 event_deferred_cb_init_(&evcb, 0, simple_callback, &cb_called); 103 104 event_active(ev, EV_TIMEOUT, 1); 105 event_callback_activate_(base, &evcb); 106 107 event_base_dispatch(base); 108 tt_int_op(cb_called, ==, 1); 109 tt_int_op(ev_called, ==, 1); 110 111 ev_called = cb_called = 0; 112 event_base_assert_ok_(base); 113 114 /* Great, it worked. Now activate and finalize and make sure only 115 * finalizing happens. */ 116 event_active(ev, EV_TIMEOUT, 1); 117 event_callback_activate_(base, &evcb); 118 event_free_finalize(0, ev, event_finalize_callback_1); 119 event_callback_finalize_(base, 0, &evcb, callback_finalize_callback_1); 120 121 event_base_dispatch(base); 122 tt_int_op(cb_called, ==, 100); 123 tt_int_op(ev_called, ==, 100); 124 125 ev_called = 0; 126 127 event_base_assert_ok_(base); 128 129 /* Okay, now add but don't have it become active, and make sure *that* 130 * works. */ 131 ev = evtimer_new(base, timer_callback, &ev_called); 132 event_add(ev, &ten_sec); 133 event_free_finalize(0, ev, event_finalize_callback_1); 134 135 event_base_dispatch(base); 136 tt_int_op(ev_called, ==, 100); 137 138 ev_called = 0; 139 event_base_assert_ok_(base); 140 141 /* Now try adding and deleting after finalizing. */ 142 ev = evtimer_new(base, timer_callback, &ev_called); 143 evtimer_assign(&ev2, base, timer_callback, &ev_called); 144 event_add(ev, &ten_sec); 145 event_free_finalize(0, ev, event_finalize_callback_1); 146 event_finalize(0, &ev2, event_finalize_callback_1); 147 148 event_add(&ev2, &ten_sec); 149 event_del(ev); 150 event_active(&ev2, EV_TIMEOUT, 1); 151 152 event_base_dispatch(base); 153 tt_int_op(ev_called, ==, 200); 154 155 event_base_assert_ok_(base); 156 157 end: 158 ; 159 } 160 161 #ifndef EVENT__DISABLE_MM_REPLACEMENT 162 static void * 163 tfff_malloc(size_t n) 164 { 165 return malloc(n); 166 } 167 static void *tfff_p1=NULL, *tfff_p2=NULL; 168 static int tfff_p1_freed=0, tfff_p2_freed=0; 169 static void 170 tfff_free(void *p) 171 { 172 if (! p) 173 return; 174 if (p == tfff_p1) 175 ++tfff_p1_freed; 176 if (p == tfff_p2) 177 ++tfff_p2_freed; 178 free(p); 179 } 180 static void * 181 tfff_realloc(void *p, size_t sz) 182 { 183 return realloc(p,sz); 184 } 185 #endif 186 187 static void 188 test_fin_free_finalize(void *arg) 189 { 190 #ifdef EVENT__DISABLE_MM_REPLACEMENT 191 tinytest_set_test_skipped_(); 192 #else 193 struct event_base *base = NULL; 194 struct event *ev, *ev2; 195 int ev_called = 0; 196 int ev2_called = 0; 197 198 (void)arg; 199 200 event_set_mem_functions(tfff_malloc, tfff_realloc, tfff_free); 201 202 base = event_base_new(); 203 tt_assert(base); 204 205 ev = evtimer_new(base, timer_callback, &ev_called); 206 ev2 = evtimer_new(base, timer_callback, &ev2_called); 207 tfff_p1 = ev; 208 tfff_p2 = ev2; 209 event_free_finalize(0, ev, event_finalize_callback_1); 210 event_finalize(0, ev2, event_finalize_callback_1); 211 212 event_base_dispatch(base); 213 214 tt_int_op(ev_called, ==, 100); 215 tt_int_op(ev2_called, ==, 100); 216 217 event_base_assert_ok_(base); 218 tt_int_op(tfff_p1_freed, ==, 1); 219 tt_int_op(tfff_p2_freed, ==, 0); 220 221 event_free(ev2); 222 223 end: 224 if (base) 225 event_base_free(base); 226 #endif 227 } 228 229 /* For test_fin_within_cb */ 230 struct event_and_count { 231 struct event *ev; 232 struct event *ev2; 233 int count; 234 }; 235 static void 236 event_finalize_callback_2(struct event *ev, void *arg) 237 { 238 struct event_and_count *evc = arg; 239 evc->count += 100; 240 event_free(ev); 241 } 242 static void 243 timer_callback_2(evutil_socket_t fd, short what, void *arg) 244 { 245 struct event_and_count *evc = arg; 246 event_finalize(0, evc->ev, event_finalize_callback_2); 247 event_finalize(0, evc->ev2, event_finalize_callback_2); 248 ++ evc->count; 249 (void)fd; 250 (void)what; 251 } 252 253 static void 254 test_fin_within_cb(void *arg) 255 { 256 struct basic_test_data *data = arg; 257 struct event_base *base = data->base; 258 259 struct event_and_count evc1, evc2; 260 evc1.count = evc2.count = 0; 261 evc2.ev2 = evc1.ev = evtimer_new(base, timer_callback_2, &evc1); 262 evc1.ev2 = evc2.ev = evtimer_new(base, timer_callback_2, &evc2); 263 264 /* Activate both. The first one will have its callback run, which 265 * will finalize both of them, preventing the second one's callback 266 * from running. */ 267 event_active(evc1.ev, EV_TIMEOUT, 1); 268 event_active(evc2.ev, EV_TIMEOUT, 1); 269 270 event_base_dispatch(base); 271 tt_int_op(evc1.count, ==, 101); 272 tt_int_op(evc2.count, ==, 100); 273 274 event_base_assert_ok_(base); 275 /* Now try with EV_PERSIST events. */ 276 evc1.count = evc2.count = 0; 277 evc2.ev2 = evc1.ev = event_new(base, -1, EV_PERSIST, timer_callback_2, &evc1); 278 evc1.ev2 = evc2.ev = event_new(base, -1, EV_PERSIST, timer_callback_2, &evc2); 279 280 event_active(evc1.ev, EV_TIMEOUT, 1); 281 event_active(evc2.ev, EV_TIMEOUT, 1); 282 283 event_base_dispatch(base); 284 tt_int_op(evc1.count, ==, 101); 285 tt_int_op(evc2.count, ==, 100); 286 287 event_base_assert_ok_(base); 288 end: 289 ; 290 } 291 292 #if 0 293 static void 294 timer_callback_3(evutil_socket_t *fd, short what, void *arg) 295 { 296 (void)fd; 297 (void)what; 298 299 } 300 static void 301 test_fin_many(void *arg) 302 { 303 struct basic_test_data *data = arg; 304 struct event_base *base = data->base; 305 306 struct event *ev1, *ev2; 307 struct event_callback evcb1, evcb2; 308 int ev1_count = 0, ev2_count = 0; 309 int evcb1_count = 0, evcb2_count = 0; 310 struct event_callback *array[4]; 311 312 int n; 313 314 /* First attempt: call finalize_many with no events running */ 315 ev1 = evtimer_new(base, timer_callback, &ev1_count); 316 ev1 = evtimer_new(base, timer_callback, &ev2_count); 317 event_deferred_cb_init_(&evcb1, 0, simple_callback, &evcb1_called); 318 event_deferred_cb_init_(&evcb2, 0, simple_callback, &evcb2_called); 319 array[0] = &ev1->ev_evcallback; 320 array[1] = &ev2->ev_evcallback; 321 array[2] = &evcb1; 322 array[3] = &evcb2; 323 324 325 326 n = event_callback_finalize_many(base, 4, array, 327 callback_finalize_callback_1); 328 329 } 330 #endif 331 332 333 #define TEST(name, flags) \ 334 { #name, test_fin_##name, (flags), &basic_setup, NULL } 335 336 struct testcase_t finalize_testcases[] = { 337 338 TEST(cb_invoked, TT_FORK|TT_NEED_BASE), 339 TEST(free_finalize, TT_FORK), 340 TEST(within_cb, TT_FORK|TT_NEED_BASE), 341 // TEST(many, TT_FORK|TT_NEED_BASE), 342 343 344 END_OF_TESTCASES 345 }; 346 347