1275970Scy/* 2275970Scy * Copyright (c) 2013 Niels Provos and Nick Mathewson 3275970Scy * 4275970Scy * Redistribution and use in source and binary forms, with or without 5275970Scy * modification, are permitted provided that the following conditions 6275970Scy * are met: 7275970Scy * 1. Redistributions of source code must retain the above copyright 8275970Scy * notice, this list of conditions and the following disclaimer. 9275970Scy * 2. Redistributions in binary form must reproduce the above copyright 10275970Scy * notice, this list of conditions and the following disclaimer in the 11275970Scy * documentation and/or other materials provided with the distribution. 12275970Scy * 3. The name of the author may not be used to endorse or promote products 13275970Scy * derived from this software without specific prior written permission. 14275970Scy * 15275970Scy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16275970Scy * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17275970Scy * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18275970Scy * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19275970Scy * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20275970Scy * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21275970Scy * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22275970Scy * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23275970Scy * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24275970Scy * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25275970Scy */ 26275970Scy 27275970Scy#include "event2/event-config.h" 28282408Scy#include "evconfig-private.h" 29275970Scy#include "tinytest.h" 30275970Scy#include "tinytest_macros.h" 31275970Scy#include <stdlib.h> 32275970Scy 33275970Scy#include "event2/event.h" 34275970Scy#include "event2/util.h" 35275970Scy#include "event-internal.h" 36275970Scy#include "defer-internal.h" 37275970Scy 38275970Scy#include "regress.h" 39275970Scy#include "regress_thread.h" 40275970Scy 41275970Scystatic void 42275970Scytimer_callback(evutil_socket_t fd, short what, void *arg) 43275970Scy{ 44275970Scy int *int_arg = arg; 45275970Scy *int_arg += 1; 46275970Scy (void)fd; 47275970Scy (void)what; 48275970Scy} 49275970Scystatic void 50275970Scysimple_callback(struct event_callback *evcb, void *arg) 51275970Scy{ 52275970Scy int *int_arg = arg; 53275970Scy *int_arg += 1; 54275970Scy (void)evcb; 55275970Scy} 56275970Scystatic void 57275970Scyevent_finalize_callback_1(struct event *ev, void *arg) 58275970Scy{ 59275970Scy int *int_arg = arg; 60275970Scy *int_arg += 100; 61275970Scy (void)ev; 62275970Scy} 63275970Scystatic void 64275970Scycallback_finalize_callback_1(struct event_callback *evcb, void *arg) 65275970Scy{ 66275970Scy int *int_arg = arg; 67275970Scy *int_arg += 100; 68275970Scy (void)evcb; 69275970Scy} 70275970Scy 71275970Scy 72275970Scystatic void 73275970Scytest_fin_cb_invoked(void *arg) 74275970Scy{ 75275970Scy struct basic_test_data *data = arg; 76275970Scy struct event_base *base = data->base; 77275970Scy 78275970Scy struct event *ev; 79275970Scy struct event ev2; 80275970Scy struct event_callback evcb; 81275970Scy int cb_called = 0; 82275970Scy int ev_called = 0; 83275970Scy 84275970Scy const struct timeval ten_sec = {10,0}; 85275970Scy 86275970Scy event_deferred_cb_init_(&evcb, 0, simple_callback, &cb_called); 87275970Scy ev = evtimer_new(base, timer_callback, &ev_called); 88275970Scy /* Just finalize them; don't bother adding. */ 89275970Scy event_free_finalize(0, ev, event_finalize_callback_1); 90275970Scy event_callback_finalize_(base, 0, &evcb, callback_finalize_callback_1); 91275970Scy 92275970Scy event_base_dispatch(base); 93275970Scy 94275970Scy tt_int_op(cb_called, ==, 100); 95275970Scy tt_int_op(ev_called, ==, 100); 96275970Scy 97275970Scy ev_called = cb_called = 0; 98275970Scy event_base_assert_ok_(base); 99275970Scy 100275970Scy /* Now try it when they're active. (actually, don't finalize: make 101275970Scy * sure activation can happen! */ 102275970Scy ev = evtimer_new(base, timer_callback, &ev_called); 103275970Scy event_deferred_cb_init_(&evcb, 0, simple_callback, &cb_called); 104275970Scy 105275970Scy event_active(ev, EV_TIMEOUT, 1); 106275970Scy event_callback_activate_(base, &evcb); 107275970Scy 108275970Scy event_base_dispatch(base); 109275970Scy tt_int_op(cb_called, ==, 1); 110275970Scy tt_int_op(ev_called, ==, 1); 111275970Scy 112275970Scy ev_called = cb_called = 0; 113275970Scy event_base_assert_ok_(base); 114275970Scy 115275970Scy /* Great, it worked. Now activate and finalize and make sure only 116275970Scy * finalizing happens. */ 117275970Scy event_active(ev, EV_TIMEOUT, 1); 118275970Scy event_callback_activate_(base, &evcb); 119275970Scy event_free_finalize(0, ev, event_finalize_callback_1); 120275970Scy event_callback_finalize_(base, 0, &evcb, callback_finalize_callback_1); 121275970Scy 122275970Scy event_base_dispatch(base); 123275970Scy tt_int_op(cb_called, ==, 100); 124275970Scy tt_int_op(ev_called, ==, 100); 125275970Scy 126275970Scy ev_called = 0; 127275970Scy 128275970Scy event_base_assert_ok_(base); 129275970Scy 130275970Scy /* Okay, now add but don't have it become active, and make sure *that* 131275970Scy * works. */ 132275970Scy ev = evtimer_new(base, timer_callback, &ev_called); 133275970Scy event_add(ev, &ten_sec); 134275970Scy event_free_finalize(0, ev, event_finalize_callback_1); 135275970Scy 136275970Scy event_base_dispatch(base); 137275970Scy tt_int_op(ev_called, ==, 100); 138275970Scy 139275970Scy ev_called = 0; 140275970Scy event_base_assert_ok_(base); 141275970Scy 142275970Scy /* Now try adding and deleting after finalizing. */ 143275970Scy ev = evtimer_new(base, timer_callback, &ev_called); 144275970Scy evtimer_assign(&ev2, base, timer_callback, &ev_called); 145275970Scy event_add(ev, &ten_sec); 146275970Scy event_free_finalize(0, ev, event_finalize_callback_1); 147275970Scy event_finalize(0, &ev2, event_finalize_callback_1); 148275970Scy 149275970Scy event_add(&ev2, &ten_sec); 150275970Scy event_del(ev); 151275970Scy event_active(&ev2, EV_TIMEOUT, 1); 152275970Scy 153275970Scy event_base_dispatch(base); 154275970Scy tt_int_op(ev_called, ==, 200); 155275970Scy 156275970Scy event_base_assert_ok_(base); 157275970Scy 158275970Scyend: 159275970Scy ; 160275970Scy} 161275970Scy 162275970Scy#ifndef EVENT__DISABLE_MM_REPLACEMENT 163275970Scystatic void * 164275970Scytfff_malloc(size_t n) 165275970Scy{ 166275970Scy return malloc(n); 167275970Scy} 168275970Scystatic void *tfff_p1=NULL, *tfff_p2=NULL; 169275970Scystatic int tfff_p1_freed=0, tfff_p2_freed=0; 170275970Scystatic void 171275970Scytfff_free(void *p) 172275970Scy{ 173275970Scy if (! p) 174275970Scy return; 175275970Scy if (p == tfff_p1) 176275970Scy ++tfff_p1_freed; 177275970Scy if (p == tfff_p2) 178275970Scy ++tfff_p2_freed; 179275970Scy free(p); 180275970Scy} 181275970Scystatic void * 182275970Scytfff_realloc(void *p, size_t sz) 183275970Scy{ 184275970Scy return realloc(p,sz); 185275970Scy} 186275970Scy#endif 187275970Scy 188275970Scystatic void 189275970Scytest_fin_free_finalize(void *arg) 190275970Scy{ 191275970Scy#ifdef EVENT__DISABLE_MM_REPLACEMENT 192275970Scy tinytest_set_test_skipped_(); 193275970Scy#else 194275970Scy struct event_base *base = NULL; 195275970Scy struct event *ev, *ev2; 196275970Scy int ev_called = 0; 197275970Scy int ev2_called = 0; 198275970Scy 199275970Scy (void)arg; 200275970Scy 201275970Scy event_set_mem_functions(tfff_malloc, tfff_realloc, tfff_free); 202275970Scy 203275970Scy base = event_base_new(); 204275970Scy tt_assert(base); 205275970Scy 206275970Scy ev = evtimer_new(base, timer_callback, &ev_called); 207275970Scy ev2 = evtimer_new(base, timer_callback, &ev2_called); 208275970Scy tfff_p1 = ev; 209275970Scy tfff_p2 = ev2; 210275970Scy event_free_finalize(0, ev, event_finalize_callback_1); 211275970Scy event_finalize(0, ev2, event_finalize_callback_1); 212275970Scy 213275970Scy event_base_dispatch(base); 214275970Scy 215275970Scy tt_int_op(ev_called, ==, 100); 216275970Scy tt_int_op(ev2_called, ==, 100); 217275970Scy 218275970Scy event_base_assert_ok_(base); 219275970Scy tt_int_op(tfff_p1_freed, ==, 1); 220275970Scy tt_int_op(tfff_p2_freed, ==, 0); 221275970Scy 222275970Scy event_free(ev2); 223275970Scy 224275970Scyend: 225275970Scy if (base) 226275970Scy event_base_free(base); 227275970Scy#endif 228275970Scy} 229275970Scy 230275970Scy/* For test_fin_within_cb */ 231275970Scystruct event_and_count { 232275970Scy struct event *ev; 233275970Scy struct event *ev2; 234275970Scy int count; 235275970Scy}; 236275970Scystatic void 237275970Scyevent_finalize_callback_2(struct event *ev, void *arg) 238275970Scy{ 239275970Scy struct event_and_count *evc = arg; 240275970Scy evc->count += 100; 241275970Scy event_free(ev); 242275970Scy} 243275970Scystatic void 244275970Scytimer_callback_2(evutil_socket_t fd, short what, void *arg) 245275970Scy{ 246275970Scy struct event_and_count *evc = arg; 247275970Scy event_finalize(0, evc->ev, event_finalize_callback_2); 248275970Scy event_finalize(0, evc->ev2, event_finalize_callback_2); 249275970Scy ++ evc->count; 250275970Scy (void)fd; 251275970Scy (void)what; 252275970Scy} 253275970Scy 254275970Scystatic void 255275970Scytest_fin_within_cb(void *arg) 256275970Scy{ 257275970Scy struct basic_test_data *data = arg; 258275970Scy struct event_base *base = data->base; 259275970Scy 260275970Scy struct event_and_count evc1, evc2; 261275970Scy evc1.count = evc2.count = 0; 262275970Scy evc2.ev2 = evc1.ev = evtimer_new(base, timer_callback_2, &evc1); 263275970Scy evc1.ev2 = evc2.ev = evtimer_new(base, timer_callback_2, &evc2); 264275970Scy 265275970Scy /* Activate both. The first one will have its callback run, which 266275970Scy * will finalize both of them, preventing the second one's callback 267275970Scy * from running. */ 268275970Scy event_active(evc1.ev, EV_TIMEOUT, 1); 269275970Scy event_active(evc2.ev, EV_TIMEOUT, 1); 270275970Scy 271275970Scy event_base_dispatch(base); 272275970Scy tt_int_op(evc1.count, ==, 101); 273275970Scy tt_int_op(evc2.count, ==, 100); 274275970Scy 275275970Scy event_base_assert_ok_(base); 276275970Scy /* Now try with EV_PERSIST events. */ 277275970Scy evc1.count = evc2.count = 0; 278275970Scy evc2.ev2 = evc1.ev = event_new(base, -1, EV_PERSIST, timer_callback_2, &evc1); 279275970Scy evc1.ev2 = evc2.ev = event_new(base, -1, EV_PERSIST, timer_callback_2, &evc2); 280275970Scy 281275970Scy event_active(evc1.ev, EV_TIMEOUT, 1); 282275970Scy event_active(evc2.ev, EV_TIMEOUT, 1); 283275970Scy 284275970Scy event_base_dispatch(base); 285275970Scy tt_int_op(evc1.count, ==, 101); 286275970Scy tt_int_op(evc2.count, ==, 100); 287275970Scy 288275970Scy event_base_assert_ok_(base); 289275970Scyend: 290275970Scy ; 291275970Scy} 292275970Scy 293275970Scy#if 0 294275970Scystatic void 295275970Scytimer_callback_3(evutil_socket_t *fd, short what, void *arg) 296275970Scy{ 297275970Scy (void)fd; 298275970Scy (void)what; 299275970Scy 300275970Scy} 301275970Scystatic void 302275970Scytest_fin_many(void *arg) 303275970Scy{ 304275970Scy struct basic_test_data *data = arg; 305275970Scy struct event_base *base = data->base; 306275970Scy 307275970Scy struct event *ev1, *ev2; 308275970Scy struct event_callback evcb1, evcb2; 309275970Scy int ev1_count = 0, ev2_count = 0; 310275970Scy int evcb1_count = 0, evcb2_count = 0; 311275970Scy struct event_callback *array[4]; 312275970Scy 313275970Scy int n; 314275970Scy 315275970Scy /* First attempt: call finalize_many with no events running */ 316275970Scy ev1 = evtimer_new(base, timer_callback, &ev1_count); 317275970Scy ev1 = evtimer_new(base, timer_callback, &ev2_count); 318275970Scy event_deferred_cb_init_(&evcb1, 0, simple_callback, &evcb1_called); 319275970Scy event_deferred_cb_init_(&evcb2, 0, simple_callback, &evcb2_called); 320275970Scy array[0] = &ev1->ev_evcallback; 321275970Scy array[1] = &ev2->ev_evcallback; 322275970Scy array[2] = &evcb1; 323275970Scy array[3] = &evcb2; 324275970Scy 325275970Scy 326275970Scy 327275970Scy n = event_callback_finalize_many(base, 4, array, 328275970Scy callback_finalize_callback_1); 329275970Scy 330275970Scy} 331275970Scy#endif 332275970Scy 333275970Scy 334275970Scy#define TEST(name, flags) \ 335275970Scy { #name, test_fin_##name, (flags), &basic_setup, NULL } 336275970Scy 337275970Scystruct testcase_t finalize_testcases[] = { 338275970Scy 339275970Scy TEST(cb_invoked, TT_FORK|TT_NEED_BASE), 340275970Scy TEST(free_finalize, TT_FORK), 341275970Scy TEST(within_cb, TT_FORK|TT_NEED_BASE), 342275970Scy// TEST(many, TT_FORK|TT_NEED_BASE), 343275970Scy 344275970Scy 345275970Scy END_OF_TESTCASES 346275970Scy}; 347275970Scy 348