xref: /minix3/external/bsd/libevent/dist/test/regress.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: regress.c,v 1.8 2015/01/29 07:26:02 spz Exp $	*/
2e985b929SDavid van Moolenbroek /*
3e985b929SDavid van Moolenbroek  * Copyright (c) 2003-2007 Niels Provos <provos@citi.umich.edu>
4e985b929SDavid van Moolenbroek  * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
5e985b929SDavid van Moolenbroek  *
6e985b929SDavid van Moolenbroek  * Redistribution and use in source and binary forms, with or without
7e985b929SDavid van Moolenbroek  * modification, are permitted provided that the following conditions
8e985b929SDavid van Moolenbroek  * are met:
9e985b929SDavid van Moolenbroek  * 1. Redistributions of source code must retain the above copyright
10e985b929SDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer.
11e985b929SDavid van Moolenbroek  * 2. Redistributions in binary form must reproduce the above copyright
12e985b929SDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer in the
13e985b929SDavid van Moolenbroek  *    documentation and/or other materials provided with the distribution.
14e985b929SDavid van Moolenbroek  * 3. The name of the author may not be used to endorse or promote products
15e985b929SDavid van Moolenbroek  *    derived from this software without specific prior written permission.
16e985b929SDavid van Moolenbroek  *
17e985b929SDavid van Moolenbroek  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18e985b929SDavid van Moolenbroek  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19e985b929SDavid van Moolenbroek  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20e985b929SDavid van Moolenbroek  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21e985b929SDavid van Moolenbroek  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22e985b929SDavid van Moolenbroek  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23e985b929SDavid van Moolenbroek  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24e985b929SDavid van Moolenbroek  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25e985b929SDavid van Moolenbroek  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26e985b929SDavid van Moolenbroek  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27e985b929SDavid van Moolenbroek  */
28e985b929SDavid van Moolenbroek 
29e985b929SDavid van Moolenbroek #ifdef WIN32
30e985b929SDavid van Moolenbroek #include <winsock2.h>
31e985b929SDavid van Moolenbroek #include <windows.h>
32e985b929SDavid van Moolenbroek #endif
33e985b929SDavid van Moolenbroek 
34e985b929SDavid van Moolenbroek #include "event2/event-config.h"
35e985b929SDavid van Moolenbroek #include <sys/cdefs.h>
36*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: regress.c,v 1.8 2015/01/29 07:26:02 spz Exp $");
37e985b929SDavid van Moolenbroek 
38e985b929SDavid van Moolenbroek #include <sys/types.h>
39e985b929SDavid van Moolenbroek #include <sys/stat.h>
40e985b929SDavid van Moolenbroek #ifdef _EVENT_HAVE_SYS_TIME_H
41e985b929SDavid van Moolenbroek #include <sys/time.h>
42e985b929SDavid van Moolenbroek #endif
43e985b929SDavid van Moolenbroek #include <sys/queue.h>
44e985b929SDavid van Moolenbroek #ifndef WIN32
45e985b929SDavid van Moolenbroek #include <sys/socket.h>
46e985b929SDavid van Moolenbroek #include <sys/wait.h>
47e985b929SDavid van Moolenbroek #include <signal.h>
48e985b929SDavid van Moolenbroek #include <unistd.h>
49e985b929SDavid van Moolenbroek #include <netdb.h>
50e985b929SDavid van Moolenbroek #endif
51e985b929SDavid van Moolenbroek #include <fcntl.h>
52e985b929SDavid van Moolenbroek #include <signal.h>
53e985b929SDavid van Moolenbroek #include <stdlib.h>
54e985b929SDavid van Moolenbroek #include <stdio.h>
55e985b929SDavid van Moolenbroek #include <string.h>
56e985b929SDavid van Moolenbroek #include <errno.h>
57e985b929SDavid van Moolenbroek #include <assert.h>
58e985b929SDavid van Moolenbroek #include <ctype.h>
59e985b929SDavid van Moolenbroek 
60e985b929SDavid van Moolenbroek #include "event2/event.h"
61e985b929SDavid van Moolenbroek #include "event2/event_struct.h"
62e985b929SDavid van Moolenbroek #include "event2/event_compat.h"
63e985b929SDavid van Moolenbroek #include "event2/tag.h"
64e985b929SDavid van Moolenbroek #include "event2/buffer.h"
65e985b929SDavid van Moolenbroek #include "event2/buffer_compat.h"
66e985b929SDavid van Moolenbroek #include "event2/util.h"
67e985b929SDavid van Moolenbroek #include "event-internal.h"
68e985b929SDavid van Moolenbroek #include "evthread-internal.h"
69e985b929SDavid van Moolenbroek #include "util-internal.h"
70e985b929SDavid van Moolenbroek #include "log-internal.h"
71e985b929SDavid van Moolenbroek 
72e985b929SDavid van Moolenbroek #include "regress.h"
73e985b929SDavid van Moolenbroek 
74e985b929SDavid van Moolenbroek #ifndef WIN32
75e985b929SDavid van Moolenbroek #include "regress.gen.h"
76e985b929SDavid van Moolenbroek #endif
77e985b929SDavid van Moolenbroek 
78e985b929SDavid van Moolenbroek evutil_socket_t pair[2];
79e985b929SDavid van Moolenbroek int test_ok;
80e985b929SDavid van Moolenbroek int called;
81e985b929SDavid van Moolenbroek struct event_base *global_base;
82e985b929SDavid van Moolenbroek 
83e985b929SDavid van Moolenbroek static char wbuf[4096];
84e985b929SDavid van Moolenbroek static char rbuf[4096];
85e985b929SDavid van Moolenbroek static int woff;
86e985b929SDavid van Moolenbroek static int roff;
87e985b929SDavid van Moolenbroek static int usepersist;
88e985b929SDavid van Moolenbroek static struct timeval tset;
89e985b929SDavid van Moolenbroek static struct timeval tcalled;
90e985b929SDavid van Moolenbroek 
91e985b929SDavid van Moolenbroek 
92e985b929SDavid van Moolenbroek #define TEST1	"this is a test"
93e985b929SDavid van Moolenbroek #define SECONDS	1
94e985b929SDavid van Moolenbroek 
95e985b929SDavid van Moolenbroek #ifndef SHUT_WR
96e985b929SDavid van Moolenbroek #define SHUT_WR 1
97e985b929SDavid van Moolenbroek #endif
98e985b929SDavid van Moolenbroek 
99e985b929SDavid van Moolenbroek #ifdef WIN32
100e985b929SDavid van Moolenbroek #define write(fd,buf,len) send((fd),(buf),(int)(len),0)
101e985b929SDavid van Moolenbroek #define read(fd,buf,len) recv((fd),(buf),(int)(len),0)
102e985b929SDavid van Moolenbroek #endif
103e985b929SDavid van Moolenbroek 
104e985b929SDavid van Moolenbroek struct basic_cb_args
105e985b929SDavid van Moolenbroek {
106e985b929SDavid van Moolenbroek 	struct event_base *eb;
107e985b929SDavid van Moolenbroek 	struct event *ev;
108e985b929SDavid van Moolenbroek 	unsigned int callcount;
109e985b929SDavid van Moolenbroek };
110e985b929SDavid van Moolenbroek 
111e985b929SDavid van Moolenbroek static void
simple_read_cb(evutil_socket_t fd,short event,void * arg)112e985b929SDavid van Moolenbroek simple_read_cb(evutil_socket_t fd, short event, void *arg)
113e985b929SDavid van Moolenbroek {
114e985b929SDavid van Moolenbroek 	char buf[256];
115e985b929SDavid van Moolenbroek 	int len;
116e985b929SDavid van Moolenbroek 
117e985b929SDavid van Moolenbroek 	len = read(fd, buf, sizeof(buf));
118e985b929SDavid van Moolenbroek 
119e985b929SDavid van Moolenbroek 	if (len) {
120e985b929SDavid van Moolenbroek 		if (!called) {
121e985b929SDavid van Moolenbroek 			if (event_add(arg, NULL) == -1)
122e985b929SDavid van Moolenbroek 				exit(1);
123e985b929SDavid van Moolenbroek 		}
124e985b929SDavid van Moolenbroek 	} else if (called == 1)
125e985b929SDavid van Moolenbroek 		test_ok = 1;
126e985b929SDavid van Moolenbroek 
127e985b929SDavid van Moolenbroek 	called++;
128e985b929SDavid van Moolenbroek }
129e985b929SDavid van Moolenbroek 
130e985b929SDavid van Moolenbroek static void
basic_read_cb(evutil_socket_t fd,short event,void * data)131e985b929SDavid van Moolenbroek basic_read_cb(evutil_socket_t fd, short event, void *data)
132e985b929SDavid van Moolenbroek {
133e985b929SDavid van Moolenbroek 	char buf[256];
134e985b929SDavid van Moolenbroek 	int len;
135e985b929SDavid van Moolenbroek 	struct basic_cb_args *arg = data;
136e985b929SDavid van Moolenbroek 
137e985b929SDavid van Moolenbroek 	len = read(fd, buf, sizeof(buf));
138e985b929SDavid van Moolenbroek 
139e985b929SDavid van Moolenbroek 	if (len < 0) {
140e985b929SDavid van Moolenbroek 		tt_fail_perror("read (callback)");
141e985b929SDavid van Moolenbroek 	} else {
142e985b929SDavid van Moolenbroek 		switch (arg->callcount++) {
143e985b929SDavid van Moolenbroek 		case 0:	 /* first call: expect to read data; cycle */
144e985b929SDavid van Moolenbroek 			if (len > 0)
145e985b929SDavid van Moolenbroek 				return;
146e985b929SDavid van Moolenbroek 
147e985b929SDavid van Moolenbroek 			tt_fail_msg("EOF before data read");
148e985b929SDavid van Moolenbroek 			break;
149e985b929SDavid van Moolenbroek 
150e985b929SDavid van Moolenbroek 		case 1:	 /* second call: expect EOF; stop */
151e985b929SDavid van Moolenbroek 			if (len > 0)
152e985b929SDavid van Moolenbroek 				tt_fail_msg("not all data read on first cycle");
153e985b929SDavid van Moolenbroek 			break;
154e985b929SDavid van Moolenbroek 
155e985b929SDavid van Moolenbroek 		default:  /* third call: should not happen */
156e985b929SDavid van Moolenbroek 			tt_fail_msg("too many cycles");
157e985b929SDavid van Moolenbroek 		}
158e985b929SDavid van Moolenbroek 	}
159e985b929SDavid van Moolenbroek 
160e985b929SDavid van Moolenbroek 	event_del(arg->ev);
161e985b929SDavid van Moolenbroek 	event_base_loopexit(arg->eb, NULL);
162e985b929SDavid van Moolenbroek }
163e985b929SDavid van Moolenbroek 
164e985b929SDavid van Moolenbroek static void
dummy_read_cb(evutil_socket_t fd,short event,void * arg)165e985b929SDavid van Moolenbroek dummy_read_cb(evutil_socket_t fd, short event, void *arg)
166e985b929SDavid van Moolenbroek {
167e985b929SDavid van Moolenbroek }
168e985b929SDavid van Moolenbroek 
169e985b929SDavid van Moolenbroek static void
simple_write_cb(evutil_socket_t fd,short event,void * arg)170e985b929SDavid van Moolenbroek simple_write_cb(evutil_socket_t fd, short event, void *arg)
171e985b929SDavid van Moolenbroek {
172e985b929SDavid van Moolenbroek 	int len;
173e985b929SDavid van Moolenbroek 
174e985b929SDavid van Moolenbroek 	len = write(fd, TEST1, strlen(TEST1) + 1);
175e985b929SDavid van Moolenbroek 	if (len == -1)
176e985b929SDavid van Moolenbroek 		test_ok = 0;
177e985b929SDavid van Moolenbroek 	else
178e985b929SDavid van Moolenbroek 		test_ok = 1;
179e985b929SDavid van Moolenbroek }
180e985b929SDavid van Moolenbroek 
181e985b929SDavid van Moolenbroek static void
multiple_write_cb(evutil_socket_t fd,short event,void * arg)182e985b929SDavid van Moolenbroek multiple_write_cb(evutil_socket_t fd, short event, void *arg)
183e985b929SDavid van Moolenbroek {
184e985b929SDavid van Moolenbroek 	struct event *ev = arg;
185e985b929SDavid van Moolenbroek 	int len;
186e985b929SDavid van Moolenbroek 
187e985b929SDavid van Moolenbroek 	len = 128;
188e985b929SDavid van Moolenbroek 	if (woff + len >= (int)sizeof(wbuf))
189e985b929SDavid van Moolenbroek 		len = sizeof(wbuf) - woff;
190e985b929SDavid van Moolenbroek 
191e985b929SDavid van Moolenbroek 	len = write(fd, wbuf + woff, len);
192e985b929SDavid van Moolenbroek 	if (len == -1) {
193e985b929SDavid van Moolenbroek 		fprintf(stderr, "%s: write\n", __func__);
194e985b929SDavid van Moolenbroek 		if (usepersist)
195e985b929SDavid van Moolenbroek 			event_del(ev);
196e985b929SDavid van Moolenbroek 		return;
197e985b929SDavid van Moolenbroek 	}
198e985b929SDavid van Moolenbroek 
199e985b929SDavid van Moolenbroek 	woff += len;
200e985b929SDavid van Moolenbroek 
201e985b929SDavid van Moolenbroek 	if (woff >= (int)sizeof(wbuf)) {
202e985b929SDavid van Moolenbroek 		shutdown(fd, SHUT_WR);
203e985b929SDavid van Moolenbroek 		if (usepersist)
204e985b929SDavid van Moolenbroek 			event_del(ev);
205e985b929SDavid van Moolenbroek 		return;
206e985b929SDavid van Moolenbroek 	}
207e985b929SDavid van Moolenbroek 
208e985b929SDavid van Moolenbroek 	if (!usepersist) {
209e985b929SDavid van Moolenbroek 		if (event_add(ev, NULL) == -1)
210e985b929SDavid van Moolenbroek 			exit(1);
211e985b929SDavid van Moolenbroek 	}
212e985b929SDavid van Moolenbroek }
213e985b929SDavid van Moolenbroek 
214e985b929SDavid van Moolenbroek static void
multiple_read_cb(evutil_socket_t fd,short event,void * arg)215e985b929SDavid van Moolenbroek multiple_read_cb(evutil_socket_t fd, short event, void *arg)
216e985b929SDavid van Moolenbroek {
217e985b929SDavid van Moolenbroek 	struct event *ev = arg;
218e985b929SDavid van Moolenbroek 	int len;
219e985b929SDavid van Moolenbroek 
220e985b929SDavid van Moolenbroek 	len = read(fd, rbuf + roff, sizeof(rbuf) - roff);
221e985b929SDavid van Moolenbroek 	if (len == -1)
222e985b929SDavid van Moolenbroek 		fprintf(stderr, "%s: read\n", __func__);
223e985b929SDavid van Moolenbroek 	if (len <= 0) {
224e985b929SDavid van Moolenbroek 		if (usepersist)
225e985b929SDavid van Moolenbroek 			event_del(ev);
226e985b929SDavid van Moolenbroek 		return;
227e985b929SDavid van Moolenbroek 	}
228e985b929SDavid van Moolenbroek 
229e985b929SDavid van Moolenbroek 	roff += len;
230e985b929SDavid van Moolenbroek 	if (!usepersist) {
231e985b929SDavid van Moolenbroek 		if (event_add(ev, NULL) == -1)
232e985b929SDavid van Moolenbroek 			exit(1);
233e985b929SDavid van Moolenbroek 	}
234e985b929SDavid van Moolenbroek }
235e985b929SDavid van Moolenbroek 
236e985b929SDavid van Moolenbroek static void
timeout_cb(evutil_socket_t fd,short event,void * arg)237e985b929SDavid van Moolenbroek timeout_cb(evutil_socket_t fd, short event, void *arg)
238e985b929SDavid van Moolenbroek {
239e985b929SDavid van Moolenbroek 	struct timeval tv;
240e985b929SDavid van Moolenbroek 	int diff;
241e985b929SDavid van Moolenbroek 
242e985b929SDavid van Moolenbroek 	evutil_gettimeofday(&tcalled, NULL);
243e985b929SDavid van Moolenbroek 	if (evutil_timercmp(&tcalled, &tset, >))
244e985b929SDavid van Moolenbroek 		evutil_timersub(&tcalled, &tset, &tv);
245e985b929SDavid van Moolenbroek 	else
246e985b929SDavid van Moolenbroek 		evutil_timersub(&tset, &tcalled, &tv);
247e985b929SDavid van Moolenbroek 
248e985b929SDavid van Moolenbroek 	diff = tv.tv_sec*1000 + tv.tv_usec/1000 - SECONDS * 1000;
249e985b929SDavid van Moolenbroek 	if (diff < 0)
250e985b929SDavid van Moolenbroek 		diff = -diff;
251e985b929SDavid van Moolenbroek 
252e985b929SDavid van Moolenbroek 	if (diff < 100)
253e985b929SDavid van Moolenbroek 		test_ok = 1;
254e985b929SDavid van Moolenbroek }
255e985b929SDavid van Moolenbroek 
256e985b929SDavid van Moolenbroek struct both {
257e985b929SDavid van Moolenbroek 	struct event ev;
258e985b929SDavid van Moolenbroek 	int nread;
259e985b929SDavid van Moolenbroek };
260e985b929SDavid van Moolenbroek 
261e985b929SDavid van Moolenbroek static void
combined_read_cb(evutil_socket_t fd,short event,void * arg)262e985b929SDavid van Moolenbroek combined_read_cb(evutil_socket_t fd, short event, void *arg)
263e985b929SDavid van Moolenbroek {
264e985b929SDavid van Moolenbroek 	struct both *both = arg;
265e985b929SDavid van Moolenbroek 	char buf[128];
266e985b929SDavid van Moolenbroek 	int len;
267e985b929SDavid van Moolenbroek 
268e985b929SDavid van Moolenbroek 	len = read(fd, buf, sizeof(buf));
269e985b929SDavid van Moolenbroek 	if (len == -1)
270e985b929SDavid van Moolenbroek 		fprintf(stderr, "%s: read\n", __func__);
271e985b929SDavid van Moolenbroek 	if (len <= 0)
272e985b929SDavid van Moolenbroek 		return;
273e985b929SDavid van Moolenbroek 
274e985b929SDavid van Moolenbroek 	both->nread += len;
275e985b929SDavid van Moolenbroek 	if (event_add(&both->ev, NULL) == -1)
276e985b929SDavid van Moolenbroek 		exit(1);
277e985b929SDavid van Moolenbroek }
278e985b929SDavid van Moolenbroek 
279e985b929SDavid van Moolenbroek static void
combined_write_cb(evutil_socket_t fd,short event,void * arg)280e985b929SDavid van Moolenbroek combined_write_cb(evutil_socket_t fd, short event, void *arg)
281e985b929SDavid van Moolenbroek {
282e985b929SDavid van Moolenbroek 	struct both *both = arg;
283e985b929SDavid van Moolenbroek 	char buf[128];
284e985b929SDavid van Moolenbroek 	int len;
285e985b929SDavid van Moolenbroek 
286e985b929SDavid van Moolenbroek 	len = sizeof(buf);
287e985b929SDavid van Moolenbroek 	if (len > both->nread)
288e985b929SDavid van Moolenbroek 		len = both->nread;
289e985b929SDavid van Moolenbroek 
290e985b929SDavid van Moolenbroek 	memset(buf, 'q', len);
291e985b929SDavid van Moolenbroek 
292e985b929SDavid van Moolenbroek 	len = write(fd, buf, len);
293e985b929SDavid van Moolenbroek 	if (len == -1)
294e985b929SDavid van Moolenbroek 		fprintf(stderr, "%s: write\n", __func__);
295e985b929SDavid van Moolenbroek 	if (len <= 0) {
296e985b929SDavid van Moolenbroek 		shutdown(fd, SHUT_WR);
297e985b929SDavid van Moolenbroek 		return;
298e985b929SDavid van Moolenbroek 	}
299e985b929SDavid van Moolenbroek 
300e985b929SDavid van Moolenbroek 	both->nread -= len;
301e985b929SDavid van Moolenbroek 	if (event_add(&both->ev, NULL) == -1)
302e985b929SDavid van Moolenbroek 		exit(1);
303e985b929SDavid van Moolenbroek }
304e985b929SDavid van Moolenbroek 
305e985b929SDavid van Moolenbroek /* These macros used to replicate the work of the legacy test wrapper code */
306e985b929SDavid van Moolenbroek #define setup_test(x) do {						\
307e985b929SDavid van Moolenbroek 	if (!in_legacy_test_wrapper) {					\
308e985b929SDavid van Moolenbroek 		TT_FAIL(("Legacy test %s not wrapped properly", x));	\
309e985b929SDavid van Moolenbroek 		return;							\
310e985b929SDavid van Moolenbroek 	}								\
311e985b929SDavid van Moolenbroek 	} while (/*CONSTCOND*/0)
312e985b929SDavid van Moolenbroek #define cleanup_test() setup_test("cleanup")
313e985b929SDavid van Moolenbroek 
314e985b929SDavid van Moolenbroek static void
test_simpleread(void)315e985b929SDavid van Moolenbroek test_simpleread(void)
316e985b929SDavid van Moolenbroek {
317e985b929SDavid van Moolenbroek 	struct event ev;
318e985b929SDavid van Moolenbroek 
319e985b929SDavid van Moolenbroek 	/* Very simple read test */
320e985b929SDavid van Moolenbroek 	setup_test("Simple read: ");
321e985b929SDavid van Moolenbroek 
322e985b929SDavid van Moolenbroek 	if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) {
323e985b929SDavid van Moolenbroek 		tt_fail_perror("write");
324e985b929SDavid van Moolenbroek 	}
325e985b929SDavid van Moolenbroek 
326e985b929SDavid van Moolenbroek 	shutdown(pair[0], SHUT_WR);
327e985b929SDavid van Moolenbroek 
328e985b929SDavid van Moolenbroek 	event_set(&ev, pair[1], EV_READ, simple_read_cb, &ev);
329e985b929SDavid van Moolenbroek 	if (event_add(&ev, NULL) == -1)
330e985b929SDavid van Moolenbroek 		exit(1);
331e985b929SDavid van Moolenbroek 	event_dispatch();
332e985b929SDavid van Moolenbroek 
333e985b929SDavid van Moolenbroek 	cleanup_test();
334e985b929SDavid van Moolenbroek }
335e985b929SDavid van Moolenbroek 
336e985b929SDavid van Moolenbroek static void
test_simplewrite(void)337e985b929SDavid van Moolenbroek test_simplewrite(void)
338e985b929SDavid van Moolenbroek {
339e985b929SDavid van Moolenbroek 	struct event ev;
340e985b929SDavid van Moolenbroek 
341e985b929SDavid van Moolenbroek 	/* Very simple write test */
342e985b929SDavid van Moolenbroek 	setup_test("Simple write: ");
343e985b929SDavid van Moolenbroek 
344e985b929SDavid van Moolenbroek 	event_set(&ev, pair[0], EV_WRITE, simple_write_cb, &ev);
345e985b929SDavid van Moolenbroek 	if (event_add(&ev, NULL) == -1)
346e985b929SDavid van Moolenbroek 		exit(1);
347e985b929SDavid van Moolenbroek 	event_dispatch();
348e985b929SDavid van Moolenbroek 
349e985b929SDavid van Moolenbroek 	cleanup_test();
350e985b929SDavid van Moolenbroek }
351e985b929SDavid van Moolenbroek 
352e985b929SDavid van Moolenbroek static void
simpleread_multiple_cb(evutil_socket_t fd,short event,void * arg)353e985b929SDavid van Moolenbroek simpleread_multiple_cb(evutil_socket_t fd, short event, void *arg)
354e985b929SDavid van Moolenbroek {
355e985b929SDavid van Moolenbroek 	if (++called == 2)
356e985b929SDavid van Moolenbroek 		test_ok = 1;
357e985b929SDavid van Moolenbroek }
358e985b929SDavid van Moolenbroek 
359e985b929SDavid van Moolenbroek static void
test_simpleread_multiple(void)360e985b929SDavid van Moolenbroek test_simpleread_multiple(void)
361e985b929SDavid van Moolenbroek {
362e985b929SDavid van Moolenbroek 	struct event one, two;
363e985b929SDavid van Moolenbroek 
364e985b929SDavid van Moolenbroek 	/* Very simple read test */
365e985b929SDavid van Moolenbroek 	setup_test("Simple read to multiple evens: ");
366e985b929SDavid van Moolenbroek 
367e985b929SDavid van Moolenbroek 	if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) {
368e985b929SDavid van Moolenbroek 		tt_fail_perror("write");
369e985b929SDavid van Moolenbroek 	}
370e985b929SDavid van Moolenbroek 
371e985b929SDavid van Moolenbroek 	shutdown(pair[0], SHUT_WR);
372e985b929SDavid van Moolenbroek 
373e985b929SDavid van Moolenbroek 	event_set(&one, pair[1], EV_READ, simpleread_multiple_cb, NULL);
374e985b929SDavid van Moolenbroek 	if (event_add(&one, NULL) == -1)
375e985b929SDavid van Moolenbroek 		exit(1);
376e985b929SDavid van Moolenbroek 	event_set(&two, pair[1], EV_READ, simpleread_multiple_cb, NULL);
377e985b929SDavid van Moolenbroek 	if (event_add(&two, NULL) == -1)
378e985b929SDavid van Moolenbroek 		exit(1);
379e985b929SDavid van Moolenbroek 	event_dispatch();
380e985b929SDavid van Moolenbroek 
381e985b929SDavid van Moolenbroek 	cleanup_test();
382e985b929SDavid van Moolenbroek }
383e985b929SDavid van Moolenbroek 
384e985b929SDavid van Moolenbroek static int have_closed = 0;
385e985b929SDavid van Moolenbroek static int premature_event = 0;
386e985b929SDavid van Moolenbroek static void
simpleclose_close_fd_cb(evutil_socket_t s,short what,void * ptr)387e985b929SDavid van Moolenbroek simpleclose_close_fd_cb(evutil_socket_t s, short what, void *ptr)
388e985b929SDavid van Moolenbroek {
389e985b929SDavid van Moolenbroek 	evutil_socket_t **fds = ptr;
390e985b929SDavid van Moolenbroek 	TT_BLATHER(("Closing"));
391e985b929SDavid van Moolenbroek 	evutil_closesocket(*fds[0]);
392e985b929SDavid van Moolenbroek 	evutil_closesocket(*fds[1]);
393e985b929SDavid van Moolenbroek 	*fds[0] = -1;
394e985b929SDavid van Moolenbroek 	*fds[1] = -1;
395e985b929SDavid van Moolenbroek 	have_closed = 1;
396e985b929SDavid van Moolenbroek }
397e985b929SDavid van Moolenbroek 
398e985b929SDavid van Moolenbroek static void
record_event_cb(evutil_socket_t s,short what,void * ptr)399e985b929SDavid van Moolenbroek record_event_cb(evutil_socket_t s, short what, void *ptr)
400e985b929SDavid van Moolenbroek {
401e985b929SDavid van Moolenbroek 	short *whatp = ptr;
402e985b929SDavid van Moolenbroek 	if (!have_closed)
403e985b929SDavid van Moolenbroek 		premature_event = 1;
404e985b929SDavid van Moolenbroek 	*whatp = what;
405e985b929SDavid van Moolenbroek 	TT_BLATHER(("Recorded %d on socket %d", (int)what, (int)s));
406e985b929SDavid van Moolenbroek }
407e985b929SDavid van Moolenbroek 
408e985b929SDavid van Moolenbroek static void
test_simpleclose(void * ptr)409e985b929SDavid van Moolenbroek test_simpleclose(void *ptr)
410e985b929SDavid van Moolenbroek {
411e985b929SDavid van Moolenbroek 	/* Test that a close of FD is detected as a read and as a write. */
412e985b929SDavid van Moolenbroek 	struct event_base *base = event_base_new();
413e985b929SDavid van Moolenbroek 	evutil_socket_t pair1[2]={-1,-1}, pair2[2] = {-1, -1};
414e985b929SDavid van Moolenbroek 	evutil_socket_t *to_close[2];
415e985b929SDavid van Moolenbroek 	struct event *rev=NULL, *wev=NULL, *closeev=NULL;
416e985b929SDavid van Moolenbroek 	struct timeval tv;
417e985b929SDavid van Moolenbroek 	short got_read_on_close = 0, got_write_on_close = 0;
418e985b929SDavid van Moolenbroek 	char buf[1024];
419e985b929SDavid van Moolenbroek 	memset(buf, 99, sizeof(buf));
420e985b929SDavid van Moolenbroek #ifdef WIN32
421e985b929SDavid van Moolenbroek #define LOCAL_SOCKETPAIR_AF AF_INET
422e985b929SDavid van Moolenbroek #else
423e985b929SDavid van Moolenbroek #define LOCAL_SOCKETPAIR_AF AF_UNIX
424e985b929SDavid van Moolenbroek #endif
425e985b929SDavid van Moolenbroek 	if (evutil_socketpair(LOCAL_SOCKETPAIR_AF, SOCK_STREAM, 0, pair1)<0)
426e985b929SDavid van Moolenbroek 		TT_DIE(("socketpair: %s", strerror(errno)));
427e985b929SDavid van Moolenbroek 	if (evutil_socketpair(LOCAL_SOCKETPAIR_AF, SOCK_STREAM, 0, pair2)<0)
428e985b929SDavid van Moolenbroek 		TT_DIE(("socketpair: %s", strerror(errno)));
429e985b929SDavid van Moolenbroek 	if (evutil_make_socket_nonblocking(pair1[1]) < 0)
430e985b929SDavid van Moolenbroek 		TT_DIE(("make_socket_nonblocking"));
431e985b929SDavid van Moolenbroek 	if (evutil_make_socket_nonblocking(pair2[1]) < 0)
432e985b929SDavid van Moolenbroek 		TT_DIE(("make_socket_nonblocking"));
433e985b929SDavid van Moolenbroek 
434e985b929SDavid van Moolenbroek 	/** Stuff pair2[1] full of data, until write fails */
435e985b929SDavid van Moolenbroek 	while (1) {
436e985b929SDavid van Moolenbroek 		int r = write(pair2[1], buf, sizeof(buf));
437e985b929SDavid van Moolenbroek 		if (r<0) {
438e985b929SDavid van Moolenbroek 			int err = evutil_socket_geterror(pair2[1]);
439e985b929SDavid van Moolenbroek 			if (! EVUTIL_ERR_RW_RETRIABLE(err))
440e985b929SDavid van Moolenbroek 				TT_DIE(("write failed strangely: %s",
441e985b929SDavid van Moolenbroek 					evutil_socket_error_to_string(err)));
442e985b929SDavid van Moolenbroek 			break;
443e985b929SDavid van Moolenbroek 		}
444e985b929SDavid van Moolenbroek 	}
445e985b929SDavid van Moolenbroek 	to_close[0] = &pair1[0];
446e985b929SDavid van Moolenbroek 	to_close[1] = &pair2[0];
447e985b929SDavid van Moolenbroek 
448e985b929SDavid van Moolenbroek 	closeev = event_new(base, -1, EV_TIMEOUT, simpleclose_close_fd_cb,
449e985b929SDavid van Moolenbroek 	    to_close);
450e985b929SDavid van Moolenbroek 	rev = event_new(base, pair1[1], EV_READ, record_event_cb,
451e985b929SDavid van Moolenbroek 	    &got_read_on_close);
452e985b929SDavid van Moolenbroek 	TT_BLATHER(("Waiting for read on %d", (int)pair1[1]));
453e985b929SDavid van Moolenbroek 	wev = event_new(base, pair2[1], EV_WRITE, record_event_cb,
454e985b929SDavid van Moolenbroek 	    &got_write_on_close);
455e985b929SDavid van Moolenbroek 	TT_BLATHER(("Waiting for write on %d", (int)pair2[1]));
456e985b929SDavid van Moolenbroek 	tv.tv_sec = 0;
457e985b929SDavid van Moolenbroek 	tv.tv_usec = 100*1000; /* Close pair1[0] after a little while, and make
458e985b929SDavid van Moolenbroek 			       * sure we get a read event. */
459e985b929SDavid van Moolenbroek 	event_add(closeev, &tv);
460e985b929SDavid van Moolenbroek 	event_add(rev, NULL);
461e985b929SDavid van Moolenbroek 	event_add(wev, NULL);
462e985b929SDavid van Moolenbroek 	/* Don't let the test go on too long. */
463e985b929SDavid van Moolenbroek 	tv.tv_sec = 0;
464e985b929SDavid van Moolenbroek 	tv.tv_usec = 200*1000;
465e985b929SDavid van Moolenbroek 	event_base_loopexit(base, &tv);
466e985b929SDavid van Moolenbroek 	event_base_loop(base, 0);
467e985b929SDavid van Moolenbroek 
468e985b929SDavid van Moolenbroek 	tt_int_op(got_read_on_close, ==, EV_READ);
469e985b929SDavid van Moolenbroek 	tt_int_op(got_write_on_close, ==, EV_WRITE);
470e985b929SDavid van Moolenbroek 	tt_int_op(premature_event, ==, 0);
471e985b929SDavid van Moolenbroek 
472e985b929SDavid van Moolenbroek end:
473e985b929SDavid van Moolenbroek 	if (pair1[0] >= 0)
474e985b929SDavid van Moolenbroek 		evutil_closesocket(pair1[0]);
475e985b929SDavid van Moolenbroek 	if (pair1[1] >= 0)
476e985b929SDavid van Moolenbroek 		evutil_closesocket(pair1[1]);
477e985b929SDavid van Moolenbroek 	if (pair2[0] >= 0)
478e985b929SDavid van Moolenbroek 		evutil_closesocket(pair2[0]);
479e985b929SDavid van Moolenbroek 	if (pair2[1] >= 0)
480e985b929SDavid van Moolenbroek 		evutil_closesocket(pair2[1]);
481e985b929SDavid van Moolenbroek 	if (rev)
482e985b929SDavid van Moolenbroek 		event_free(rev);
483e985b929SDavid van Moolenbroek 	if (wev)
484e985b929SDavid van Moolenbroek 		event_free(wev);
485e985b929SDavid van Moolenbroek 	if (closeev)
486e985b929SDavid van Moolenbroek 		event_free(closeev);
487e985b929SDavid van Moolenbroek 	if (base)
488e985b929SDavid van Moolenbroek 		event_base_free(base);
489e985b929SDavid van Moolenbroek }
490e985b929SDavid van Moolenbroek 
491e985b929SDavid van Moolenbroek 
492e985b929SDavid van Moolenbroek static void
test_multiple(void)493e985b929SDavid van Moolenbroek test_multiple(void)
494e985b929SDavid van Moolenbroek {
495e985b929SDavid van Moolenbroek 	struct event ev, ev2;
496e985b929SDavid van Moolenbroek 	int i;
497e985b929SDavid van Moolenbroek 
498e985b929SDavid van Moolenbroek 	/* Multiple read and write test */
499e985b929SDavid van Moolenbroek 	setup_test("Multiple read/write: ");
500e985b929SDavid van Moolenbroek 	memset(rbuf, 0, sizeof(rbuf));
501e985b929SDavid van Moolenbroek 	for (i = 0; i < (int)sizeof(wbuf); i++)
502e985b929SDavid van Moolenbroek 		wbuf[i] = i;
503e985b929SDavid van Moolenbroek 
504e985b929SDavid van Moolenbroek 	roff = woff = 0;
505e985b929SDavid van Moolenbroek 	usepersist = 0;
506e985b929SDavid van Moolenbroek 
507e985b929SDavid van Moolenbroek 	event_set(&ev, pair[0], EV_WRITE, multiple_write_cb, &ev);
508e985b929SDavid van Moolenbroek 	if (event_add(&ev, NULL) == -1)
509e985b929SDavid van Moolenbroek 		exit(1);
510e985b929SDavid van Moolenbroek 	event_set(&ev2, pair[1], EV_READ, multiple_read_cb, &ev2);
511e985b929SDavid van Moolenbroek 	if (event_add(&ev2, NULL) == -1)
512e985b929SDavid van Moolenbroek 		exit(1);
513e985b929SDavid van Moolenbroek 	event_dispatch();
514e985b929SDavid van Moolenbroek 
515e985b929SDavid van Moolenbroek 	if (roff == woff)
516e985b929SDavid van Moolenbroek 		test_ok = memcmp(rbuf, wbuf, sizeof(wbuf)) == 0;
517e985b929SDavid van Moolenbroek 
518e985b929SDavid van Moolenbroek 	cleanup_test();
519e985b929SDavid van Moolenbroek }
520e985b929SDavid van Moolenbroek 
521e985b929SDavid van Moolenbroek static void
test_persistent(void)522e985b929SDavid van Moolenbroek test_persistent(void)
523e985b929SDavid van Moolenbroek {
524e985b929SDavid van Moolenbroek 	struct event ev, ev2;
525e985b929SDavid van Moolenbroek 	int i;
526e985b929SDavid van Moolenbroek 
527e985b929SDavid van Moolenbroek 	/* Multiple read and write test with persist */
528e985b929SDavid van Moolenbroek 	setup_test("Persist read/write: ");
529e985b929SDavid van Moolenbroek 	memset(rbuf, 0, sizeof(rbuf));
530e985b929SDavid van Moolenbroek 	for (i = 0; i < (int)sizeof(wbuf); i++)
531e985b929SDavid van Moolenbroek 		wbuf[i] = i;
532e985b929SDavid van Moolenbroek 
533e985b929SDavid van Moolenbroek 	roff = woff = 0;
534e985b929SDavid van Moolenbroek 	usepersist = 1;
535e985b929SDavid van Moolenbroek 
536e985b929SDavid van Moolenbroek 	event_set(&ev, pair[0], EV_WRITE|EV_PERSIST, multiple_write_cb, &ev);
537e985b929SDavid van Moolenbroek 	if (event_add(&ev, NULL) == -1)
538e985b929SDavid van Moolenbroek 		exit(1);
539e985b929SDavid van Moolenbroek 	event_set(&ev2, pair[1], EV_READ|EV_PERSIST, multiple_read_cb, &ev2);
540e985b929SDavid van Moolenbroek 	if (event_add(&ev2, NULL) == -1)
541e985b929SDavid van Moolenbroek 		exit(1);
542e985b929SDavid van Moolenbroek 	event_dispatch();
543e985b929SDavid van Moolenbroek 
544e985b929SDavid van Moolenbroek 	if (roff == woff)
545e985b929SDavid van Moolenbroek 		test_ok = memcmp(rbuf, wbuf, sizeof(wbuf)) == 0;
546e985b929SDavid van Moolenbroek 
547e985b929SDavid van Moolenbroek 	cleanup_test();
548e985b929SDavid van Moolenbroek }
549e985b929SDavid van Moolenbroek 
550e985b929SDavid van Moolenbroek static void
test_combined(void)551e985b929SDavid van Moolenbroek test_combined(void)
552e985b929SDavid van Moolenbroek {
553e985b929SDavid van Moolenbroek 	struct both r1, r2, w1, w2;
554e985b929SDavid van Moolenbroek 
555e985b929SDavid van Moolenbroek 	setup_test("Combined read/write: ");
556e985b929SDavid van Moolenbroek 	memset(&r1, 0, sizeof(r1));
557e985b929SDavid van Moolenbroek 	memset(&r2, 0, sizeof(r2));
558e985b929SDavid van Moolenbroek 	memset(&w1, 0, sizeof(w1));
559e985b929SDavid van Moolenbroek 	memset(&w2, 0, sizeof(w2));
560e985b929SDavid van Moolenbroek 
561e985b929SDavid van Moolenbroek 	w1.nread = 4096;
562e985b929SDavid van Moolenbroek 	w2.nread = 8192;
563e985b929SDavid van Moolenbroek 
564e985b929SDavid van Moolenbroek 	event_set(&r1.ev, pair[0], EV_READ, combined_read_cb, &r1);
565e985b929SDavid van Moolenbroek 	event_set(&w1.ev, pair[0], EV_WRITE, combined_write_cb, &w1);
566e985b929SDavid van Moolenbroek 	event_set(&r2.ev, pair[1], EV_READ, combined_read_cb, &r2);
567e985b929SDavid van Moolenbroek 	event_set(&w2.ev, pair[1], EV_WRITE, combined_write_cb, &w2);
568e985b929SDavid van Moolenbroek 	tt_assert(event_add(&r1.ev, NULL) != -1);
569e985b929SDavid van Moolenbroek 	tt_assert(!event_add(&w1.ev, NULL));
570e985b929SDavid van Moolenbroek 	tt_assert(!event_add(&r2.ev, NULL));
571e985b929SDavid van Moolenbroek 	tt_assert(!event_add(&w2.ev, NULL));
572e985b929SDavid van Moolenbroek 	event_dispatch();
573e985b929SDavid van Moolenbroek 
574e985b929SDavid van Moolenbroek 	if (r1.nread == 8192 && r2.nread == 4096)
575e985b929SDavid van Moolenbroek 		test_ok = 1;
576e985b929SDavid van Moolenbroek 
577e985b929SDavid van Moolenbroek end:
578e985b929SDavid van Moolenbroek 	cleanup_test();
579e985b929SDavid van Moolenbroek }
580e985b929SDavid van Moolenbroek 
581e985b929SDavid van Moolenbroek static void
test_simpletimeout(void)582e985b929SDavid van Moolenbroek test_simpletimeout(void)
583e985b929SDavid van Moolenbroek {
584e985b929SDavid van Moolenbroek 	struct timeval tv;
585e985b929SDavid van Moolenbroek 	struct event ev;
586e985b929SDavid van Moolenbroek 
587e985b929SDavid van Moolenbroek 	setup_test("Simple timeout: ");
588e985b929SDavid van Moolenbroek 
589e985b929SDavid van Moolenbroek 	tv.tv_usec = 0;
590e985b929SDavid van Moolenbroek 	tv.tv_sec = SECONDS;
591e985b929SDavid van Moolenbroek 	evtimer_set(&ev, timeout_cb, NULL);
592e985b929SDavid van Moolenbroek 	evtimer_add(&ev, &tv);
593e985b929SDavid van Moolenbroek 
594e985b929SDavid van Moolenbroek 	evutil_gettimeofday(&tset, NULL);
595e985b929SDavid van Moolenbroek 	event_dispatch();
596e985b929SDavid van Moolenbroek 
597e985b929SDavid van Moolenbroek 	cleanup_test();
598e985b929SDavid van Moolenbroek }
599e985b929SDavid van Moolenbroek 
600e985b929SDavid van Moolenbroek static void
periodic_timeout_cb(evutil_socket_t fd,short event,void * arg)601e985b929SDavid van Moolenbroek periodic_timeout_cb(evutil_socket_t fd, short event, void *arg)
602e985b929SDavid van Moolenbroek {
603e985b929SDavid van Moolenbroek 	int *count = arg;
604e985b929SDavid van Moolenbroek 
605e985b929SDavid van Moolenbroek 	(*count)++;
606e985b929SDavid van Moolenbroek 	if (*count == 6) {
607e985b929SDavid van Moolenbroek 		/* call loopexit only once - on slow machines(?), it is
608e985b929SDavid van Moolenbroek 		 * apparently possible for this to get called twice. */
609e985b929SDavid van Moolenbroek 		test_ok = 1;
610e985b929SDavid van Moolenbroek 		event_base_loopexit(global_base, NULL);
611e985b929SDavid van Moolenbroek 	}
612e985b929SDavid van Moolenbroek }
613e985b929SDavid van Moolenbroek 
614e985b929SDavid van Moolenbroek static void
test_persistent_timeout(void)615e985b929SDavid van Moolenbroek test_persistent_timeout(void)
616e985b929SDavid van Moolenbroek {
617e985b929SDavid van Moolenbroek 	struct timeval tv;
618e985b929SDavid van Moolenbroek 	struct event ev;
619e985b929SDavid van Moolenbroek 	int count = 0;
620e985b929SDavid van Moolenbroek 
621e985b929SDavid van Moolenbroek 	evutil_timerclear(&tv);
622e985b929SDavid van Moolenbroek 	tv.tv_usec = 10000;
623e985b929SDavid van Moolenbroek 
624e985b929SDavid van Moolenbroek 	event_assign(&ev, global_base, -1, EV_TIMEOUT|EV_PERSIST,
625e985b929SDavid van Moolenbroek 	    periodic_timeout_cb, &count);
626e985b929SDavid van Moolenbroek 	event_add(&ev, &tv);
627e985b929SDavid van Moolenbroek 
628e985b929SDavid van Moolenbroek 	event_dispatch();
629e985b929SDavid van Moolenbroek 
630e985b929SDavid van Moolenbroek 	event_del(&ev);
631e985b929SDavid van Moolenbroek }
632e985b929SDavid van Moolenbroek 
633e985b929SDavid van Moolenbroek static void
test_persistent_timeout_jump(void * ptr)634e985b929SDavid van Moolenbroek test_persistent_timeout_jump(void *ptr)
635e985b929SDavid van Moolenbroek {
636e985b929SDavid van Moolenbroek 	struct basic_test_data *data = ptr;
637e985b929SDavid van Moolenbroek 	struct event ev;
638e985b929SDavid van Moolenbroek 	int count = 0;
639e985b929SDavid van Moolenbroek 	struct timeval msec100 = { 0, 100 * 1000 };
640e985b929SDavid van Moolenbroek 	struct timeval msec50 = { 0, 50 * 1000 };
641e985b929SDavid van Moolenbroek 
642e985b929SDavid van Moolenbroek 	event_assign(&ev, data->base, -1, EV_PERSIST, periodic_timeout_cb, &count);
643e985b929SDavid van Moolenbroek 	event_add(&ev, &msec100);
644e985b929SDavid van Moolenbroek 	/* Wait for a bit */
645e985b929SDavid van Moolenbroek #ifdef _WIN32
646e985b929SDavid van Moolenbroek 	Sleep(1000);
647e985b929SDavid van Moolenbroek #else
648e985b929SDavid van Moolenbroek 	sleep(1);
649e985b929SDavid van Moolenbroek #endif
650e985b929SDavid van Moolenbroek 	event_base_loopexit(data->base, &msec50);
651e985b929SDavid van Moolenbroek 	event_base_dispatch(data->base);
652e985b929SDavid van Moolenbroek 	tt_int_op(count, ==, 1);
653e985b929SDavid van Moolenbroek 
654e985b929SDavid van Moolenbroek end:
655e985b929SDavid van Moolenbroek 	event_del(&ev);
656e985b929SDavid van Moolenbroek }
657e985b929SDavid van Moolenbroek 
658e985b929SDavid van Moolenbroek struct persist_active_timeout_called {
659e985b929SDavid van Moolenbroek 	int n;
660e985b929SDavid van Moolenbroek 	short events[16];
661e985b929SDavid van Moolenbroek 	struct timeval tvs[16];
662e985b929SDavid van Moolenbroek };
663e985b929SDavid van Moolenbroek 
664e985b929SDavid van Moolenbroek static void
activate_cb(evutil_socket_t fd,short event,void * arg)665e985b929SDavid van Moolenbroek activate_cb(evutil_socket_t fd, short event, void *arg)
666e985b929SDavid van Moolenbroek {
667e985b929SDavid van Moolenbroek 	struct event *ev = arg;
668e985b929SDavid van Moolenbroek 	event_active(ev, EV_READ, 1);
669e985b929SDavid van Moolenbroek }
670e985b929SDavid van Moolenbroek 
671e985b929SDavid van Moolenbroek static void
persist_active_timeout_cb(evutil_socket_t fd,short event,void * arg)672e985b929SDavid van Moolenbroek persist_active_timeout_cb(evutil_socket_t fd, short event, void *arg)
673e985b929SDavid van Moolenbroek {
674e985b929SDavid van Moolenbroek 	struct persist_active_timeout_called *c = arg;
675e985b929SDavid van Moolenbroek 	if (c->n < 15) {
676e985b929SDavid van Moolenbroek 		c->events[c->n] = event;
677e985b929SDavid van Moolenbroek 		evutil_gettimeofday(&c->tvs[c->n], NULL);
678e985b929SDavid van Moolenbroek 		++c->n;
679e985b929SDavid van Moolenbroek 	}
680e985b929SDavid van Moolenbroek }
681e985b929SDavid van Moolenbroek 
682e985b929SDavid van Moolenbroek static void
test_persistent_active_timeout(void * ptr)683e985b929SDavid van Moolenbroek test_persistent_active_timeout(void *ptr)
684e985b929SDavid van Moolenbroek {
685e985b929SDavid van Moolenbroek 	struct timeval tv, tv2, tv_exit, start;
686e985b929SDavid van Moolenbroek 	struct event ev;
687e985b929SDavid van Moolenbroek 	struct persist_active_timeout_called res;
688e985b929SDavid van Moolenbroek 
689e985b929SDavid van Moolenbroek 	struct basic_test_data *data = ptr;
690e985b929SDavid van Moolenbroek 	struct event_base *base = data->base;
691e985b929SDavid van Moolenbroek 
692e985b929SDavid van Moolenbroek 	memset(&res, 0, sizeof(res));
693e985b929SDavid van Moolenbroek 
694e985b929SDavid van Moolenbroek 	tv.tv_sec = 0;
695e985b929SDavid van Moolenbroek 	tv.tv_usec = 200 * 1000;
696e985b929SDavid van Moolenbroek 	event_assign(&ev, base, -1, EV_TIMEOUT|EV_PERSIST,
697e985b929SDavid van Moolenbroek 	    persist_active_timeout_cb, &res);
698e985b929SDavid van Moolenbroek 	event_add(&ev, &tv);
699e985b929SDavid van Moolenbroek 
700e985b929SDavid van Moolenbroek 	tv2.tv_sec = 0;
701e985b929SDavid van Moolenbroek 	tv2.tv_usec = 100 * 1000;
702e985b929SDavid van Moolenbroek 	event_base_once(base, -1, EV_TIMEOUT, activate_cb, &ev, &tv2);
703e985b929SDavid van Moolenbroek 
704e985b929SDavid van Moolenbroek 	tv_exit.tv_sec = 0;
705e985b929SDavid van Moolenbroek 	tv_exit.tv_usec = 600 * 1000;
706e985b929SDavid van Moolenbroek 	event_base_loopexit(base, &tv_exit);
707e985b929SDavid van Moolenbroek 
708e985b929SDavid van Moolenbroek 	event_base_assert_ok(base);
709e985b929SDavid van Moolenbroek 	evutil_gettimeofday(&start, NULL);
710e985b929SDavid van Moolenbroek 
711e985b929SDavid van Moolenbroek 	event_base_dispatch(base);
712e985b929SDavid van Moolenbroek 	event_base_assert_ok(base);
713e985b929SDavid van Moolenbroek 
714e985b929SDavid van Moolenbroek 	tt_int_op(res.n, ==, 3);
715e985b929SDavid van Moolenbroek 	tt_int_op(res.events[0], ==, EV_READ);
716e985b929SDavid van Moolenbroek 	tt_int_op(res.events[1], ==, EV_TIMEOUT);
717e985b929SDavid van Moolenbroek 	tt_int_op(res.events[2], ==, EV_TIMEOUT);
718e985b929SDavid van Moolenbroek 	test_timeval_diff_eq(&start, &res.tvs[0], 100);
719e985b929SDavid van Moolenbroek 	test_timeval_diff_eq(&start, &res.tvs[1], 300);
720e985b929SDavid van Moolenbroek 	test_timeval_diff_eq(&start, &res.tvs[2], 500);
721e985b929SDavid van Moolenbroek end:
722e985b929SDavid van Moolenbroek 	event_del(&ev);
723e985b929SDavid van Moolenbroek }
724e985b929SDavid van Moolenbroek 
725e985b929SDavid van Moolenbroek struct common_timeout_info {
726e985b929SDavid van Moolenbroek 	struct event ev;
727e985b929SDavid van Moolenbroek 	struct timeval called_at;
728e985b929SDavid van Moolenbroek 	int which;
729e985b929SDavid van Moolenbroek 	int count;
730e985b929SDavid van Moolenbroek };
731e985b929SDavid van Moolenbroek 
732e985b929SDavid van Moolenbroek static void
common_timeout_cb(evutil_socket_t fd,short event,void * arg)733e985b929SDavid van Moolenbroek common_timeout_cb(evutil_socket_t fd, short event, void *arg)
734e985b929SDavid van Moolenbroek {
735e985b929SDavid van Moolenbroek 	struct common_timeout_info *ti = arg;
736e985b929SDavid van Moolenbroek 	++ti->count;
737e985b929SDavid van Moolenbroek 	evutil_gettimeofday(&ti->called_at, NULL);
738e985b929SDavid van Moolenbroek 	if (ti->count >= 6)
739e985b929SDavid van Moolenbroek 		event_del(&ti->ev);
740e985b929SDavid van Moolenbroek }
741e985b929SDavid van Moolenbroek 
742e985b929SDavid van Moolenbroek static void
test_common_timeout(void * ptr)743e985b929SDavid van Moolenbroek test_common_timeout(void *ptr)
744e985b929SDavid van Moolenbroek {
745e985b929SDavid van Moolenbroek 	struct basic_test_data *data = ptr;
746e985b929SDavid van Moolenbroek 
747e985b929SDavid van Moolenbroek 	struct event_base *base = data->base;
748e985b929SDavid van Moolenbroek 	int i;
749e985b929SDavid van Moolenbroek 	struct common_timeout_info info[100];
750e985b929SDavid van Moolenbroek 
751e985b929SDavid van Moolenbroek 	struct timeval now;
752e985b929SDavid van Moolenbroek 	struct timeval tmp_100_ms = { 0, 100*1000 };
753e985b929SDavid van Moolenbroek 	struct timeval tmp_200_ms = { 0, 200*1000 };
754e985b929SDavid van Moolenbroek 
755e985b929SDavid van Moolenbroek 	const struct timeval *ms_100, *ms_200;
756e985b929SDavid van Moolenbroek 
757e985b929SDavid van Moolenbroek 	ms_100 = event_base_init_common_timeout(base, &tmp_100_ms);
758e985b929SDavid van Moolenbroek 	ms_200 = event_base_init_common_timeout(base, &tmp_200_ms);
759e985b929SDavid van Moolenbroek 	tt_assert(ms_100);
760e985b929SDavid van Moolenbroek 	tt_assert(ms_200);
761e985b929SDavid van Moolenbroek 	tt_ptr_op(event_base_init_common_timeout(base, &tmp_200_ms),
762e985b929SDavid van Moolenbroek 	    ==, ms_200);
763e985b929SDavid van Moolenbroek 	tt_int_op(ms_100->tv_sec, ==, 0);
764e985b929SDavid van Moolenbroek 	tt_int_op(ms_200->tv_sec, ==, 0);
765e985b929SDavid van Moolenbroek 	tt_int_op(ms_100->tv_usec, ==, 100000|0x50000000);
766e985b929SDavid van Moolenbroek 	tt_int_op(ms_200->tv_usec, ==, 200000|0x50100000);
767e985b929SDavid van Moolenbroek 
768e985b929SDavid van Moolenbroek 	memset(info, 0, sizeof(info));
769e985b929SDavid van Moolenbroek 
770e985b929SDavid van Moolenbroek 	for (i=0; i<100; ++i) {
771e985b929SDavid van Moolenbroek 		info[i].which = i;
772e985b929SDavid van Moolenbroek 		event_assign(&info[i].ev, base, -1, EV_TIMEOUT|EV_PERSIST,
773e985b929SDavid van Moolenbroek 		    common_timeout_cb, &info[i]);
774e985b929SDavid van Moolenbroek 		if (i % 2) {
775e985b929SDavid van Moolenbroek 			event_add(&info[i].ev, ms_100);
776e985b929SDavid van Moolenbroek 		} else {
777e985b929SDavid van Moolenbroek 			event_add(&info[i].ev, ms_200);
778e985b929SDavid van Moolenbroek 		}
779e985b929SDavid van Moolenbroek 	}
780e985b929SDavid van Moolenbroek 
781e985b929SDavid van Moolenbroek 	event_base_assert_ok(base);
782e985b929SDavid van Moolenbroek 	event_base_dispatch(base);
783e985b929SDavid van Moolenbroek 
784e985b929SDavid van Moolenbroek 	evutil_gettimeofday(&now, NULL);
785e985b929SDavid van Moolenbroek 	event_base_assert_ok(base);
786e985b929SDavid van Moolenbroek 
787e985b929SDavid van Moolenbroek 	for (i=0; i<10; ++i) {
788e985b929SDavid van Moolenbroek 		struct timeval tmp;
789e985b929SDavid van Moolenbroek 		int ms_diff;
790e985b929SDavid van Moolenbroek 		tt_int_op(info[i].count, ==, 6);
791e985b929SDavid van Moolenbroek 		evutil_timersub(&now, &info[i].called_at, &tmp);
792e985b929SDavid van Moolenbroek 		ms_diff = tmp.tv_usec/1000 + tmp.tv_sec*1000;
793e985b929SDavid van Moolenbroek 		if (i % 2) {
794e985b929SDavid van Moolenbroek 			tt_int_op(ms_diff, >, 500);
795e985b929SDavid van Moolenbroek 			tt_int_op(ms_diff, <, 700);
796e985b929SDavid van Moolenbroek 		} else {
797e985b929SDavid van Moolenbroek 			tt_int_op(ms_diff, >, -100);
798e985b929SDavid van Moolenbroek 			tt_int_op(ms_diff, <, 100);
799e985b929SDavid van Moolenbroek 		}
800e985b929SDavid van Moolenbroek 	}
801e985b929SDavid van Moolenbroek 
802e985b929SDavid van Moolenbroek 	/* Make sure we can free the base with some events in. */
803e985b929SDavid van Moolenbroek 	for (i=0; i<100; ++i) {
804e985b929SDavid van Moolenbroek 		if (i % 2) {
805e985b929SDavid van Moolenbroek 			event_add(&info[i].ev, ms_100);
806e985b929SDavid van Moolenbroek 		} else {
807e985b929SDavid van Moolenbroek 			event_add(&info[i].ev, ms_200);
808e985b929SDavid van Moolenbroek 		}
809e985b929SDavid van Moolenbroek 	}
810e985b929SDavid van Moolenbroek 
811e985b929SDavid van Moolenbroek end:
812e985b929SDavid van Moolenbroek 	event_base_free(data->base); /* need to do this here before info is
813e985b929SDavid van Moolenbroek 				      * out-of-scope */
814e985b929SDavid van Moolenbroek 	data->base = NULL;
815e985b929SDavid van Moolenbroek }
816e985b929SDavid van Moolenbroek 
817e985b929SDavid van Moolenbroek #ifndef WIN32
818e985b929SDavid van Moolenbroek static void signal_cb(evutil_socket_t fd, short event, void *arg);
819e985b929SDavid van Moolenbroek 
820e985b929SDavid van Moolenbroek #define current_base event_global_current_base_
821e985b929SDavid van Moolenbroek extern struct event_base *current_base;
822e985b929SDavid van Moolenbroek 
823e985b929SDavid van Moolenbroek static void
child_signal_cb(evutil_socket_t fd,short event,void * arg)824e985b929SDavid van Moolenbroek child_signal_cb(evutil_socket_t fd, short event, void *arg)
825e985b929SDavid van Moolenbroek {
826e985b929SDavid van Moolenbroek 	struct timeval tv;
827e985b929SDavid van Moolenbroek 	int *pint = arg;
828e985b929SDavid van Moolenbroek 
829e985b929SDavid van Moolenbroek 	*pint = 1;
830e985b929SDavid van Moolenbroek 
831e985b929SDavid van Moolenbroek 	tv.tv_usec = 500000;
832e985b929SDavid van Moolenbroek 	tv.tv_sec = 0;
833e985b929SDavid van Moolenbroek 	event_loopexit(&tv);
834e985b929SDavid van Moolenbroek }
835e985b929SDavid van Moolenbroek 
836e985b929SDavid van Moolenbroek static void
test_fork(void)837e985b929SDavid van Moolenbroek test_fork(void)
838e985b929SDavid van Moolenbroek {
839e985b929SDavid van Moolenbroek 	int status, got_sigchld = 0;
840e985b929SDavid van Moolenbroek 	struct event ev, sig_ev;
841e985b929SDavid van Moolenbroek 	pid_t pid;
842e985b929SDavid van Moolenbroek 
843e985b929SDavid van Moolenbroek 	setup_test("After fork: ");
844e985b929SDavid van Moolenbroek 
845e985b929SDavid van Moolenbroek 	tt_assert(current_base);
846e985b929SDavid van Moolenbroek 	evthread_make_base_notifiable(current_base);
847e985b929SDavid van Moolenbroek 
848e985b929SDavid van Moolenbroek 	if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) {
849e985b929SDavid van Moolenbroek 		tt_fail_perror("write");
850e985b929SDavid van Moolenbroek 	}
851e985b929SDavid van Moolenbroek 
852e985b929SDavid van Moolenbroek 	event_set(&ev, pair[1], EV_READ, simple_read_cb, &ev);
853e985b929SDavid van Moolenbroek 	if (event_add(&ev, NULL) == -1)
854e985b929SDavid van Moolenbroek 		exit(1);
855e985b929SDavid van Moolenbroek 
856e985b929SDavid van Moolenbroek 	evsignal_set(&sig_ev, SIGCHLD, child_signal_cb, &got_sigchld);
857e985b929SDavid van Moolenbroek 	evsignal_add(&sig_ev, NULL);
858e985b929SDavid van Moolenbroek 
859e985b929SDavid van Moolenbroek 	event_base_assert_ok(current_base);
860e985b929SDavid van Moolenbroek 	TT_BLATHER(("Before fork"));
861e985b929SDavid van Moolenbroek 	if ((pid = regress_fork()) == 0) {
862e985b929SDavid van Moolenbroek 		/* in the child */
863e985b929SDavid van Moolenbroek 		TT_BLATHER(("In child, before reinit"));
864e985b929SDavid van Moolenbroek 		event_base_assert_ok(current_base);
865e985b929SDavid van Moolenbroek 		if (event_reinit(current_base) == -1) {
866e985b929SDavid van Moolenbroek 			fprintf(stdout, "FAILED (reinit)\n");
867e985b929SDavid van Moolenbroek 			exit(1);
868e985b929SDavid van Moolenbroek 		}
869e985b929SDavid van Moolenbroek 		TT_BLATHER(("After reinit"));
870e985b929SDavid van Moolenbroek 		event_base_assert_ok(current_base);
871e985b929SDavid van Moolenbroek 		TT_BLATHER(("After assert-ok"));
872e985b929SDavid van Moolenbroek 
873e985b929SDavid van Moolenbroek 		evsignal_del(&sig_ev);
874e985b929SDavid van Moolenbroek 
875e985b929SDavid van Moolenbroek 		called = 0;
876e985b929SDavid van Moolenbroek 
877e985b929SDavid van Moolenbroek 		event_dispatch();
878e985b929SDavid van Moolenbroek 
879e985b929SDavid van Moolenbroek 		event_base_free(current_base);
880e985b929SDavid van Moolenbroek 
881e985b929SDavid van Moolenbroek 		/* we do not send an EOF; simple_read_cb requires an EOF
882e985b929SDavid van Moolenbroek 		 * to set test_ok.  we just verify that the callback was
883e985b929SDavid van Moolenbroek 		 * called. */
884e985b929SDavid van Moolenbroek 		exit(test_ok != 0 || called != 2 ? -2 : 76);
885e985b929SDavid van Moolenbroek 	}
886e985b929SDavid van Moolenbroek 
887e985b929SDavid van Moolenbroek 	/* wait for the child to read the data */
888e985b929SDavid van Moolenbroek 	sleep(1);
889e985b929SDavid van Moolenbroek 
890e985b929SDavid van Moolenbroek 	if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) {
891e985b929SDavid van Moolenbroek 		tt_fail_perror("write");
892e985b929SDavid van Moolenbroek 	}
893e985b929SDavid van Moolenbroek 
894e985b929SDavid van Moolenbroek 	TT_BLATHER(("Before waitpid"));
895e985b929SDavid van Moolenbroek 	if (waitpid(pid, &status, 0) == -1) {
896e985b929SDavid van Moolenbroek 		fprintf(stdout, "FAILED (fork)\n");
897e985b929SDavid van Moolenbroek 		exit(1);
898e985b929SDavid van Moolenbroek 	}
899e985b929SDavid van Moolenbroek 	TT_BLATHER(("After waitpid"));
900e985b929SDavid van Moolenbroek 
901e985b929SDavid van Moolenbroek 	if (WEXITSTATUS(status) != 76) {
902e985b929SDavid van Moolenbroek 		fprintf(stdout, "FAILED (exit): %d\n", WEXITSTATUS(status));
903e985b929SDavid van Moolenbroek 		exit(1);
904e985b929SDavid van Moolenbroek 	}
905e985b929SDavid van Moolenbroek 
906e985b929SDavid van Moolenbroek 	/* test that the current event loop still works */
907e985b929SDavid van Moolenbroek 	if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) {
908e985b929SDavid van Moolenbroek 		fprintf(stderr, "%s: write\n", __func__);
909e985b929SDavid van Moolenbroek 	}
910e985b929SDavid van Moolenbroek 
911e985b929SDavid van Moolenbroek 	shutdown(pair[0], SHUT_WR);
912e985b929SDavid van Moolenbroek 
913e985b929SDavid van Moolenbroek 	event_dispatch();
914e985b929SDavid van Moolenbroek 
915e985b929SDavid van Moolenbroek 	if (!got_sigchld) {
916e985b929SDavid van Moolenbroek 		fprintf(stdout, "FAILED (sigchld)\n");
917e985b929SDavid van Moolenbroek 		exit(1);
918e985b929SDavid van Moolenbroek 	}
919e985b929SDavid van Moolenbroek 
920e985b929SDavid van Moolenbroek 	evsignal_del(&sig_ev);
921e985b929SDavid van Moolenbroek 
922e985b929SDavid van Moolenbroek 	end:
923e985b929SDavid van Moolenbroek 	cleanup_test();
924e985b929SDavid van Moolenbroek }
925e985b929SDavid van Moolenbroek 
926e985b929SDavid van Moolenbroek static void
signal_cb_sa(int sig)927e985b929SDavid van Moolenbroek signal_cb_sa(int sig)
928e985b929SDavid van Moolenbroek {
929e985b929SDavid van Moolenbroek 	test_ok = 2;
930e985b929SDavid van Moolenbroek }
931e985b929SDavid van Moolenbroek 
932e985b929SDavid van Moolenbroek static void
signal_cb(evutil_socket_t fd,short event,void * arg)933e985b929SDavid van Moolenbroek signal_cb(evutil_socket_t fd, short event, void *arg)
934e985b929SDavid van Moolenbroek {
935e985b929SDavid van Moolenbroek 	struct event *ev = arg;
936e985b929SDavid van Moolenbroek 
937e985b929SDavid van Moolenbroek 	evsignal_del(ev);
938e985b929SDavid van Moolenbroek 	test_ok = 1;
939e985b929SDavid van Moolenbroek }
940e985b929SDavid van Moolenbroek 
941e985b929SDavid van Moolenbroek static void
test_simplesignal(void)942e985b929SDavid van Moolenbroek test_simplesignal(void)
943e985b929SDavid van Moolenbroek {
944e985b929SDavid van Moolenbroek 	struct event ev;
945e985b929SDavid van Moolenbroek 	struct itimerval itv;
946e985b929SDavid van Moolenbroek 
947e985b929SDavid van Moolenbroek 	setup_test("Simple signal: ");
948e985b929SDavid van Moolenbroek 	evsignal_set(&ev, SIGALRM, signal_cb, &ev);
949e985b929SDavid van Moolenbroek 	evsignal_add(&ev, NULL);
950e985b929SDavid van Moolenbroek 	/* find bugs in which operations are re-ordered */
951e985b929SDavid van Moolenbroek 	evsignal_del(&ev);
952e985b929SDavid van Moolenbroek 	evsignal_add(&ev, NULL);
953e985b929SDavid van Moolenbroek 
954e985b929SDavid van Moolenbroek 	memset(&itv, 0, sizeof(itv));
955e985b929SDavid van Moolenbroek 	itv.it_value.tv_sec = 1;
956e985b929SDavid van Moolenbroek 	if (setitimer(ITIMER_REAL, &itv, NULL) == -1)
957e985b929SDavid van Moolenbroek 		goto skip_simplesignal;
958e985b929SDavid van Moolenbroek 
959e985b929SDavid van Moolenbroek 	event_dispatch();
960e985b929SDavid van Moolenbroek  skip_simplesignal:
961e985b929SDavid van Moolenbroek 	if (evsignal_del(&ev) == -1)
962e985b929SDavid van Moolenbroek 		test_ok = 0;
963e985b929SDavid van Moolenbroek 
964e985b929SDavid van Moolenbroek 	cleanup_test();
965e985b929SDavid van Moolenbroek }
966e985b929SDavid van Moolenbroek 
967e985b929SDavid van Moolenbroek static void
test_multiplesignal(void)968e985b929SDavid van Moolenbroek test_multiplesignal(void)
969e985b929SDavid van Moolenbroek {
970e985b929SDavid van Moolenbroek 	struct event ev_one, ev_two;
971e985b929SDavid van Moolenbroek 	struct itimerval itv;
972e985b929SDavid van Moolenbroek 
973e985b929SDavid van Moolenbroek 	setup_test("Multiple signal: ");
974e985b929SDavid van Moolenbroek 
975e985b929SDavid van Moolenbroek 	evsignal_set(&ev_one, SIGALRM, signal_cb, &ev_one);
976e985b929SDavid van Moolenbroek 	evsignal_add(&ev_one, NULL);
977e985b929SDavid van Moolenbroek 
978e985b929SDavid van Moolenbroek 	evsignal_set(&ev_two, SIGALRM, signal_cb, &ev_two);
979e985b929SDavid van Moolenbroek 	evsignal_add(&ev_two, NULL);
980e985b929SDavid van Moolenbroek 
981e985b929SDavid van Moolenbroek 	memset(&itv, 0, sizeof(itv));
982e985b929SDavid van Moolenbroek 	itv.it_value.tv_sec = 1;
983e985b929SDavid van Moolenbroek 	if (setitimer(ITIMER_REAL, &itv, NULL) == -1)
984e985b929SDavid van Moolenbroek 		goto skip_simplesignal;
985e985b929SDavid van Moolenbroek 
986e985b929SDavid van Moolenbroek 	event_dispatch();
987e985b929SDavid van Moolenbroek 
988e985b929SDavid van Moolenbroek  skip_simplesignal:
989e985b929SDavid van Moolenbroek 	if (evsignal_del(&ev_one) == -1)
990e985b929SDavid van Moolenbroek 		test_ok = 0;
991e985b929SDavid van Moolenbroek 	if (evsignal_del(&ev_two) == -1)
992e985b929SDavid van Moolenbroek 		test_ok = 0;
993e985b929SDavid van Moolenbroek 
994e985b929SDavid van Moolenbroek 	cleanup_test();
995e985b929SDavid van Moolenbroek }
996e985b929SDavid van Moolenbroek 
997e985b929SDavid van Moolenbroek static void
test_immediatesignal(void)998e985b929SDavid van Moolenbroek test_immediatesignal(void)
999e985b929SDavid van Moolenbroek {
1000e985b929SDavid van Moolenbroek 	struct event ev;
1001e985b929SDavid van Moolenbroek 
1002e985b929SDavid van Moolenbroek 	test_ok = 0;
1003e985b929SDavid van Moolenbroek 	evsignal_set(&ev, SIGUSR1, signal_cb, &ev);
1004e985b929SDavid van Moolenbroek 	evsignal_add(&ev, NULL);
1005e985b929SDavid van Moolenbroek 	raise(SIGUSR1);
1006e985b929SDavid van Moolenbroek 	event_loop(EVLOOP_NONBLOCK);
1007e985b929SDavid van Moolenbroek 	evsignal_del(&ev);
1008e985b929SDavid van Moolenbroek 	cleanup_test();
1009e985b929SDavid van Moolenbroek }
1010e985b929SDavid van Moolenbroek 
1011e985b929SDavid van Moolenbroek static void
test_signal_dealloc(void)1012e985b929SDavid van Moolenbroek test_signal_dealloc(void)
1013e985b929SDavid van Moolenbroek {
1014e985b929SDavid van Moolenbroek 	/* make sure that evsignal_event is event_del'ed and pipe closed */
1015e985b929SDavid van Moolenbroek 	struct event ev;
1016e985b929SDavid van Moolenbroek 	struct event_base *base = event_init();
1017e985b929SDavid van Moolenbroek 	evsignal_set(&ev, SIGUSR1, signal_cb, &ev);
1018e985b929SDavid van Moolenbroek 	evsignal_add(&ev, NULL);
1019e985b929SDavid van Moolenbroek 	evsignal_del(&ev);
1020e985b929SDavid van Moolenbroek 	event_base_free(base);
1021e985b929SDavid van Moolenbroek 	/* If we got here without asserting, we're fine. */
1022e985b929SDavid van Moolenbroek 	test_ok = 1;
1023e985b929SDavid van Moolenbroek 	cleanup_test();
1024e985b929SDavid van Moolenbroek }
1025e985b929SDavid van Moolenbroek 
1026e985b929SDavid van Moolenbroek static void
test_signal_pipeloss(void)1027e985b929SDavid van Moolenbroek test_signal_pipeloss(void)
1028e985b929SDavid van Moolenbroek {
1029e985b929SDavid van Moolenbroek 	/* make sure that the base1 pipe is closed correctly. */
1030e985b929SDavid van Moolenbroek 	struct event_base *base1, *base2;
1031e985b929SDavid van Moolenbroek 	int pipe1;
1032e985b929SDavid van Moolenbroek 	test_ok = 0;
1033e985b929SDavid van Moolenbroek 	base1 = event_init();
1034e985b929SDavid van Moolenbroek 	pipe1 = base1->sig.ev_signal_pair[0];
1035e985b929SDavid van Moolenbroek 	base2 = event_init();
1036e985b929SDavid van Moolenbroek 	event_base_free(base2);
1037e985b929SDavid van Moolenbroek 	event_base_free(base1);
1038e985b929SDavid van Moolenbroek 	if (close(pipe1) != -1 || errno!=EBADF) {
1039e985b929SDavid van Moolenbroek 		/* fd must be closed, so second close gives -1, EBADF */
1040e985b929SDavid van Moolenbroek 		printf("signal pipe not closed. ");
1041e985b929SDavid van Moolenbroek 		test_ok = 0;
1042e985b929SDavid van Moolenbroek 	} else {
1043e985b929SDavid van Moolenbroek 		test_ok = 1;
1044e985b929SDavid van Moolenbroek 	}
1045e985b929SDavid van Moolenbroek 	cleanup_test();
1046e985b929SDavid van Moolenbroek }
1047e985b929SDavid van Moolenbroek 
1048e985b929SDavid van Moolenbroek /*
1049e985b929SDavid van Moolenbroek  * make two bases to catch signals, use both of them.  this only works
1050e985b929SDavid van Moolenbroek  * for event mechanisms that use our signal pipe trick.	 kqueue handles
1051e985b929SDavid van Moolenbroek  * signals internally, and all interested kqueues get all the signals.
1052e985b929SDavid van Moolenbroek  */
1053e985b929SDavid van Moolenbroek static void
test_signal_switchbase(void)1054e985b929SDavid van Moolenbroek test_signal_switchbase(void)
1055e985b929SDavid van Moolenbroek {
1056e985b929SDavid van Moolenbroek 	struct event ev1, ev2;
1057e985b929SDavid van Moolenbroek 	struct event_base *base1, *base2;
1058e985b929SDavid van Moolenbroek 	int is_kqueue;
1059e985b929SDavid van Moolenbroek 	test_ok = 0;
1060e985b929SDavid van Moolenbroek 	base1 = event_init();
1061e985b929SDavid van Moolenbroek 	base2 = event_init();
1062e985b929SDavid van Moolenbroek 	is_kqueue = !strcmp(event_get_method(),"kqueue");
1063e985b929SDavid van Moolenbroek 	evsignal_set(&ev1, SIGUSR1, signal_cb, &ev1);
1064e985b929SDavid van Moolenbroek 	evsignal_set(&ev2, SIGUSR1, signal_cb, &ev2);
1065e985b929SDavid van Moolenbroek 	if (event_base_set(base1, &ev1) ||
1066e985b929SDavid van Moolenbroek 	    event_base_set(base2, &ev2) ||
1067e985b929SDavid van Moolenbroek 	    event_add(&ev1, NULL) ||
1068e985b929SDavid van Moolenbroek 	    event_add(&ev2, NULL)) {
1069e985b929SDavid van Moolenbroek 		fprintf(stderr, "%s: cannot set base, add\n", __func__);
1070e985b929SDavid van Moolenbroek 		exit(1);
1071e985b929SDavid van Moolenbroek 	}
1072e985b929SDavid van Moolenbroek 
1073e985b929SDavid van Moolenbroek 	tt_ptr_op(event_get_base(&ev1), ==, base1);
1074e985b929SDavid van Moolenbroek 	tt_ptr_op(event_get_base(&ev2), ==, base2);
1075e985b929SDavid van Moolenbroek 
1076e985b929SDavid van Moolenbroek 	test_ok = 0;
1077e985b929SDavid van Moolenbroek 	/* can handle signal before loop is called */
1078e985b929SDavid van Moolenbroek 	raise(SIGUSR1);
1079e985b929SDavid van Moolenbroek 	event_base_loop(base2, EVLOOP_NONBLOCK);
1080e985b929SDavid van Moolenbroek 	if (is_kqueue) {
1081e985b929SDavid van Moolenbroek 		if (!test_ok)
1082e985b929SDavid van Moolenbroek 			goto end;
1083e985b929SDavid van Moolenbroek 		test_ok = 0;
1084e985b929SDavid van Moolenbroek 	}
1085e985b929SDavid van Moolenbroek 	event_base_loop(base1, EVLOOP_NONBLOCK);
1086e985b929SDavid van Moolenbroek 	if (test_ok && !is_kqueue) {
1087e985b929SDavid van Moolenbroek 		test_ok = 0;
1088e985b929SDavid van Moolenbroek 
1089e985b929SDavid van Moolenbroek 		/* set base1 to handle signals */
1090e985b929SDavid van Moolenbroek 		event_base_loop(base1, EVLOOP_NONBLOCK);
1091e985b929SDavid van Moolenbroek 		raise(SIGUSR1);
1092e985b929SDavid van Moolenbroek 		event_base_loop(base1, EVLOOP_NONBLOCK);
1093e985b929SDavid van Moolenbroek 		event_base_loop(base2, EVLOOP_NONBLOCK);
1094e985b929SDavid van Moolenbroek 	}
1095e985b929SDavid van Moolenbroek end:
1096e985b929SDavid van Moolenbroek 	event_base_free(base1);
1097e985b929SDavid van Moolenbroek 	event_base_free(base2);
1098e985b929SDavid van Moolenbroek 	cleanup_test();
1099e985b929SDavid van Moolenbroek }
1100e985b929SDavid van Moolenbroek 
1101e985b929SDavid van Moolenbroek /*
1102e985b929SDavid van Moolenbroek  * assert that a signal event removed from the event queue really is
1103e985b929SDavid van Moolenbroek  * removed - with no possibility of it's parent handler being fired.
1104e985b929SDavid van Moolenbroek  */
1105e985b929SDavid van Moolenbroek static void
test_signal_assert(void)1106e985b929SDavid van Moolenbroek test_signal_assert(void)
1107e985b929SDavid van Moolenbroek {
1108e985b929SDavid van Moolenbroek 	struct event ev;
1109e985b929SDavid van Moolenbroek 	struct event_base *base = event_init();
1110e985b929SDavid van Moolenbroek 	test_ok = 0;
1111e985b929SDavid van Moolenbroek 	/* use SIGCONT so we don't kill ourselves when we signal to nowhere */
1112e985b929SDavid van Moolenbroek 	evsignal_set(&ev, SIGCONT, signal_cb, &ev);
1113e985b929SDavid van Moolenbroek 	evsignal_add(&ev, NULL);
1114e985b929SDavid van Moolenbroek 	/*
1115e985b929SDavid van Moolenbroek 	 * if evsignal_del() fails to reset the handler, it's current handler
1116e985b929SDavid van Moolenbroek 	 * will still point to evsig_handler().
1117e985b929SDavid van Moolenbroek 	 */
1118e985b929SDavid van Moolenbroek 	evsignal_del(&ev);
1119e985b929SDavid van Moolenbroek 
1120e985b929SDavid van Moolenbroek 	raise(SIGCONT);
1121e985b929SDavid van Moolenbroek #if 0
1122e985b929SDavid van Moolenbroek 	/* only way to verify we were in evsig_handler() */
1123e985b929SDavid van Moolenbroek 	/* XXXX Now there's no longer a good way. */
1124e985b929SDavid van Moolenbroek 	if (base->sig.evsig_caught)
1125e985b929SDavid van Moolenbroek 		test_ok = 0;
1126e985b929SDavid van Moolenbroek 	else
1127e985b929SDavid van Moolenbroek 		test_ok = 1;
1128e985b929SDavid van Moolenbroek #else
1129e985b929SDavid van Moolenbroek 	test_ok = 1;
1130e985b929SDavid van Moolenbroek #endif
1131e985b929SDavid van Moolenbroek 
1132e985b929SDavid van Moolenbroek 	event_base_free(base);
1133e985b929SDavid van Moolenbroek 	cleanup_test();
1134e985b929SDavid van Moolenbroek 	return;
1135e985b929SDavid van Moolenbroek }
1136e985b929SDavid van Moolenbroek 
1137e985b929SDavid van Moolenbroek /*
1138e985b929SDavid van Moolenbroek  * assert that we restore our previous signal handler properly.
1139e985b929SDavid van Moolenbroek  */
1140e985b929SDavid van Moolenbroek static void
test_signal_restore(void)1141e985b929SDavid van Moolenbroek test_signal_restore(void)
1142e985b929SDavid van Moolenbroek {
1143e985b929SDavid van Moolenbroek 	struct event ev;
1144e985b929SDavid van Moolenbroek 	struct event_base *base = event_init();
1145e985b929SDavid van Moolenbroek #ifdef _EVENT_HAVE_SIGACTION
1146e985b929SDavid van Moolenbroek 	struct sigaction sa;
1147e985b929SDavid van Moolenbroek #endif
1148e985b929SDavid van Moolenbroek 
1149e985b929SDavid van Moolenbroek 	test_ok = 0;
1150e985b929SDavid van Moolenbroek #ifdef _EVENT_HAVE_SIGACTION
1151e985b929SDavid van Moolenbroek 	sa.sa_handler = signal_cb_sa;
1152e985b929SDavid van Moolenbroek 	sa.sa_flags = 0x0;
1153e985b929SDavid van Moolenbroek 	sigemptyset(&sa.sa_mask);
1154e985b929SDavid van Moolenbroek 	if (sigaction(SIGUSR1, &sa, NULL) == -1)
1155e985b929SDavid van Moolenbroek 		goto out;
1156e985b929SDavid van Moolenbroek #else
1157e985b929SDavid van Moolenbroek 	if (signal(SIGUSR1, signal_cb_sa) == SIG_ERR)
1158e985b929SDavid van Moolenbroek 		goto out;
1159e985b929SDavid van Moolenbroek #endif
1160e985b929SDavid van Moolenbroek 	evsignal_set(&ev, SIGUSR1, signal_cb, &ev);
1161e985b929SDavid van Moolenbroek 	evsignal_add(&ev, NULL);
1162e985b929SDavid van Moolenbroek 	evsignal_del(&ev);
1163e985b929SDavid van Moolenbroek 
1164e985b929SDavid van Moolenbroek 	raise(SIGUSR1);
1165e985b929SDavid van Moolenbroek 	/* 1 == signal_cb, 2 == signal_cb_sa, we want our previous handler */
1166e985b929SDavid van Moolenbroek 	if (test_ok != 2)
1167e985b929SDavid van Moolenbroek 		test_ok = 0;
1168e985b929SDavid van Moolenbroek out:
1169e985b929SDavid van Moolenbroek 	event_base_free(base);
1170e985b929SDavid van Moolenbroek 	cleanup_test();
1171e985b929SDavid van Moolenbroek 	return;
1172e985b929SDavid van Moolenbroek }
1173e985b929SDavid van Moolenbroek 
1174e985b929SDavid van Moolenbroek static void
signal_cb_swp(int sig,short event,void * arg)1175e985b929SDavid van Moolenbroek signal_cb_swp(int sig, short event, void *arg)
1176e985b929SDavid van Moolenbroek {
1177e985b929SDavid van Moolenbroek 	called++;
1178e985b929SDavid van Moolenbroek 	if (called < 5)
1179e985b929SDavid van Moolenbroek 		raise(sig);
1180e985b929SDavid van Moolenbroek 	else
1181e985b929SDavid van Moolenbroek 		event_loopexit(NULL);
1182e985b929SDavid van Moolenbroek }
1183e985b929SDavid van Moolenbroek static void
timeout_cb_swp(evutil_socket_t fd,short event,void * arg)1184e985b929SDavid van Moolenbroek timeout_cb_swp(evutil_socket_t fd, short event, void *arg)
1185e985b929SDavid van Moolenbroek {
1186e985b929SDavid van Moolenbroek 	if (called == -1) {
1187e985b929SDavid van Moolenbroek 		struct timeval tv = {5, 0};
1188e985b929SDavid van Moolenbroek 
1189e985b929SDavid van Moolenbroek 		called = 0;
1190e985b929SDavid van Moolenbroek 		evtimer_add((struct event *)arg, &tv);
1191e985b929SDavid van Moolenbroek 		raise(SIGUSR1);
1192e985b929SDavid van Moolenbroek 		return;
1193e985b929SDavid van Moolenbroek 	}
1194e985b929SDavid van Moolenbroek 	test_ok = 0;
1195e985b929SDavid van Moolenbroek 	event_loopexit(NULL);
1196e985b929SDavid van Moolenbroek }
1197e985b929SDavid van Moolenbroek 
1198e985b929SDavid van Moolenbroek static void
test_signal_while_processing(void)1199e985b929SDavid van Moolenbroek test_signal_while_processing(void)
1200e985b929SDavid van Moolenbroek {
1201e985b929SDavid van Moolenbroek 	struct event_base *base = event_init();
1202e985b929SDavid van Moolenbroek 	struct event ev, ev_timer;
1203e985b929SDavid van Moolenbroek 	struct timeval tv = {0, 0};
1204e985b929SDavid van Moolenbroek 
1205e985b929SDavid van Moolenbroek 	setup_test("Receiving a signal while processing other signal: ");
1206e985b929SDavid van Moolenbroek 
1207e985b929SDavid van Moolenbroek 	called = -1;
1208e985b929SDavid van Moolenbroek 	test_ok = 1;
1209e985b929SDavid van Moolenbroek 	signal_set(&ev, SIGUSR1, signal_cb_swp, NULL);
1210e985b929SDavid van Moolenbroek 	signal_add(&ev, NULL);
1211e985b929SDavid van Moolenbroek 	evtimer_set(&ev_timer, timeout_cb_swp, &ev_timer);
1212e985b929SDavid van Moolenbroek 	evtimer_add(&ev_timer, &tv);
1213e985b929SDavid van Moolenbroek 	event_dispatch();
1214e985b929SDavid van Moolenbroek 
1215e985b929SDavid van Moolenbroek 	event_base_free(base);
1216e985b929SDavid van Moolenbroek 	cleanup_test();
1217e985b929SDavid van Moolenbroek 	return;
1218e985b929SDavid van Moolenbroek }
1219e985b929SDavid van Moolenbroek #endif
1220e985b929SDavid van Moolenbroek 
1221e985b929SDavid van Moolenbroek static void
test_free_active_base(void * ptr)1222e985b929SDavid van Moolenbroek test_free_active_base(void *ptr)
1223e985b929SDavid van Moolenbroek {
1224e985b929SDavid van Moolenbroek 	struct basic_test_data *data = ptr;
1225e985b929SDavid van Moolenbroek 	struct event_base *base1;
1226e985b929SDavid van Moolenbroek 	struct event ev1;
1227e985b929SDavid van Moolenbroek 
1228e985b929SDavid van Moolenbroek 	base1 = event_init();
1229e985b929SDavid van Moolenbroek 	if (base1) {
1230e985b929SDavid van Moolenbroek 		event_assign(&ev1, base1, data->pair[1], EV_READ,
1231e985b929SDavid van Moolenbroek 			     dummy_read_cb, NULL);
1232e985b929SDavid van Moolenbroek 		event_add(&ev1, NULL);
1233e985b929SDavid van Moolenbroek 		event_base_free(base1);	 /* should not crash */
1234e985b929SDavid van Moolenbroek 	} else {
1235e985b929SDavid van Moolenbroek 		tt_fail_msg("failed to create event_base for test");
1236e985b929SDavid van Moolenbroek 	}
1237e985b929SDavid van Moolenbroek 
1238e985b929SDavid van Moolenbroek 	base1 = event_init();
1239e985b929SDavid van Moolenbroek 	tt_assert(base1);
1240e985b929SDavid van Moolenbroek 	event_assign(&ev1, base1, 0, 0, dummy_read_cb, NULL);
1241e985b929SDavid van Moolenbroek 	event_active(&ev1, EV_READ, 1);
1242e985b929SDavid van Moolenbroek 	event_base_free(base1);
1243e985b929SDavid van Moolenbroek end:
1244e985b929SDavid van Moolenbroek 	;
1245e985b929SDavid van Moolenbroek }
1246e985b929SDavid van Moolenbroek 
1247e985b929SDavid van Moolenbroek static void
test_manipulate_active_events(void * ptr)1248e985b929SDavid van Moolenbroek test_manipulate_active_events(void *ptr)
1249e985b929SDavid van Moolenbroek {
1250e985b929SDavid van Moolenbroek 	struct basic_test_data *data = ptr;
1251e985b929SDavid van Moolenbroek 	struct event_base *base = data->base;
1252e985b929SDavid van Moolenbroek 	struct event ev1;
1253e985b929SDavid van Moolenbroek 
1254e985b929SDavid van Moolenbroek 	event_assign(&ev1, base, -1, EV_TIMEOUT, dummy_read_cb, NULL);
1255e985b929SDavid van Moolenbroek 
1256e985b929SDavid van Moolenbroek 	/* Make sure an active event is pending. */
1257e985b929SDavid van Moolenbroek 	event_active(&ev1, EV_READ, 1);
1258e985b929SDavid van Moolenbroek 	tt_int_op(event_pending(&ev1, EV_READ|EV_TIMEOUT|EV_WRITE, NULL),
1259e985b929SDavid van Moolenbroek 	    ==, EV_READ);
1260e985b929SDavid van Moolenbroek 
1261e985b929SDavid van Moolenbroek 	/* Make sure that activating an event twice works. */
1262e985b929SDavid van Moolenbroek 	event_active(&ev1, EV_WRITE, 1);
1263e985b929SDavid van Moolenbroek 	tt_int_op(event_pending(&ev1, EV_READ|EV_TIMEOUT|EV_WRITE, NULL),
1264e985b929SDavid van Moolenbroek 	    ==, EV_READ|EV_WRITE);
1265e985b929SDavid van Moolenbroek 
1266e985b929SDavid van Moolenbroek end:
1267e985b929SDavid van Moolenbroek 	event_del(&ev1);
1268e985b929SDavid van Moolenbroek }
1269e985b929SDavid van Moolenbroek 
1270e985b929SDavid van Moolenbroek static void
test_bad_assign(void * ptr)1271e985b929SDavid van Moolenbroek test_bad_assign(void *ptr)
1272e985b929SDavid van Moolenbroek {
1273e985b929SDavid van Moolenbroek 	struct event ev;
1274e985b929SDavid van Moolenbroek 	int r;
1275e985b929SDavid van Moolenbroek 	/* READ|SIGNAL is not allowed */
1276e985b929SDavid van Moolenbroek 	r = event_assign(&ev, NULL, -1, EV_SIGNAL|EV_READ, dummy_read_cb, NULL);
1277e985b929SDavid van Moolenbroek 	tt_int_op(r,==,-1);
1278e985b929SDavid van Moolenbroek 
1279e985b929SDavid van Moolenbroek end:
1280e985b929SDavid van Moolenbroek 	;
1281e985b929SDavid van Moolenbroek }
1282e985b929SDavid van Moolenbroek 
1283e985b929SDavid van Moolenbroek static int reentrant_cb_run = 0;
1284e985b929SDavid van Moolenbroek 
1285e985b929SDavid van Moolenbroek static void
bad_reentrant_run_loop_cb(evutil_socket_t fd,short what,void * ptr)1286e985b929SDavid van Moolenbroek bad_reentrant_run_loop_cb(evutil_socket_t fd, short what, void *ptr)
1287e985b929SDavid van Moolenbroek {
1288e985b929SDavid van Moolenbroek 	struct event_base *base = ptr;
1289e985b929SDavid van Moolenbroek 	int r;
1290e985b929SDavid van Moolenbroek 	reentrant_cb_run = 1;
1291e985b929SDavid van Moolenbroek 	/* This reentrant call to event_base_loop should be detected and
1292e985b929SDavid van Moolenbroek 	 * should fail */
1293e985b929SDavid van Moolenbroek 	r = event_base_loop(base, 0);
1294e985b929SDavid van Moolenbroek 	tt_int_op(r, ==, -1);
1295e985b929SDavid van Moolenbroek end:
1296e985b929SDavid van Moolenbroek 	;
1297e985b929SDavid van Moolenbroek }
1298e985b929SDavid van Moolenbroek 
1299e985b929SDavid van Moolenbroek static void
test_bad_reentrant(void * ptr)1300e985b929SDavid van Moolenbroek test_bad_reentrant(void *ptr)
1301e985b929SDavid van Moolenbroek {
1302e985b929SDavid van Moolenbroek 	struct basic_test_data *data = ptr;
1303e985b929SDavid van Moolenbroek 	struct event_base *base = data->base;
1304e985b929SDavid van Moolenbroek 	struct event ev;
1305e985b929SDavid van Moolenbroek 	int r;
1306e985b929SDavid van Moolenbroek 	event_assign(&ev, base, -1,
1307e985b929SDavid van Moolenbroek 	    0, bad_reentrant_run_loop_cb, base);
1308e985b929SDavid van Moolenbroek 
1309e985b929SDavid van Moolenbroek 	event_active(&ev, EV_WRITE, 1);
1310e985b929SDavid van Moolenbroek 	r = event_base_loop(base, 0);
1311e985b929SDavid van Moolenbroek 	tt_int_op(r, ==, 1);
1312e985b929SDavid van Moolenbroek 	tt_int_op(reentrant_cb_run, ==, 1);
1313e985b929SDavid van Moolenbroek end:
1314e985b929SDavid van Moolenbroek 	;
1315e985b929SDavid van Moolenbroek }
1316e985b929SDavid van Moolenbroek 
1317e985b929SDavid van Moolenbroek static void
test_event_base_new(void * ptr)1318e985b929SDavid van Moolenbroek test_event_base_new(void *ptr)
1319e985b929SDavid van Moolenbroek {
1320e985b929SDavid van Moolenbroek 	struct basic_test_data *data = ptr;
1321e985b929SDavid van Moolenbroek 	struct event_base *base = 0;
1322e985b929SDavid van Moolenbroek 	struct event ev1;
1323e985b929SDavid van Moolenbroek 	struct basic_cb_args args;
1324e985b929SDavid van Moolenbroek 
1325e985b929SDavid van Moolenbroek 	int towrite = (int)strlen(TEST1)+1;
1326e985b929SDavid van Moolenbroek 	int len = write(data->pair[0], TEST1, towrite);
1327e985b929SDavid van Moolenbroek 
1328e985b929SDavid van Moolenbroek 	if (len < 0)
1329e985b929SDavid van Moolenbroek 		tt_abort_perror("initial write");
1330e985b929SDavid van Moolenbroek 	else if (len != towrite)
1331e985b929SDavid van Moolenbroek 		tt_abort_printf(("initial write fell short (%d of %d bytes)",
1332e985b929SDavid van Moolenbroek 				 len, towrite));
1333e985b929SDavid van Moolenbroek 
1334e985b929SDavid van Moolenbroek 	if (shutdown(data->pair[0], SHUT_WR))
1335e985b929SDavid van Moolenbroek 		tt_abort_perror("initial write shutdown");
1336e985b929SDavid van Moolenbroek 
1337e985b929SDavid van Moolenbroek 	base = event_base_new();
1338e985b929SDavid van Moolenbroek 	if (!base)
1339e985b929SDavid van Moolenbroek 		tt_abort_msg("failed to create event base");
1340e985b929SDavid van Moolenbroek 
1341e985b929SDavid van Moolenbroek 	args.eb = base;
1342e985b929SDavid van Moolenbroek 	args.ev = &ev1;
1343e985b929SDavid van Moolenbroek 	args.callcount = 0;
1344e985b929SDavid van Moolenbroek 	event_assign(&ev1, base, data->pair[1],
1345e985b929SDavid van Moolenbroek 		     EV_READ|EV_PERSIST, basic_read_cb, &args);
1346e985b929SDavid van Moolenbroek 
1347e985b929SDavid van Moolenbroek 	if (event_add(&ev1, NULL))
1348e985b929SDavid van Moolenbroek 		tt_abort_perror("initial event_add");
1349e985b929SDavid van Moolenbroek 
1350e985b929SDavid van Moolenbroek 	if (event_base_loop(base, 0))
1351e985b929SDavid van Moolenbroek 		tt_abort_msg("unsuccessful exit from event loop");
1352e985b929SDavid van Moolenbroek 
1353e985b929SDavid van Moolenbroek end:
1354e985b929SDavid van Moolenbroek 	if (base)
1355e985b929SDavid van Moolenbroek 		event_base_free(base);
1356e985b929SDavid van Moolenbroek }
1357e985b929SDavid van Moolenbroek 
1358e985b929SDavid van Moolenbroek static void
test_loopexit(void)1359e985b929SDavid van Moolenbroek test_loopexit(void)
1360e985b929SDavid van Moolenbroek {
1361e985b929SDavid van Moolenbroek 	struct timeval tv, tv_start, tv_end;
1362e985b929SDavid van Moolenbroek 	struct event ev;
1363e985b929SDavid van Moolenbroek 
1364e985b929SDavid van Moolenbroek 	setup_test("Loop exit: ");
1365e985b929SDavid van Moolenbroek 
1366e985b929SDavid van Moolenbroek 	tv.tv_usec = 0;
1367e985b929SDavid van Moolenbroek 	tv.tv_sec = 60*60*24;
1368e985b929SDavid van Moolenbroek 	evtimer_set(&ev, timeout_cb, NULL);
1369e985b929SDavid van Moolenbroek 	evtimer_add(&ev, &tv);
1370e985b929SDavid van Moolenbroek 
1371e985b929SDavid van Moolenbroek 	tv.tv_usec = 0;
1372*0a6a1f1dSLionel Sambuc 	tv.tv_sec = 1;
1373e985b929SDavid van Moolenbroek 	event_loopexit(&tv);
1374e985b929SDavid van Moolenbroek 
1375e985b929SDavid van Moolenbroek 	evutil_gettimeofday(&tv_start, NULL);
1376e985b929SDavid van Moolenbroek 	event_dispatch();
1377e985b929SDavid van Moolenbroek 	evutil_gettimeofday(&tv_end, NULL);
1378e985b929SDavid van Moolenbroek 	evutil_timersub(&tv_end, &tv_start, &tv_end);
1379e985b929SDavid van Moolenbroek 
1380e985b929SDavid van Moolenbroek 	evtimer_del(&ev);
1381e985b929SDavid van Moolenbroek 
1382e985b929SDavid van Moolenbroek 	tt_assert(event_base_got_exit(global_base));
1383e985b929SDavid van Moolenbroek 	tt_assert(!event_base_got_break(global_base));
1384e985b929SDavid van Moolenbroek 
1385e985b929SDavid van Moolenbroek 	if (tv.tv_sec < 2)
1386e985b929SDavid van Moolenbroek 		test_ok = 1;
1387e985b929SDavid van Moolenbroek 
1388e985b929SDavid van Moolenbroek end:
1389e985b929SDavid van Moolenbroek 	cleanup_test();
1390e985b929SDavid van Moolenbroek }
1391e985b929SDavid van Moolenbroek 
1392e985b929SDavid van Moolenbroek static void
test_loopexit_multiple(void)1393e985b929SDavid van Moolenbroek test_loopexit_multiple(void)
1394e985b929SDavid van Moolenbroek {
1395e985b929SDavid van Moolenbroek 	struct timeval tv;
1396e985b929SDavid van Moolenbroek 	struct event_base *base;
1397e985b929SDavid van Moolenbroek 
1398e985b929SDavid van Moolenbroek 	setup_test("Loop Multiple exit: ");
1399e985b929SDavid van Moolenbroek 
1400e985b929SDavid van Moolenbroek 	base = event_base_new();
1401e985b929SDavid van Moolenbroek 
1402e985b929SDavid van Moolenbroek 	tv.tv_usec = 0;
1403e985b929SDavid van Moolenbroek 	tv.tv_sec = 1;
1404e985b929SDavid van Moolenbroek 	event_base_loopexit(base, &tv);
1405e985b929SDavid van Moolenbroek 
1406e985b929SDavid van Moolenbroek 	tv.tv_usec = 0;
1407e985b929SDavid van Moolenbroek 	tv.tv_sec = 2;
1408e985b929SDavid van Moolenbroek 	event_base_loopexit(base, &tv);
1409e985b929SDavid van Moolenbroek 
1410e985b929SDavid van Moolenbroek 	event_base_dispatch(base);
1411e985b929SDavid van Moolenbroek 
1412e985b929SDavid van Moolenbroek 	tt_assert(event_base_got_exit(base));
1413e985b929SDavid van Moolenbroek 	tt_assert(!event_base_got_break(base));
1414e985b929SDavid van Moolenbroek 
1415e985b929SDavid van Moolenbroek 	event_base_free(base);
1416e985b929SDavid van Moolenbroek 
1417e985b929SDavid van Moolenbroek 	test_ok = 1;
1418e985b929SDavid van Moolenbroek 
1419e985b929SDavid van Moolenbroek end:
1420e985b929SDavid van Moolenbroek 	cleanup_test();
1421e985b929SDavid van Moolenbroek }
1422e985b929SDavid van Moolenbroek 
1423e985b929SDavid van Moolenbroek static void
break_cb(evutil_socket_t fd,short events,void * arg)1424e985b929SDavid van Moolenbroek break_cb(evutil_socket_t fd, short events, void *arg)
1425e985b929SDavid van Moolenbroek {
1426e985b929SDavid van Moolenbroek 	test_ok = 1;
1427e985b929SDavid van Moolenbroek 	event_loopbreak();
1428e985b929SDavid van Moolenbroek }
1429e985b929SDavid van Moolenbroek 
1430e985b929SDavid van Moolenbroek static void
fail_cb(evutil_socket_t fd,short events,void * arg)1431e985b929SDavid van Moolenbroek fail_cb(evutil_socket_t fd, short events, void *arg)
1432e985b929SDavid van Moolenbroek {
1433e985b929SDavid van Moolenbroek 	test_ok = 0;
1434e985b929SDavid van Moolenbroek }
1435e985b929SDavid van Moolenbroek 
1436e985b929SDavid van Moolenbroek static void
test_loopbreak(void)1437e985b929SDavid van Moolenbroek test_loopbreak(void)
1438e985b929SDavid van Moolenbroek {
1439e985b929SDavid van Moolenbroek 	struct event ev1, ev2;
1440e985b929SDavid van Moolenbroek 	struct timeval tv;
1441e985b929SDavid van Moolenbroek 
1442e985b929SDavid van Moolenbroek 	setup_test("Loop break: ");
1443e985b929SDavid van Moolenbroek 
1444e985b929SDavid van Moolenbroek 	tv.tv_sec = 0;
1445e985b929SDavid van Moolenbroek 	tv.tv_usec = 0;
1446e985b929SDavid van Moolenbroek 	evtimer_set(&ev1, break_cb, NULL);
1447e985b929SDavid van Moolenbroek 	evtimer_add(&ev1, &tv);
1448e985b929SDavid van Moolenbroek 	evtimer_set(&ev2, fail_cb, NULL);
1449e985b929SDavid van Moolenbroek 	evtimer_add(&ev2, &tv);
1450e985b929SDavid van Moolenbroek 
1451e985b929SDavid van Moolenbroek 	event_dispatch();
1452e985b929SDavid van Moolenbroek 
1453e985b929SDavid van Moolenbroek 	tt_assert(!event_base_got_exit(global_base));
1454e985b929SDavid van Moolenbroek 	tt_assert(event_base_got_break(global_base));
1455e985b929SDavid van Moolenbroek 
1456e985b929SDavid van Moolenbroek 	evtimer_del(&ev1);
1457e985b929SDavid van Moolenbroek 	evtimer_del(&ev2);
1458e985b929SDavid van Moolenbroek 
1459e985b929SDavid van Moolenbroek end:
1460e985b929SDavid van Moolenbroek 	cleanup_test();
1461e985b929SDavid van Moolenbroek }
1462e985b929SDavid van Moolenbroek 
1463e985b929SDavid van Moolenbroek static struct event *readd_test_event_last_added = NULL;
1464e985b929SDavid van Moolenbroek static void
re_add_read_cb(evutil_socket_t fd,short event,void * arg)1465e985b929SDavid van Moolenbroek re_add_read_cb(evutil_socket_t fd, short event, void *arg)
1466e985b929SDavid van Moolenbroek {
1467e985b929SDavid van Moolenbroek 	char buf[256];
1468e985b929SDavid van Moolenbroek 	struct event *ev_other = arg;
1469e985b929SDavid van Moolenbroek 	readd_test_event_last_added = ev_other;
1470e985b929SDavid van Moolenbroek 
1471e985b929SDavid van Moolenbroek 	if (read(fd, buf, sizeof(buf)) < 0) {
1472e985b929SDavid van Moolenbroek 		tt_fail_perror("read");
1473e985b929SDavid van Moolenbroek 	}
1474e985b929SDavid van Moolenbroek 
1475e985b929SDavid van Moolenbroek 	event_add(ev_other, NULL);
1476e985b929SDavid van Moolenbroek 	++test_ok;
1477e985b929SDavid van Moolenbroek }
1478e985b929SDavid van Moolenbroek 
1479e985b929SDavid van Moolenbroek static void
test_nonpersist_readd(void)1480e985b929SDavid van Moolenbroek test_nonpersist_readd(void)
1481e985b929SDavid van Moolenbroek {
1482e985b929SDavid van Moolenbroek 	struct event ev1, ev2;
1483e985b929SDavid van Moolenbroek 
1484e985b929SDavid van Moolenbroek 	setup_test("Re-add nonpersistent events: ");
1485e985b929SDavid van Moolenbroek 	event_set(&ev1, pair[0], EV_READ, re_add_read_cb, &ev2);
1486e985b929SDavid van Moolenbroek 	event_set(&ev2, pair[1], EV_READ, re_add_read_cb, &ev1);
1487e985b929SDavid van Moolenbroek 
1488e985b929SDavid van Moolenbroek 	if (write(pair[0], "Hello", 5) < 0) {
1489e985b929SDavid van Moolenbroek 		tt_fail_perror("write(pair[0])");
1490e985b929SDavid van Moolenbroek 	}
1491e985b929SDavid van Moolenbroek 
1492e985b929SDavid van Moolenbroek 	if (write(pair[1], "Hello", 5) < 0) {
1493e985b929SDavid van Moolenbroek 		tt_fail_perror("write(pair[1])\n");
1494e985b929SDavid van Moolenbroek 	}
1495e985b929SDavid van Moolenbroek 
1496e985b929SDavid van Moolenbroek 	if (event_add(&ev1, NULL) == -1 ||
1497e985b929SDavid van Moolenbroek 	    event_add(&ev2, NULL) == -1) {
1498e985b929SDavid van Moolenbroek 		test_ok = 0;
1499e985b929SDavid van Moolenbroek 	}
1500e985b929SDavid van Moolenbroek 	if (test_ok != 0)
1501e985b929SDavid van Moolenbroek 		exit(1);
1502e985b929SDavid van Moolenbroek 	event_loop(EVLOOP_ONCE);
1503e985b929SDavid van Moolenbroek 	if (test_ok != 2)
1504e985b929SDavid van Moolenbroek 		exit(1);
1505e985b929SDavid van Moolenbroek 	/* At this point, we executed both callbacks.  Whichever one got
1506e985b929SDavid van Moolenbroek 	 * called first added the second, but the second then immediately got
1507e985b929SDavid van Moolenbroek 	 * deleted before its callback was called.  At this point, though, it
1508e985b929SDavid van Moolenbroek 	 * re-added the first.
1509e985b929SDavid van Moolenbroek 	 */
1510e985b929SDavid van Moolenbroek 	if (!readd_test_event_last_added) {
1511e985b929SDavid van Moolenbroek 		test_ok = 0;
1512e985b929SDavid van Moolenbroek 	} else if (readd_test_event_last_added == &ev1) {
1513e985b929SDavid van Moolenbroek 		if (!event_pending(&ev1, EV_READ, NULL) ||
1514e985b929SDavid van Moolenbroek 		    event_pending(&ev2, EV_READ, NULL))
1515e985b929SDavid van Moolenbroek 			test_ok = 0;
1516e985b929SDavid van Moolenbroek 	} else {
1517e985b929SDavid van Moolenbroek 		if (event_pending(&ev1, EV_READ, NULL) ||
1518e985b929SDavid van Moolenbroek 		    !event_pending(&ev2, EV_READ, NULL))
1519e985b929SDavid van Moolenbroek 			test_ok = 0;
1520e985b929SDavid van Moolenbroek 	}
1521e985b929SDavid van Moolenbroek 
1522e985b929SDavid van Moolenbroek 	event_del(&ev1);
1523e985b929SDavid van Moolenbroek 	event_del(&ev2);
1524e985b929SDavid van Moolenbroek 
1525e985b929SDavid van Moolenbroek 	cleanup_test();
1526e985b929SDavid van Moolenbroek }
1527e985b929SDavid van Moolenbroek 
1528e985b929SDavid van Moolenbroek struct test_pri_event {
1529e985b929SDavid van Moolenbroek 	struct event ev;
1530e985b929SDavid van Moolenbroek 	int count;
1531e985b929SDavid van Moolenbroek };
1532e985b929SDavid van Moolenbroek 
1533e985b929SDavid van Moolenbroek static void
test_priorities_cb(evutil_socket_t fd,short what,void * arg)1534e985b929SDavid van Moolenbroek test_priorities_cb(evutil_socket_t fd, short what, void *arg)
1535e985b929SDavid van Moolenbroek {
1536e985b929SDavid van Moolenbroek 	struct test_pri_event *pri = arg;
1537e985b929SDavid van Moolenbroek 	struct timeval tv;
1538e985b929SDavid van Moolenbroek 
1539e985b929SDavid van Moolenbroek 	if (pri->count == 3) {
1540e985b929SDavid van Moolenbroek 		event_loopexit(NULL);
1541e985b929SDavid van Moolenbroek 		return;
1542e985b929SDavid van Moolenbroek 	}
1543e985b929SDavid van Moolenbroek 
1544e985b929SDavid van Moolenbroek 	pri->count++;
1545e985b929SDavid van Moolenbroek 
1546e985b929SDavid van Moolenbroek 	evutil_timerclear(&tv);
1547e985b929SDavid van Moolenbroek 	event_add(&pri->ev, &tv);
1548e985b929SDavid van Moolenbroek }
1549e985b929SDavid van Moolenbroek 
1550e985b929SDavid van Moolenbroek static void
test_priorities_impl(int npriorities)1551e985b929SDavid van Moolenbroek test_priorities_impl(int npriorities)
1552e985b929SDavid van Moolenbroek {
1553e985b929SDavid van Moolenbroek 	struct test_pri_event one, two;
1554e985b929SDavid van Moolenbroek 	struct timeval tv;
1555e985b929SDavid van Moolenbroek 
1556e985b929SDavid van Moolenbroek 	TT_BLATHER(("Testing Priorities %d: ", npriorities));
1557e985b929SDavid van Moolenbroek 
1558e985b929SDavid van Moolenbroek 	event_base_priority_init(global_base, npriorities);
1559e985b929SDavid van Moolenbroek 
1560e985b929SDavid van Moolenbroek 	memset(&one, 0, sizeof(one));
1561e985b929SDavid van Moolenbroek 	memset(&two, 0, sizeof(two));
1562e985b929SDavid van Moolenbroek 
1563e985b929SDavid van Moolenbroek 	timeout_set(&one.ev, test_priorities_cb, &one);
1564e985b929SDavid van Moolenbroek 	if (event_priority_set(&one.ev, 0) == -1) {
1565e985b929SDavid van Moolenbroek 		fprintf(stderr, "%s: failed to set priority", __func__);
1566e985b929SDavid van Moolenbroek 		exit(1);
1567e985b929SDavid van Moolenbroek 	}
1568e985b929SDavid van Moolenbroek 
1569e985b929SDavid van Moolenbroek 	timeout_set(&two.ev, test_priorities_cb, &two);
1570e985b929SDavid van Moolenbroek 	if (event_priority_set(&two.ev, npriorities - 1) == -1) {
1571e985b929SDavid van Moolenbroek 		fprintf(stderr, "%s: failed to set priority", __func__);
1572e985b929SDavid van Moolenbroek 		exit(1);
1573e985b929SDavid van Moolenbroek 	}
1574e985b929SDavid van Moolenbroek 
1575e985b929SDavid van Moolenbroek 	evutil_timerclear(&tv);
1576e985b929SDavid van Moolenbroek 
1577e985b929SDavid van Moolenbroek 	if (event_add(&one.ev, &tv) == -1)
1578e985b929SDavid van Moolenbroek 		exit(1);
1579e985b929SDavid van Moolenbroek 	if (event_add(&two.ev, &tv) == -1)
1580e985b929SDavid van Moolenbroek 		exit(1);
1581e985b929SDavid van Moolenbroek 
1582e985b929SDavid van Moolenbroek 	event_dispatch();
1583e985b929SDavid van Moolenbroek 
1584e985b929SDavid van Moolenbroek 	event_del(&one.ev);
1585e985b929SDavid van Moolenbroek 	event_del(&two.ev);
1586e985b929SDavid van Moolenbroek 
1587e985b929SDavid van Moolenbroek 	if (npriorities == 1) {
1588e985b929SDavid van Moolenbroek 		if (one.count == 3 && two.count == 3)
1589e985b929SDavid van Moolenbroek 			test_ok = 1;
1590e985b929SDavid van Moolenbroek 	} else if (npriorities == 2) {
1591e985b929SDavid van Moolenbroek 		/* Two is called once because event_loopexit is priority 1 */
1592e985b929SDavid van Moolenbroek 		if (one.count == 3 && two.count == 1)
1593e985b929SDavid van Moolenbroek 			test_ok = 1;
1594e985b929SDavid van Moolenbroek 	} else {
1595e985b929SDavid van Moolenbroek 		if (one.count == 3 && two.count == 0)
1596e985b929SDavid van Moolenbroek 			test_ok = 1;
1597e985b929SDavid van Moolenbroek 	}
1598e985b929SDavid van Moolenbroek }
1599e985b929SDavid van Moolenbroek 
1600e985b929SDavid van Moolenbroek static void
test_priorities(void)1601e985b929SDavid van Moolenbroek test_priorities(void)
1602e985b929SDavid van Moolenbroek {
1603e985b929SDavid van Moolenbroek 	test_priorities_impl(1);
1604e985b929SDavid van Moolenbroek 	if (test_ok)
1605e985b929SDavid van Moolenbroek 		test_priorities_impl(2);
1606e985b929SDavid van Moolenbroek 	if (test_ok)
1607e985b929SDavid van Moolenbroek 		test_priorities_impl(3);
1608e985b929SDavid van Moolenbroek }
1609e985b929SDavid van Moolenbroek 
1610e985b929SDavid van Moolenbroek /* priority-active-inversion: activate a higher-priority event, and make sure
1611e985b929SDavid van Moolenbroek  * it keeps us from running a lower-priority event first. */
1612e985b929SDavid van Moolenbroek static int n_pai_calls = 0;
1613e985b929SDavid van Moolenbroek static struct event pai_events[3];
1614e985b929SDavid van Moolenbroek 
1615e985b929SDavid van Moolenbroek static void
prio_active_inversion_cb(evutil_socket_t fd,short what,void * arg)1616e985b929SDavid van Moolenbroek prio_active_inversion_cb(evutil_socket_t fd, short what, void *arg)
1617e985b929SDavid van Moolenbroek {
1618e985b929SDavid van Moolenbroek 	int *call_order = arg;
1619e985b929SDavid van Moolenbroek 	*call_order = n_pai_calls++;
1620e985b929SDavid van Moolenbroek 	if (n_pai_calls == 1) {
1621e985b929SDavid van Moolenbroek 		/* This should activate later, even though it shares a
1622e985b929SDavid van Moolenbroek 		   priority with us. */
1623e985b929SDavid van Moolenbroek 		event_active(&pai_events[1], EV_READ, 1);
1624e985b929SDavid van Moolenbroek 		/* This should activate next, since its priority is higher,
1625e985b929SDavid van Moolenbroek 		   even though we activated it second. */
1626e985b929SDavid van Moolenbroek 		event_active(&pai_events[2], EV_TIMEOUT, 1);
1627e985b929SDavid van Moolenbroek 	}
1628e985b929SDavid van Moolenbroek }
1629e985b929SDavid van Moolenbroek 
1630e985b929SDavid van Moolenbroek static void
test_priority_active_inversion(void * data_)1631e985b929SDavid van Moolenbroek test_priority_active_inversion(void *data_)
1632e985b929SDavid van Moolenbroek {
1633e985b929SDavid van Moolenbroek 	struct basic_test_data *data = data_;
1634e985b929SDavid van Moolenbroek 	struct event_base *base = data->base;
1635e985b929SDavid van Moolenbroek 	int call_order[3];
1636e985b929SDavid van Moolenbroek 	int i;
1637e985b929SDavid van Moolenbroek 	tt_int_op(event_base_priority_init(base, 8), ==, 0);
1638e985b929SDavid van Moolenbroek 
1639e985b929SDavid van Moolenbroek 	n_pai_calls = 0;
1640e985b929SDavid van Moolenbroek 	memset(call_order, 0, sizeof(call_order));
1641e985b929SDavid van Moolenbroek 
1642e985b929SDavid van Moolenbroek 	for (i=0;i<3;++i) {
1643e985b929SDavid van Moolenbroek 		event_assign(&pai_events[i], data->base, -1, 0,
1644e985b929SDavid van Moolenbroek 		    prio_active_inversion_cb, &call_order[i]);
1645e985b929SDavid van Moolenbroek 	}
1646e985b929SDavid van Moolenbroek 
1647e985b929SDavid van Moolenbroek 	event_priority_set(&pai_events[0], 4);
1648e985b929SDavid van Moolenbroek 	event_priority_set(&pai_events[1], 4);
1649e985b929SDavid van Moolenbroek 	event_priority_set(&pai_events[2], 0);
1650e985b929SDavid van Moolenbroek 
1651e985b929SDavid van Moolenbroek 	event_active(&pai_events[0], EV_WRITE, 1);
1652e985b929SDavid van Moolenbroek 
1653e985b929SDavid van Moolenbroek 	event_base_dispatch(base);
1654e985b929SDavid van Moolenbroek 	tt_int_op(n_pai_calls, ==, 3);
1655e985b929SDavid van Moolenbroek 	tt_int_op(call_order[0], ==, 0);
1656e985b929SDavid van Moolenbroek 	tt_int_op(call_order[1], ==, 2);
1657e985b929SDavid van Moolenbroek 	tt_int_op(call_order[2], ==, 1);
1658e985b929SDavid van Moolenbroek end:
1659e985b929SDavid van Moolenbroek 	;
1660e985b929SDavid van Moolenbroek }
1661e985b929SDavid van Moolenbroek 
1662e985b929SDavid van Moolenbroek 
1663e985b929SDavid van Moolenbroek static void
test_multiple_cb(evutil_socket_t fd,short event,void * arg)1664e985b929SDavid van Moolenbroek test_multiple_cb(evutil_socket_t fd, short event, void *arg)
1665e985b929SDavid van Moolenbroek {
1666e985b929SDavid van Moolenbroek 	if (event & EV_READ)
1667e985b929SDavid van Moolenbroek 		test_ok |= 1;
1668e985b929SDavid van Moolenbroek 	else if (event & EV_WRITE)
1669e985b929SDavid van Moolenbroek 		test_ok |= 2;
1670e985b929SDavid van Moolenbroek }
1671e985b929SDavid van Moolenbroek 
1672e985b929SDavid van Moolenbroek static void
test_multiple_events_for_same_fd(void)1673e985b929SDavid van Moolenbroek test_multiple_events_for_same_fd(void)
1674e985b929SDavid van Moolenbroek {
1675e985b929SDavid van Moolenbroek    struct event e1, e2;
1676e985b929SDavid van Moolenbroek 
1677e985b929SDavid van Moolenbroek    setup_test("Multiple events for same fd: ");
1678e985b929SDavid van Moolenbroek 
1679e985b929SDavid van Moolenbroek    event_set(&e1, pair[0], EV_READ, test_multiple_cb, NULL);
1680e985b929SDavid van Moolenbroek    event_add(&e1, NULL);
1681e985b929SDavid van Moolenbroek    event_set(&e2, pair[0], EV_WRITE, test_multiple_cb, NULL);
1682e985b929SDavid van Moolenbroek    event_add(&e2, NULL);
1683e985b929SDavid van Moolenbroek    event_loop(EVLOOP_ONCE);
1684e985b929SDavid van Moolenbroek    event_del(&e2);
1685e985b929SDavid van Moolenbroek 
1686e985b929SDavid van Moolenbroek    if (write(pair[1], TEST1, strlen(TEST1)+1) < 0) {
1687e985b929SDavid van Moolenbroek 	   tt_fail_perror("write");
1688e985b929SDavid van Moolenbroek    }
1689e985b929SDavid van Moolenbroek 
1690e985b929SDavid van Moolenbroek    event_loop(EVLOOP_ONCE);
1691e985b929SDavid van Moolenbroek    event_del(&e1);
1692e985b929SDavid van Moolenbroek 
1693e985b929SDavid van Moolenbroek    if (test_ok != 3)
1694e985b929SDavid van Moolenbroek 	   test_ok = 0;
1695e985b929SDavid van Moolenbroek 
1696e985b929SDavid van Moolenbroek    cleanup_test();
1697e985b929SDavid van Moolenbroek }
1698e985b929SDavid van Moolenbroek 
1699e985b929SDavid van Moolenbroek int evtag_decode_int(ev_uint32_t *pnumber, struct evbuffer *evbuf);
1700e985b929SDavid van Moolenbroek int evtag_decode_int64(ev_uint64_t *pnumber, struct evbuffer *evbuf);
1701e985b929SDavid van Moolenbroek int evtag_encode_tag(struct evbuffer *evbuf, ev_uint32_t number);
1702e985b929SDavid van Moolenbroek int evtag_decode_tag(ev_uint32_t *pnumber, struct evbuffer *evbuf);
1703e985b929SDavid van Moolenbroek 
1704e985b929SDavid van Moolenbroek static void
read_once_cb(evutil_socket_t fd,short event,void * arg)1705e985b929SDavid van Moolenbroek read_once_cb(evutil_socket_t fd, short event, void *arg)
1706e985b929SDavid van Moolenbroek {
1707e985b929SDavid van Moolenbroek 	char buf[256];
1708e985b929SDavid van Moolenbroek 	int len;
1709e985b929SDavid van Moolenbroek 
1710e985b929SDavid van Moolenbroek 	len = read(fd, buf, sizeof(buf));
1711e985b929SDavid van Moolenbroek 
1712e985b929SDavid van Moolenbroek 	if (called) {
1713e985b929SDavid van Moolenbroek 		test_ok = 0;
1714e985b929SDavid van Moolenbroek 	} else if (len) {
1715e985b929SDavid van Moolenbroek 		/* Assumes global pair[0] can be used for writing */
1716e985b929SDavid van Moolenbroek 		if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) {
1717e985b929SDavid van Moolenbroek 			tt_fail_perror("write");
1718e985b929SDavid van Moolenbroek 			test_ok = 0;
1719e985b929SDavid van Moolenbroek 		} else {
1720e985b929SDavid van Moolenbroek 			test_ok = 1;
1721e985b929SDavid van Moolenbroek 		}
1722e985b929SDavid van Moolenbroek 	}
1723e985b929SDavid van Moolenbroek 
1724e985b929SDavid van Moolenbroek 	called++;
1725e985b929SDavid van Moolenbroek }
1726e985b929SDavid van Moolenbroek 
1727e985b929SDavid van Moolenbroek static void
test_want_only_once(void)1728e985b929SDavid van Moolenbroek test_want_only_once(void)
1729e985b929SDavid van Moolenbroek {
1730e985b929SDavid van Moolenbroek 	struct event ev;
1731e985b929SDavid van Moolenbroek 	struct timeval tv;
1732e985b929SDavid van Moolenbroek 
1733e985b929SDavid van Moolenbroek 	/* Very simple read test */
1734e985b929SDavid van Moolenbroek 	setup_test("Want read only once: ");
1735e985b929SDavid van Moolenbroek 
1736e985b929SDavid van Moolenbroek 	if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) {
1737e985b929SDavid van Moolenbroek 		tt_fail_perror("write");
1738e985b929SDavid van Moolenbroek 	}
1739e985b929SDavid van Moolenbroek 
1740e985b929SDavid van Moolenbroek 	/* Setup the loop termination */
1741e985b929SDavid van Moolenbroek 	evutil_timerclear(&tv);
1742e985b929SDavid van Moolenbroek 	tv.tv_sec = 1;
1743e985b929SDavid van Moolenbroek 	event_loopexit(&tv);
1744e985b929SDavid van Moolenbroek 
1745e985b929SDavid van Moolenbroek 	event_set(&ev, pair[1], EV_READ, read_once_cb, &ev);
1746e985b929SDavid van Moolenbroek 	if (event_add(&ev, NULL) == -1)
1747e985b929SDavid van Moolenbroek 		exit(1);
1748e985b929SDavid van Moolenbroek 	event_dispatch();
1749e985b929SDavid van Moolenbroek 
1750e985b929SDavid van Moolenbroek 	cleanup_test();
1751e985b929SDavid van Moolenbroek }
1752e985b929SDavid van Moolenbroek 
1753e985b929SDavid van Moolenbroek #define TEST_MAX_INT	6
1754e985b929SDavid van Moolenbroek 
1755e985b929SDavid van Moolenbroek static void
evtag_int_test(void * ptr)1756e985b929SDavid van Moolenbroek evtag_int_test(void *ptr)
1757e985b929SDavid van Moolenbroek {
1758e985b929SDavid van Moolenbroek 	struct evbuffer *tmp = evbuffer_new();
1759e985b929SDavid van Moolenbroek 	ev_uint32_t integers[TEST_MAX_INT] = {
1760e985b929SDavid van Moolenbroek 		0xaf0, 0x1000, 0x1, 0xdeadbeef, 0x00, 0xbef000
1761e985b929SDavid van Moolenbroek 	};
1762e985b929SDavid van Moolenbroek 	ev_uint32_t integer;
1763e985b929SDavid van Moolenbroek 	ev_uint64_t big_int;
1764e985b929SDavid van Moolenbroek 	int i;
1765e985b929SDavid van Moolenbroek 
1766e985b929SDavid van Moolenbroek 	evtag_init();
1767e985b929SDavid van Moolenbroek 
1768e985b929SDavid van Moolenbroek 	for (i = 0; i < TEST_MAX_INT; i++) {
1769e985b929SDavid van Moolenbroek 		int oldlen, newlen;
1770e985b929SDavid van Moolenbroek 		oldlen = (int)EVBUFFER_LENGTH(tmp);
1771e985b929SDavid van Moolenbroek 		evtag_encode_int(tmp, integers[i]);
1772e985b929SDavid van Moolenbroek 		newlen = (int)EVBUFFER_LENGTH(tmp);
1773e985b929SDavid van Moolenbroek 		TT_BLATHER(("encoded 0x%08x with %d bytes",
1774e985b929SDavid van Moolenbroek 			(unsigned)integers[i], newlen - oldlen));
1775e985b929SDavid van Moolenbroek 		big_int = integers[i];
1776e985b929SDavid van Moolenbroek 		big_int *= 1000000000; /* 1 billion */
1777e985b929SDavid van Moolenbroek 		evtag_encode_int64(tmp, big_int);
1778e985b929SDavid van Moolenbroek 	}
1779e985b929SDavid van Moolenbroek 
1780e985b929SDavid van Moolenbroek 	for (i = 0; i < TEST_MAX_INT; i++) {
1781e985b929SDavid van Moolenbroek 		tt_int_op(evtag_decode_int(&integer, tmp), !=, -1);
1782e985b929SDavid van Moolenbroek 		tt_uint_op(integer, ==, integers[i]);
1783e985b929SDavid van Moolenbroek 		tt_int_op(evtag_decode_int64(&big_int, tmp), !=, -1);
1784e985b929SDavid van Moolenbroek 		tt_assert((big_int / 1000000000) == integers[i]);
1785e985b929SDavid van Moolenbroek 	}
1786e985b929SDavid van Moolenbroek 
1787e985b929SDavid van Moolenbroek 	tt_uint_op(EVBUFFER_LENGTH(tmp), ==, 0);
1788e985b929SDavid van Moolenbroek end:
1789e985b929SDavid van Moolenbroek 	evbuffer_free(tmp);
1790e985b929SDavid van Moolenbroek }
1791e985b929SDavid van Moolenbroek 
1792e985b929SDavid van Moolenbroek static void
evtag_fuzz(void * ptr)1793e985b929SDavid van Moolenbroek evtag_fuzz(void *ptr)
1794e985b929SDavid van Moolenbroek {
1795e985b929SDavid van Moolenbroek 	u_char buffer[4096];
1796e985b929SDavid van Moolenbroek 	struct evbuffer *tmp = evbuffer_new();
1797e985b929SDavid van Moolenbroek 	struct timeval tv;
1798e985b929SDavid van Moolenbroek 	int i, j;
1799e985b929SDavid van Moolenbroek 
1800e985b929SDavid van Moolenbroek 	int not_failed = 0;
1801e985b929SDavid van Moolenbroek 
1802e985b929SDavid van Moolenbroek 	evtag_init();
1803e985b929SDavid van Moolenbroek 
1804e985b929SDavid van Moolenbroek 	for (j = 0; j < 100; j++) {
1805e985b929SDavid van Moolenbroek 		for (i = 0; i < (int)sizeof(buffer); i++)
1806e985b929SDavid van Moolenbroek 			buffer[i] = rand();
1807e985b929SDavid van Moolenbroek 		evbuffer_drain(tmp, -1);
1808e985b929SDavid van Moolenbroek 		evbuffer_add(tmp, buffer, sizeof(buffer));
1809e985b929SDavid van Moolenbroek 
1810e985b929SDavid van Moolenbroek 		if (evtag_unmarshal_timeval(tmp, 0, &tv) != -1)
1811e985b929SDavid van Moolenbroek 			not_failed++;
1812e985b929SDavid van Moolenbroek 	}
1813e985b929SDavid van Moolenbroek 
1814e985b929SDavid van Moolenbroek 	/* The majority of decodes should fail */
1815e985b929SDavid van Moolenbroek 	tt_int_op(not_failed, <, 10);
1816e985b929SDavid van Moolenbroek 
1817e985b929SDavid van Moolenbroek 	/* Now insert some corruption into the tag length field */
1818e985b929SDavid van Moolenbroek 	evbuffer_drain(tmp, -1);
1819e985b929SDavid van Moolenbroek 	evutil_timerclear(&tv);
1820e985b929SDavid van Moolenbroek 	tv.tv_sec = 1;
1821e985b929SDavid van Moolenbroek 	evtag_marshal_timeval(tmp, 0, &tv);
1822e985b929SDavid van Moolenbroek 	evbuffer_add(tmp, buffer, sizeof(buffer));
1823e985b929SDavid van Moolenbroek 
1824e985b929SDavid van Moolenbroek 	((char *)EVBUFFER_DATA(tmp))[1] = '\xff';
1825e985b929SDavid van Moolenbroek 	if (evtag_unmarshal_timeval(tmp, 0, &tv) != -1) {
1826e985b929SDavid van Moolenbroek 		tt_abort_msg("evtag_unmarshal_timeval should have failed");
1827e985b929SDavid van Moolenbroek 	}
1828e985b929SDavid van Moolenbroek 
1829e985b929SDavid van Moolenbroek end:
1830e985b929SDavid van Moolenbroek 	evbuffer_free(tmp);
1831e985b929SDavid van Moolenbroek }
1832e985b929SDavid van Moolenbroek 
1833e985b929SDavid van Moolenbroek static void
evtag_tag_encoding(void * ptr)1834e985b929SDavid van Moolenbroek evtag_tag_encoding(void *ptr)
1835e985b929SDavid van Moolenbroek {
1836e985b929SDavid van Moolenbroek 	struct evbuffer *tmp = evbuffer_new();
1837e985b929SDavid van Moolenbroek 	ev_uint32_t integers[TEST_MAX_INT] = {
1838e985b929SDavid van Moolenbroek 		0xaf0, 0x1000, 0x1, 0xdeadbeef, 0x00, 0xbef000
1839e985b929SDavid van Moolenbroek 	};
1840e985b929SDavid van Moolenbroek 	ev_uint32_t integer;
1841e985b929SDavid van Moolenbroek 	int i;
1842e985b929SDavid van Moolenbroek 
1843e985b929SDavid van Moolenbroek 	evtag_init();
1844e985b929SDavid van Moolenbroek 
1845e985b929SDavid van Moolenbroek 	for (i = 0; i < TEST_MAX_INT; i++) {
1846e985b929SDavid van Moolenbroek 		int oldlen, newlen;
1847e985b929SDavid van Moolenbroek 		oldlen = (int)EVBUFFER_LENGTH(tmp);
1848e985b929SDavid van Moolenbroek 		evtag_encode_tag(tmp, integers[i]);
1849e985b929SDavid van Moolenbroek 		newlen = (int)EVBUFFER_LENGTH(tmp);
1850e985b929SDavid van Moolenbroek 		TT_BLATHER(("encoded 0x%08x with %d bytes",
1851e985b929SDavid van Moolenbroek 			(unsigned)integers[i], newlen - oldlen));
1852e985b929SDavid van Moolenbroek 	}
1853e985b929SDavid van Moolenbroek 
1854e985b929SDavid van Moolenbroek 	for (i = 0; i < TEST_MAX_INT; i++) {
1855e985b929SDavid van Moolenbroek 		tt_int_op(evtag_decode_tag(&integer, tmp), !=, -1);
1856e985b929SDavid van Moolenbroek 		tt_uint_op(integer, ==, integers[i]);
1857e985b929SDavid van Moolenbroek 	}
1858e985b929SDavid van Moolenbroek 
1859e985b929SDavid van Moolenbroek 	tt_uint_op(EVBUFFER_LENGTH(tmp), ==, 0);
1860e985b929SDavid van Moolenbroek 
1861e985b929SDavid van Moolenbroek end:
1862e985b929SDavid van Moolenbroek 	evbuffer_free(tmp);
1863e985b929SDavid van Moolenbroek }
1864e985b929SDavid van Moolenbroek 
1865e985b929SDavid van Moolenbroek static void
evtag_test_peek(void * ptr)1866e985b929SDavid van Moolenbroek evtag_test_peek(void *ptr)
1867e985b929SDavid van Moolenbroek {
1868e985b929SDavid van Moolenbroek 	struct evbuffer *tmp = evbuffer_new();
1869e985b929SDavid van Moolenbroek 	ev_uint32_t u32;
1870e985b929SDavid van Moolenbroek 
1871e985b929SDavid van Moolenbroek 	evtag_marshal_int(tmp, 30, 0);
1872e985b929SDavid van Moolenbroek 	evtag_marshal_string(tmp, 40, "Hello world");
1873e985b929SDavid van Moolenbroek 
1874e985b929SDavid van Moolenbroek 	tt_int_op(evtag_peek(tmp, &u32), ==, 1);
1875e985b929SDavid van Moolenbroek 	tt_int_op(u32, ==, 30);
1876e985b929SDavid van Moolenbroek 	tt_int_op(evtag_peek_length(tmp, &u32), ==, 0);
1877e985b929SDavid van Moolenbroek 	tt_int_op(u32, ==, 1+1+1);
1878e985b929SDavid van Moolenbroek 	tt_int_op(evtag_consume(tmp), ==, 0);
1879e985b929SDavid van Moolenbroek 
1880e985b929SDavid van Moolenbroek 	tt_int_op(evtag_peek(tmp, &u32), ==, 1);
1881e985b929SDavid van Moolenbroek 	tt_int_op(u32, ==, 40);
1882e985b929SDavid van Moolenbroek 	tt_int_op(evtag_peek_length(tmp, &u32), ==, 0);
1883e985b929SDavid van Moolenbroek 	tt_int_op(u32, ==, 1+1+11);
1884e985b929SDavid van Moolenbroek 	tt_int_op(evtag_payload_length(tmp, &u32), ==, 0);
1885e985b929SDavid van Moolenbroek 	tt_int_op(u32, ==, 11);
1886e985b929SDavid van Moolenbroek 
1887e985b929SDavid van Moolenbroek end:
1888e985b929SDavid van Moolenbroek 	evbuffer_free(tmp);
1889e985b929SDavid van Moolenbroek }
1890e985b929SDavid van Moolenbroek 
1891e985b929SDavid van Moolenbroek 
1892e985b929SDavid van Moolenbroek static void
test_methods(void * ptr)1893e985b929SDavid van Moolenbroek test_methods(void *ptr)
1894e985b929SDavid van Moolenbroek {
1895e985b929SDavid van Moolenbroek 	const char **methods = event_get_supported_methods();
1896e985b929SDavid van Moolenbroek 	struct event_config *cfg = NULL;
1897e985b929SDavid van Moolenbroek 	struct event_base *base = NULL;
1898e985b929SDavid van Moolenbroek 	const char *backend;
1899e985b929SDavid van Moolenbroek 	int n_methods = 0;
1900e985b929SDavid van Moolenbroek 
1901e985b929SDavid van Moolenbroek 	tt_assert(methods);
1902e985b929SDavid van Moolenbroek 
1903e985b929SDavid van Moolenbroek 	backend = methods[0];
1904e985b929SDavid van Moolenbroek 	while (*methods != NULL) {
1905e985b929SDavid van Moolenbroek 		TT_BLATHER(("Support method: %s", *methods));
1906e985b929SDavid van Moolenbroek 		++methods;
1907e985b929SDavid van Moolenbroek 		++n_methods;
1908e985b929SDavid van Moolenbroek 	}
1909e985b929SDavid van Moolenbroek 
1910e985b929SDavid van Moolenbroek 	cfg = event_config_new();
1911e985b929SDavid van Moolenbroek 	assert(cfg != NULL);
1912e985b929SDavid van Moolenbroek 
1913e985b929SDavid van Moolenbroek 	tt_int_op(event_config_avoid_method(cfg, backend), ==, 0);
1914e985b929SDavid van Moolenbroek 	event_config_set_flag(cfg, EVENT_BASE_FLAG_IGNORE_ENV);
1915e985b929SDavid van Moolenbroek 
1916e985b929SDavid van Moolenbroek 	base = event_base_new_with_config(cfg);
1917e985b929SDavid van Moolenbroek 	if (n_methods > 1) {
1918e985b929SDavid van Moolenbroek 		tt_assert(base);
1919e985b929SDavid van Moolenbroek 		tt_str_op(backend, !=, event_base_get_method(base));
1920e985b929SDavid van Moolenbroek 	} else {
1921e985b929SDavid van Moolenbroek 		tt_assert(base == NULL);
1922e985b929SDavid van Moolenbroek 	}
1923e985b929SDavid van Moolenbroek 
1924e985b929SDavid van Moolenbroek end:
1925e985b929SDavid van Moolenbroek 	if (base)
1926e985b929SDavid van Moolenbroek 		event_base_free(base);
1927e985b929SDavid van Moolenbroek 	if (cfg)
1928e985b929SDavid van Moolenbroek 		event_config_free(cfg);
1929e985b929SDavid van Moolenbroek }
1930e985b929SDavid van Moolenbroek 
1931e985b929SDavid van Moolenbroek static void
test_version(void * arg)1932e985b929SDavid van Moolenbroek test_version(void *arg)
1933e985b929SDavid van Moolenbroek {
1934e985b929SDavid van Moolenbroek 	const char *vstr;
1935e985b929SDavid van Moolenbroek 	ev_uint32_t vint;
1936e985b929SDavid van Moolenbroek 	int major, minor, patch, n;
1937e985b929SDavid van Moolenbroek 
1938e985b929SDavid van Moolenbroek 	vstr = event_get_version();
1939e985b929SDavid van Moolenbroek 	vint = event_get_version_number();
1940e985b929SDavid van Moolenbroek 
1941e985b929SDavid van Moolenbroek 	tt_assert(vstr);
1942e985b929SDavid van Moolenbroek 	tt_assert(vint);
1943e985b929SDavid van Moolenbroek 
1944e985b929SDavid van Moolenbroek 	tt_str_op(vstr, ==, LIBEVENT_VERSION);
1945e985b929SDavid van Moolenbroek 	tt_int_op(vint, ==, LIBEVENT_VERSION_NUMBER);
1946e985b929SDavid van Moolenbroek 
1947e985b929SDavid van Moolenbroek 	n = sscanf(vstr, "%d.%d.%d", &major, &minor, &patch);
1948e985b929SDavid van Moolenbroek 	tt_assert(3 == n);
1949e985b929SDavid van Moolenbroek 	tt_int_op((vint&0xffffff00), ==, ((major<<24)|(minor<<16)|(patch<<8)));
1950e985b929SDavid van Moolenbroek end:
1951e985b929SDavid van Moolenbroek 	;
1952e985b929SDavid van Moolenbroek }
1953e985b929SDavid van Moolenbroek 
1954e985b929SDavid van Moolenbroek static void
test_base_features(void * arg)1955e985b929SDavid van Moolenbroek test_base_features(void *arg)
1956e985b929SDavid van Moolenbroek {
1957e985b929SDavid van Moolenbroek 	struct event_base *base = NULL;
1958e985b929SDavid van Moolenbroek 	struct event_config *cfg = NULL;
1959e985b929SDavid van Moolenbroek 
1960e985b929SDavid van Moolenbroek 	cfg = event_config_new();
1961e985b929SDavid van Moolenbroek 
1962e985b929SDavid van Moolenbroek 	tt_assert(0 == event_config_require_features(cfg, EV_FEATURE_ET));
1963e985b929SDavid van Moolenbroek 
1964e985b929SDavid van Moolenbroek 	base = event_base_new_with_config(cfg);
1965e985b929SDavid van Moolenbroek 	if (base) {
1966e985b929SDavid van Moolenbroek 		tt_int_op(EV_FEATURE_ET, ==,
1967e985b929SDavid van Moolenbroek 		    event_base_get_features(base) & EV_FEATURE_ET);
1968e985b929SDavid van Moolenbroek 	} else {
1969e985b929SDavid van Moolenbroek 		base = event_base_new();
1970e985b929SDavid van Moolenbroek 		tt_int_op(0, ==, event_base_get_features(base) & EV_FEATURE_ET);
1971e985b929SDavid van Moolenbroek 	}
1972e985b929SDavid van Moolenbroek 
1973e985b929SDavid van Moolenbroek end:
1974e985b929SDavid van Moolenbroek 	if (base)
1975e985b929SDavid van Moolenbroek 		event_base_free(base);
1976e985b929SDavid van Moolenbroek 	if (cfg)
1977e985b929SDavid van Moolenbroek 		event_config_free(cfg);
1978e985b929SDavid van Moolenbroek }
1979e985b929SDavid van Moolenbroek 
1980e985b929SDavid van Moolenbroek #ifdef _EVENT_HAVE_SETENV
1981e985b929SDavid van Moolenbroek #define SETENV_OK
1982e985b929SDavid van Moolenbroek #elif !defined(_EVENT_HAVE_SETENV) && defined(_EVENT_HAVE_PUTENV)
setenv(const char * k,const char * v,int _o)1983e985b929SDavid van Moolenbroek static void setenv(const char *k, const char *v, int _o)
1984e985b929SDavid van Moolenbroek {
1985e985b929SDavid van Moolenbroek 	char b[256];
1986e985b929SDavid van Moolenbroek 	evutil_snprintf(b, sizeof(b), "%s=%s",k,v);
1987e985b929SDavid van Moolenbroek 	putenv(b);
1988e985b929SDavid van Moolenbroek }
1989e985b929SDavid van Moolenbroek #define SETENV_OK
1990e985b929SDavid van Moolenbroek #endif
1991e985b929SDavid van Moolenbroek 
1992e985b929SDavid van Moolenbroek #ifdef _EVENT_HAVE_UNSETENV
1993e985b929SDavid van Moolenbroek #define UNSETENV_OK
1994e985b929SDavid van Moolenbroek #elif !defined(_EVENT_HAVE_UNSETENV) && defined(_EVENT_HAVE_PUTENV)
unsetenv(const char * k)1995e985b929SDavid van Moolenbroek static void unsetenv(const char *k)
1996e985b929SDavid van Moolenbroek {
1997e985b929SDavid van Moolenbroek 	char b[256];
1998e985b929SDavid van Moolenbroek 	evutil_snprintf(b, sizeof(b), "%s=",k);
1999e985b929SDavid van Moolenbroek 	putenv(b);
2000e985b929SDavid van Moolenbroek }
2001e985b929SDavid van Moolenbroek #define UNSETENV_OK
2002e985b929SDavid van Moolenbroek #endif
2003e985b929SDavid van Moolenbroek 
2004e985b929SDavid van Moolenbroek #if defined(SETENV_OK) && defined(UNSETENV_OK)
2005e985b929SDavid van Moolenbroek static void
methodname_to_envvar(const char * mname,char * buf,size_t buflen)2006e985b929SDavid van Moolenbroek methodname_to_envvar(const char *mname, char *buf, size_t buflen)
2007e985b929SDavid van Moolenbroek {
2008e985b929SDavid van Moolenbroek 	char *cp;
2009e985b929SDavid van Moolenbroek 	evutil_snprintf(buf, buflen, "EVENT_NO%s", mname);
2010e985b929SDavid van Moolenbroek 	for (cp = buf; *cp; ++cp) {
2011e985b929SDavid van Moolenbroek 		*cp = EVUTIL_TOUPPER(*cp);
2012e985b929SDavid van Moolenbroek 	}
2013e985b929SDavid van Moolenbroek }
2014e985b929SDavid van Moolenbroek #endif
2015e985b929SDavid van Moolenbroek 
2016e985b929SDavid van Moolenbroek static void
test_base_environ(void * arg)2017e985b929SDavid van Moolenbroek test_base_environ(void *arg)
2018e985b929SDavid van Moolenbroek {
2019e985b929SDavid van Moolenbroek 	struct event_base *base = NULL;
2020e985b929SDavid van Moolenbroek 	struct event_config *cfg = NULL;
2021e985b929SDavid van Moolenbroek 
2022e985b929SDavid van Moolenbroek #if defined(SETENV_OK) && defined(UNSETENV_OK)
2023e985b929SDavid van Moolenbroek 	const char **basenames;
2024e985b929SDavid van Moolenbroek 	int i, n_methods=0;
2025e985b929SDavid van Moolenbroek 	char varbuf[128];
2026e985b929SDavid van Moolenbroek 	const char *defaultname, *ignoreenvname;
2027e985b929SDavid van Moolenbroek 
2028e985b929SDavid van Moolenbroek 	/* See if unsetenv works before we rely on it. */
2029e985b929SDavid van Moolenbroek 	setenv("EVENT_NOWAFFLES", "1", 1);
2030e985b929SDavid van Moolenbroek 	unsetenv("EVENT_NOWAFFLES");
2031e985b929SDavid van Moolenbroek 	if (getenv("EVENT_NOWAFFLES") != NULL) {
2032e985b929SDavid van Moolenbroek #ifndef _EVENT_HAVE_UNSETENV
2033e985b929SDavid van Moolenbroek 		TT_DECLARE("NOTE", ("Can't fake unsetenv; skipping test"));
2034e985b929SDavid van Moolenbroek #else
2035e985b929SDavid van Moolenbroek 		TT_DECLARE("NOTE", ("unsetenv doesn't work; skipping test"));
2036e985b929SDavid van Moolenbroek #endif
2037e985b929SDavid van Moolenbroek 		tt_skip();
2038e985b929SDavid van Moolenbroek 	}
2039e985b929SDavid van Moolenbroek 
2040e985b929SDavid van Moolenbroek 	basenames = event_get_supported_methods();
2041e985b929SDavid van Moolenbroek 	for (i = 0; basenames[i]; ++i) {
2042e985b929SDavid van Moolenbroek 		methodname_to_envvar(basenames[i], varbuf, sizeof(varbuf));
2043e985b929SDavid van Moolenbroek 		unsetenv(varbuf);
2044e985b929SDavid van Moolenbroek 		++n_methods;
2045e985b929SDavid van Moolenbroek 	}
2046e985b929SDavid van Moolenbroek 
2047e985b929SDavid van Moolenbroek 	base = event_base_new();
2048e985b929SDavid van Moolenbroek 	tt_assert(base);
2049e985b929SDavid van Moolenbroek 
2050e985b929SDavid van Moolenbroek 	defaultname = event_base_get_method(base);
2051e985b929SDavid van Moolenbroek 	TT_BLATHER(("default is <%s>", defaultname));
2052e985b929SDavid van Moolenbroek 	event_base_free(base);
2053e985b929SDavid van Moolenbroek 	base = NULL;
2054e985b929SDavid van Moolenbroek 
2055e985b929SDavid van Moolenbroek 	/* Can we disable the method with EVENT_NOfoo ? */
2056e985b929SDavid van Moolenbroek 	if (!strcmp(defaultname, "epoll (with changelist)")) {
2057e985b929SDavid van Moolenbroek  		setenv("EVENT_NOEPOLL", "1", 1);
2058e985b929SDavid van Moolenbroek 		ignoreenvname = "epoll";
2059e985b929SDavid van Moolenbroek 	} else {
2060e985b929SDavid van Moolenbroek 		methodname_to_envvar(defaultname, varbuf, sizeof(varbuf));
2061e985b929SDavid van Moolenbroek 		setenv(varbuf, "1", 1);
2062e985b929SDavid van Moolenbroek 		ignoreenvname = defaultname;
2063e985b929SDavid van Moolenbroek 	}
2064e985b929SDavid van Moolenbroek 
2065e985b929SDavid van Moolenbroek 	/* Use an empty cfg rather than NULL so a failure doesn't exit() */
2066e985b929SDavid van Moolenbroek 	cfg = event_config_new();
2067e985b929SDavid van Moolenbroek 	base = event_base_new_with_config(cfg);
2068e985b929SDavid van Moolenbroek 	event_config_free(cfg);
2069e985b929SDavid van Moolenbroek 	cfg = NULL;
2070e985b929SDavid van Moolenbroek 	if (n_methods == 1) {
2071e985b929SDavid van Moolenbroek 		tt_assert(!base);
2072e985b929SDavid van Moolenbroek 	} else {
2073e985b929SDavid van Moolenbroek 		tt_assert(base);
2074e985b929SDavid van Moolenbroek 		tt_str_op(defaultname, !=, event_base_get_method(base));
2075e985b929SDavid van Moolenbroek 		event_base_free(base);
2076e985b929SDavid van Moolenbroek 		base = NULL;
2077e985b929SDavid van Moolenbroek 	}
2078e985b929SDavid van Moolenbroek 
2079e985b929SDavid van Moolenbroek 	/* Can we disable looking at the environment with IGNORE_ENV ? */
2080e985b929SDavid van Moolenbroek 	cfg = event_config_new();
2081e985b929SDavid van Moolenbroek 	event_config_set_flag(cfg, EVENT_BASE_FLAG_IGNORE_ENV);
2082e985b929SDavid van Moolenbroek 	base = event_base_new_with_config(cfg);
2083e985b929SDavid van Moolenbroek 	tt_assert(base);
2084e985b929SDavid van Moolenbroek 	tt_str_op(ignoreenvname, ==, event_base_get_method(base));
2085e985b929SDavid van Moolenbroek #else
2086e985b929SDavid van Moolenbroek 	tt_skip();
2087e985b929SDavid van Moolenbroek #endif
2088e985b929SDavid van Moolenbroek 
2089e985b929SDavid van Moolenbroek end:
2090e985b929SDavid van Moolenbroek 	if (base)
2091e985b929SDavid van Moolenbroek 		event_base_free(base);
2092e985b929SDavid van Moolenbroek 	if (cfg)
2093e985b929SDavid van Moolenbroek 		event_config_free(cfg);
2094e985b929SDavid van Moolenbroek }
2095e985b929SDavid van Moolenbroek 
2096e985b929SDavid van Moolenbroek static void
read_called_once_cb(evutil_socket_t fd,short event,void * arg)2097e985b929SDavid van Moolenbroek read_called_once_cb(evutil_socket_t fd, short event, void *arg)
2098e985b929SDavid van Moolenbroek {
2099e985b929SDavid van Moolenbroek 	tt_int_op(event, ==, EV_READ);
2100e985b929SDavid van Moolenbroek 	called += 1;
2101e985b929SDavid van Moolenbroek end:
2102e985b929SDavid van Moolenbroek 	;
2103e985b929SDavid van Moolenbroek }
2104e985b929SDavid van Moolenbroek 
2105e985b929SDavid van Moolenbroek static void
timeout_called_once_cb(evutil_socket_t fd,short event,void * arg)2106e985b929SDavid van Moolenbroek timeout_called_once_cb(evutil_socket_t fd, short event, void *arg)
2107e985b929SDavid van Moolenbroek {
2108e985b929SDavid van Moolenbroek 	tt_int_op(event, ==, EV_TIMEOUT);
2109e985b929SDavid van Moolenbroek 	called += 100;
2110e985b929SDavid van Moolenbroek end:
2111e985b929SDavid van Moolenbroek 	;
2112e985b929SDavid van Moolenbroek }
2113e985b929SDavid van Moolenbroek 
2114e985b929SDavid van Moolenbroek static void
test_event_once(void * ptr)2115e985b929SDavid van Moolenbroek test_event_once(void *ptr)
2116e985b929SDavid van Moolenbroek {
2117e985b929SDavid van Moolenbroek 	struct basic_test_data *data = ptr;
2118e985b929SDavid van Moolenbroek 	struct timeval tv;
2119e985b929SDavid van Moolenbroek 	int r;
2120e985b929SDavid van Moolenbroek 
2121e985b929SDavid van Moolenbroek 	tv.tv_sec = 0;
2122e985b929SDavid van Moolenbroek 	tv.tv_usec = 50*1000;
2123e985b929SDavid van Moolenbroek 	called = 0;
2124e985b929SDavid van Moolenbroek 	r = event_base_once(data->base, data->pair[0], EV_READ,
2125e985b929SDavid van Moolenbroek 	    read_called_once_cb, NULL, NULL);
2126e985b929SDavid van Moolenbroek 	tt_int_op(r, ==, 0);
2127e985b929SDavid van Moolenbroek 	r = event_base_once(data->base, -1, EV_TIMEOUT,
2128e985b929SDavid van Moolenbroek 	    timeout_called_once_cb, NULL, &tv);
2129e985b929SDavid van Moolenbroek 	tt_int_op(r, ==, 0);
2130e985b929SDavid van Moolenbroek 	r = event_base_once(data->base, -1, 0, NULL, NULL, NULL);
2131e985b929SDavid van Moolenbroek 	tt_int_op(r, <, 0);
2132e985b929SDavid van Moolenbroek 
2133e985b929SDavid van Moolenbroek 	if (write(data->pair[1], TEST1, strlen(TEST1)+1) < 0) {
2134e985b929SDavid van Moolenbroek 		tt_fail_perror("write");
2135e985b929SDavid van Moolenbroek 	}
2136e985b929SDavid van Moolenbroek 
2137e985b929SDavid van Moolenbroek 	shutdown(data->pair[1], SHUT_WR);
2138e985b929SDavid van Moolenbroek 
2139e985b929SDavid van Moolenbroek 	event_base_dispatch(data->base);
2140e985b929SDavid van Moolenbroek 
2141e985b929SDavid van Moolenbroek 	tt_int_op(called, ==, 101);
2142e985b929SDavid van Moolenbroek end:
2143e985b929SDavid van Moolenbroek 	;
2144e985b929SDavid van Moolenbroek }
2145e985b929SDavid van Moolenbroek 
2146e985b929SDavid van Moolenbroek static void
test_event_pending(void * ptr)2147e985b929SDavid van Moolenbroek test_event_pending(void *ptr)
2148e985b929SDavid van Moolenbroek {
2149e985b929SDavid van Moolenbroek 	struct basic_test_data *data = ptr;
2150e985b929SDavid van Moolenbroek 	struct event *r=NULL, *w=NULL, *t=NULL;
2151e985b929SDavid van Moolenbroek 	struct timeval tv, now, tv2, diff;
2152e985b929SDavid van Moolenbroek 
2153e985b929SDavid van Moolenbroek 	tv.tv_sec = 0;
2154e985b929SDavid van Moolenbroek 	tv.tv_usec = 500 * 1000;
2155e985b929SDavid van Moolenbroek 	r = event_new(data->base, data->pair[0], EV_READ, simple_read_cb,
2156e985b929SDavid van Moolenbroek 	    NULL);
2157e985b929SDavid van Moolenbroek 	w = event_new(data->base, data->pair[1], EV_WRITE, simple_write_cb,
2158e985b929SDavid van Moolenbroek 	    NULL);
2159e985b929SDavid van Moolenbroek 	t = evtimer_new(data->base, timeout_cb, NULL);
2160e985b929SDavid van Moolenbroek 
2161e985b929SDavid van Moolenbroek 	tt_assert(r);
2162e985b929SDavid van Moolenbroek 	tt_assert(w);
2163e985b929SDavid van Moolenbroek 	tt_assert(t);
2164e985b929SDavid van Moolenbroek 
2165e985b929SDavid van Moolenbroek 	evutil_gettimeofday(&now, NULL);
2166e985b929SDavid van Moolenbroek 	event_add(r, NULL);
2167e985b929SDavid van Moolenbroek 	event_add(t, &tv);
2168e985b929SDavid van Moolenbroek 
2169e985b929SDavid van Moolenbroek 	tt_assert( event_pending(r, EV_READ, NULL));
2170e985b929SDavid van Moolenbroek 	tt_assert(!event_pending(w, EV_WRITE, NULL));
2171e985b929SDavid van Moolenbroek 	tt_assert(!event_pending(r, EV_WRITE, NULL));
2172e985b929SDavid van Moolenbroek 	tt_assert( event_pending(r, EV_READ|EV_WRITE, NULL));
2173e985b929SDavid van Moolenbroek 	tt_assert(!event_pending(r, EV_TIMEOUT, NULL));
2174e985b929SDavid van Moolenbroek 	tt_assert( event_pending(t, EV_TIMEOUT, NULL));
2175e985b929SDavid van Moolenbroek 	tt_assert( event_pending(t, EV_TIMEOUT, &tv2));
2176e985b929SDavid van Moolenbroek 
2177e985b929SDavid van Moolenbroek 	tt_assert(evutil_timercmp(&tv2, &now, >));
2178e985b929SDavid van Moolenbroek 	evutil_timeradd(&now, &tv, &tv);
2179e985b929SDavid van Moolenbroek 	evutil_timersub(&tv2, &tv, &diff);
2180e985b929SDavid van Moolenbroek 	tt_int_op(diff.tv_sec, ==, 0);
2181e985b929SDavid van Moolenbroek 	tt_int_op(labs(diff.tv_usec), <, 1000);
2182e985b929SDavid van Moolenbroek 
2183e985b929SDavid van Moolenbroek end:
2184e985b929SDavid van Moolenbroek 	if (r) {
2185e985b929SDavid van Moolenbroek 		event_del(r);
2186e985b929SDavid van Moolenbroek 		event_free(r);
2187e985b929SDavid van Moolenbroek 	}
2188e985b929SDavid van Moolenbroek 	if (w) {
2189e985b929SDavid van Moolenbroek 		event_del(w);
2190e985b929SDavid van Moolenbroek 		event_free(w);
2191e985b929SDavid van Moolenbroek 	}
2192e985b929SDavid van Moolenbroek 	if (t) {
2193e985b929SDavid van Moolenbroek 		event_del(t);
2194e985b929SDavid van Moolenbroek 		event_free(t);
2195e985b929SDavid van Moolenbroek 	}
2196e985b929SDavid van Moolenbroek }
2197e985b929SDavid van Moolenbroek 
2198e985b929SDavid van Moolenbroek #ifndef WIN32
2199e985b929SDavid van Moolenbroek /* You can't do this test on windows, since dup2 doesn't work on sockets */
2200e985b929SDavid van Moolenbroek 
2201e985b929SDavid van Moolenbroek static void
dfd_cb(evutil_socket_t fd,short e,void * data)2202e985b929SDavid van Moolenbroek dfd_cb(evutil_socket_t fd, short e, void *data)
2203e985b929SDavid van Moolenbroek {
2204e985b929SDavid van Moolenbroek 	*(int*)data = (int)e;
2205e985b929SDavid van Moolenbroek }
2206e985b929SDavid van Moolenbroek 
2207e985b929SDavid van Moolenbroek /* Regression test for our workaround for a fun epoll/linux related bug
2208e985b929SDavid van Moolenbroek  * where fd2 = dup(fd1); add(fd2); close(fd2); dup2(fd1,fd2); add(fd2)
2209e985b929SDavid van Moolenbroek  * will get you an EEXIST */
2210e985b929SDavid van Moolenbroek static void
test_dup_fd(void * arg)2211e985b929SDavid van Moolenbroek test_dup_fd(void *arg)
2212e985b929SDavid van Moolenbroek {
2213e985b929SDavid van Moolenbroek 	struct basic_test_data *data = arg;
2214e985b929SDavid van Moolenbroek 	struct event_base *base = data->base;
2215e985b929SDavid van Moolenbroek 	struct event *ev1=NULL, *ev2=NULL;
2216e985b929SDavid van Moolenbroek 	int fd, dfd=-1;
2217e985b929SDavid van Moolenbroek 	int ev1_got, ev2_got;
2218e985b929SDavid van Moolenbroek 
2219e985b929SDavid van Moolenbroek 	tt_int_op(write(data->pair[0], "Hello world",
2220e985b929SDavid van Moolenbroek 		strlen("Hello world")), >, 0);
2221e985b929SDavid van Moolenbroek 	fd = data->pair[1];
2222e985b929SDavid van Moolenbroek 
2223e985b929SDavid van Moolenbroek 	dfd = dup(fd);
2224e985b929SDavid van Moolenbroek 	tt_int_op(dfd, >=, 0);
2225e985b929SDavid van Moolenbroek 
2226e985b929SDavid van Moolenbroek 	ev1 = event_new(base, fd, EV_READ|EV_PERSIST, dfd_cb, &ev1_got);
2227e985b929SDavid van Moolenbroek 	ev2 = event_new(base, dfd, EV_READ|EV_PERSIST, dfd_cb, &ev2_got);
2228e985b929SDavid van Moolenbroek 	ev1_got = ev2_got = 0;
2229e985b929SDavid van Moolenbroek 	event_add(ev1, NULL);
2230e985b929SDavid van Moolenbroek 	event_add(ev2, NULL);
2231e985b929SDavid van Moolenbroek 	event_base_loop(base, EVLOOP_ONCE);
2232e985b929SDavid van Moolenbroek 	tt_int_op(ev1_got, ==, EV_READ);
2233e985b929SDavid van Moolenbroek 	tt_int_op(ev2_got, ==, EV_READ);
2234e985b929SDavid van Moolenbroek 
2235e985b929SDavid van Moolenbroek 	/* Now close and delete dfd then dispatch.  We need to do the
2236e985b929SDavid van Moolenbroek 	 * dispatch here so that when we add it later, we think there
2237e985b929SDavid van Moolenbroek 	 * was an intermediate delete. */
2238e985b929SDavid van Moolenbroek 	close(dfd);
2239e985b929SDavid van Moolenbroek 	event_del(ev2);
2240e985b929SDavid van Moolenbroek 	ev1_got = ev2_got = 0;
2241e985b929SDavid van Moolenbroek 	event_base_loop(base, EVLOOP_ONCE);
2242e985b929SDavid van Moolenbroek 	tt_want_int_op(ev1_got, ==, EV_READ);
2243e985b929SDavid van Moolenbroek 	tt_int_op(ev2_got, ==, 0);
2244e985b929SDavid van Moolenbroek 
2245e985b929SDavid van Moolenbroek 	/* Re-duplicate the fd.  We need to get the same duplicated
2246e985b929SDavid van Moolenbroek 	 * value that we closed to provoke the epoll quirk.  Also, we
2247e985b929SDavid van Moolenbroek 	 * need to change the events to write, or else the old lingering
2248e985b929SDavid van Moolenbroek 	 * read event will make the test pass whether the change was
2249e985b929SDavid van Moolenbroek 	 * successful or not. */
2250e985b929SDavid van Moolenbroek 	tt_int_op(dup2(fd, dfd), ==, dfd);
2251e985b929SDavid van Moolenbroek 	event_free(ev2);
2252e985b929SDavid van Moolenbroek 	ev2 = event_new(base, dfd, EV_WRITE|EV_PERSIST, dfd_cb, &ev2_got);
2253e985b929SDavid van Moolenbroek 	event_add(ev2, NULL);
2254e985b929SDavid van Moolenbroek 	ev1_got = ev2_got = 0;
2255e985b929SDavid van Moolenbroek 	event_base_loop(base, EVLOOP_ONCE);
2256e985b929SDavid van Moolenbroek 	tt_want_int_op(ev1_got, ==, EV_READ);
2257e985b929SDavid van Moolenbroek 	tt_int_op(ev2_got, ==, EV_WRITE);
2258e985b929SDavid van Moolenbroek 
2259e985b929SDavid van Moolenbroek end:
2260e985b929SDavid van Moolenbroek 	if (ev1)
2261e985b929SDavid van Moolenbroek 		event_free(ev1);
2262e985b929SDavid van Moolenbroek 	if (ev2)
2263e985b929SDavid van Moolenbroek 		event_free(ev2);
2264e985b929SDavid van Moolenbroek 	if (dfd >= 0)
2265e985b929SDavid van Moolenbroek 		close(dfd);
2266e985b929SDavid van Moolenbroek }
2267e985b929SDavid van Moolenbroek #endif
2268e985b929SDavid van Moolenbroek 
2269e985b929SDavid van Moolenbroek #ifdef _EVENT_DISABLE_MM_REPLACEMENT
2270e985b929SDavid van Moolenbroek static void
test_mm_functions(void * arg)2271e985b929SDavid van Moolenbroek test_mm_functions(void *arg)
2272e985b929SDavid van Moolenbroek {
2273e985b929SDavid van Moolenbroek 	_tinytest_set_test_skipped();
2274e985b929SDavid van Moolenbroek }
2275e985b929SDavid van Moolenbroek #else
2276e985b929SDavid van Moolenbroek static int
check_dummy_mem_ok(void * _mem)2277e985b929SDavid van Moolenbroek check_dummy_mem_ok(void *_mem)
2278e985b929SDavid van Moolenbroek {
2279e985b929SDavid van Moolenbroek 	char *mem = _mem;
2280e985b929SDavid van Moolenbroek 	mem -= 16;
2281e985b929SDavid van Moolenbroek 	return !memcmp(mem, "{[<guardedram>]}", 16);
2282e985b929SDavid van Moolenbroek }
2283e985b929SDavid van Moolenbroek 
2284e985b929SDavid van Moolenbroek static void *
dummy_malloc(size_t len)2285e985b929SDavid van Moolenbroek dummy_malloc(size_t len)
2286e985b929SDavid van Moolenbroek {
2287e985b929SDavid van Moolenbroek 	char *mem = malloc(len+16);
2288e985b929SDavid van Moolenbroek 	memcpy(mem, "{[<guardedram>]}", 16);
2289e985b929SDavid van Moolenbroek 	return mem+16;
2290e985b929SDavid van Moolenbroek }
2291e985b929SDavid van Moolenbroek 
2292e985b929SDavid van Moolenbroek static void *
dummy_realloc(void * _mem,size_t len)2293e985b929SDavid van Moolenbroek dummy_realloc(void *_mem, size_t len)
2294e985b929SDavid van Moolenbroek {
2295e985b929SDavid van Moolenbroek 	char *mem = _mem;
2296e985b929SDavid van Moolenbroek 	if (!mem)
2297e985b929SDavid van Moolenbroek 		return dummy_malloc(len);
2298e985b929SDavid van Moolenbroek 	tt_want(check_dummy_mem_ok(_mem));
2299e985b929SDavid van Moolenbroek 	mem -= 16;
2300e985b929SDavid van Moolenbroek 	mem = realloc(mem, len+16);
2301e985b929SDavid van Moolenbroek 	return mem+16;
2302e985b929SDavid van Moolenbroek }
2303e985b929SDavid van Moolenbroek 
2304e985b929SDavid van Moolenbroek static void
dummy_free(void * _mem)2305e985b929SDavid van Moolenbroek dummy_free(void *_mem)
2306e985b929SDavid van Moolenbroek {
2307e985b929SDavid van Moolenbroek 	char *mem = _mem;
2308e985b929SDavid van Moolenbroek 	tt_want(check_dummy_mem_ok(_mem));
2309e985b929SDavid van Moolenbroek 	mem -= 16;
2310e985b929SDavid van Moolenbroek 	free(mem);
2311e985b929SDavid van Moolenbroek }
2312e985b929SDavid van Moolenbroek 
2313e985b929SDavid van Moolenbroek static void
test_mm_functions(void * arg)2314e985b929SDavid van Moolenbroek test_mm_functions(void *arg)
2315e985b929SDavid van Moolenbroek {
2316e985b929SDavid van Moolenbroek 	struct event_base *b = NULL;
2317e985b929SDavid van Moolenbroek 	struct event_config *cfg = NULL;
2318e985b929SDavid van Moolenbroek 	event_set_mem_functions(dummy_malloc, dummy_realloc, dummy_free);
2319e985b929SDavid van Moolenbroek 	cfg = event_config_new();
2320e985b929SDavid van Moolenbroek 	event_config_avoid_method(cfg, "Nonesuch");
2321e985b929SDavid van Moolenbroek 	b = event_base_new_with_config(cfg);
2322e985b929SDavid van Moolenbroek 	tt_assert(b);
2323e985b929SDavid van Moolenbroek 	tt_assert(check_dummy_mem_ok(b));
2324e985b929SDavid van Moolenbroek end:
2325e985b929SDavid van Moolenbroek 	if (cfg)
2326e985b929SDavid van Moolenbroek 		event_config_free(cfg);
2327e985b929SDavid van Moolenbroek 	if (b)
2328e985b929SDavid van Moolenbroek 		event_base_free(b);
2329e985b929SDavid van Moolenbroek }
2330e985b929SDavid van Moolenbroek #endif
2331e985b929SDavid van Moolenbroek 
2332e985b929SDavid van Moolenbroek static void
many_event_cb(evutil_socket_t fd,short event,void * arg)2333e985b929SDavid van Moolenbroek many_event_cb(evutil_socket_t fd, short event, void *arg)
2334e985b929SDavid van Moolenbroek {
2335e985b929SDavid van Moolenbroek 	int *calledp = arg;
2336e985b929SDavid van Moolenbroek 	*calledp += 1;
2337e985b929SDavid van Moolenbroek }
2338e985b929SDavid van Moolenbroek 
2339e985b929SDavid van Moolenbroek static void
test_many_events(void * arg)2340e985b929SDavid van Moolenbroek test_many_events(void *arg)
2341e985b929SDavid van Moolenbroek {
2342e985b929SDavid van Moolenbroek 	/* Try 70 events that should all be ready at once.  This will
2343e985b929SDavid van Moolenbroek 	 * exercise the "resize" code on most of the backends, and will make
2344e985b929SDavid van Moolenbroek 	 * sure that we can get past the 64-handle limit of some windows
2345e985b929SDavid van Moolenbroek 	 * functions. */
2346e985b929SDavid van Moolenbroek #define MANY 70
2347e985b929SDavid van Moolenbroek 
2348e985b929SDavid van Moolenbroek 	struct basic_test_data *data = arg;
2349e985b929SDavid van Moolenbroek 	struct event_base *base = data->base;
2350e985b929SDavid van Moolenbroek 	int one_at_a_time = data->setup_data != NULL;
2351e985b929SDavid van Moolenbroek 	evutil_socket_t sock[MANY];
2352e985b929SDavid van Moolenbroek 	struct event *ev[MANY];
2353e985b929SDavid van Moolenbroek 	int xcalled[MANY];
2354e985b929SDavid van Moolenbroek 	int i;
2355e985b929SDavid van Moolenbroek 	int loopflags = EVLOOP_NONBLOCK, evflags=0;
2356e985b929SDavid van Moolenbroek 	const int is_evport = !strcmp(event_base_get_method(base),"evport");
2357e985b929SDavid van Moolenbroek 	if (one_at_a_time) {
2358e985b929SDavid van Moolenbroek 		loopflags |= EVLOOP_ONCE;
2359e985b929SDavid van Moolenbroek 		evflags = EV_PERSIST;
2360e985b929SDavid van Moolenbroek 	}
2361e985b929SDavid van Moolenbroek 
2362e985b929SDavid van Moolenbroek 	memset(sock, 0xff, sizeof(sock));
2363e985b929SDavid van Moolenbroek 	memset(ev, 0, sizeof(ev));
2364e985b929SDavid van Moolenbroek 	memset(xcalled, 0, sizeof(xcalled));
2365e985b929SDavid van Moolenbroek 	if (is_evport && one_at_a_time) {
2366e985b929SDavid van Moolenbroek 		TT_DECLARE("NOTE", ("evport can't pass this in 2.0; skipping\n"));
2367e985b929SDavid van Moolenbroek 		tt_skip();
2368e985b929SDavid van Moolenbroek 	}
2369e985b929SDavid van Moolenbroek 
2370e985b929SDavid van Moolenbroek 	for (i = 0; i < MANY; ++i) {
2371e985b929SDavid van Moolenbroek 		/* We need an event that will hit the backend, and that will
2372e985b929SDavid van Moolenbroek 		 * be ready immediately.  "Send a datagram" is an easy
2373e985b929SDavid van Moolenbroek 		 * instance of that. */
2374e985b929SDavid van Moolenbroek 		sock[i] = socket(AF_INET, SOCK_DGRAM, 0);
2375e985b929SDavid van Moolenbroek 		tt_assert(sock[i] >= 0);
2376e985b929SDavid van Moolenbroek 		xcalled[i] = 0;
2377e985b929SDavid van Moolenbroek 		ev[i] = event_new(base, sock[i], EV_WRITE|evflags,
2378e985b929SDavid van Moolenbroek 		    many_event_cb, &xcalled[i]);
2379e985b929SDavid van Moolenbroek 		event_add(ev[i], NULL);
2380e985b929SDavid van Moolenbroek 		if (one_at_a_time)
2381e985b929SDavid van Moolenbroek 			event_base_loop(base, EVLOOP_NONBLOCK|EVLOOP_ONCE);
2382e985b929SDavid van Moolenbroek 	}
2383e985b929SDavid van Moolenbroek 
2384e985b929SDavid van Moolenbroek 	event_base_loop(base, loopflags);
2385e985b929SDavid van Moolenbroek 
2386e985b929SDavid van Moolenbroek 	for (i = 0; i < MANY; ++i) {
2387e985b929SDavid van Moolenbroek 		if (one_at_a_time)
2388e985b929SDavid van Moolenbroek 			tt_int_op(xcalled[i], ==, MANY - i + 1);
2389e985b929SDavid van Moolenbroek 		else
2390e985b929SDavid van Moolenbroek 			tt_int_op(xcalled[i], ==, 1);
2391e985b929SDavid van Moolenbroek 	}
2392e985b929SDavid van Moolenbroek 
2393e985b929SDavid van Moolenbroek end:
2394e985b929SDavid van Moolenbroek 	for (i = 0; i < MANY; ++i) {
2395e985b929SDavid van Moolenbroek 		if (ev[i])
2396e985b929SDavid van Moolenbroek 			event_free(ev[i]);
2397e985b929SDavid van Moolenbroek 		if (sock[i] >= 0)
2398e985b929SDavid van Moolenbroek 			evutil_closesocket(sock[i]);
2399e985b929SDavid van Moolenbroek 	}
2400e985b929SDavid van Moolenbroek #undef MANY
2401e985b929SDavid van Moolenbroek }
2402e985b929SDavid van Moolenbroek 
2403e985b929SDavid van Moolenbroek static void
test_struct_event_size(void * arg)2404e985b929SDavid van Moolenbroek test_struct_event_size(void *arg)
2405e985b929SDavid van Moolenbroek {
2406e985b929SDavid van Moolenbroek 	tt_int_op(event_get_struct_event_size(), <=, sizeof(struct event));
2407e985b929SDavid van Moolenbroek end:
2408e985b929SDavid van Moolenbroek 	;
2409e985b929SDavid van Moolenbroek }
2410e985b929SDavid van Moolenbroek 
2411e985b929SDavid van Moolenbroek struct testcase_t main_testcases[] = {
2412e985b929SDavid van Moolenbroek 	/* Some converted-over tests */
2413e985b929SDavid van Moolenbroek 	{ "methods", test_methods, TT_FORK, NULL, NULL },
2414e985b929SDavid van Moolenbroek 	{ "version", test_version, 0, NULL, NULL },
2415e985b929SDavid van Moolenbroek 	BASIC(base_features, TT_FORK|TT_NO_LOGS),
2416e985b929SDavid van Moolenbroek 	{ "base_environ", test_base_environ, TT_FORK, NULL, NULL },
2417e985b929SDavid van Moolenbroek 
2418e985b929SDavid van Moolenbroek 	BASIC(event_base_new, TT_FORK|TT_NEED_SOCKETPAIR),
2419e985b929SDavid van Moolenbroek 	BASIC(free_active_base, TT_FORK|TT_NEED_SOCKETPAIR),
2420e985b929SDavid van Moolenbroek 
2421e985b929SDavid van Moolenbroek 	BASIC(manipulate_active_events, TT_FORK|TT_NEED_BASE),
2422e985b929SDavid van Moolenbroek 
2423e985b929SDavid van Moolenbroek 	BASIC(bad_assign, TT_FORK|TT_NEED_BASE|TT_NO_LOGS),
2424e985b929SDavid van Moolenbroek 	BASIC(bad_reentrant, TT_FORK|TT_NEED_BASE|TT_NO_LOGS),
2425e985b929SDavid van Moolenbroek 
2426e985b929SDavid van Moolenbroek 	LEGACY(persistent_timeout, TT_FORK|TT_NEED_BASE),
2427e985b929SDavid van Moolenbroek 	{ "persistent_timeout_jump", test_persistent_timeout_jump, TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
2428e985b929SDavid van Moolenbroek 	{ "persistent_active_timeout", test_persistent_active_timeout,
2429e985b929SDavid van Moolenbroek 	  TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
2430e985b929SDavid van Moolenbroek 	LEGACY(priorities, TT_FORK|TT_NEED_BASE),
2431e985b929SDavid van Moolenbroek 	BASIC(priority_active_inversion, TT_FORK|TT_NEED_BASE),
2432e985b929SDavid van Moolenbroek 	{ "common_timeout", test_common_timeout, TT_FORK|TT_NEED_BASE,
2433e985b929SDavid van Moolenbroek 	  &basic_setup, NULL },
2434e985b929SDavid van Moolenbroek 
2435e985b929SDavid van Moolenbroek 	/* These legacy tests may not all need all of these flags. */
2436e985b929SDavid van Moolenbroek 	LEGACY(simpleread, TT_ISOLATED),
2437e985b929SDavid van Moolenbroek 	LEGACY(simpleread_multiple, TT_ISOLATED),
2438e985b929SDavid van Moolenbroek 	LEGACY(simplewrite, TT_ISOLATED),
2439e985b929SDavid van Moolenbroek 	{ "simpleclose", test_simpleclose, TT_FORK, &basic_setup,
2440e985b929SDavid van Moolenbroek 	  NULL },
2441e985b929SDavid van Moolenbroek 	LEGACY(multiple, TT_ISOLATED),
2442e985b929SDavid van Moolenbroek 	LEGACY(persistent, TT_ISOLATED),
2443e985b929SDavid van Moolenbroek 	LEGACY(combined, TT_ISOLATED),
2444e985b929SDavid van Moolenbroek 	LEGACY(simpletimeout, TT_ISOLATED),
2445e985b929SDavid van Moolenbroek 	LEGACY(loopbreak, TT_ISOLATED),
2446e985b929SDavid van Moolenbroek 	LEGACY(loopexit, TT_ISOLATED),
2447e985b929SDavid van Moolenbroek 	LEGACY(loopexit_multiple, TT_ISOLATED),
2448e985b929SDavid van Moolenbroek 	LEGACY(nonpersist_readd, TT_ISOLATED),
2449e985b929SDavid van Moolenbroek 	LEGACY(multiple_events_for_same_fd, TT_ISOLATED),
2450e985b929SDavid van Moolenbroek 	LEGACY(want_only_once, TT_ISOLATED),
2451e985b929SDavid van Moolenbroek 	{ "event_once", test_event_once, TT_ISOLATED, &basic_setup, NULL },
2452e985b929SDavid van Moolenbroek 	{ "event_pending", test_event_pending, TT_ISOLATED, &basic_setup,
2453e985b929SDavid van Moolenbroek 	  NULL },
2454e985b929SDavid van Moolenbroek #ifndef WIN32
2455e985b929SDavid van Moolenbroek 	{ "dup_fd", test_dup_fd, TT_ISOLATED, &basic_setup, NULL },
2456e985b929SDavid van Moolenbroek #endif
2457e985b929SDavid van Moolenbroek 	{ "mm_functions", test_mm_functions, TT_FORK, NULL, NULL },
2458e985b929SDavid van Moolenbroek 	{ "many_events", test_many_events, TT_ISOLATED, &basic_setup, NULL },
2459e985b929SDavid van Moolenbroek 	{ "many_events_slow_add", test_many_events, TT_ISOLATED, &basic_setup, (void*)1 },
2460e985b929SDavid van Moolenbroek 
2461e985b929SDavid van Moolenbroek 	{ "struct_event_size", test_struct_event_size, 0, NULL, NULL },
2462e985b929SDavid van Moolenbroek 
2463e985b929SDavid van Moolenbroek #ifndef WIN32
2464e985b929SDavid van Moolenbroek 	LEGACY(fork, TT_ISOLATED),
2465e985b929SDavid van Moolenbroek #endif
2466e985b929SDavid van Moolenbroek 	END_OF_TESTCASES
2467e985b929SDavid van Moolenbroek };
2468e985b929SDavid van Moolenbroek 
2469e985b929SDavid van Moolenbroek struct testcase_t evtag_testcases[] = {
2470e985b929SDavid van Moolenbroek 	{ "int", evtag_int_test, TT_FORK, NULL, NULL },
2471e985b929SDavid van Moolenbroek 	{ "fuzz", evtag_fuzz, TT_FORK, NULL, NULL },
2472e985b929SDavid van Moolenbroek 	{ "encoding", evtag_tag_encoding, TT_FORK, NULL, NULL },
2473e985b929SDavid van Moolenbroek 	{ "peek", evtag_test_peek, 0, NULL, NULL },
2474e985b929SDavid van Moolenbroek 
2475e985b929SDavid van Moolenbroek 	END_OF_TESTCASES
2476e985b929SDavid van Moolenbroek };
2477e985b929SDavid van Moolenbroek 
2478e985b929SDavid van Moolenbroek struct testcase_t signal_testcases[] = {
2479e985b929SDavid van Moolenbroek #ifndef WIN32
2480e985b929SDavid van Moolenbroek 	LEGACY(simplesignal, TT_ISOLATED),
2481e985b929SDavid van Moolenbroek 	LEGACY(multiplesignal, TT_ISOLATED),
2482e985b929SDavid van Moolenbroek 	LEGACY(immediatesignal, TT_ISOLATED),
2483e985b929SDavid van Moolenbroek 	LEGACY(signal_dealloc, TT_ISOLATED),
2484e985b929SDavid van Moolenbroek 	LEGACY(signal_pipeloss, TT_ISOLATED),
2485e985b929SDavid van Moolenbroek 	LEGACY(signal_switchbase, TT_ISOLATED|TT_NO_LOGS),
2486e985b929SDavid van Moolenbroek 	LEGACY(signal_restore, TT_ISOLATED),
2487e985b929SDavid van Moolenbroek 	LEGACY(signal_assert, TT_ISOLATED),
2488e985b929SDavid van Moolenbroek 	LEGACY(signal_while_processing, TT_ISOLATED),
2489e985b929SDavid van Moolenbroek #endif
2490e985b929SDavid van Moolenbroek 	END_OF_TESTCASES
2491e985b929SDavid van Moolenbroek };
2492e985b929SDavid van Moolenbroek 
2493