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