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