2003-03-08 06:39:30 +00:00
|
|
|
/*
|
2009-01-27 22:34:36 +00:00
|
|
|
* Copyright (c) 2003-2007 Niels Provos <provos@citi.umich.edu>
|
2012-02-10 17:29:53 -05:00
|
|
|
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
|
2003-03-08 06:39:30 +00:00
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
2003-10-04 23:33:04 +00:00
|
|
|
* 3. The name of the author may not be used to endorse or promote products
|
2003-03-08 06:39:30 +00:00
|
|
|
* derived from this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
2012-01-24 16:08:00 -05:00
|
|
|
#include "util-internal.h"
|
2003-03-08 06:39:30 +00:00
|
|
|
|
2011-05-25 19:50:56 -04:00
|
|
|
#ifdef _WIN32
|
2004-05-24 00:19:52 +00:00
|
|
|
#include <winsock2.h>
|
|
|
|
#include <windows.h>
|
|
|
|
#endif
|
|
|
|
|
2010-07-07 16:45:03 -04:00
|
|
|
#include "event2/event-config.h"
|
2003-03-08 14:44:08 +00:00
|
|
|
|
2003-03-08 06:39:30 +00:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
2012-02-29 15:07:31 -05:00
|
|
|
#ifdef EVENT__HAVE_SYS_TIME_H
|
2003-03-08 06:39:30 +00:00
|
|
|
#include <sys/time.h>
|
2004-05-24 00:19:52 +00:00
|
|
|
#endif
|
2006-01-22 05:08:50 +00:00
|
|
|
#include <sys/queue.h>
|
2011-05-25 19:50:56 -04:00
|
|
|
#ifndef _WIN32
|
2003-03-08 06:39:30 +00:00
|
|
|
#include <sys/socket.h>
|
2007-11-25 06:57:59 +00:00
|
|
|
#include <sys/wait.h>
|
2019-04-24 22:55:24 +02:00
|
|
|
#include <limits.h>
|
2009-01-22 02:47:35 +00:00
|
|
|
#include <signal.h>
|
2004-05-24 00:19:52 +00:00
|
|
|
#include <unistd.h>
|
2006-01-22 05:08:50 +00:00
|
|
|
#include <netdb.h>
|
2007-09-20 19:08:20 +00:00
|
|
|
#endif
|
2003-03-08 06:39:30 +00:00
|
|
|
#include <fcntl.h>
|
2007-06-30 18:58:34 +00:00
|
|
|
#include <signal.h>
|
2003-03-08 06:39:30 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <errno.h>
|
2008-03-31 02:04:34 +00:00
|
|
|
#include <assert.h>
|
2009-04-28 19:08:27 +00:00
|
|
|
#include <ctype.h>
|
2003-03-08 06:39:30 +00:00
|
|
|
|
2008-05-05 15:46:00 +00:00
|
|
|
#include "event2/event.h"
|
|
|
|
#include "event2/event_struct.h"
|
|
|
|
#include "event2/event_compat.h"
|
|
|
|
#include "event2/tag.h"
|
|
|
|
#include "event2/buffer.h"
|
2009-04-17 06:56:09 +00:00
|
|
|
#include "event2/buffer_compat.h"
|
2008-05-05 15:46:00 +00:00
|
|
|
#include "event2/util.h"
|
2007-03-10 06:37:53 +00:00
|
|
|
#include "event-internal.h"
|
2010-09-08 13:29:06 -04:00
|
|
|
#include "evthread-internal.h"
|
2009-01-13 20:26:37 +00:00
|
|
|
#include "log-internal.h"
|
2012-04-20 12:27:12 -04:00
|
|
|
#include "time-internal.h"
|
2003-03-08 06:39:30 +00:00
|
|
|
|
2006-01-22 05:08:50 +00:00
|
|
|
#include "regress.h"
|
2020-01-13 22:24:54 +03:00
|
|
|
#include "regress_thread.h"
|
2008-06-24 18:04:41 +00:00
|
|
|
|
2011-05-25 19:50:56 -04:00
|
|
|
#ifndef _WIN32
|
2005-08-22 01:34:34 +00:00
|
|
|
#include "regress.gen.h"
|
2008-06-24 18:04:41 +00:00
|
|
|
#endif
|
2005-08-22 01:34:34 +00:00
|
|
|
|
2010-10-26 22:27:57 -04:00
|
|
|
evutil_socket_t pair[2];
|
2006-01-22 05:08:50 +00:00
|
|
|
int test_ok;
|
2009-01-29 23:19:57 +00:00
|
|
|
int called;
|
|
|
|
struct event_base *global_base;
|
|
|
|
|
2003-03-08 06:39:30 +00:00
|
|
|
static char wbuf[4096];
|
|
|
|
static char rbuf[4096];
|
|
|
|
static int woff;
|
|
|
|
static int roff;
|
2003-03-08 14:21:14 +00:00
|
|
|
static int usepersist;
|
2003-03-08 06:39:30 +00:00
|
|
|
static struct timeval tset;
|
|
|
|
static struct timeval tcalled;
|
2009-01-29 23:19:57 +00:00
|
|
|
|
|
|
|
|
2003-03-08 06:39:30 +00:00
|
|
|
#define TEST1 "this is a test"
|
|
|
|
|
2011-05-25 19:50:56 -04:00
|
|
|
#ifdef _WIN32
|
2010-11-03 14:38:45 -07:00
|
|
|
#define write(fd,buf,len) send((fd),(buf),(int)(len),0)
|
|
|
|
#define read(fd,buf,len) recv((fd),(buf),(int)(len),0)
|
2007-10-12 18:02:56 +00:00
|
|
|
#endif
|
|
|
|
|
2009-07-14 18:49:42 +00:00
|
|
|
struct basic_cb_args
|
|
|
|
{
|
|
|
|
struct event_base *eb;
|
|
|
|
struct event *ev;
|
|
|
|
unsigned int callcount;
|
|
|
|
};
|
|
|
|
|
2007-11-26 19:18:49 +00:00
|
|
|
static void
|
2010-03-05 12:47:46 -05:00
|
|
|
simple_read_cb(evutil_socket_t fd, short event, void *arg)
|
2003-03-08 06:39:30 +00:00
|
|
|
{
|
|
|
|
char buf[256];
|
|
|
|
int len;
|
|
|
|
|
|
|
|
len = read(fd, buf, sizeof(buf));
|
|
|
|
|
|
|
|
if (len) {
|
2004-07-30 04:57:21 +00:00
|
|
|
if (!called) {
|
|
|
|
if (event_add(arg, NULL) == -1)
|
|
|
|
exit(1);
|
|
|
|
}
|
2003-03-08 06:39:30 +00:00
|
|
|
} else if (called == 1)
|
|
|
|
test_ok = 1;
|
|
|
|
|
|
|
|
called++;
|
|
|
|
}
|
|
|
|
|
2009-07-14 18:49:42 +00:00
|
|
|
static void
|
2010-03-05 12:47:46 -05:00
|
|
|
basic_read_cb(evutil_socket_t fd, short event, void *data)
|
2009-07-14 18:49:42 +00:00
|
|
|
{
|
|
|
|
char buf[256];
|
|
|
|
int len;
|
|
|
|
struct basic_cb_args *arg = data;
|
|
|
|
|
|
|
|
len = read(fd, buf, sizeof(buf));
|
|
|
|
|
|
|
|
if (len < 0) {
|
|
|
|
tt_fail_perror("read (callback)");
|
|
|
|
} else {
|
|
|
|
switch (arg->callcount++) {
|
2010-02-18 17:41:15 -05:00
|
|
|
case 0: /* first call: expect to read data; cycle */
|
2009-07-14 18:49:42 +00:00
|
|
|
if (len > 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
tt_fail_msg("EOF before data read");
|
|
|
|
break;
|
|
|
|
|
2010-02-18 17:41:15 -05:00
|
|
|
case 1: /* second call: expect EOF; stop */
|
2009-07-14 18:49:42 +00:00
|
|
|
if (len > 0)
|
|
|
|
tt_fail_msg("not all data read on first cycle");
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: /* third call: should not happen */
|
|
|
|
tt_fail_msg("too many cycles");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
event_del(arg->ev);
|
|
|
|
event_base_loopexit(arg->eb, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2010-03-05 12:47:46 -05:00
|
|
|
dummy_read_cb(evutil_socket_t fd, short event, void *arg)
|
2009-07-14 18:49:42 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2007-11-26 19:18:49 +00:00
|
|
|
static void
|
2010-03-05 12:47:46 -05:00
|
|
|
simple_write_cb(evutil_socket_t fd, short event, void *arg)
|
2003-03-08 06:39:30 +00:00
|
|
|
{
|
|
|
|
int len;
|
|
|
|
|
|
|
|
len = write(fd, TEST1, strlen(TEST1) + 1);
|
|
|
|
if (len == -1)
|
|
|
|
test_ok = 0;
|
|
|
|
else
|
|
|
|
test_ok = 1;
|
|
|
|
}
|
|
|
|
|
2007-11-26 19:18:49 +00:00
|
|
|
static void
|
2010-03-05 12:47:46 -05:00
|
|
|
multiple_write_cb(evutil_socket_t fd, short event, void *arg)
|
2003-03-08 06:39:30 +00:00
|
|
|
{
|
|
|
|
struct event *ev = arg;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
len = 128;
|
2010-10-14 13:16:41 -04:00
|
|
|
if (woff + len >= (int)sizeof(wbuf))
|
2003-03-08 06:39:30 +00:00
|
|
|
len = sizeof(wbuf) - woff;
|
|
|
|
|
|
|
|
len = write(fd, wbuf + woff, len);
|
|
|
|
if (len == -1) {
|
|
|
|
fprintf(stderr, "%s: write\n", __func__);
|
2003-03-09 23:29:57 +00:00
|
|
|
if (usepersist)
|
|
|
|
event_del(ev);
|
2003-03-08 06:39:30 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
woff += len;
|
2009-07-17 18:38:38 +00:00
|
|
|
|
2010-10-14 13:16:41 -04:00
|
|
|
if (woff >= (int)sizeof(wbuf)) {
|
2016-03-11 01:27:52 +03:00
|
|
|
shutdown(fd, EVUTIL_SHUT_WR);
|
2003-03-08 14:21:14 +00:00
|
|
|
if (usepersist)
|
|
|
|
event_del(ev);
|
2003-03-08 06:39:30 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2004-07-30 04:57:21 +00:00
|
|
|
if (!usepersist) {
|
|
|
|
if (event_add(ev, NULL) == -1)
|
|
|
|
exit(1);
|
|
|
|
}
|
2003-03-08 06:39:30 +00:00
|
|
|
}
|
|
|
|
|
2007-11-26 19:18:49 +00:00
|
|
|
static void
|
2010-03-05 12:47:46 -05:00
|
|
|
multiple_read_cb(evutil_socket_t fd, short event, void *arg)
|
2003-03-08 06:39:30 +00:00
|
|
|
{
|
|
|
|
struct event *ev = arg;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
len = read(fd, rbuf + roff, sizeof(rbuf) - roff);
|
2003-03-09 23:29:57 +00:00
|
|
|
if (len == -1)
|
2003-03-08 06:39:30 +00:00
|
|
|
fprintf(stderr, "%s: read\n", __func__);
|
2003-03-09 23:29:57 +00:00
|
|
|
if (len <= 0) {
|
2003-03-08 14:21:14 +00:00
|
|
|
if (usepersist)
|
|
|
|
event_del(ev);
|
2003-03-08 06:39:30 +00:00
|
|
|
return;
|
2003-03-08 14:21:14 +00:00
|
|
|
}
|
2003-03-08 06:39:30 +00:00
|
|
|
|
|
|
|
roff += len;
|
2004-07-30 04:57:21 +00:00
|
|
|
if (!usepersist) {
|
2009-01-27 21:10:31 +00:00
|
|
|
if (event_add(ev, NULL) == -1)
|
2004-07-30 04:57:21 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
2003-03-08 06:39:30 +00:00
|
|
|
}
|
|
|
|
|
2007-11-26 19:18:49 +00:00
|
|
|
static void
|
2010-03-05 12:47:46 -05:00
|
|
|
timeout_cb(evutil_socket_t fd, short event, void *arg)
|
2003-03-08 06:39:30 +00:00
|
|
|
{
|
2008-06-24 18:04:41 +00:00
|
|
|
evutil_gettimeofday(&tcalled, NULL);
|
2003-03-08 06:39:30 +00:00
|
|
|
}
|
|
|
|
|
2003-03-08 20:14:39 +00:00
|
|
|
struct both {
|
|
|
|
struct event ev;
|
|
|
|
int nread;
|
|
|
|
};
|
|
|
|
|
2007-11-26 19:18:49 +00:00
|
|
|
static void
|
2010-03-05 12:47:46 -05:00
|
|
|
combined_read_cb(evutil_socket_t fd, short event, void *arg)
|
2003-03-08 20:14:39 +00:00
|
|
|
{
|
|
|
|
struct both *both = arg;
|
|
|
|
char buf[128];
|
|
|
|
int len;
|
|
|
|
|
|
|
|
len = read(fd, buf, sizeof(buf));
|
|
|
|
if (len == -1)
|
|
|
|
fprintf(stderr, "%s: read\n", __func__);
|
|
|
|
if (len <= 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
both->nread += len;
|
2004-07-30 04:57:21 +00:00
|
|
|
if (event_add(&both->ev, NULL) == -1)
|
|
|
|
exit(1);
|
2003-03-08 20:14:39 +00:00
|
|
|
}
|
|
|
|
|
2007-11-26 19:18:49 +00:00
|
|
|
static void
|
2010-03-05 12:47:46 -05:00
|
|
|
combined_write_cb(evutil_socket_t fd, short event, void *arg)
|
2003-03-08 20:14:39 +00:00
|
|
|
{
|
|
|
|
struct both *both = arg;
|
|
|
|
char buf[128];
|
|
|
|
int len;
|
|
|
|
|
|
|
|
len = sizeof(buf);
|
|
|
|
if (len > both->nread)
|
|
|
|
len = both->nread;
|
|
|
|
|
2010-03-12 20:38:25 -05:00
|
|
|
memset(buf, 'q', len);
|
|
|
|
|
2003-03-08 20:14:39 +00:00
|
|
|
len = write(fd, buf, len);
|
|
|
|
if (len == -1)
|
|
|
|
fprintf(stderr, "%s: write\n", __func__);
|
|
|
|
if (len <= 0) {
|
2016-03-11 01:27:52 +03:00
|
|
|
shutdown(fd, EVUTIL_SHUT_WR);
|
2003-03-08 20:14:39 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
both->nread -= len;
|
2004-07-30 04:57:21 +00:00
|
|
|
if (event_add(&both->ev, NULL) == -1)
|
|
|
|
exit(1);
|
2003-03-08 20:14:39 +00:00
|
|
|
}
|
|
|
|
|
2010-05-26 13:18:30 -04:00
|
|
|
/* These macros used to replicate the work of the legacy test wrapper code */
|
|
|
|
#define setup_test(x) do { \
|
|
|
|
if (!in_legacy_test_wrapper) { \
|
|
|
|
TT_FAIL(("Legacy test %s not wrapped properly", x)); \
|
|
|
|
return; \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
#define cleanup_test() setup_test("cleanup")
|
2003-03-08 06:39:30 +00:00
|
|
|
|
2007-11-26 19:18:49 +00:00
|
|
|
static void
|
2005-12-06 03:26:28 +00:00
|
|
|
test_simpleread(void)
|
2003-03-08 06:39:30 +00:00
|
|
|
{
|
2004-04-04 02:19:08 +00:00
|
|
|
struct event ev;
|
2003-03-08 06:39:30 +00:00
|
|
|
|
|
|
|
/* Very simple read test */
|
2003-03-08 14:21:14 +00:00
|
|
|
setup_test("Simple read: ");
|
2009-01-27 21:10:31 +00:00
|
|
|
|
2011-07-12 13:05:36 -04:00
|
|
|
if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) {
|
2011-10-03 12:45:36 -04:00
|
|
|
tt_fail_perror("write");
|
2011-07-12 13:05:36 -04:00
|
|
|
}
|
|
|
|
|
2016-03-11 01:27:52 +03:00
|
|
|
shutdown(pair[0], EVUTIL_SHUT_WR);
|
2003-03-08 06:39:30 +00:00
|
|
|
|
|
|
|
event_set(&ev, pair[1], EV_READ, simple_read_cb, &ev);
|
2004-07-30 04:57:21 +00:00
|
|
|
if (event_add(&ev, NULL) == -1)
|
|
|
|
exit(1);
|
2003-03-08 06:39:30 +00:00
|
|
|
event_dispatch();
|
|
|
|
|
|
|
|
cleanup_test();
|
2004-04-04 02:19:08 +00:00
|
|
|
}
|
|
|
|
|
2007-11-26 19:18:49 +00:00
|
|
|
static void
|
2005-12-06 03:26:28 +00:00
|
|
|
test_simplewrite(void)
|
2004-04-04 02:19:08 +00:00
|
|
|
{
|
|
|
|
struct event ev;
|
2003-03-08 06:39:30 +00:00
|
|
|
|
|
|
|
/* Very simple write test */
|
|
|
|
setup_test("Simple write: ");
|
2009-01-27 21:10:31 +00:00
|
|
|
|
2003-03-08 06:39:30 +00:00
|
|
|
event_set(&ev, pair[0], EV_WRITE, simple_write_cb, &ev);
|
2004-07-30 04:57:21 +00:00
|
|
|
if (event_add(&ev, NULL) == -1)
|
|
|
|
exit(1);
|
2003-03-08 06:39:30 +00:00
|
|
|
event_dispatch();
|
|
|
|
|
|
|
|
cleanup_test();
|
2004-04-04 02:19:08 +00:00
|
|
|
}
|
|
|
|
|
2008-12-23 16:37:01 +00:00
|
|
|
static void
|
2010-03-05 12:47:46 -05:00
|
|
|
simpleread_multiple_cb(evutil_socket_t fd, short event, void *arg)
|
2008-12-23 16:37:01 +00:00
|
|
|
{
|
|
|
|
if (++called == 2)
|
|
|
|
test_ok = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
test_simpleread_multiple(void)
|
|
|
|
{
|
|
|
|
struct event one, two;
|
|
|
|
|
|
|
|
/* Very simple read test */
|
|
|
|
setup_test("Simple read to multiple evens: ");
|
2009-01-27 21:10:31 +00:00
|
|
|
|
2011-07-12 13:05:36 -04:00
|
|
|
if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) {
|
2011-10-03 12:45:36 -04:00
|
|
|
tt_fail_perror("write");
|
2011-07-12 13:05:36 -04:00
|
|
|
}
|
|
|
|
|
2016-03-11 01:27:52 +03:00
|
|
|
shutdown(pair[0], EVUTIL_SHUT_WR);
|
2008-12-23 16:37:01 +00:00
|
|
|
|
|
|
|
event_set(&one, pair[1], EV_READ, simpleread_multiple_cb, NULL);
|
|
|
|
if (event_add(&one, NULL) == -1)
|
|
|
|
exit(1);
|
|
|
|
event_set(&two, pair[1], EV_READ, simpleread_multiple_cb, NULL);
|
|
|
|
if (event_add(&two, NULL) == -1)
|
|
|
|
exit(1);
|
|
|
|
event_dispatch();
|
|
|
|
|
|
|
|
cleanup_test();
|
|
|
|
}
|
|
|
|
|
2010-06-03 11:25:54 -04:00
|
|
|
static int have_closed = 0;
|
|
|
|
static int premature_event = 0;
|
|
|
|
static void
|
|
|
|
simpleclose_close_fd_cb(evutil_socket_t s, short what, void *ptr)
|
|
|
|
{
|
|
|
|
evutil_socket_t **fds = ptr;
|
|
|
|
TT_BLATHER(("Closing"));
|
|
|
|
evutil_closesocket(*fds[0]);
|
|
|
|
evutil_closesocket(*fds[1]);
|
|
|
|
*fds[0] = -1;
|
|
|
|
*fds[1] = -1;
|
|
|
|
have_closed = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
record_event_cb(evutil_socket_t s, short what, void *ptr)
|
|
|
|
{
|
|
|
|
short *whatp = ptr;
|
|
|
|
if (!have_closed)
|
|
|
|
premature_event = 1;
|
|
|
|
*whatp = what;
|
|
|
|
TT_BLATHER(("Recorded %d on socket %d", (int)what, (int)s));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2020-04-09 00:14:26 +03:00
|
|
|
test_simpleclose_rw(void *ptr)
|
2010-06-03 11:25:54 -04:00
|
|
|
{
|
|
|
|
/* Test that a close of FD is detected as a read and as a write. */
|
|
|
|
struct event_base *base = event_base_new();
|
2024-06-24 14:19:12 +08:00
|
|
|
evutil_socket_t pair1[2]={EVUTIL_INVALID_SOCKET,EVUTIL_INVALID_SOCKET}, pair2[2] = {EVUTIL_INVALID_SOCKET, EVUTIL_INVALID_SOCKET};
|
2010-06-03 11:25:54 -04:00
|
|
|
evutil_socket_t *to_close[2];
|
|
|
|
struct event *rev=NULL, *wev=NULL, *closeev=NULL;
|
|
|
|
struct timeval tv;
|
|
|
|
short got_read_on_close = 0, got_write_on_close = 0;
|
|
|
|
char buf[1024];
|
|
|
|
memset(buf, 99, sizeof(buf));
|
2011-05-25 19:50:56 -04:00
|
|
|
#ifdef _WIN32
|
2010-06-03 11:25:54 -04:00
|
|
|
#define LOCAL_SOCKETPAIR_AF AF_INET
|
|
|
|
#else
|
|
|
|
#define LOCAL_SOCKETPAIR_AF AF_UNIX
|
|
|
|
#endif
|
|
|
|
if (evutil_socketpair(LOCAL_SOCKETPAIR_AF, SOCK_STREAM, 0, pair1)<0)
|
|
|
|
TT_DIE(("socketpair: %s", strerror(errno)));
|
|
|
|
if (evutil_socketpair(LOCAL_SOCKETPAIR_AF, SOCK_STREAM, 0, pair2)<0)
|
|
|
|
TT_DIE(("socketpair: %s", strerror(errno)));
|
|
|
|
if (evutil_make_socket_nonblocking(pair1[1]) < 0)
|
|
|
|
TT_DIE(("make_socket_nonblocking"));
|
|
|
|
if (evutil_make_socket_nonblocking(pair2[1]) < 0)
|
|
|
|
TT_DIE(("make_socket_nonblocking"));
|
|
|
|
|
|
|
|
/** Stuff pair2[1] full of data, until write fails */
|
|
|
|
while (1) {
|
|
|
|
int r = write(pair2[1], buf, sizeof(buf));
|
|
|
|
if (r<0) {
|
|
|
|
int err = evutil_socket_geterror(pair2[1]);
|
|
|
|
if (! EVUTIL_ERR_RW_RETRIABLE(err))
|
|
|
|
TT_DIE(("write failed strangely: %s",
|
|
|
|
evutil_socket_error_to_string(err)));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
to_close[0] = &pair1[0];
|
|
|
|
to_close[1] = &pair2[0];
|
|
|
|
|
|
|
|
closeev = event_new(base, -1, EV_TIMEOUT, simpleclose_close_fd_cb,
|
|
|
|
to_close);
|
|
|
|
rev = event_new(base, pair1[1], EV_READ, record_event_cb,
|
|
|
|
&got_read_on_close);
|
|
|
|
TT_BLATHER(("Waiting for read on %d", (int)pair1[1]));
|
|
|
|
wev = event_new(base, pair2[1], EV_WRITE, record_event_cb,
|
|
|
|
&got_write_on_close);
|
2024-04-10 15:47:57 +08:00
|
|
|
tt_assert(closeev);
|
|
|
|
tt_assert(rev);
|
|
|
|
tt_assert(wev);
|
2010-06-03 11:25:54 -04:00
|
|
|
TT_BLATHER(("Waiting for write on %d", (int)pair2[1]));
|
|
|
|
tv.tv_sec = 0;
|
|
|
|
tv.tv_usec = 100*1000; /* Close pair1[0] after a little while, and make
|
|
|
|
* sure we get a read event. */
|
|
|
|
event_add(closeev, &tv);
|
|
|
|
event_add(rev, NULL);
|
|
|
|
event_add(wev, NULL);
|
|
|
|
/* Don't let the test go on too long. */
|
|
|
|
tv.tv_sec = 0;
|
|
|
|
tv.tv_usec = 200*1000;
|
|
|
|
event_base_loopexit(base, &tv);
|
|
|
|
event_base_loop(base, 0);
|
|
|
|
|
|
|
|
tt_int_op(got_read_on_close, ==, EV_READ);
|
|
|
|
tt_int_op(got_write_on_close, ==, EV_WRITE);
|
|
|
|
tt_int_op(premature_event, ==, 0);
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (pair1[0] >= 0)
|
|
|
|
evutil_closesocket(pair1[0]);
|
|
|
|
if (pair1[1] >= 0)
|
|
|
|
evutil_closesocket(pair1[1]);
|
|
|
|
if (pair2[0] >= 0)
|
|
|
|
evutil_closesocket(pair2[0]);
|
|
|
|
if (pair2[1] >= 0)
|
|
|
|
evutil_closesocket(pair2[1]);
|
|
|
|
if (rev)
|
|
|
|
event_free(rev);
|
2010-09-07 10:28:15 -04:00
|
|
|
if (wev)
|
|
|
|
event_free(wev);
|
2010-06-03 11:25:54 -04:00
|
|
|
if (closeev)
|
|
|
|
event_free(closeev);
|
|
|
|
if (base)
|
|
|
|
event_base_free(base);
|
|
|
|
}
|
|
|
|
|
2020-04-09 00:30:57 +03:00
|
|
|
static void
|
|
|
|
test_simpleclose(void *ptr)
|
|
|
|
{
|
|
|
|
struct basic_test_data *data = ptr;
|
|
|
|
struct event_base *base = data->base;
|
|
|
|
evutil_socket_t *pair = data->pair;
|
|
|
|
const char *flags = (const char *)data->setup_data;
|
|
|
|
int et = !!strstr(flags, "ET");
|
|
|
|
int persist = !!strstr(flags, "persist");
|
|
|
|
short events = EV_CLOSED | (et ? EV_ET : 0) | (persist ? EV_PERSIST : 0);
|
|
|
|
struct event *ev = NULL;
|
|
|
|
short got_event;
|
|
|
|
|
|
|
|
if (!(event_base_get_features(data->base) & EV_FEATURE_EARLY_CLOSE))
|
|
|
|
tt_skip();
|
|
|
|
|
|
|
|
/* XXX: should this code moved to regress_et.c ? */
|
|
|
|
if (et && !(event_base_get_features(data->base) & EV_FEATURE_ET))
|
|
|
|
tt_skip();
|
|
|
|
|
|
|
|
ev = event_new(base, pair[0], events, record_event_cb, &got_event);
|
|
|
|
tt_assert(ev);
|
|
|
|
tt_assert(!event_add(ev, NULL));
|
|
|
|
|
|
|
|
got_event = 0;
|
|
|
|
if (strstr(flags, "close")) {
|
2020-05-07 21:14:13 -07:00
|
|
|
tt_assert(!evutil_closesocket(pair[1]));
|
2020-04-09 00:30:57 +03:00
|
|
|
/* avoid closing in setup routines */
|
|
|
|
pair[1] = -1;
|
|
|
|
} else if (strstr(flags, "shutdown")) {
|
|
|
|
tt_assert(!shutdown(pair[1], EVUTIL_SHUT_WR));
|
|
|
|
} else {
|
|
|
|
tt_abort_msg("unknown flags");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* w/o edge-triggerd but w/ persist it will not stop */
|
|
|
|
if (!et && persist) {
|
|
|
|
struct timeval tv;
|
|
|
|
tv.tv_sec = 0;
|
|
|
|
tv.tv_usec = 10000;
|
|
|
|
tt_assert(!event_base_loopexit(base, &tv));
|
|
|
|
}
|
|
|
|
|
2020-05-05 00:21:18 +03:00
|
|
|
tt_int_op(event_base_loop(base, EVLOOP_NONBLOCK), ==, !persist);
|
|
|
|
tt_int_op(got_event, ==, (events & ~EV_PERSIST));
|
2020-04-09 00:30:57 +03:00
|
|
|
|
|
|
|
end:
|
|
|
|
if (ev)
|
|
|
|
event_free(ev);
|
|
|
|
}
|
2010-06-03 11:25:54 -04:00
|
|
|
|
2007-11-26 19:18:49 +00:00
|
|
|
static void
|
2005-12-06 03:26:28 +00:00
|
|
|
test_multiple(void)
|
2004-04-04 02:19:08 +00:00
|
|
|
{
|
|
|
|
struct event ev, ev2;
|
|
|
|
int i;
|
2003-03-08 06:39:30 +00:00
|
|
|
|
|
|
|
/* Multiple read and write test */
|
|
|
|
setup_test("Multiple read/write: ");
|
2003-03-08 14:21:14 +00:00
|
|
|
memset(rbuf, 0, sizeof(rbuf));
|
2010-10-14 13:16:41 -04:00
|
|
|
for (i = 0; i < (int)sizeof(wbuf); i++)
|
2003-03-08 06:39:30 +00:00
|
|
|
wbuf[i] = i;
|
|
|
|
|
|
|
|
roff = woff = 0;
|
2003-03-08 14:21:14 +00:00
|
|
|
usepersist = 0;
|
2003-03-08 06:39:30 +00:00
|
|
|
|
|
|
|
event_set(&ev, pair[0], EV_WRITE, multiple_write_cb, &ev);
|
2004-07-30 04:57:21 +00:00
|
|
|
if (event_add(&ev, NULL) == -1)
|
|
|
|
exit(1);
|
2003-03-08 06:39:30 +00:00
|
|
|
event_set(&ev2, pair[1], EV_READ, multiple_read_cb, &ev2);
|
2004-07-30 04:57:21 +00:00
|
|
|
if (event_add(&ev2, NULL) == -1)
|
|
|
|
exit(1);
|
2003-03-08 06:39:30 +00:00
|
|
|
event_dispatch();
|
|
|
|
|
|
|
|
if (roff == woff)
|
|
|
|
test_ok = memcmp(rbuf, wbuf, sizeof(wbuf)) == 0;
|
|
|
|
|
|
|
|
cleanup_test();
|
2004-04-04 02:19:08 +00:00
|
|
|
}
|
|
|
|
|
2007-11-26 19:18:49 +00:00
|
|
|
static void
|
2005-12-06 03:26:28 +00:00
|
|
|
test_persistent(void)
|
2004-04-04 02:19:08 +00:00
|
|
|
{
|
|
|
|
struct event ev, ev2;
|
|
|
|
int i;
|
2003-03-08 06:39:30 +00:00
|
|
|
|
2003-03-08 14:21:14 +00:00
|
|
|
/* Multiple read and write test with persist */
|
|
|
|
setup_test("Persist read/write: ");
|
|
|
|
memset(rbuf, 0, sizeof(rbuf));
|
2010-10-14 13:16:41 -04:00
|
|
|
for (i = 0; i < (int)sizeof(wbuf); i++)
|
2003-03-08 14:21:14 +00:00
|
|
|
wbuf[i] = i;
|
|
|
|
|
|
|
|
roff = woff = 0;
|
|
|
|
usepersist = 1;
|
|
|
|
|
|
|
|
event_set(&ev, pair[0], EV_WRITE|EV_PERSIST, multiple_write_cb, &ev);
|
2004-07-30 04:57:21 +00:00
|
|
|
if (event_add(&ev, NULL) == -1)
|
|
|
|
exit(1);
|
2003-03-08 14:21:14 +00:00
|
|
|
event_set(&ev2, pair[1], EV_READ|EV_PERSIST, multiple_read_cb, &ev2);
|
2004-07-30 04:57:21 +00:00
|
|
|
if (event_add(&ev2, NULL) == -1)
|
|
|
|
exit(1);
|
2003-03-08 14:21:14 +00:00
|
|
|
event_dispatch();
|
|
|
|
|
|
|
|
if (roff == woff)
|
|
|
|
test_ok = memcmp(rbuf, wbuf, sizeof(wbuf)) == 0;
|
|
|
|
|
|
|
|
cleanup_test();
|
2004-04-04 02:19:08 +00:00
|
|
|
}
|
|
|
|
|
2007-11-26 19:18:49 +00:00
|
|
|
static void
|
2005-12-06 03:26:28 +00:00
|
|
|
test_combined(void)
|
2004-04-04 02:19:08 +00:00
|
|
|
{
|
|
|
|
struct both r1, r2, w1, w2;
|
2003-03-08 14:21:14 +00:00
|
|
|
|
2003-03-08 20:14:39 +00:00
|
|
|
setup_test("Combined read/write: ");
|
|
|
|
memset(&r1, 0, sizeof(r1));
|
|
|
|
memset(&r2, 0, sizeof(r2));
|
|
|
|
memset(&w1, 0, sizeof(w1));
|
|
|
|
memset(&w2, 0, sizeof(w2));
|
|
|
|
|
|
|
|
w1.nread = 4096;
|
|
|
|
w2.nread = 8192;
|
|
|
|
|
|
|
|
event_set(&r1.ev, pair[0], EV_READ, combined_read_cb, &r1);
|
|
|
|
event_set(&w1.ev, pair[0], EV_WRITE, combined_write_cb, &w1);
|
|
|
|
event_set(&r2.ev, pair[1], EV_READ, combined_read_cb, &r2);
|
|
|
|
event_set(&w2.ev, pair[1], EV_WRITE, combined_write_cb, &w2);
|
2009-10-02 03:03:58 +00:00
|
|
|
tt_assert(event_add(&r1.ev, NULL) != -1);
|
|
|
|
tt_assert(!event_add(&w1.ev, NULL));
|
|
|
|
tt_assert(!event_add(&r2.ev, NULL));
|
|
|
|
tt_assert(!event_add(&w2.ev, NULL));
|
2003-03-08 20:14:39 +00:00
|
|
|
event_dispatch();
|
|
|
|
|
|
|
|
if (r1.nread == 8192 && r2.nread == 4096)
|
|
|
|
test_ok = 1;
|
|
|
|
|
2009-10-02 03:03:58 +00:00
|
|
|
end:
|
2003-03-08 20:14:39 +00:00
|
|
|
cleanup_test();
|
2004-04-04 02:19:08 +00:00
|
|
|
}
|
|
|
|
|
2007-11-26 19:18:49 +00:00
|
|
|
static void
|
2005-12-06 03:26:28 +00:00
|
|
|
test_simpletimeout(void)
|
2004-04-04 02:19:08 +00:00
|
|
|
{
|
2012-01-24 14:59:37 -05:00
|
|
|
struct timeval tv;
|
2004-04-04 02:19:08 +00:00
|
|
|
struct event ev;
|
2003-03-08 20:14:39 +00:00
|
|
|
|
2003-03-08 06:39:30 +00:00
|
|
|
setup_test("Simple timeout: ");
|
|
|
|
|
2012-01-24 14:33:10 -05:00
|
|
|
tv.tv_usec = 200*1000;
|
|
|
|
tv.tv_sec = 0;
|
|
|
|
evutil_timerclear(&tcalled);
|
2003-03-08 06:39:30 +00:00
|
|
|
evtimer_set(&ev, timeout_cb, NULL);
|
|
|
|
evtimer_add(&ev, &tv);
|
|
|
|
|
2008-06-24 18:04:41 +00:00
|
|
|
evutil_gettimeofday(&tset, NULL);
|
2003-03-08 06:39:30 +00:00
|
|
|
event_dispatch();
|
2012-01-24 14:59:37 -05:00
|
|
|
test_timeval_diff_eq(&tset, &tcalled, 200);
|
2003-03-08 06:39:30 +00:00
|
|
|
|
2012-01-24 14:33:10 -05:00
|
|
|
test_ok = 1;
|
|
|
|
end:
|
2003-03-08 06:39:30 +00:00
|
|
|
cleanup_test();
|
2004-04-04 02:19:08 +00:00
|
|
|
}
|
|
|
|
|
2008-05-03 22:10:09 +00:00
|
|
|
static void
|
2010-03-05 12:47:46 -05:00
|
|
|
periodic_timeout_cb(evutil_socket_t fd, short event, void *arg)
|
2008-05-03 22:10:09 +00:00
|
|
|
{
|
|
|
|
int *count = arg;
|
|
|
|
|
|
|
|
(*count)++;
|
2009-01-27 16:35:28 +00:00
|
|
|
if (*count == 6) {
|
|
|
|
/* call loopexit only once - on slow machines(?), it is
|
|
|
|
* apparently possible for this to get called twice. */
|
2008-05-03 22:10:09 +00:00
|
|
|
test_ok = 1;
|
|
|
|
event_base_loopexit(global_base, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-22 02:33:38 +00:00
|
|
|
static void
|
|
|
|
test_persistent_timeout(void)
|
|
|
|
{
|
|
|
|
struct timeval tv;
|
|
|
|
struct event ev;
|
|
|
|
int count = 0;
|
|
|
|
|
Remove compat/sys/_time.h
I've gone through everything that it declared to see where it was used,
and it seems that we probably don't need it anywhere.
Here's what it declared, and why I think we're okay dropping it.
o struct timeval {}
(Used all over, and we can't really get away with declaring it ourselves;
we need the same definition the system uses. If we can't find struct
timeval, we're pretty much sunk.)
o struct timespec {}
(Used in event.c, evdns.c, kqueue.c, evport.c. Of these,
kqueue.c and event.c include sys/_time.h. event.c conditions its use on
_EVENT_HAVE_CLOCK_GETTIME, and kqueue() only works if timespec is defined.)
o TIMEVAL_TO_TIMESPEC
(Used in kqueue.c, but every place with kqueue has sys/time.h)
o struct timezone {}
(event2/util.h has a forward declaration; only evutil.c references it and
doesn't look at its contents.)
o timerclear, timerisset, timercmp, timeradd, timersub
(Everything now uses the evutil_timer* variants.)
o ITIMER_REAL, ITIMER_VIRTUAL, ITIMER_PROF, struct itemerval
(These are only used in test/regress.c, which does not include _time.h)
o CLOCK_REALTIME
(Only used in evdns.c, which does not include _time.h)
o TIMESPEC_TO_TIMEVAL
o DST_*
o timespecclear, timespecisset, timespeccmp, timespecadd, timespecsub
o struct clockinfo {}
o CLOCK_VIRTUAL, CLOCK_PROF
o TIMER_RELTIME, TIMER_ABSTIME
(unused)
svn:r1494
2009-11-03 19:54:56 +00:00
|
|
|
evutil_timerclear(&tv);
|
2009-01-22 02:33:38 +00:00
|
|
|
tv.tv_usec = 10000;
|
|
|
|
|
|
|
|
event_assign(&ev, global_base, -1, EV_TIMEOUT|EV_PERSIST,
|
|
|
|
periodic_timeout_cb, &count);
|
|
|
|
event_add(&ev, &tv);
|
|
|
|
|
|
|
|
event_dispatch();
|
|
|
|
|
|
|
|
event_del(&ev);
|
2009-11-09 17:16:30 +00:00
|
|
|
}
|
|
|
|
|
2012-04-19 00:25:12 -04:00
|
|
|
static void
|
|
|
|
test_persistent_timeout_jump(void *ptr)
|
|
|
|
{
|
|
|
|
struct basic_test_data *data = ptr;
|
|
|
|
struct event ev;
|
|
|
|
int count = 0;
|
|
|
|
struct timeval msec100 = { 0, 100 * 1000 };
|
|
|
|
struct timeval msec50 = { 0, 50 * 1000 };
|
2012-04-20 11:53:32 -04:00
|
|
|
struct timeval msec300 = { 0, 300 * 1000 };
|
2012-04-19 00:25:12 -04:00
|
|
|
|
|
|
|
event_assign(&ev, data->base, -1, EV_PERSIST, periodic_timeout_cb, &count);
|
|
|
|
event_add(&ev, &msec100);
|
|
|
|
/* Wait for a bit */
|
2012-04-20 11:53:32 -04:00
|
|
|
evutil_usleep_(&msec300);
|
2012-04-19 00:25:12 -04:00
|
|
|
event_base_loopexit(data->base, &msec50);
|
|
|
|
event_base_dispatch(data->base);
|
|
|
|
tt_int_op(count, ==, 1);
|
|
|
|
|
|
|
|
end:
|
|
|
|
event_del(&ev);
|
|
|
|
}
|
|
|
|
|
2010-02-23 23:55:32 -05:00
|
|
|
struct persist_active_timeout_called {
|
|
|
|
int n;
|
|
|
|
short events[16];
|
|
|
|
struct timeval tvs[16];
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
2010-03-05 12:47:46 -05:00
|
|
|
activate_cb(evutil_socket_t fd, short event, void *arg)
|
2010-02-23 23:55:32 -05:00
|
|
|
{
|
|
|
|
struct event *ev = arg;
|
|
|
|
event_active(ev, EV_READ, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2010-03-05 12:47:46 -05:00
|
|
|
persist_active_timeout_cb(evutil_socket_t fd, short event, void *arg)
|
2010-02-23 23:55:32 -05:00
|
|
|
{
|
|
|
|
struct persist_active_timeout_called *c = arg;
|
|
|
|
if (c->n < 15) {
|
|
|
|
c->events[c->n] = event;
|
|
|
|
evutil_gettimeofday(&c->tvs[c->n], NULL);
|
|
|
|
++c->n;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
test_persistent_active_timeout(void *ptr)
|
|
|
|
{
|
|
|
|
struct timeval tv, tv2, tv_exit, start;
|
|
|
|
struct event ev;
|
|
|
|
struct persist_active_timeout_called res;
|
|
|
|
|
|
|
|
struct basic_test_data *data = ptr;
|
|
|
|
struct event_base *base = data->base;
|
|
|
|
|
|
|
|
memset(&res, 0, sizeof(res));
|
|
|
|
|
|
|
|
tv.tv_sec = 0;
|
|
|
|
tv.tv_usec = 200 * 1000;
|
|
|
|
event_assign(&ev, base, -1, EV_TIMEOUT|EV_PERSIST,
|
|
|
|
persist_active_timeout_cb, &res);
|
|
|
|
event_add(&ev, &tv);
|
|
|
|
|
|
|
|
tv2.tv_sec = 0;
|
|
|
|
tv2.tv_usec = 100 * 1000;
|
|
|
|
event_base_once(base, -1, EV_TIMEOUT, activate_cb, &ev, &tv2);
|
|
|
|
|
|
|
|
tv_exit.tv_sec = 0;
|
|
|
|
tv_exit.tv_usec = 600 * 1000;
|
|
|
|
event_base_loopexit(base, &tv_exit);
|
|
|
|
|
2012-02-29 15:07:33 -05:00
|
|
|
event_base_assert_ok_(base);
|
2010-02-23 23:55:32 -05:00
|
|
|
evutil_gettimeofday(&start, NULL);
|
|
|
|
|
|
|
|
event_base_dispatch(base);
|
2012-02-29 15:07:33 -05:00
|
|
|
event_base_assert_ok_(base);
|
2010-02-23 23:55:32 -05:00
|
|
|
|
|
|
|
tt_int_op(res.n, ==, 3);
|
|
|
|
tt_int_op(res.events[0], ==, EV_READ);
|
|
|
|
tt_int_op(res.events[1], ==, EV_TIMEOUT);
|
|
|
|
tt_int_op(res.events[2], ==, EV_TIMEOUT);
|
|
|
|
test_timeval_diff_eq(&start, &res.tvs[0], 100);
|
|
|
|
test_timeval_diff_eq(&start, &res.tvs[1], 300);
|
|
|
|
test_timeval_diff_eq(&start, &res.tvs[2], 500);
|
|
|
|
end:
|
2010-02-24 13:40:06 -05:00
|
|
|
event_del(&ev);
|
2010-02-23 23:55:32 -05:00
|
|
|
}
|
|
|
|
|
2009-11-09 17:16:30 +00:00
|
|
|
struct common_timeout_info {
|
|
|
|
struct event ev;
|
|
|
|
struct timeval called_at;
|
|
|
|
int which;
|
|
|
|
int count;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
2010-03-05 12:47:46 -05:00
|
|
|
common_timeout_cb(evutil_socket_t fd, short event, void *arg)
|
2009-11-09 17:16:30 +00:00
|
|
|
{
|
|
|
|
struct common_timeout_info *ti = arg;
|
|
|
|
++ti->count;
|
|
|
|
evutil_gettimeofday(&ti->called_at, NULL);
|
2012-01-24 14:33:10 -05:00
|
|
|
if (ti->count >= 4)
|
2009-11-09 17:16:30 +00:00
|
|
|
event_del(&ti->ev);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
test_common_timeout(void *ptr)
|
|
|
|
{
|
|
|
|
struct basic_test_data *data = ptr;
|
|
|
|
|
|
|
|
struct event_base *base = data->base;
|
|
|
|
int i;
|
|
|
|
struct common_timeout_info info[100];
|
|
|
|
|
2012-01-24 14:33:10 -05:00
|
|
|
struct timeval start;
|
2009-11-09 17:16:30 +00:00
|
|
|
struct timeval tmp_100_ms = { 0, 100*1000 };
|
|
|
|
struct timeval tmp_200_ms = { 0, 200*1000 };
|
2013-04-26 17:51:33 -04:00
|
|
|
struct timeval tmp_5_sec = { 5, 0 };
|
|
|
|
struct timeval tmp_5M_usec = { 0, 5*1000*1000 };
|
2009-11-09 17:16:30 +00:00
|
|
|
|
2013-04-26 17:51:33 -04:00
|
|
|
const struct timeval *ms_100, *ms_200, *sec_5;
|
2009-11-09 17:16:30 +00:00
|
|
|
|
|
|
|
ms_100 = event_base_init_common_timeout(base, &tmp_100_ms);
|
|
|
|
ms_200 = event_base_init_common_timeout(base, &tmp_200_ms);
|
2013-04-26 17:51:33 -04:00
|
|
|
sec_5 = event_base_init_common_timeout(base, &tmp_5_sec);
|
2009-11-09 17:16:30 +00:00
|
|
|
tt_assert(ms_100);
|
|
|
|
tt_assert(ms_200);
|
2013-04-26 17:51:33 -04:00
|
|
|
tt_assert(sec_5);
|
2009-11-09 17:16:30 +00:00
|
|
|
tt_ptr_op(event_base_init_common_timeout(base, &tmp_200_ms),
|
|
|
|
==, ms_200);
|
2013-04-26 17:51:33 -04:00
|
|
|
tt_ptr_op(event_base_init_common_timeout(base, ms_200), ==, ms_200);
|
|
|
|
tt_ptr_op(event_base_init_common_timeout(base, &tmp_5M_usec), ==, sec_5);
|
2009-11-09 17:16:30 +00:00
|
|
|
tt_int_op(ms_100->tv_sec, ==, 0);
|
|
|
|
tt_int_op(ms_200->tv_sec, ==, 0);
|
2013-04-26 17:51:33 -04:00
|
|
|
tt_int_op(sec_5->tv_sec, ==, 5);
|
2009-11-09 17:16:30 +00:00
|
|
|
tt_int_op(ms_100->tv_usec, ==, 100000|0x50000000);
|
|
|
|
tt_int_op(ms_200->tv_usec, ==, 200000|0x50100000);
|
2013-04-26 17:51:33 -04:00
|
|
|
tt_int_op(sec_5->tv_usec, ==, 0|0x50200000);
|
2009-11-09 17:16:30 +00:00
|
|
|
|
|
|
|
memset(info, 0, sizeof(info));
|
|
|
|
|
|
|
|
for (i=0; i<100; ++i) {
|
|
|
|
info[i].which = i;
|
|
|
|
event_assign(&info[i].ev, base, -1, EV_TIMEOUT|EV_PERSIST,
|
|
|
|
common_timeout_cb, &info[i]);
|
|
|
|
if (i % 2) {
|
2012-03-23 18:42:56 -04:00
|
|
|
if ((i%20)==1) {
|
|
|
|
/* Glass-box test: Make sure we survive the
|
|
|
|
* transition to non-common timeouts. It's
|
|
|
|
* a little tricky. */
|
|
|
|
event_add(&info[i].ev, ms_200);
|
|
|
|
event_add(&info[i].ev, &tmp_100_ms);
|
|
|
|
} else if ((i%20)==3) {
|
|
|
|
/* Check heap-to-common too. */
|
|
|
|
event_add(&info[i].ev, &tmp_200_ms);
|
|
|
|
event_add(&info[i].ev, ms_100);
|
2012-03-23 19:30:02 -04:00
|
|
|
} else if ((i%20)==5) {
|
2012-03-23 18:42:56 -04:00
|
|
|
/* Also check common-to-common. */
|
|
|
|
event_add(&info[i].ev, ms_200);
|
|
|
|
event_add(&info[i].ev, ms_100);
|
|
|
|
} else {
|
|
|
|
event_add(&info[i].ev, ms_100);
|
|
|
|
}
|
2009-11-09 17:16:30 +00:00
|
|
|
} else {
|
|
|
|
event_add(&info[i].ev, ms_200);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-29 15:07:33 -05:00
|
|
|
event_base_assert_ok_(base);
|
2012-01-24 14:33:10 -05:00
|
|
|
evutil_gettimeofday(&start, NULL);
|
2009-11-09 17:16:30 +00:00
|
|
|
event_base_dispatch(base);
|
|
|
|
|
2012-02-29 15:07:33 -05:00
|
|
|
event_base_assert_ok_(base);
|
2009-01-22 02:33:38 +00:00
|
|
|
|
2009-11-09 17:16:30 +00:00
|
|
|
for (i=0; i<10; ++i) {
|
2012-01-24 14:33:10 -05:00
|
|
|
tt_int_op(info[i].count, ==, 4);
|
2009-11-09 17:16:30 +00:00
|
|
|
if (i % 2) {
|
2012-01-24 14:59:37 -05:00
|
|
|
test_timeval_diff_eq(&start, &info[i].called_at, 400);
|
2009-11-09 17:16:30 +00:00
|
|
|
} else {
|
2012-01-24 14:59:37 -05:00
|
|
|
test_timeval_diff_eq(&start, &info[i].called_at, 800);
|
2009-11-09 17:16:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Make sure we can free the base with some events in. */
|
|
|
|
for (i=0; i<100; ++i) {
|
|
|
|
if (i % 2) {
|
|
|
|
event_add(&info[i].ev, ms_100);
|
|
|
|
} else {
|
|
|
|
event_add(&info[i].ev, ms_200);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
end:
|
|
|
|
event_base_free(data->base); /* need to do this here before info is
|
|
|
|
* out-of-scope */
|
|
|
|
data->base = NULL;
|
2009-01-22 02:33:38 +00:00
|
|
|
}
|
|
|
|
|
2011-05-25 19:50:56 -04:00
|
|
|
#ifndef _WIN32
|
2008-07-20 23:31:28 +00:00
|
|
|
|
2010-05-04 13:27:36 -04:00
|
|
|
#define current_base event_global_current_base_
|
2007-11-26 19:18:49 +00:00
|
|
|
extern struct event_base *current_base;
|
2008-07-25 00:48:30 +00:00
|
|
|
|
|
|
|
static void
|
2015-12-27 02:31:03 +03:00
|
|
|
fork_signal_cb(evutil_socket_t fd, short events, void *arg)
|
2008-07-25 00:48:30 +00:00
|
|
|
{
|
2015-12-27 02:31:03 +03:00
|
|
|
event_del(arg);
|
2008-07-25 00:48:30 +00:00
|
|
|
}
|
|
|
|
|
2016-08-11 13:43:14 +03:00
|
|
|
int child_pair[2] = { -1, -1 };
|
|
|
|
static void
|
|
|
|
simple_child_read_cb(evutil_socket_t fd, short event, void *arg)
|
|
|
|
{
|
|
|
|
char buf[256];
|
|
|
|
int len;
|
|
|
|
|
|
|
|
len = read(fd, buf, sizeof(buf));
|
|
|
|
if (write(child_pair[0], "", 1) < 0)
|
|
|
|
tt_fail_perror("write");
|
|
|
|
|
|
|
|
if (len) {
|
|
|
|
if (!called) {
|
|
|
|
if (event_add(arg, NULL) == -1)
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
} else if (called == 1)
|
|
|
|
test_ok = 1;
|
2015-12-27 02:31:03 +03:00
|
|
|
|
2016-08-11 13:43:14 +03:00
|
|
|
called++;
|
|
|
|
}
|
2017-03-13 23:52:15 +03:00
|
|
|
|
|
|
|
#define TEST_FORK_EXIT_SUCCESS 76
|
|
|
|
static void fork_wait_check(int pid)
|
|
|
|
{
|
|
|
|
int status;
|
|
|
|
|
|
|
|
TT_BLATHER(("Before waitpid"));
|
|
|
|
|
|
|
|
#ifdef WNOWAIT
|
|
|
|
if ((waitpid(pid, &status, WNOWAIT) == -1 && errno == EINVAL) &&
|
|
|
|
#else
|
|
|
|
if (
|
|
|
|
#endif
|
|
|
|
waitpid(pid, &status, 0) == -1) {
|
|
|
|
perror("waitpid");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
TT_BLATHER(("After waitpid"));
|
|
|
|
|
|
|
|
if (WEXITSTATUS(status) != TEST_FORK_EXIT_SUCCESS) {
|
|
|
|
fprintf(stdout, "FAILED (exit): %d\n", WEXITSTATUS(status));
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
2007-11-26 19:18:49 +00:00
|
|
|
static void
|
2007-11-25 06:57:59 +00:00
|
|
|
test_fork(void)
|
|
|
|
{
|
2016-08-11 13:43:14 +03:00
|
|
|
char c;
|
2015-12-27 02:48:40 +03:00
|
|
|
struct event ev, sig_ev, usr_ev, existing_ev;
|
2007-11-25 06:57:59 +00:00
|
|
|
pid_t pid;
|
|
|
|
|
|
|
|
setup_test("After fork: ");
|
|
|
|
|
2016-08-11 13:43:14 +03:00
|
|
|
{
|
|
|
|
if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, child_pair) == -1) {
|
|
|
|
fprintf(stderr, "%s: socketpair\n", __func__);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (evutil_make_socket_nonblocking(child_pair[0]) == -1) {
|
|
|
|
fprintf(stderr, "fcntl(O_NONBLOCK)");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-08 13:29:06 -04:00
|
|
|
tt_assert(current_base);
|
|
|
|
evthread_make_base_notifiable(current_base);
|
|
|
|
|
2011-07-12 13:05:36 -04:00
|
|
|
if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) {
|
2011-10-03 12:45:36 -04:00
|
|
|
tt_fail_perror("write");
|
2011-07-12 13:05:36 -04:00
|
|
|
}
|
2007-11-25 06:57:59 +00:00
|
|
|
|
2016-08-11 13:43:14 +03:00
|
|
|
event_set(&ev, pair[1], EV_READ, simple_child_read_cb, &ev);
|
2007-11-25 06:57:59 +00:00
|
|
|
if (event_add(&ev, NULL) == -1)
|
|
|
|
exit(1);
|
|
|
|
|
2015-12-27 02:31:03 +03:00
|
|
|
evsignal_set(&sig_ev, SIGCHLD, fork_signal_cb, &sig_ev);
|
2008-12-23 22:23:37 +00:00
|
|
|
evsignal_add(&sig_ev, NULL);
|
2008-07-20 23:31:28 +00:00
|
|
|
|
2015-12-27 02:48:40 +03:00
|
|
|
evsignal_set(&existing_ev, SIGUSR2, fork_signal_cb, &existing_ev);
|
|
|
|
evsignal_add(&existing_ev, NULL);
|
|
|
|
|
2012-02-29 15:07:33 -05:00
|
|
|
event_base_assert_ok_(current_base);
|
2012-01-21 12:55:15 -05:00
|
|
|
TT_BLATHER(("Before fork"));
|
2012-04-11 21:33:27 -04:00
|
|
|
if ((pid = regress_fork()) == 0) {
|
2007-11-25 06:57:59 +00:00
|
|
|
/* in the child */
|
2012-01-21 12:55:15 -05:00
|
|
|
TT_BLATHER(("In child, before reinit"));
|
2012-02-29 15:07:33 -05:00
|
|
|
event_base_assert_ok_(current_base);
|
2007-11-25 06:57:59 +00:00
|
|
|
if (event_reinit(current_base) == -1) {
|
2008-05-29 01:39:43 +00:00
|
|
|
fprintf(stdout, "FAILED (reinit)\n");
|
2007-11-25 06:57:59 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
2012-01-21 12:55:15 -05:00
|
|
|
TT_BLATHER(("After reinit"));
|
2012-02-29 15:07:33 -05:00
|
|
|
event_base_assert_ok_(current_base);
|
2012-01-21 12:55:15 -05:00
|
|
|
TT_BLATHER(("After assert-ok"));
|
2007-11-25 06:57:59 +00:00
|
|
|
|
2008-12-23 22:23:37 +00:00
|
|
|
evsignal_del(&sig_ev);
|
2008-07-20 23:31:28 +00:00
|
|
|
|
2015-12-27 09:26:54 +03:00
|
|
|
evsignal_set(&usr_ev, SIGUSR1, fork_signal_cb, &usr_ev);
|
|
|
|
evsignal_add(&usr_ev, NULL);
|
2019-02-24 17:07:18 +03:00
|
|
|
kill(getpid(), SIGUSR1);
|
|
|
|
kill(getpid(), SIGUSR2);
|
2015-12-27 09:26:54 +03:00
|
|
|
|
2008-05-16 01:55:40 +00:00
|
|
|
called = 0;
|
|
|
|
|
2007-11-25 06:57:59 +00:00
|
|
|
event_dispatch();
|
|
|
|
|
2008-07-20 23:31:28 +00:00
|
|
|
event_base_free(current_base);
|
|
|
|
|
2009-01-27 21:10:31 +00:00
|
|
|
/* we do not send an EOF; simple_read_cb requires an EOF
|
2007-11-29 02:52:32 +00:00
|
|
|
* to set test_ok. we just verify that the callback was
|
|
|
|
* called. */
|
2017-03-13 23:52:15 +03:00
|
|
|
exit(test_ok != 0 || called != 2 ? -2 : TEST_FORK_EXIT_SUCCESS);
|
2007-11-25 06:57:59 +00:00
|
|
|
}
|
|
|
|
|
2016-08-11 13:43:14 +03:00
|
|
|
/** wait until client read first message */
|
|
|
|
if (read(child_pair[1], &c, 1) < 0) {
|
|
|
|
tt_fail_perror("read");
|
2012-01-24 11:45:00 -05:00
|
|
|
}
|
2011-07-12 13:05:36 -04:00
|
|
|
if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) {
|
2011-10-03 12:45:36 -04:00
|
|
|
tt_fail_perror("write");
|
2011-07-12 13:05:36 -04:00
|
|
|
}
|
2007-11-25 06:57:59 +00:00
|
|
|
|
2017-03-13 23:52:15 +03:00
|
|
|
fork_wait_check(pid);
|
2007-11-27 06:11:28 +00:00
|
|
|
|
|
|
|
/* test that the current event loop still works */
|
2011-07-12 13:05:36 -04:00
|
|
|
if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) {
|
|
|
|
fprintf(stderr, "%s: write\n", __func__);
|
|
|
|
}
|
|
|
|
|
2016-03-11 01:27:52 +03:00
|
|
|
shutdown(pair[0], EVUTIL_SHUT_WR);
|
2007-11-27 06:11:28 +00:00
|
|
|
|
2015-12-27 09:26:54 +03:00
|
|
|
evsignal_set(&usr_ev, SIGUSR1, fork_signal_cb, &usr_ev);
|
|
|
|
evsignal_add(&usr_ev, NULL);
|
2019-02-24 17:07:18 +03:00
|
|
|
kill(getpid(), SIGUSR1);
|
|
|
|
kill(getpid(), SIGUSR2);
|
2015-12-27 09:26:54 +03:00
|
|
|
|
2007-11-27 06:11:28 +00:00
|
|
|
event_dispatch();
|
2008-07-25 00:48:30 +00:00
|
|
|
|
2008-12-23 22:23:37 +00:00
|
|
|
evsignal_del(&sig_ev);
|
2016-08-11 13:43:14 +03:00
|
|
|
tt_int_op(test_ok, ==, 1);
|
2008-07-25 00:48:30 +00:00
|
|
|
|
2010-09-08 13:29:06 -04:00
|
|
|
end:
|
2007-11-25 06:57:59 +00:00
|
|
|
cleanup_test();
|
2016-08-11 13:43:14 +03:00
|
|
|
if (child_pair[0] != -1)
|
|
|
|
evutil_closesocket(child_pair[0]);
|
|
|
|
if (child_pair[1] != -1)
|
|
|
|
evutil_closesocket(child_pair[1]);
|
2007-11-25 06:57:59 +00:00
|
|
|
}
|
|
|
|
|
2008-02-26 04:54:19 +00:00
|
|
|
static void
|
|
|
|
signal_cb_sa(int sig)
|
|
|
|
{
|
|
|
|
test_ok = 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2010-03-05 12:47:46 -05:00
|
|
|
signal_cb(evutil_socket_t fd, short event, void *arg)
|
2008-02-26 04:54:19 +00:00
|
|
|
{
|
|
|
|
struct event *ev = arg;
|
|
|
|
|
2008-12-23 22:23:37 +00:00
|
|
|
evsignal_del(ev);
|
2008-02-26 04:54:19 +00:00
|
|
|
test_ok = 1;
|
|
|
|
}
|
|
|
|
|
2024-10-28 10:06:45 +01:00
|
|
|
static void
|
|
|
|
signal_alarm_fallback(int sig)
|
|
|
|
{
|
|
|
|
TT_DIE(("ALRM received not from event loop!"));
|
|
|
|
end:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
2007-11-26 19:18:49 +00:00
|
|
|
static void
|
2024-10-28 08:23:48 +01:00
|
|
|
test_simple_signal_impl(int find_reorder)
|
2004-04-04 02:19:08 +00:00
|
|
|
{
|
|
|
|
struct event ev;
|
|
|
|
struct itimerval itv;
|
2003-03-08 06:39:30 +00:00
|
|
|
|
2024-10-28 10:06:45 +01:00
|
|
|
signal(SIGALRM, signal_alarm_fallback);
|
|
|
|
|
2008-12-23 22:23:37 +00:00
|
|
|
evsignal_set(&ev, SIGALRM, signal_cb, &ev);
|
|
|
|
evsignal_add(&ev, NULL);
|
2008-07-11 15:15:04 +00:00
|
|
|
/* find bugs in which operations are re-ordered */
|
2014-02-23 02:31:51 +04:00
|
|
|
if (find_reorder) {
|
|
|
|
evsignal_del(&ev);
|
|
|
|
evsignal_add(&ev, NULL);
|
|
|
|
}
|
2003-03-08 06:39:30 +00:00
|
|
|
|
|
|
|
memset(&itv, 0, sizeof(itv));
|
2012-01-24 14:33:10 -05:00
|
|
|
itv.it_value.tv_sec = 0;
|
|
|
|
itv.it_value.tv_usec = 100000;
|
2024-10-28 10:03:17 +01:00
|
|
|
tt_int_op(setitimer(ITIMER_REAL, &itv, NULL), ==, 0);
|
2003-03-08 06:39:30 +00:00
|
|
|
|
|
|
|
event_dispatch();
|
2024-10-28 10:03:17 +01:00
|
|
|
end:
|
2008-12-23 22:23:37 +00:00
|
|
|
if (evsignal_del(&ev) == -1)
|
2006-09-03 21:12:59 +00:00
|
|
|
test_ok = 0;
|
2003-03-08 06:39:30 +00:00
|
|
|
|
|
|
|
cleanup_test();
|
2004-04-04 02:19:08 +00:00
|
|
|
}
|
2007-02-28 04:29:18 +00:00
|
|
|
|
2014-02-23 02:31:51 +04:00
|
|
|
static void
|
2024-10-28 08:23:48 +01:00
|
|
|
test_simple_signal(void)
|
2014-02-23 02:31:51 +04:00
|
|
|
{
|
|
|
|
setup_test("Simplest one signal: ");
|
2024-10-28 08:23:48 +01:00
|
|
|
test_simple_signal_impl(0);
|
2014-02-23 02:31:51 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2024-10-28 08:23:48 +01:00
|
|
|
test_simple_signal_re_order(void)
|
2014-02-23 02:31:51 +04:00
|
|
|
{
|
|
|
|
setup_test("Simple signal: ");
|
2024-10-28 08:23:48 +01:00
|
|
|
test_simple_signal_impl(1);
|
2014-02-23 02:31:51 +04:00
|
|
|
}
|
|
|
|
|
2024-10-20 21:57:02 +02:00
|
|
|
/* signal_free_in_callback */
|
|
|
|
static void
|
|
|
|
signal_cb_free_event(evutil_socket_t fd, short event, void *arg)
|
|
|
|
{
|
|
|
|
struct event *ev = arg;
|
|
|
|
event_free(ev);
|
|
|
|
++test_ok;
|
|
|
|
}
|
|
|
|
static void
|
|
|
|
test_signal_free_in_callback(void *ptr)
|
|
|
|
{
|
|
|
|
struct basic_test_data *data = ptr;
|
|
|
|
struct event_base *base = data->base;
|
|
|
|
struct event *ev;
|
|
|
|
|
|
|
|
ev = evsignal_new(base, SIGUSR1, signal_cb_free_event, event_self_cbarg());
|
|
|
|
evsignal_add(ev, NULL);
|
|
|
|
|
|
|
|
kill(getpid(), SIGUSR1);
|
|
|
|
kill(getpid(), SIGUSR1);
|
|
|
|
test_ok = 0;
|
|
|
|
|
|
|
|
event_base_loop(base, 0);
|
|
|
|
tt_int_op(test_ok, ==, 1);
|
|
|
|
test_ok = 0;
|
|
|
|
return;
|
|
|
|
|
|
|
|
end:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
2008-07-11 15:49:04 +00:00
|
|
|
static void
|
|
|
|
test_multiplesignal(void)
|
|
|
|
{
|
|
|
|
struct event ev_one, ev_two;
|
|
|
|
struct itimerval itv;
|
|
|
|
|
|
|
|
setup_test("Multiple signal: ");
|
|
|
|
|
2024-10-28 10:06:45 +01:00
|
|
|
signal(SIGALRM, signal_alarm_fallback);
|
|
|
|
|
2008-12-23 22:23:37 +00:00
|
|
|
evsignal_set(&ev_one, SIGALRM, signal_cb, &ev_one);
|
|
|
|
evsignal_add(&ev_one, NULL);
|
2008-07-11 15:49:04 +00:00
|
|
|
|
2008-12-23 22:23:37 +00:00
|
|
|
evsignal_set(&ev_two, SIGALRM, signal_cb, &ev_two);
|
|
|
|
evsignal_add(&ev_two, NULL);
|
2008-07-11 15:49:04 +00:00
|
|
|
|
|
|
|
memset(&itv, 0, sizeof(itv));
|
2012-01-24 14:33:10 -05:00
|
|
|
itv.it_value.tv_sec = 0;
|
|
|
|
itv.it_value.tv_usec = 100000;
|
2024-10-28 10:03:17 +01:00
|
|
|
tt_int_op(setitimer(ITIMER_REAL, &itv, NULL), ==, 0);
|
2008-07-11 15:49:04 +00:00
|
|
|
|
|
|
|
event_dispatch();
|
|
|
|
|
2024-10-28 10:03:17 +01:00
|
|
|
end:
|
2008-12-23 22:23:37 +00:00
|
|
|
if (evsignal_del(&ev_one) == -1)
|
2008-07-11 15:49:04 +00:00
|
|
|
test_ok = 0;
|
2008-12-23 22:23:37 +00:00
|
|
|
if (evsignal_del(&ev_two) == -1)
|
2008-07-11 15:49:04 +00:00
|
|
|
test_ok = 0;
|
|
|
|
|
|
|
|
cleanup_test();
|
|
|
|
}
|
|
|
|
|
2007-11-26 19:18:49 +00:00
|
|
|
static void
|
2007-02-28 04:29:18 +00:00
|
|
|
test_immediatesignal(void)
|
|
|
|
{
|
|
|
|
struct event ev;
|
|
|
|
|
2007-11-22 16:41:29 +00:00
|
|
|
test_ok = 0;
|
2008-12-23 22:23:37 +00:00
|
|
|
evsignal_set(&ev, SIGUSR1, signal_cb, &ev);
|
|
|
|
evsignal_add(&ev, NULL);
|
2019-02-24 17:07:18 +03:00
|
|
|
kill(getpid(), SIGUSR1);
|
2007-02-28 04:29:18 +00:00
|
|
|
event_loop(EVLOOP_NONBLOCK);
|
2008-12-23 22:23:37 +00:00
|
|
|
evsignal_del(&ev);
|
2007-02-28 04:29:18 +00:00
|
|
|
cleanup_test();
|
|
|
|
}
|
2007-03-10 06:37:53 +00:00
|
|
|
|
2024-02-18 16:06:28 +01:00
|
|
|
static void
|
|
|
|
test_signal_timeout(void)
|
|
|
|
{
|
|
|
|
struct event ev;
|
|
|
|
struct timeval tv = { 0, 10 };
|
|
|
|
|
|
|
|
test_ok = 0;
|
|
|
|
evsignal_set(&ev, SIGUSR1, signal_cb, &ev);
|
|
|
|
tt_int_op(evsignal_add(&ev, &tv), ==, 0);
|
|
|
|
event_loop(EVLOOP_ONCE);
|
|
|
|
evsignal_del(&ev);
|
|
|
|
tt_int_op(test_ok, ==, 1);
|
|
|
|
|
|
|
|
end:
|
|
|
|
cleanup_test();
|
|
|
|
}
|
|
|
|
|
2007-11-26 19:18:49 +00:00
|
|
|
static void
|
2007-03-10 06:37:53 +00:00
|
|
|
test_signal_dealloc(void)
|
|
|
|
{
|
2008-12-23 22:23:37 +00:00
|
|
|
/* make sure that evsignal_event is event_del'ed and pipe closed */
|
2007-03-10 06:37:53 +00:00
|
|
|
struct event ev;
|
|
|
|
struct event_base *base = event_init();
|
2008-12-23 22:23:37 +00:00
|
|
|
evsignal_set(&ev, SIGUSR1, signal_cb, &ev);
|
|
|
|
evsignal_add(&ev, NULL);
|
|
|
|
evsignal_del(&ev);
|
2007-03-10 06:37:53 +00:00
|
|
|
event_base_free(base);
|
2010-02-18 17:41:15 -05:00
|
|
|
/* If we got here without asserting, we're fine. */
|
|
|
|
test_ok = 1;
|
2007-03-10 06:37:53 +00:00
|
|
|
cleanup_test();
|
|
|
|
}
|
|
|
|
|
2007-11-26 19:18:49 +00:00
|
|
|
static void
|
2007-03-10 06:37:53 +00:00
|
|
|
test_signal_pipeloss(void)
|
|
|
|
{
|
|
|
|
/* make sure that the base1 pipe is closed correctly. */
|
|
|
|
struct event_base *base1, *base2;
|
|
|
|
int pipe1;
|
2007-11-22 16:41:29 +00:00
|
|
|
test_ok = 0;
|
2007-03-10 06:37:53 +00:00
|
|
|
base1 = event_init();
|
|
|
|
pipe1 = base1->sig.ev_signal_pair[0];
|
|
|
|
base2 = event_init();
|
|
|
|
event_base_free(base2);
|
|
|
|
event_base_free(base1);
|
|
|
|
if (close(pipe1) != -1 || errno!=EBADF) {
|
|
|
|
/* fd must be closed, so second close gives -1, EBADF */
|
|
|
|
printf("signal pipe not closed. ");
|
|
|
|
test_ok = 0;
|
|
|
|
} else {
|
|
|
|
test_ok = 1;
|
|
|
|
}
|
|
|
|
cleanup_test();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* make two bases to catch signals, use both of them. this only works
|
2010-02-18 17:41:15 -05:00
|
|
|
* for event mechanisms that use our signal pipe trick. kqueue handles
|
2007-11-25 17:15:28 +00:00
|
|
|
* signals internally, and all interested kqueues get all the signals.
|
2022-10-25 11:30:34 +03:00
|
|
|
* This is not expected to work with signalfd - having more than one
|
|
|
|
* descriptor in attempt to accept the same signal (or intersecting sets
|
|
|
|
* of signals) is not the thing signalfd() was designed for.
|
2007-03-10 06:37:53 +00:00
|
|
|
*/
|
2007-11-26 19:18:49 +00:00
|
|
|
static void
|
2007-03-10 06:37:53 +00:00
|
|
|
test_signal_switchbase(void)
|
|
|
|
{
|
|
|
|
struct event ev1, ev2;
|
|
|
|
struct event_base *base1, *base2;
|
2010-02-18 17:41:15 -05:00
|
|
|
int is_kqueue;
|
2007-03-10 06:37:53 +00:00
|
|
|
base1 = event_init();
|
|
|
|
base2 = event_init();
|
2022-10-25 11:30:34 +03:00
|
|
|
|
|
|
|
test_ok = 1;
|
|
|
|
if (!strcmp(event_base_get_signal_method(base1), "signalfd_signal") ||
|
|
|
|
!strcmp(event_base_get_signal_method(base2), "signalfd_signal")) {
|
|
|
|
tt_skip();
|
|
|
|
}
|
|
|
|
test_ok = 0;
|
|
|
|
|
2010-02-18 17:41:15 -05:00
|
|
|
is_kqueue = !strcmp(event_get_method(),"kqueue");
|
2008-12-23 22:23:37 +00:00
|
|
|
evsignal_set(&ev1, SIGUSR1, signal_cb, &ev1);
|
|
|
|
evsignal_set(&ev2, SIGUSR1, signal_cb, &ev2);
|
2007-03-10 06:37:53 +00:00
|
|
|
if (event_base_set(base1, &ev1) ||
|
|
|
|
event_base_set(base2, &ev2) ||
|
|
|
|
event_add(&ev1, NULL) ||
|
|
|
|
event_add(&ev2, NULL)) {
|
|
|
|
fprintf(stderr, "%s: cannot set base, add\n", __func__);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2009-07-21 19:20:44 +00:00
|
|
|
tt_ptr_op(event_get_base(&ev1), ==, base1);
|
|
|
|
tt_ptr_op(event_get_base(&ev2), ==, base2);
|
|
|
|
|
2007-03-10 06:37:53 +00:00
|
|
|
test_ok = 0;
|
|
|
|
/* can handle signal before loop is called */
|
2019-02-24 17:07:18 +03:00
|
|
|
kill(getpid(), SIGUSR1);
|
2007-03-10 06:37:53 +00:00
|
|
|
event_base_loop(base2, EVLOOP_NONBLOCK);
|
2010-02-18 17:41:15 -05:00
|
|
|
if (is_kqueue) {
|
|
|
|
if (!test_ok)
|
|
|
|
goto end;
|
|
|
|
test_ok = 0;
|
|
|
|
}
|
2007-03-10 06:37:53 +00:00
|
|
|
event_base_loop(base1, EVLOOP_NONBLOCK);
|
2007-11-25 17:15:28 +00:00
|
|
|
if (test_ok && !is_kqueue) {
|
2007-03-10 06:37:53 +00:00
|
|
|
test_ok = 0;
|
2007-11-25 17:15:28 +00:00
|
|
|
|
2007-03-10 06:37:53 +00:00
|
|
|
/* set base1 to handle signals */
|
|
|
|
event_base_loop(base1, EVLOOP_NONBLOCK);
|
2019-02-24 17:07:18 +03:00
|
|
|
kill(getpid(), SIGUSR1);
|
2007-03-10 06:37:53 +00:00
|
|
|
event_base_loop(base1, EVLOOP_NONBLOCK);
|
|
|
|
event_base_loop(base2, EVLOOP_NONBLOCK);
|
|
|
|
}
|
2009-07-21 19:20:44 +00:00
|
|
|
end:
|
2007-03-10 06:37:53 +00:00
|
|
|
event_base_free(base1);
|
|
|
|
event_base_free(base2);
|
|
|
|
cleanup_test();
|
|
|
|
}
|
2007-11-10 05:18:17 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* assert that a signal event removed from the event queue really is
|
|
|
|
* removed - with no possibility of it's parent handler being fired.
|
|
|
|
*/
|
2007-11-26 19:18:49 +00:00
|
|
|
static void
|
|
|
|
test_signal_assert(void)
|
2007-11-10 05:18:17 +00:00
|
|
|
{
|
|
|
|
struct event ev;
|
|
|
|
struct event_base *base = event_init();
|
2007-11-22 16:41:29 +00:00
|
|
|
test_ok = 0;
|
2007-11-10 05:18:17 +00:00
|
|
|
/* use SIGCONT so we don't kill ourselves when we signal to nowhere */
|
2008-12-23 22:23:37 +00:00
|
|
|
evsignal_set(&ev, SIGCONT, signal_cb, &ev);
|
|
|
|
evsignal_add(&ev, NULL);
|
2007-11-10 05:18:17 +00:00
|
|
|
/*
|
2008-12-23 22:23:37 +00:00
|
|
|
* if evsignal_del() fails to reset the handler, it's current handler
|
|
|
|
* will still point to evsig_handler().
|
2007-11-10 05:18:17 +00:00
|
|
|
*/
|
2008-12-23 22:23:37 +00:00
|
|
|
evsignal_del(&ev);
|
2007-11-10 05:18:17 +00:00
|
|
|
|
2019-02-24 17:07:18 +03:00
|
|
|
kill(getpid(), SIGCONT);
|
2010-09-15 01:54:51 -04:00
|
|
|
#if 0
|
2008-12-23 22:23:37 +00:00
|
|
|
/* only way to verify we were in evsig_handler() */
|
2010-09-15 01:54:51 -04:00
|
|
|
/* XXXX Now there's no longer a good way. */
|
2008-12-23 22:23:37 +00:00
|
|
|
if (base->sig.evsig_caught)
|
2007-11-10 05:18:17 +00:00
|
|
|
test_ok = 0;
|
|
|
|
else
|
|
|
|
test_ok = 1;
|
2010-09-15 01:54:51 -04:00
|
|
|
#else
|
|
|
|
test_ok = 1;
|
|
|
|
#endif
|
2007-11-10 05:18:17 +00:00
|
|
|
|
|
|
|
event_base_free(base);
|
|
|
|
cleanup_test();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* assert that we restore our previous signal handler properly.
|
|
|
|
*/
|
2007-11-26 19:18:49 +00:00
|
|
|
static void
|
|
|
|
test_signal_restore(void)
|
2007-11-10 05:18:17 +00:00
|
|
|
{
|
|
|
|
struct event ev;
|
|
|
|
struct event_base *base = event_init();
|
2012-02-29 15:07:31 -05:00
|
|
|
#ifdef EVENT__HAVE_SIGACTION
|
2007-11-10 05:18:17 +00:00
|
|
|
struct sigaction sa;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
test_ok = 0;
|
2012-02-29 15:07:31 -05:00
|
|
|
#ifdef EVENT__HAVE_SIGACTION
|
2007-11-10 05:18:17 +00:00
|
|
|
sa.sa_handler = signal_cb_sa;
|
|
|
|
sa.sa_flags = 0x0;
|
|
|
|
sigemptyset(&sa.sa_mask);
|
|
|
|
if (sigaction(SIGUSR1, &sa, NULL) == -1)
|
|
|
|
goto out;
|
|
|
|
#else
|
|
|
|
if (signal(SIGUSR1, signal_cb_sa) == SIG_ERR)
|
|
|
|
goto out;
|
|
|
|
#endif
|
2008-12-23 22:23:37 +00:00
|
|
|
evsignal_set(&ev, SIGUSR1, signal_cb, &ev);
|
|
|
|
evsignal_add(&ev, NULL);
|
|
|
|
evsignal_del(&ev);
|
2007-11-10 05:18:17 +00:00
|
|
|
|
2019-02-24 17:07:18 +03:00
|
|
|
kill(getpid(), SIGUSR1);
|
2007-11-10 05:18:17 +00:00
|
|
|
/* 1 == signal_cb, 2 == signal_cb_sa, we want our previous handler */
|
|
|
|
if (test_ok != 2)
|
|
|
|
test_ok = 0;
|
|
|
|
out:
|
|
|
|
event_base_free(base);
|
|
|
|
cleanup_test();
|
|
|
|
return;
|
|
|
|
}
|
2009-01-22 06:23:14 +00:00
|
|
|
|
2009-01-22 17:48:16 +00:00
|
|
|
static void
|
2009-01-22 06:23:14 +00:00
|
|
|
signal_cb_swp(int sig, short event, void *arg)
|
|
|
|
{
|
|
|
|
called++;
|
|
|
|
if (called < 5)
|
2019-02-24 17:07:18 +03:00
|
|
|
kill(getpid(), sig);
|
2009-01-22 06:23:14 +00:00
|
|
|
else
|
|
|
|
event_loopexit(NULL);
|
|
|
|
}
|
2009-01-22 17:48:16 +00:00
|
|
|
static void
|
2010-03-05 12:47:46 -05:00
|
|
|
timeout_cb_swp(evutil_socket_t fd, short event, void *arg)
|
2009-01-22 06:23:14 +00:00
|
|
|
{
|
|
|
|
if (called == -1) {
|
|
|
|
struct timeval tv = {5, 0};
|
|
|
|
|
|
|
|
called = 0;
|
|
|
|
evtimer_add((struct event *)arg, &tv);
|
2019-02-24 17:07:18 +03:00
|
|
|
kill(getpid(), SIGUSR1);
|
2009-01-22 06:23:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
test_ok = 0;
|
|
|
|
event_loopexit(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
test_signal_while_processing(void)
|
|
|
|
{
|
|
|
|
struct event_base *base = event_init();
|
|
|
|
struct event ev, ev_timer;
|
|
|
|
struct timeval tv = {0, 0};
|
|
|
|
|
|
|
|
setup_test("Receiving a signal while processing other signal: ");
|
|
|
|
|
|
|
|
called = -1;
|
|
|
|
test_ok = 1;
|
|
|
|
signal_set(&ev, SIGUSR1, signal_cb_swp, NULL);
|
|
|
|
signal_add(&ev, NULL);
|
|
|
|
evtimer_set(&ev_timer, timeout_cb_swp, &ev_timer);
|
|
|
|
evtimer_add(&ev_timer, &tv);
|
|
|
|
event_dispatch();
|
|
|
|
|
|
|
|
event_base_free(base);
|
|
|
|
cleanup_test();
|
|
|
|
return;
|
|
|
|
}
|
2023-02-12 21:39:04 +01:00
|
|
|
#endif // \_WIN32
|
|
|
|
|
|
|
|
#ifndef EVENT__DISABLE_THREAD_SUPPORT
|
2024-05-19 00:18:48 +08:00
|
|
|
|
|
|
|
static THREAD_FN
|
|
|
|
del_wait_thread(void *arg)
|
2023-02-12 21:39:04 +01:00
|
|
|
{
|
|
|
|
struct timeval tv_start, tv_end;
|
|
|
|
|
|
|
|
evutil_gettimeofday(&tv_start, NULL);
|
|
|
|
event_dispatch();
|
|
|
|
evutil_gettimeofday(&tv_end, NULL);
|
|
|
|
|
|
|
|
test_timeval_diff_eq(&tv_start, &tv_end, 300);
|
|
|
|
|
|
|
|
end:
|
2024-05-19 00:18:48 +08:00
|
|
|
THREAD_RETURN();
|
2023-02-12 21:39:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
del_wait_cb(evutil_socket_t fd, short event, void *arg)
|
|
|
|
{
|
|
|
|
struct timeval delay = { 0, 300*1000 };
|
|
|
|
TT_BLATHER(("Sleeping: %i", test_ok));
|
|
|
|
evutil_usleep_(&delay);
|
|
|
|
++test_ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
test_del_wait(void)
|
|
|
|
{
|
|
|
|
struct event ev;
|
|
|
|
THREAD_T thread;
|
|
|
|
|
|
|
|
setup_test("event_del will wait: ");
|
|
|
|
|
|
|
|
event_set(&ev, pair[1], EV_READ|EV_PERSIST, del_wait_cb, &ev);
|
|
|
|
event_add(&ev, NULL);
|
|
|
|
|
|
|
|
THREAD_START(thread, del_wait_thread, NULL);
|
|
|
|
|
|
|
|
if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) {
|
|
|
|
tt_fail_perror("write");
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
struct timeval delay = { 0, 30*1000 };
|
|
|
|
evutil_usleep_(&delay);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
struct timeval tv_start, tv_end;
|
|
|
|
evutil_gettimeofday(&tv_start, NULL);
|
|
|
|
event_del(&ev);
|
|
|
|
evutil_gettimeofday(&tv_end, NULL);
|
|
|
|
test_timeval_diff_eq(&tv_start, &tv_end, 270);
|
|
|
|
}
|
|
|
|
|
|
|
|
THREAD_JOIN(thread);
|
|
|
|
|
|
|
|
tt_int_op(test_ok, ==, 1);
|
|
|
|
|
|
|
|
end:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void null_cb(evutil_socket_t fd, short what, void *arg) {}
|
2024-05-19 00:18:48 +08:00
|
|
|
|
|
|
|
static THREAD_FN
|
|
|
|
test_del_notify_thread(void *arg)
|
2023-02-12 21:39:04 +01:00
|
|
|
{
|
|
|
|
event_dispatch();
|
2024-05-19 00:18:48 +08:00
|
|
|
THREAD_RETURN();
|
2023-02-12 21:39:04 +01:00
|
|
|
}
|
2024-05-19 00:18:48 +08:00
|
|
|
|
2023-02-12 21:39:04 +01:00
|
|
|
static void
|
|
|
|
test_del_notify(void)
|
|
|
|
{
|
|
|
|
struct event ev;
|
|
|
|
THREAD_T thread;
|
|
|
|
|
|
|
|
test_ok = 1;
|
|
|
|
|
|
|
|
event_set(&ev, -1, EV_READ, null_cb, &ev);
|
|
|
|
event_add(&ev, NULL);
|
|
|
|
|
|
|
|
THREAD_START(thread, test_del_notify_thread, NULL);
|
|
|
|
|
|
|
|
{
|
|
|
|
struct timeval delay = { 0, 1000 };
|
|
|
|
evutil_usleep_(&delay);
|
|
|
|
}
|
|
|
|
|
|
|
|
event_del(&ev);
|
|
|
|
THREAD_JOIN(thread);
|
|
|
|
}
|
2004-05-24 00:19:52 +00:00
|
|
|
#endif
|
2004-04-04 02:19:08 +00:00
|
|
|
|
2023-02-12 21:39:04 +01:00
|
|
|
|
2007-11-26 19:18:49 +00:00
|
|
|
static void
|
2009-07-14 18:49:42 +00:00
|
|
|
test_free_active_base(void *ptr)
|
2007-11-07 05:02:21 +00:00
|
|
|
{
|
2009-07-14 18:49:42 +00:00
|
|
|
struct basic_test_data *data = ptr;
|
2007-11-07 05:02:21 +00:00
|
|
|
struct event_base *base1;
|
2009-07-17 18:38:21 +00:00
|
|
|
struct event ev1;
|
2009-07-14 18:49:42 +00:00
|
|
|
|
2007-11-07 05:02:21 +00:00
|
|
|
base1 = event_init();
|
2018-11-04 00:59:33 +03:00
|
|
|
tt_assert(base1);
|
|
|
|
event_assign(&ev1, base1, data->pair[1], EV_READ, dummy_read_cb, NULL);
|
|
|
|
event_add(&ev1, NULL);
|
|
|
|
event_base_free(base1); /* should not crash */
|
2009-07-17 18:38:21 +00:00
|
|
|
|
|
|
|
base1 = event_init();
|
|
|
|
tt_assert(base1);
|
2018-11-04 00:59:33 +03:00
|
|
|
event_assign(&ev1, base1, data->pair[0], 0, dummy_read_cb, NULL);
|
2009-07-17 18:38:21 +00:00
|
|
|
event_active(&ev1, EV_READ, 1);
|
|
|
|
event_base_free(base1);
|
|
|
|
end:
|
|
|
|
;
|
2007-11-07 05:02:21 +00:00
|
|
|
}
|
|
|
|
|
2009-07-21 19:20:44 +00:00
|
|
|
static void
|
|
|
|
test_manipulate_active_events(void *ptr)
|
|
|
|
{
|
|
|
|
struct basic_test_data *data = ptr;
|
|
|
|
struct event_base *base = data->base;
|
|
|
|
struct event ev1;
|
|
|
|
|
|
|
|
event_assign(&ev1, base, -1, EV_TIMEOUT, dummy_read_cb, NULL);
|
|
|
|
|
|
|
|
/* Make sure an active event is pending. */
|
|
|
|
event_active(&ev1, EV_READ, 1);
|
|
|
|
tt_int_op(event_pending(&ev1, EV_READ|EV_TIMEOUT|EV_WRITE, NULL),
|
|
|
|
==, EV_READ);
|
|
|
|
|
|
|
|
/* Make sure that activating an event twice works. */
|
|
|
|
event_active(&ev1, EV_WRITE, 1);
|
|
|
|
tt_int_op(event_pending(&ev1, EV_READ|EV_TIMEOUT|EV_WRITE, NULL),
|
|
|
|
==, EV_READ|EV_WRITE);
|
|
|
|
|
|
|
|
end:
|
|
|
|
event_del(&ev1);
|
|
|
|
}
|
|
|
|
|
2012-03-12 21:32:45 +02:00
|
|
|
static void
|
|
|
|
event_selfarg_cb(evutil_socket_t fd, short event, void *arg)
|
|
|
|
{
|
|
|
|
struct event *ev = arg;
|
|
|
|
struct event_base *base = event_get_base(ev);
|
|
|
|
event_base_assert_ok_(base);
|
|
|
|
event_base_loopexit(base, NULL);
|
2012-03-25 18:54:40 -04:00
|
|
|
tt_want(ev == event_base_get_running_event(base));
|
2012-03-12 21:32:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-03-13 21:42:40 +02:00
|
|
|
test_event_new_selfarg(void *ptr)
|
2012-03-12 21:32:45 +02:00
|
|
|
{
|
|
|
|
struct basic_test_data *data = ptr;
|
|
|
|
struct event_base *base = data->base;
|
|
|
|
struct event *ev = event_new(base, -1, EV_READ, event_selfarg_cb,
|
|
|
|
event_self_cbarg());
|
|
|
|
|
|
|
|
event_active(ev, EV_READ, 1);
|
|
|
|
event_base_dispatch(base);
|
|
|
|
|
|
|
|
event_free(ev);
|
|
|
|
}
|
|
|
|
|
2012-03-13 21:42:40 +02:00
|
|
|
static void
|
|
|
|
test_event_assign_selfarg(void *ptr)
|
|
|
|
{
|
|
|
|
struct basic_test_data *data = ptr;
|
|
|
|
struct event_base *base = data->base;
|
|
|
|
struct event ev;
|
|
|
|
|
|
|
|
event_assign(&ev, base, -1, EV_READ, event_selfarg_cb,
|
|
|
|
event_self_cbarg());
|
|
|
|
event_active(&ev, EV_READ, 1);
|
|
|
|
event_base_dispatch(base);
|
|
|
|
}
|
|
|
|
|
2013-07-02 16:01:02 -04:00
|
|
|
static void
|
|
|
|
test_event_base_get_num_events(void *ptr)
|
|
|
|
{
|
|
|
|
struct basic_test_data *data = ptr;
|
|
|
|
struct event_base *base = data->base;
|
|
|
|
struct event ev;
|
|
|
|
int event_count_active;
|
|
|
|
int event_count_virtual;
|
|
|
|
int event_count_added;
|
|
|
|
int event_count_active_virtual;
|
|
|
|
int event_count_active_added;
|
|
|
|
int event_count_virtual_added;
|
|
|
|
int event_count_active_added_virtual;
|
|
|
|
|
|
|
|
struct timeval qsec = {0, 100000};
|
|
|
|
|
|
|
|
event_assign(&ev, base, -1, EV_READ, event_selfarg_cb,
|
|
|
|
event_self_cbarg());
|
|
|
|
|
|
|
|
event_add(&ev, &qsec);
|
|
|
|
event_count_active = event_base_get_num_events(base,
|
|
|
|
EVENT_BASE_COUNT_ACTIVE);
|
|
|
|
event_count_virtual = event_base_get_num_events(base,
|
|
|
|
EVENT_BASE_COUNT_VIRTUAL);
|
|
|
|
event_count_added = event_base_get_num_events(base,
|
|
|
|
EVENT_BASE_COUNT_ADDED);
|
|
|
|
event_count_active_virtual = event_base_get_num_events(base,
|
|
|
|
EVENT_BASE_COUNT_ACTIVE|EVENT_BASE_COUNT_VIRTUAL);
|
|
|
|
event_count_active_added = event_base_get_num_events(base,
|
|
|
|
EVENT_BASE_COUNT_ACTIVE|EVENT_BASE_COUNT_ADDED);
|
|
|
|
event_count_virtual_added = event_base_get_num_events(base,
|
|
|
|
EVENT_BASE_COUNT_VIRTUAL|EVENT_BASE_COUNT_ADDED);
|
|
|
|
event_count_active_added_virtual = event_base_get_num_events(base,
|
|
|
|
EVENT_BASE_COUNT_ACTIVE|
|
|
|
|
EVENT_BASE_COUNT_ADDED|
|
|
|
|
EVENT_BASE_COUNT_VIRTUAL);
|
|
|
|
tt_int_op(event_count_active, ==, 0);
|
|
|
|
tt_int_op(event_count_virtual, ==, 0);
|
|
|
|
/* libevent itself adds a timeout event, so the event_count is 2 here */
|
|
|
|
tt_int_op(event_count_added, ==, 2);
|
|
|
|
tt_int_op(event_count_active_virtual, ==, 0);
|
|
|
|
tt_int_op(event_count_active_added, ==, 2);
|
|
|
|
tt_int_op(event_count_virtual_added, ==, 2);
|
|
|
|
tt_int_op(event_count_active_added_virtual, ==, 2);
|
|
|
|
|
|
|
|
event_active(&ev, EV_READ, 1);
|
|
|
|
event_count_active = event_base_get_num_events(base,
|
|
|
|
EVENT_BASE_COUNT_ACTIVE);
|
|
|
|
event_count_virtual = event_base_get_num_events(base,
|
|
|
|
EVENT_BASE_COUNT_VIRTUAL);
|
|
|
|
event_count_added = event_base_get_num_events(base,
|
|
|
|
EVENT_BASE_COUNT_ADDED);
|
|
|
|
event_count_active_virtual = event_base_get_num_events(base,
|
|
|
|
EVENT_BASE_COUNT_ACTIVE|EVENT_BASE_COUNT_VIRTUAL);
|
|
|
|
event_count_active_added = event_base_get_num_events(base,
|
|
|
|
EVENT_BASE_COUNT_ACTIVE|EVENT_BASE_COUNT_ADDED);
|
|
|
|
event_count_virtual_added = event_base_get_num_events(base,
|
|
|
|
EVENT_BASE_COUNT_VIRTUAL|EVENT_BASE_COUNT_ADDED);
|
|
|
|
event_count_active_added_virtual = event_base_get_num_events(base,
|
|
|
|
EVENT_BASE_COUNT_ACTIVE|
|
|
|
|
EVENT_BASE_COUNT_ADDED|
|
|
|
|
EVENT_BASE_COUNT_VIRTUAL);
|
|
|
|
tt_int_op(event_count_active, ==, 1);
|
|
|
|
tt_int_op(event_count_virtual, ==, 0);
|
|
|
|
tt_int_op(event_count_added, ==, 3);
|
|
|
|
tt_int_op(event_count_active_virtual, ==, 1);
|
|
|
|
tt_int_op(event_count_active_added, ==, 4);
|
|
|
|
tt_int_op(event_count_virtual_added, ==, 3);
|
|
|
|
tt_int_op(event_count_active_added_virtual, ==, 4);
|
|
|
|
|
|
|
|
event_base_loop(base, 0);
|
|
|
|
event_count_active = event_base_get_num_events(base,
|
|
|
|
EVENT_BASE_COUNT_ACTIVE);
|
|
|
|
event_count_virtual = event_base_get_num_events(base,
|
|
|
|
EVENT_BASE_COUNT_VIRTUAL);
|
|
|
|
event_count_added = event_base_get_num_events(base,
|
|
|
|
EVENT_BASE_COUNT_ADDED);
|
|
|
|
event_count_active_virtual = event_base_get_num_events(base,
|
|
|
|
EVENT_BASE_COUNT_ACTIVE|EVENT_BASE_COUNT_VIRTUAL);
|
|
|
|
event_count_active_added = event_base_get_num_events(base,
|
|
|
|
EVENT_BASE_COUNT_ACTIVE|EVENT_BASE_COUNT_ADDED);
|
|
|
|
event_count_virtual_added = event_base_get_num_events(base,
|
|
|
|
EVENT_BASE_COUNT_VIRTUAL|EVENT_BASE_COUNT_ADDED);
|
|
|
|
event_count_active_added_virtual = event_base_get_num_events(base,
|
|
|
|
EVENT_BASE_COUNT_ACTIVE|
|
|
|
|
EVENT_BASE_COUNT_ADDED|
|
|
|
|
EVENT_BASE_COUNT_VIRTUAL);
|
|
|
|
tt_int_op(event_count_active, ==, 0);
|
|
|
|
tt_int_op(event_count_virtual, ==, 0);
|
|
|
|
tt_int_op(event_count_added, ==, 0);
|
|
|
|
tt_int_op(event_count_active_virtual, ==, 0);
|
|
|
|
tt_int_op(event_count_active_added, ==, 0);
|
|
|
|
tt_int_op(event_count_virtual_added, ==, 0);
|
|
|
|
tt_int_op(event_count_active_added_virtual, ==, 0);
|
|
|
|
|
|
|
|
event_base_add_virtual_(base);
|
|
|
|
event_count_active = event_base_get_num_events(base,
|
|
|
|
EVENT_BASE_COUNT_ACTIVE);
|
|
|
|
event_count_virtual = event_base_get_num_events(base,
|
|
|
|
EVENT_BASE_COUNT_VIRTUAL);
|
|
|
|
event_count_added = event_base_get_num_events(base,
|
|
|
|
EVENT_BASE_COUNT_ADDED);
|
|
|
|
event_count_active_virtual = event_base_get_num_events(base,
|
|
|
|
EVENT_BASE_COUNT_ACTIVE|EVENT_BASE_COUNT_VIRTUAL);
|
|
|
|
event_count_active_added = event_base_get_num_events(base,
|
|
|
|
EVENT_BASE_COUNT_ACTIVE|EVENT_BASE_COUNT_ADDED);
|
|
|
|
event_count_virtual_added = event_base_get_num_events(base,
|
|
|
|
EVENT_BASE_COUNT_VIRTUAL|EVENT_BASE_COUNT_ADDED);
|
|
|
|
event_count_active_added_virtual = event_base_get_num_events(base,
|
|
|
|
EVENT_BASE_COUNT_ACTIVE|
|
|
|
|
EVENT_BASE_COUNT_ADDED|
|
|
|
|
EVENT_BASE_COUNT_VIRTUAL);
|
|
|
|
tt_int_op(event_count_active, ==, 0);
|
|
|
|
tt_int_op(event_count_virtual, ==, 1);
|
|
|
|
tt_int_op(event_count_added, ==, 0);
|
|
|
|
tt_int_op(event_count_active_virtual, ==, 1);
|
|
|
|
tt_int_op(event_count_active_added, ==, 0);
|
|
|
|
tt_int_op(event_count_virtual_added, ==, 1);
|
|
|
|
tt_int_op(event_count_active_added_virtual, ==, 1);
|
|
|
|
|
|
|
|
end:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
2014-01-05 16:30:35 -05:00
|
|
|
static void
|
|
|
|
test_event_base_get_max_events(void *ptr)
|
|
|
|
{
|
|
|
|
struct basic_test_data *data = ptr;
|
|
|
|
struct event_base *base = data->base;
|
|
|
|
struct event ev;
|
|
|
|
struct event ev2;
|
|
|
|
int event_count_active;
|
|
|
|
int event_count_virtual;
|
|
|
|
int event_count_added;
|
|
|
|
int event_count_active_virtual;
|
|
|
|
int event_count_active_added;
|
|
|
|
int event_count_virtual_added;
|
|
|
|
int event_count_active_added_virtual;
|
|
|
|
|
|
|
|
struct timeval qsec = {0, 100000};
|
|
|
|
|
|
|
|
event_assign(&ev, base, -1, EV_READ, event_selfarg_cb,
|
|
|
|
event_self_cbarg());
|
|
|
|
event_assign(&ev2, base, -1, EV_READ, event_selfarg_cb,
|
|
|
|
event_self_cbarg());
|
|
|
|
|
|
|
|
event_add(&ev, &qsec);
|
|
|
|
event_add(&ev2, &qsec);
|
|
|
|
event_del(&ev2);
|
|
|
|
|
|
|
|
event_count_active = event_base_get_max_events(base,
|
|
|
|
EVENT_BASE_COUNT_ACTIVE, 0);
|
|
|
|
event_count_virtual = event_base_get_max_events(base,
|
|
|
|
EVENT_BASE_COUNT_VIRTUAL, 0);
|
|
|
|
event_count_added = event_base_get_max_events(base,
|
|
|
|
EVENT_BASE_COUNT_ADDED, 0);
|
|
|
|
event_count_active_virtual = event_base_get_max_events(base,
|
|
|
|
EVENT_BASE_COUNT_ACTIVE | EVENT_BASE_COUNT_VIRTUAL, 0);
|
|
|
|
event_count_active_added = event_base_get_max_events(base,
|
|
|
|
EVENT_BASE_COUNT_ACTIVE | EVENT_BASE_COUNT_ADDED, 0);
|
|
|
|
event_count_virtual_added = event_base_get_max_events(base,
|
|
|
|
EVENT_BASE_COUNT_VIRTUAL | EVENT_BASE_COUNT_ADDED, 0);
|
|
|
|
event_count_active_added_virtual = event_base_get_max_events(base,
|
|
|
|
EVENT_BASE_COUNT_ACTIVE |
|
|
|
|
EVENT_BASE_COUNT_ADDED |
|
|
|
|
EVENT_BASE_COUNT_VIRTUAL, 0);
|
|
|
|
|
|
|
|
tt_int_op(event_count_active, ==, 0);
|
|
|
|
tt_int_op(event_count_virtual, ==, 0);
|
|
|
|
/* libevent itself adds a timeout event, so the event_count is 4 here */
|
|
|
|
tt_int_op(event_count_added, ==, 4);
|
|
|
|
tt_int_op(event_count_active_virtual, ==, 0);
|
|
|
|
tt_int_op(event_count_active_added, ==, 4);
|
|
|
|
tt_int_op(event_count_virtual_added, ==, 4);
|
|
|
|
tt_int_op(event_count_active_added_virtual, ==, 4);
|
|
|
|
|
|
|
|
event_active(&ev, EV_READ, 1);
|
|
|
|
event_count_active = event_base_get_max_events(base,
|
|
|
|
EVENT_BASE_COUNT_ACTIVE, 0);
|
|
|
|
event_count_virtual = event_base_get_max_events(base,
|
|
|
|
EVENT_BASE_COUNT_VIRTUAL, 0);
|
|
|
|
event_count_added = event_base_get_max_events(base,
|
|
|
|
EVENT_BASE_COUNT_ADDED, 0);
|
|
|
|
event_count_active_virtual = event_base_get_max_events(base,
|
|
|
|
EVENT_BASE_COUNT_ACTIVE | EVENT_BASE_COUNT_VIRTUAL, 0);
|
|
|
|
event_count_active_added = event_base_get_max_events(base,
|
|
|
|
EVENT_BASE_COUNT_ACTIVE | EVENT_BASE_COUNT_ADDED, 0);
|
|
|
|
event_count_virtual_added = event_base_get_max_events(base,
|
|
|
|
EVENT_BASE_COUNT_VIRTUAL | EVENT_BASE_COUNT_ADDED, 0);
|
|
|
|
event_count_active_added_virtual = event_base_get_max_events(base,
|
|
|
|
EVENT_BASE_COUNT_ACTIVE |
|
|
|
|
EVENT_BASE_COUNT_ADDED |
|
|
|
|
EVENT_BASE_COUNT_VIRTUAL, 0);
|
|
|
|
|
|
|
|
tt_int_op(event_count_active, ==, 1);
|
|
|
|
tt_int_op(event_count_virtual, ==, 0);
|
|
|
|
tt_int_op(event_count_added, ==, 4);
|
|
|
|
tt_int_op(event_count_active_virtual, ==, 1);
|
|
|
|
tt_int_op(event_count_active_added, ==, 5);
|
|
|
|
tt_int_op(event_count_virtual_added, ==, 4);
|
|
|
|
tt_int_op(event_count_active_added_virtual, ==, 5);
|
|
|
|
|
|
|
|
event_base_loop(base, 0);
|
|
|
|
event_count_active = event_base_get_max_events(base,
|
|
|
|
EVENT_BASE_COUNT_ACTIVE, 1);
|
|
|
|
event_count_virtual = event_base_get_max_events(base,
|
|
|
|
EVENT_BASE_COUNT_VIRTUAL, 1);
|
|
|
|
event_count_added = event_base_get_max_events(base,
|
|
|
|
EVENT_BASE_COUNT_ADDED, 1);
|
|
|
|
event_count_active_virtual = event_base_get_max_events(base,
|
|
|
|
EVENT_BASE_COUNT_ACTIVE | EVENT_BASE_COUNT_VIRTUAL, 0);
|
|
|
|
event_count_active_added = event_base_get_max_events(base,
|
|
|
|
EVENT_BASE_COUNT_ACTIVE | EVENT_BASE_COUNT_ADDED, 0);
|
|
|
|
event_count_virtual_added = event_base_get_max_events(base,
|
|
|
|
EVENT_BASE_COUNT_VIRTUAL | EVENT_BASE_COUNT_ADDED, 0);
|
|
|
|
event_count_active_added_virtual = event_base_get_max_events(base,
|
|
|
|
EVENT_BASE_COUNT_ACTIVE |
|
|
|
|
EVENT_BASE_COUNT_ADDED |
|
|
|
|
EVENT_BASE_COUNT_VIRTUAL, 1);
|
|
|
|
|
|
|
|
tt_int_op(event_count_active, ==, 1);
|
|
|
|
tt_int_op(event_count_virtual, ==, 0);
|
|
|
|
tt_int_op(event_count_added, ==, 4);
|
|
|
|
tt_int_op(event_count_active_virtual, ==, 0);
|
|
|
|
tt_int_op(event_count_active_added, ==, 0);
|
|
|
|
tt_int_op(event_count_virtual_added, ==, 0);
|
|
|
|
tt_int_op(event_count_active_added_virtual, ==, 0);
|
|
|
|
|
|
|
|
event_count_active = event_base_get_max_events(base,
|
|
|
|
EVENT_BASE_COUNT_ACTIVE, 0);
|
|
|
|
event_count_virtual = event_base_get_max_events(base,
|
|
|
|
EVENT_BASE_COUNT_VIRTUAL, 0);
|
|
|
|
event_count_added = event_base_get_max_events(base,
|
|
|
|
EVENT_BASE_COUNT_ADDED, 0);
|
|
|
|
tt_int_op(event_count_active, ==, 0);
|
|
|
|
tt_int_op(event_count_virtual, ==, 0);
|
|
|
|
tt_int_op(event_count_added, ==, 0);
|
|
|
|
|
|
|
|
event_base_add_virtual_(base);
|
|
|
|
event_count_active = event_base_get_max_events(base,
|
|
|
|
EVENT_BASE_COUNT_ACTIVE, 0);
|
|
|
|
event_count_virtual = event_base_get_max_events(base,
|
|
|
|
EVENT_BASE_COUNT_VIRTUAL, 0);
|
|
|
|
event_count_added = event_base_get_max_events(base,
|
|
|
|
EVENT_BASE_COUNT_ADDED, 0);
|
|
|
|
event_count_active_virtual = event_base_get_max_events(base,
|
|
|
|
EVENT_BASE_COUNT_ACTIVE | EVENT_BASE_COUNT_VIRTUAL, 0);
|
|
|
|
event_count_active_added = event_base_get_max_events(base,
|
|
|
|
EVENT_BASE_COUNT_ACTIVE | EVENT_BASE_COUNT_ADDED, 0);
|
|
|
|
event_count_virtual_added = event_base_get_max_events(base,
|
|
|
|
EVENT_BASE_COUNT_VIRTUAL | EVENT_BASE_COUNT_ADDED, 0);
|
|
|
|
event_count_active_added_virtual = event_base_get_max_events(base,
|
|
|
|
EVENT_BASE_COUNT_ACTIVE |
|
|
|
|
EVENT_BASE_COUNT_ADDED |
|
|
|
|
EVENT_BASE_COUNT_VIRTUAL, 0);
|
|
|
|
|
|
|
|
tt_int_op(event_count_active, ==, 0);
|
|
|
|
tt_int_op(event_count_virtual, ==, 1);
|
|
|
|
tt_int_op(event_count_added, ==, 0);
|
|
|
|
tt_int_op(event_count_active_virtual, ==, 1);
|
|
|
|
tt_int_op(event_count_active_added, ==, 0);
|
|
|
|
tt_int_op(event_count_virtual_added, ==, 1);
|
|
|
|
tt_int_op(event_count_active_added_virtual, ==, 1);
|
|
|
|
|
|
|
|
end:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
2009-10-27 04:25:45 +00:00
|
|
|
static void
|
|
|
|
test_bad_assign(void *ptr)
|
|
|
|
{
|
|
|
|
struct event ev;
|
|
|
|
int r;
|
|
|
|
/* READ|SIGNAL is not allowed */
|
|
|
|
r = event_assign(&ev, NULL, -1, EV_SIGNAL|EV_READ, dummy_read_cb, NULL);
|
|
|
|
tt_int_op(r,==,-1);
|
|
|
|
|
|
|
|
end:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
2010-03-21 13:28:48 -04:00
|
|
|
static int reentrant_cb_run = 0;
|
|
|
|
|
|
|
|
static void
|
|
|
|
bad_reentrant_run_loop_cb(evutil_socket_t fd, short what, void *ptr)
|
|
|
|
{
|
|
|
|
struct event_base *base = ptr;
|
|
|
|
int r;
|
|
|
|
reentrant_cb_run = 1;
|
|
|
|
/* This reentrant call to event_base_loop should be detected and
|
|
|
|
* should fail */
|
|
|
|
r = event_base_loop(base, 0);
|
|
|
|
tt_int_op(r, ==, -1);
|
|
|
|
end:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
test_bad_reentrant(void *ptr)
|
|
|
|
{
|
|
|
|
struct basic_test_data *data = ptr;
|
|
|
|
struct event_base *base = data->base;
|
|
|
|
struct event ev;
|
|
|
|
int r;
|
|
|
|
event_assign(&ev, base, -1,
|
|
|
|
0, bad_reentrant_run_loop_cb, base);
|
|
|
|
|
|
|
|
event_active(&ev, EV_WRITE, 1);
|
|
|
|
r = event_base_loop(base, 0);
|
|
|
|
tt_int_op(r, ==, 1);
|
|
|
|
tt_int_op(reentrant_cb_run, ==, 1);
|
|
|
|
end:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
2012-04-06 03:00:40 -04:00
|
|
|
static int n_write_a_byte_cb=0;
|
|
|
|
static int n_read_and_drain_cb=0;
|
|
|
|
static int n_activate_other_event_cb=0;
|
|
|
|
static void
|
|
|
|
write_a_byte_cb(evutil_socket_t fd, short what, void *arg)
|
|
|
|
{
|
|
|
|
char buf[] = "x";
|
2012-06-29 12:47:03 -04:00
|
|
|
if (write(fd, buf, 1) == 1)
|
|
|
|
++n_write_a_byte_cb;
|
2012-04-06 03:00:40 -04:00
|
|
|
}
|
|
|
|
static void
|
|
|
|
read_and_drain_cb(evutil_socket_t fd, short what, void *arg)
|
|
|
|
{
|
|
|
|
char buf[128];
|
|
|
|
int n;
|
|
|
|
++n_read_and_drain_cb;
|
|
|
|
while ((n = read(fd, buf, sizeof(buf))) > 0)
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
activate_other_event_cb(evutil_socket_t fd, short what, void *other_)
|
|
|
|
{
|
|
|
|
struct event *ev_activate = other_;
|
|
|
|
++n_activate_other_event_cb;
|
|
|
|
event_active_later_(ev_activate, EV_READ);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
test_active_later(void *ptr)
|
|
|
|
{
|
|
|
|
struct basic_test_data *data = ptr;
|
2014-09-18 12:40:38 -04:00
|
|
|
struct event *ev1 = NULL, *ev2 = NULL;
|
2012-04-06 03:00:40 -04:00
|
|
|
struct event ev3, ev4;
|
|
|
|
struct timeval qsec = {0, 100000};
|
|
|
|
ev1 = event_new(data->base, data->pair[0], EV_READ|EV_PERSIST, read_and_drain_cb, NULL);
|
|
|
|
ev2 = event_new(data->base, data->pair[1], EV_WRITE|EV_PERSIST, write_a_byte_cb, NULL);
|
2024-04-10 15:47:57 +08:00
|
|
|
tt_assert(ev1);
|
|
|
|
tt_assert(ev2);
|
2012-04-06 03:00:40 -04:00
|
|
|
event_assign(&ev3, data->base, -1, 0, activate_other_event_cb, &ev4);
|
|
|
|
event_assign(&ev4, data->base, -1, 0, activate_other_event_cb, &ev3);
|
|
|
|
event_add(ev1, NULL);
|
|
|
|
event_add(ev2, NULL);
|
|
|
|
event_active_later_(&ev3, EV_READ);
|
|
|
|
|
|
|
|
event_base_loopexit(data->base, &qsec);
|
|
|
|
|
|
|
|
event_base_loop(data->base, 0);
|
|
|
|
|
|
|
|
TT_BLATHER(("%d write calls, %d read calls, %d activate-other calls.",
|
|
|
|
n_write_a_byte_cb, n_read_and_drain_cb, n_activate_other_event_cb));
|
|
|
|
event_del(&ev3);
|
|
|
|
event_del(&ev4);
|
|
|
|
|
|
|
|
tt_int_op(n_write_a_byte_cb, ==, n_activate_other_event_cb);
|
|
|
|
tt_int_op(n_write_a_byte_cb, >, 100);
|
|
|
|
tt_int_op(n_read_and_drain_cb, >, 100);
|
|
|
|
tt_int_op(n_activate_other_event_cb, >, 100);
|
2013-04-10 18:03:16 -04:00
|
|
|
|
2013-04-26 13:49:45 -04:00
|
|
|
event_active_later_(&ev4, EV_READ);
|
|
|
|
event_active(&ev4, EV_READ, 1); /* This should make the event
|
|
|
|
active immediately. */
|
|
|
|
tt_assert((ev4.ev_flags & EVLIST_ACTIVE) != 0);
|
|
|
|
tt_assert((ev4.ev_flags & EVLIST_ACTIVE_LATER) == 0);
|
|
|
|
|
2013-04-10 18:03:16 -04:00
|
|
|
/* Now leave this one around, so that event_free sees it and removes
|
|
|
|
* it. */
|
|
|
|
event_active_later_(&ev3, EV_READ);
|
|
|
|
event_base_assert_ok_(data->base);
|
2014-09-18 12:40:38 -04:00
|
|
|
|
|
|
|
end:
|
|
|
|
if (ev1)
|
|
|
|
event_free(ev1);
|
|
|
|
if (ev2)
|
|
|
|
event_free(ev2);
|
|
|
|
|
2013-04-10 18:03:16 -04:00
|
|
|
event_base_free(data->base);
|
|
|
|
data->base = NULL;
|
2012-04-06 03:00:40 -04:00
|
|
|
}
|
|
|
|
|
2012-11-16 16:15:03 -05:00
|
|
|
|
|
|
|
static void incr_arg_cb(evutil_socket_t fd, short what, void *arg)
|
|
|
|
{
|
|
|
|
int *intptr = arg;
|
|
|
|
(void) fd; (void) what;
|
|
|
|
++*intptr;
|
|
|
|
}
|
|
|
|
static void remove_timers_cb(evutil_socket_t fd, short what, void *arg)
|
|
|
|
{
|
|
|
|
struct event **ep = arg;
|
|
|
|
(void) fd; (void) what;
|
|
|
|
event_remove_timer(ep[0]);
|
|
|
|
event_remove_timer(ep[1]);
|
|
|
|
}
|
|
|
|
static void send_a_byte_cb(evutil_socket_t fd, short what, void *arg)
|
|
|
|
{
|
|
|
|
evutil_socket_t *sockp = arg;
|
|
|
|
(void) fd; (void) what;
|
2017-09-11 21:56:30 +02:00
|
|
|
if (write(*sockp, "A", 1) < 0)
|
|
|
|
tt_fail_perror("write");
|
2012-11-16 16:15:03 -05:00
|
|
|
}
|
2013-02-13 11:38:57 -05:00
|
|
|
struct read_not_timeout_param
|
|
|
|
{
|
|
|
|
struct event **ev;
|
|
|
|
int events;
|
|
|
|
int count;
|
|
|
|
};
|
2012-11-16 16:15:03 -05:00
|
|
|
static void read_not_timeout_cb(evutil_socket_t fd, short what, void *arg)
|
|
|
|
{
|
2013-02-13 11:38:57 -05:00
|
|
|
struct read_not_timeout_param *rntp = arg;
|
|
|
|
char c;
|
2014-01-08 11:51:22 -05:00
|
|
|
ev_ssize_t n;
|
2012-11-16 16:15:03 -05:00
|
|
|
(void) fd; (void) what;
|
2014-01-08 11:51:22 -05:00
|
|
|
n = read(fd, &c, 1);
|
|
|
|
tt_int_op(n, ==, 1);
|
2013-02-13 11:38:57 -05:00
|
|
|
rntp->events |= what;
|
|
|
|
++rntp->count;
|
|
|
|
if(2 == rntp->count) event_del(rntp->ev[0]);
|
2014-01-08 11:51:22 -05:00
|
|
|
end:
|
|
|
|
;
|
2012-11-16 16:15:03 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
test_event_remove_timeout(void *ptr)
|
|
|
|
{
|
|
|
|
struct basic_test_data *data = ptr;
|
|
|
|
struct event_base *base = data->base;
|
2013-02-13 11:38:57 -05:00
|
|
|
struct event *ev[5];
|
|
|
|
int ev1_fired=0;
|
2012-11-16 16:15:03 -05:00
|
|
|
struct timeval ms25 = { 0, 25*1000 },
|
2013-02-13 11:38:57 -05:00
|
|
|
ms40 = { 0, 40*1000 },
|
2012-11-16 16:15:03 -05:00
|
|
|
ms75 = { 0, 75*1000 },
|
|
|
|
ms125 = { 0, 125*1000 };
|
2013-02-13 11:38:57 -05:00
|
|
|
struct read_not_timeout_param rntp = { ev, 0, 0 };
|
2012-11-16 16:15:03 -05:00
|
|
|
|
|
|
|
event_base_assert_ok_(base);
|
|
|
|
|
2013-02-13 11:38:57 -05:00
|
|
|
ev[0] = event_new(base, data->pair[0], EV_READ|EV_PERSIST,
|
|
|
|
read_not_timeout_cb, &rntp);
|
2012-11-16 16:15:03 -05:00
|
|
|
ev[1] = evtimer_new(base, incr_arg_cb, &ev1_fired);
|
|
|
|
ev[2] = evtimer_new(base, remove_timers_cb, ev);
|
|
|
|
ev[3] = evtimer_new(base, send_a_byte_cb, &data->pair[1]);
|
2013-02-13 11:38:57 -05:00
|
|
|
ev[4] = evtimer_new(base, send_a_byte_cb, &data->pair[1]);
|
2012-11-16 16:15:03 -05:00
|
|
|
tt_assert(base);
|
2024-04-10 15:47:57 +08:00
|
|
|
tt_assert(ev[0]);
|
|
|
|
tt_assert(ev[1]);
|
|
|
|
tt_assert(ev[2]);
|
|
|
|
tt_assert(ev[3]);
|
|
|
|
tt_assert(ev[4]);
|
2012-11-16 16:15:03 -05:00
|
|
|
event_add(ev[2], &ms25); /* remove timers */
|
2013-02-13 11:38:57 -05:00
|
|
|
event_add(ev[4], &ms40); /* write to test if timer re-activates */
|
2012-11-16 16:15:03 -05:00
|
|
|
event_add(ev[0], &ms75); /* read */
|
|
|
|
event_add(ev[1], &ms75); /* timer */
|
|
|
|
event_add(ev[3], &ms125); /* timeout. */
|
|
|
|
event_base_assert_ok_(base);
|
|
|
|
|
|
|
|
event_base_dispatch(base);
|
|
|
|
|
|
|
|
tt_int_op(ev1_fired, ==, 0);
|
2013-02-13 11:38:57 -05:00
|
|
|
tt_int_op(rntp.events, ==, EV_READ);
|
2012-11-16 16:15:03 -05:00
|
|
|
|
|
|
|
event_base_assert_ok_(base);
|
|
|
|
end:
|
|
|
|
event_free(ev[0]);
|
|
|
|
event_free(ev[1]);
|
|
|
|
event_free(ev[2]);
|
|
|
|
event_free(ev[3]);
|
2013-02-13 11:38:57 -05:00
|
|
|
event_free(ev[4]);
|
2012-11-16 16:15:03 -05:00
|
|
|
}
|
|
|
|
|
2024-10-27 16:41:12 +01:00
|
|
|
static void
|
|
|
|
test_event_timeout_lost_cb(evutil_socket_t fd, short events, void *arg)
|
|
|
|
{
|
|
|
|
short *res_events = arg;
|
|
|
|
*res_events = events;
|
|
|
|
}
|
|
|
|
static void
|
|
|
|
test_event_timeout_lost(void *ptr)
|
|
|
|
{
|
|
|
|
struct basic_test_data *data = ptr;
|
|
|
|
struct event_base *base = data->base;
|
|
|
|
struct event *ev;
|
|
|
|
short res_events = 0;
|
|
|
|
|
|
|
|
event_base_assert_ok_(base);
|
|
|
|
|
|
|
|
ev = event_new(base, data->pair[0], EV_TIMEOUT|EV_READ, test_event_timeout_lost_cb, &res_events);
|
|
|
|
tt_assert(ev);
|
|
|
|
|
|
|
|
{
|
|
|
|
struct timeval timeout = { 0, 100 };
|
|
|
|
event_add(ev, &timeout);
|
|
|
|
}
|
|
|
|
|
|
|
|
event_active(ev, EV_READ, 1);
|
|
|
|
|
|
|
|
/* Ensure that timeout had been elapsed */
|
|
|
|
{
|
|
|
|
struct timeval delay = { 1, 0 };
|
|
|
|
evutil_usleep_(&delay);
|
|
|
|
}
|
|
|
|
|
|
|
|
event_base_assert_ok_(base);
|
|
|
|
event_base_loop(base, EVLOOP_ONCE|EVLOOP_NONBLOCK);
|
|
|
|
event_base_assert_ok_(base);
|
|
|
|
|
|
|
|
tt_int_op(res_events, ==, EV_READ|EV_TIMEOUT);
|
|
|
|
|
|
|
|
end:
|
|
|
|
event_free(ev);
|
|
|
|
}
|
|
|
|
|
2024-10-20 23:52:33 +02:00
|
|
|
/* del_timeout_notify */
|
|
|
|
#ifndef EVENT__DISABLE_THREAD_SUPPORT
|
|
|
|
static THREAD_FN
|
|
|
|
event_base_dispatch_threadcb(void *arg)
|
|
|
|
{
|
|
|
|
event_base_dispatch(arg);
|
|
|
|
THREAD_RETURN();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Regression test for the case when removing active event with EV_TIMEOUT does
|
|
|
|
* not notifies the base properly like it should */
|
|
|
|
static void
|
|
|
|
test_del_timeout_notify(void *ptr)
|
|
|
|
{
|
|
|
|
struct basic_test_data *data = ptr;
|
|
|
|
struct event_base *base = data->base;
|
|
|
|
struct event *ev;
|
|
|
|
struct timeval start_tv, now_tv;
|
|
|
|
THREAD_T thread;
|
|
|
|
|
|
|
|
ev = event_new(base, -1, EV_PERSIST, null_cb, NULL);
|
|
|
|
{
|
|
|
|
struct timeval tv;
|
|
|
|
tv.tv_sec = 5;
|
|
|
|
tv.tv_usec = 0;
|
|
|
|
event_add(ev, &tv);
|
|
|
|
}
|
|
|
|
|
|
|
|
THREAD_START(thread, event_base_dispatch_threadcb, base);
|
|
|
|
|
|
|
|
/* FIXME: let's consider that 1 second is enough for the OS to spawn the
|
|
|
|
* thread and enter event loop */
|
|
|
|
{
|
|
|
|
struct timeval delay = { 1, 0 };
|
|
|
|
evutil_usleep_(&delay);
|
|
|
|
}
|
|
|
|
|
|
|
|
evutil_gettimeofday(&start_tv, NULL);
|
|
|
|
event_del(ev);
|
|
|
|
THREAD_JOIN(thread);
|
|
|
|
|
|
|
|
evutil_gettimeofday(&now_tv, NULL);
|
|
|
|
/* Let's consider that 1 second is enough to notify the base thread */
|
|
|
|
tt_int_op(timeval_msec_diff(&start_tv, &now_tv), <, 1000);
|
|
|
|
|
|
|
|
event_base_assert_ok_(base);
|
|
|
|
|
|
|
|
end:
|
|
|
|
event_free(ev);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2007-11-26 19:18:49 +00:00
|
|
|
static void
|
2009-07-14 18:49:42 +00:00
|
|
|
test_event_base_new(void *ptr)
|
2007-11-14 17:52:21 +00:00
|
|
|
{
|
2009-07-14 18:49:42 +00:00
|
|
|
struct basic_test_data *data = ptr;
|
|
|
|
struct event_base *base = 0;
|
2007-11-14 17:52:21 +00:00
|
|
|
struct event ev1;
|
2009-07-14 18:49:42 +00:00
|
|
|
struct basic_cb_args args;
|
2007-11-14 17:52:21 +00:00
|
|
|
|
2010-11-03 14:38:45 -07:00
|
|
|
int towrite = (int)strlen(TEST1)+1;
|
2009-07-14 18:49:42 +00:00
|
|
|
int len = write(data->pair[0], TEST1, towrite);
|
|
|
|
|
2009-07-17 18:38:38 +00:00
|
|
|
if (len < 0)
|
2009-07-14 18:49:42 +00:00
|
|
|
tt_abort_perror("initial write");
|
|
|
|
else if (len != towrite)
|
|
|
|
tt_abort_printf(("initial write fell short (%d of %d bytes)",
|
|
|
|
len, towrite));
|
2009-07-17 18:38:38 +00:00
|
|
|
|
2016-03-11 01:27:52 +03:00
|
|
|
if (shutdown(data->pair[0], EVUTIL_SHUT_WR))
|
2009-07-14 18:49:42 +00:00
|
|
|
tt_abort_perror("initial write shutdown");
|
2007-11-14 17:52:21 +00:00
|
|
|
|
|
|
|
base = event_base_new();
|
2009-07-14 18:49:42 +00:00
|
|
|
if (!base)
|
|
|
|
tt_abort_msg("failed to create event base");
|
2007-11-14 17:52:21 +00:00
|
|
|
|
2009-07-14 18:49:42 +00:00
|
|
|
args.eb = base;
|
|
|
|
args.ev = &ev1;
|
|
|
|
args.callcount = 0;
|
|
|
|
event_assign(&ev1, base, data->pair[1],
|
|
|
|
EV_READ|EV_PERSIST, basic_read_cb, &args);
|
2007-11-14 17:52:21 +00:00
|
|
|
|
2009-07-14 18:49:42 +00:00
|
|
|
if (event_add(&ev1, NULL))
|
|
|
|
tt_abort_perror("initial event_add");
|
|
|
|
|
|
|
|
if (event_base_loop(base, 0))
|
|
|
|
tt_abort_msg("unsuccessful exit from event loop");
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (base)
|
|
|
|
event_base_free(base);
|
2007-11-14 17:52:21 +00:00
|
|
|
}
|
|
|
|
|
2007-11-26 19:18:49 +00:00
|
|
|
static void
|
2005-12-06 03:26:28 +00:00
|
|
|
test_loopexit(void)
|
2004-04-04 02:19:08 +00:00
|
|
|
{
|
|
|
|
struct timeval tv, tv_start, tv_end;
|
|
|
|
struct event ev;
|
|
|
|
|
|
|
|
setup_test("Loop exit: ");
|
|
|
|
|
|
|
|
tv.tv_usec = 0;
|
|
|
|
tv.tv_sec = 60*60*24;
|
|
|
|
evtimer_set(&ev, timeout_cb, NULL);
|
|
|
|
evtimer_add(&ev, &tv);
|
|
|
|
|
2012-01-24 14:33:10 -05:00
|
|
|
tv.tv_usec = 300*1000;
|
|
|
|
tv.tv_sec = 0;
|
2004-04-04 02:19:08 +00:00
|
|
|
event_loopexit(&tv);
|
|
|
|
|
2008-06-24 18:04:41 +00:00
|
|
|
evutil_gettimeofday(&tv_start, NULL);
|
2004-04-04 02:19:08 +00:00
|
|
|
event_dispatch();
|
2008-06-24 18:04:41 +00:00
|
|
|
evutil_gettimeofday(&tv_end, NULL);
|
2004-04-04 02:19:08 +00:00
|
|
|
|
|
|
|
evtimer_del(&ev);
|
|
|
|
|
2009-11-09 18:36:34 +00:00
|
|
|
tt_assert(event_base_got_exit(global_base));
|
|
|
|
tt_assert(!event_base_got_break(global_base));
|
|
|
|
|
2012-01-24 14:33:10 -05:00
|
|
|
test_timeval_diff_eq(&tv_start, &tv_end, 300);
|
2004-04-04 02:19:08 +00:00
|
|
|
|
2012-01-24 14:33:10 -05:00
|
|
|
test_ok = 1;
|
2009-11-09 18:36:34 +00:00
|
|
|
end:
|
2004-04-04 02:19:08 +00:00
|
|
|
cleanup_test();
|
|
|
|
}
|
|
|
|
|
2008-01-26 07:29:57 +00:00
|
|
|
static void
|
|
|
|
test_loopexit_multiple(void)
|
|
|
|
{
|
2012-01-24 14:33:10 -05:00
|
|
|
struct timeval tv, tv_start, tv_end;
|
2008-01-26 07:29:57 +00:00
|
|
|
struct event_base *base;
|
|
|
|
|
|
|
|
setup_test("Loop Multiple exit: ");
|
|
|
|
|
|
|
|
base = event_base_new();
|
2009-01-27 21:10:31 +00:00
|
|
|
|
2024-08-07 17:20:46 +08:00
|
|
|
tt_assert(base);
|
|
|
|
|
2012-01-24 14:33:10 -05:00
|
|
|
tv.tv_usec = 200*1000;
|
|
|
|
tv.tv_sec = 0;
|
2008-01-26 07:29:57 +00:00
|
|
|
event_base_loopexit(base, &tv);
|
|
|
|
|
|
|
|
tv.tv_usec = 0;
|
2012-01-24 14:33:10 -05:00
|
|
|
tv.tv_sec = 3;
|
2008-01-26 07:29:57 +00:00
|
|
|
event_base_loopexit(base, &tv);
|
|
|
|
|
2012-01-24 14:33:10 -05:00
|
|
|
evutil_gettimeofday(&tv_start, NULL);
|
2008-01-26 07:29:57 +00:00
|
|
|
event_base_dispatch(base);
|
2012-01-24 14:33:10 -05:00
|
|
|
evutil_gettimeofday(&tv_end, NULL);
|
2008-01-26 07:29:57 +00:00
|
|
|
|
2009-11-09 18:36:34 +00:00
|
|
|
tt_assert(event_base_got_exit(base));
|
|
|
|
tt_assert(!event_base_got_break(base));
|
|
|
|
|
2009-11-27 15:24:32 -05:00
|
|
|
event_base_free(base);
|
|
|
|
|
2012-01-24 14:33:10 -05:00
|
|
|
test_timeval_diff_eq(&tv_start, &tv_end, 200);
|
|
|
|
|
2008-01-26 07:29:57 +00:00
|
|
|
test_ok = 1;
|
|
|
|
|
2009-11-09 18:36:34 +00:00
|
|
|
end:
|
2008-01-26 07:29:57 +00:00
|
|
|
cleanup_test();
|
|
|
|
}
|
|
|
|
|
2007-11-17 22:21:42 +00:00
|
|
|
static void
|
2010-03-05 12:47:46 -05:00
|
|
|
break_cb(evutil_socket_t fd, short events, void *arg)
|
2007-11-17 22:21:42 +00:00
|
|
|
{
|
|
|
|
test_ok = 1;
|
|
|
|
event_loopbreak();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2010-03-05 12:47:46 -05:00
|
|
|
fail_cb(evutil_socket_t fd, short events, void *arg)
|
2007-11-17 22:21:42 +00:00
|
|
|
{
|
|
|
|
test_ok = 0;
|
|
|
|
}
|
|
|
|
|
2007-11-26 19:18:49 +00:00
|
|
|
static void
|
2007-11-17 22:21:42 +00:00
|
|
|
test_loopbreak(void)
|
|
|
|
{
|
|
|
|
struct event ev1, ev2;
|
|
|
|
struct timeval tv;
|
|
|
|
|
|
|
|
setup_test("Loop break: ");
|
|
|
|
|
|
|
|
tv.tv_sec = 0;
|
|
|
|
tv.tv_usec = 0;
|
|
|
|
evtimer_set(&ev1, break_cb, NULL);
|
|
|
|
evtimer_add(&ev1, &tv);
|
|
|
|
evtimer_set(&ev2, fail_cb, NULL);
|
|
|
|
evtimer_add(&ev2, &tv);
|
|
|
|
|
|
|
|
event_dispatch();
|
|
|
|
|
2009-11-09 18:36:34 +00:00
|
|
|
tt_assert(!event_base_got_exit(global_base));
|
|
|
|
tt_assert(event_base_got_break(global_base));
|
|
|
|
|
2007-11-17 22:21:42 +00:00
|
|
|
evtimer_del(&ev1);
|
|
|
|
evtimer_del(&ev2);
|
|
|
|
|
2009-11-09 18:36:34 +00:00
|
|
|
end:
|
2007-11-17 22:21:42 +00:00
|
|
|
cleanup_test();
|
|
|
|
}
|
|
|
|
|
2007-12-01 09:30:07 +00:00
|
|
|
static struct event *readd_test_event_last_added = NULL;
|
|
|
|
static void
|
2010-03-05 12:47:46 -05:00
|
|
|
re_add_read_cb(evutil_socket_t fd, short event, void *arg)
|
2007-12-01 09:30:07 +00:00
|
|
|
{
|
|
|
|
char buf[256];
|
|
|
|
struct event *ev_other = arg;
|
2014-01-08 11:51:22 -05:00
|
|
|
ev_ssize_t n_read;
|
|
|
|
|
2014-01-21 12:21:37 -05:00
|
|
|
readd_test_event_last_added = ev_other;
|
|
|
|
|
2014-01-08 11:51:22 -05:00
|
|
|
n_read = read(fd, buf, sizeof(buf));
|
2011-07-12 13:05:36 -04:00
|
|
|
|
2014-01-08 11:51:22 -05:00
|
|
|
if (n_read < 0) {
|
2011-10-03 12:45:36 -04:00
|
|
|
tt_fail_perror("read");
|
2014-01-08 11:51:22 -05:00
|
|
|
event_base_loopbreak(event_get_base(ev_other));
|
|
|
|
} else {
|
|
|
|
event_add(ev_other, NULL);
|
|
|
|
++test_ok;
|
2011-07-12 13:05:36 -04:00
|
|
|
}
|
2007-12-01 09:30:07 +00:00
|
|
|
}
|
|
|
|
static void
|
2019-01-12 13:58:50 +03:00
|
|
|
test_nonpersist_readd(void *_data)
|
2007-12-01 09:30:07 +00:00
|
|
|
{
|
|
|
|
struct event ev1, ev2;
|
2019-01-12 13:58:50 +03:00
|
|
|
struct basic_test_data *data = _data;
|
2010-12-09 11:43:12 -05:00
|
|
|
|
2019-01-12 13:58:50 +03:00
|
|
|
memset(&ev1, 0, sizeof(ev1));
|
|
|
|
memset(&ev2, 0, sizeof(ev2));
|
2011-07-12 13:05:36 -04:00
|
|
|
|
2019-01-12 13:58:50 +03:00
|
|
|
tt_assert(!event_assign(&ev1, data->base, data->pair[0], EV_READ, re_add_read_cb, &ev2));
|
|
|
|
tt_assert(!event_assign(&ev2, data->base, data->pair[1], EV_READ, re_add_read_cb, &ev1));
|
2011-07-12 13:05:36 -04:00
|
|
|
|
2019-01-12 13:58:50 +03:00
|
|
|
tt_int_op(write(data->pair[0], "Hello", 5), ==, 5);
|
|
|
|
tt_int_op(write(data->pair[1], "Hello", 5), ==, 5);
|
|
|
|
|
|
|
|
tt_int_op(event_add(&ev1, NULL), ==, 0);
|
|
|
|
tt_int_op(event_add(&ev2, NULL), ==, 0);
|
|
|
|
tt_int_op(event_base_loop(data->base, EVLOOP_ONCE), ==, 0);
|
|
|
|
tt_int_op(test_ok, ==, 2);
|
2011-07-12 13:05:36 -04:00
|
|
|
|
2007-12-01 09:30:07 +00:00
|
|
|
/* At this point, we executed both callbacks. Whichever one got
|
|
|
|
* called first added the second, but the second then immediately got
|
|
|
|
* deleted before its callback was called. At this point, though, it
|
|
|
|
* re-added the first.
|
|
|
|
*/
|
2019-01-12 13:58:50 +03:00
|
|
|
tt_assert(readd_test_event_last_added);
|
|
|
|
if (readd_test_event_last_added == &ev1) {
|
|
|
|
tt_assert(event_pending(&ev1, EV_READ, NULL) && !event_pending(&ev2, EV_READ, NULL));
|
2007-12-01 09:30:07 +00:00
|
|
|
} else {
|
2019-01-12 13:58:50 +03:00
|
|
|
tt_assert(event_pending(&ev2, EV_READ, NULL) && !event_pending(&ev1, EV_READ, NULL));
|
2007-12-01 09:30:07 +00:00
|
|
|
}
|
|
|
|
|
2019-01-12 13:58:50 +03:00
|
|
|
end:
|
|
|
|
if (event_initialized(&ev1))
|
|
|
|
event_del(&ev1);
|
|
|
|
if (event_initialized(&ev2))
|
|
|
|
event_del(&ev2);
|
2007-12-01 09:30:07 +00:00
|
|
|
}
|
|
|
|
|
2004-09-19 21:08:09 +00:00
|
|
|
struct test_pri_event {
|
|
|
|
struct event ev;
|
|
|
|
int count;
|
|
|
|
};
|
|
|
|
|
2007-11-26 19:18:49 +00:00
|
|
|
static void
|
2010-03-05 12:47:46 -05:00
|
|
|
test_priorities_cb(evutil_socket_t fd, short what, void *arg)
|
2004-09-19 21:08:09 +00:00
|
|
|
{
|
|
|
|
struct test_pri_event *pri = arg;
|
|
|
|
struct timeval tv;
|
|
|
|
|
|
|
|
if (pri->count == 3) {
|
|
|
|
event_loopexit(NULL);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
pri->count++;
|
|
|
|
|
2007-11-07 06:01:57 +00:00
|
|
|
evutil_timerclear(&tv);
|
2004-09-19 21:08:09 +00:00
|
|
|
event_add(&pri->ev, &tv);
|
|
|
|
}
|
|
|
|
|
2007-11-26 19:18:49 +00:00
|
|
|
static void
|
2009-01-29 23:19:57 +00:00
|
|
|
test_priorities_impl(int npriorities)
|
2004-09-19 21:08:09 +00:00
|
|
|
{
|
|
|
|
struct test_pri_event one, two;
|
|
|
|
struct timeval tv;
|
|
|
|
|
2009-01-29 23:19:57 +00:00
|
|
|
TT_BLATHER(("Testing Priorities %d: ", npriorities));
|
2004-09-19 21:08:09 +00:00
|
|
|
|
2007-08-19 02:41:23 +00:00
|
|
|
event_base_priority_init(global_base, npriorities);
|
2004-09-19 21:08:09 +00:00
|
|
|
|
|
|
|
memset(&one, 0, sizeof(one));
|
|
|
|
memset(&two, 0, sizeof(two));
|
|
|
|
|
|
|
|
timeout_set(&one.ev, test_priorities_cb, &one);
|
|
|
|
if (event_priority_set(&one.ev, 0) == -1) {
|
|
|
|
fprintf(stderr, "%s: failed to set priority", __func__);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
timeout_set(&two.ev, test_priorities_cb, &two);
|
|
|
|
if (event_priority_set(&two.ev, npriorities - 1) == -1) {
|
|
|
|
fprintf(stderr, "%s: failed to set priority", __func__);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2007-11-07 06:01:57 +00:00
|
|
|
evutil_timerclear(&tv);
|
2004-09-19 21:08:09 +00:00
|
|
|
|
|
|
|
if (event_add(&one.ev, &tv) == -1)
|
|
|
|
exit(1);
|
|
|
|
if (event_add(&two.ev, &tv) == -1)
|
|
|
|
exit(1);
|
|
|
|
|
|
|
|
event_dispatch();
|
|
|
|
|
|
|
|
event_del(&one.ev);
|
|
|
|
event_del(&two.ev);
|
|
|
|
|
|
|
|
if (npriorities == 1) {
|
|
|
|
if (one.count == 3 && two.count == 3)
|
|
|
|
test_ok = 1;
|
|
|
|
} else if (npriorities == 2) {
|
|
|
|
/* Two is called once because event_loopexit is priority 1 */
|
|
|
|
if (one.count == 3 && two.count == 1)
|
|
|
|
test_ok = 1;
|
|
|
|
} else {
|
|
|
|
if (one.count == 3 && two.count == 0)
|
|
|
|
test_ok = 1;
|
|
|
|
}
|
2009-01-29 23:19:57 +00:00
|
|
|
}
|
2004-09-19 21:08:09 +00:00
|
|
|
|
2009-01-29 23:19:57 +00:00
|
|
|
static void
|
|
|
|
test_priorities(void)
|
|
|
|
{
|
2010-02-18 17:41:15 -05:00
|
|
|
test_priorities_impl(1);
|
|
|
|
if (test_ok)
|
|
|
|
test_priorities_impl(2);
|
|
|
|
if (test_ok)
|
|
|
|
test_priorities_impl(3);
|
2004-09-19 21:08:09 +00:00
|
|
|
}
|
|
|
|
|
2012-04-30 17:30:48 -04:00
|
|
|
/* priority-active-inversion: activate a higher-priority event, and make sure
|
|
|
|
* it keeps us from running a lower-priority event first. */
|
|
|
|
static int n_pai_calls = 0;
|
|
|
|
static struct event pai_events[3];
|
|
|
|
|
|
|
|
static void
|
|
|
|
prio_active_inversion_cb(evutil_socket_t fd, short what, void *arg)
|
|
|
|
{
|
|
|
|
int *call_order = arg;
|
|
|
|
*call_order = n_pai_calls++;
|
|
|
|
if (n_pai_calls == 1) {
|
|
|
|
/* This should activate later, even though it shares a
|
|
|
|
priority with us. */
|
|
|
|
event_active(&pai_events[1], EV_READ, 1);
|
|
|
|
/* This should activate next, since its priority is higher,
|
|
|
|
even though we activated it second. */
|
|
|
|
event_active(&pai_events[2], EV_TIMEOUT, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
test_priority_active_inversion(void *data_)
|
|
|
|
{
|
|
|
|
struct basic_test_data *data = data_;
|
|
|
|
struct event_base *base = data->base;
|
|
|
|
int call_order[3];
|
|
|
|
int i;
|
|
|
|
tt_int_op(event_base_priority_init(base, 8), ==, 0);
|
|
|
|
|
|
|
|
n_pai_calls = 0;
|
|
|
|
memset(call_order, 0, sizeof(call_order));
|
|
|
|
|
|
|
|
for (i=0;i<3;++i) {
|
|
|
|
event_assign(&pai_events[i], data->base, -1, 0,
|
|
|
|
prio_active_inversion_cb, &call_order[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
event_priority_set(&pai_events[0], 4);
|
|
|
|
event_priority_set(&pai_events[1], 4);
|
|
|
|
event_priority_set(&pai_events[2], 0);
|
|
|
|
|
|
|
|
event_active(&pai_events[0], EV_WRITE, 1);
|
|
|
|
|
|
|
|
event_base_dispatch(base);
|
|
|
|
tt_int_op(n_pai_calls, ==, 3);
|
|
|
|
tt_int_op(call_order[0], ==, 0);
|
|
|
|
tt_int_op(call_order[1], ==, 2);
|
|
|
|
tt_int_op(call_order[2], ==, 1);
|
|
|
|
end:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
2009-01-29 23:19:57 +00:00
|
|
|
|
2005-03-29 07:16:52 +00:00
|
|
|
static void
|
2010-03-05 12:47:46 -05:00
|
|
|
test_multiple_cb(evutil_socket_t fd, short event, void *arg)
|
2005-03-29 07:16:52 +00:00
|
|
|
{
|
|
|
|
if (event & EV_READ)
|
|
|
|
test_ok |= 1;
|
|
|
|
else if (event & EV_WRITE)
|
|
|
|
test_ok |= 2;
|
|
|
|
}
|
|
|
|
|
2007-11-26 19:18:49 +00:00
|
|
|
static void
|
2005-03-29 07:16:52 +00:00
|
|
|
test_multiple_events_for_same_fd(void)
|
|
|
|
{
|
|
|
|
struct event e1, e2;
|
|
|
|
|
|
|
|
setup_test("Multiple events for same fd: ");
|
|
|
|
|
|
|
|
event_set(&e1, pair[0], EV_READ, test_multiple_cb, NULL);
|
|
|
|
event_add(&e1, NULL);
|
|
|
|
event_set(&e2, pair[0], EV_WRITE, test_multiple_cb, NULL);
|
|
|
|
event_add(&e2, NULL);
|
|
|
|
event_loop(EVLOOP_ONCE);
|
|
|
|
event_del(&e2);
|
2011-07-12 13:05:36 -04:00
|
|
|
|
|
|
|
if (write(pair[1], TEST1, strlen(TEST1)+1) < 0) {
|
2011-10-03 12:45:36 -04:00
|
|
|
tt_fail_perror("write");
|
2011-07-12 13:05:36 -04:00
|
|
|
}
|
|
|
|
|
2005-03-29 07:16:52 +00:00
|
|
|
event_loop(EVLOOP_ONCE);
|
|
|
|
event_del(&e1);
|
2009-01-27 21:10:31 +00:00
|
|
|
|
2005-03-29 07:16:52 +00:00
|
|
|
if (test_ok != 3)
|
|
|
|
test_ok = 0;
|
|
|
|
|
|
|
|
cleanup_test();
|
|
|
|
}
|
|
|
|
|
2008-02-18 20:04:01 +00:00
|
|
|
int evtag_decode_int(ev_uint32_t *pnumber, struct evbuffer *evbuf);
|
2009-07-20 14:55:35 +00:00
|
|
|
int evtag_decode_int64(ev_uint64_t *pnumber, struct evbuffer *evbuf);
|
2008-02-18 20:04:01 +00:00
|
|
|
int evtag_encode_tag(struct evbuffer *evbuf, ev_uint32_t number);
|
|
|
|
int evtag_decode_tag(ev_uint32_t *pnumber, struct evbuffer *evbuf);
|
2005-08-22 01:34:34 +00:00
|
|
|
|
2007-11-26 19:18:49 +00:00
|
|
|
static void
|
2010-03-05 12:47:46 -05:00
|
|
|
read_once_cb(evutil_socket_t fd, short event, void *arg)
|
2005-12-17 20:15:25 +00:00
|
|
|
{
|
|
|
|
char buf[256];
|
|
|
|
int len;
|
|
|
|
|
|
|
|
len = read(fd, buf, sizeof(buf));
|
|
|
|
|
|
|
|
if (called) {
|
|
|
|
test_ok = 0;
|
|
|
|
} else if (len) {
|
|
|
|
/* Assumes global pair[0] can be used for writing */
|
2011-07-12 13:05:36 -04:00
|
|
|
if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) {
|
2011-10-03 12:45:36 -04:00
|
|
|
tt_fail_perror("write");
|
2011-07-12 13:05:36 -04:00
|
|
|
test_ok = 0;
|
|
|
|
} else {
|
|
|
|
test_ok = 1;
|
|
|
|
}
|
2005-12-17 20:15:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
called++;
|
|
|
|
}
|
|
|
|
|
2007-11-26 19:18:49 +00:00
|
|
|
static void
|
2005-12-17 20:15:25 +00:00
|
|
|
test_want_only_once(void)
|
|
|
|
{
|
|
|
|
struct event ev;
|
|
|
|
struct timeval tv;
|
|
|
|
|
|
|
|
/* Very simple read test */
|
|
|
|
setup_test("Want read only once: ");
|
2009-01-27 21:10:31 +00:00
|
|
|
|
2011-07-12 13:05:36 -04:00
|
|
|
if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) {
|
2011-10-03 12:45:36 -04:00
|
|
|
tt_fail_perror("write");
|
2011-07-12 13:05:36 -04:00
|
|
|
}
|
2005-12-17 20:15:25 +00:00
|
|
|
|
|
|
|
/* Setup the loop termination */
|
2007-11-07 06:01:57 +00:00
|
|
|
evutil_timerclear(&tv);
|
2012-01-24 14:33:10 -05:00
|
|
|
tv.tv_usec = 300*1000;
|
2005-12-17 20:15:25 +00:00
|
|
|
event_loopexit(&tv);
|
2009-01-27 21:10:31 +00:00
|
|
|
|
2005-12-17 20:15:25 +00:00
|
|
|
event_set(&ev, pair[1], EV_READ, read_once_cb, &ev);
|
|
|
|
if (event_add(&ev, NULL) == -1)
|
|
|
|
exit(1);
|
|
|
|
event_dispatch();
|
|
|
|
|
|
|
|
cleanup_test();
|
|
|
|
}
|
|
|
|
|
2005-08-22 01:34:34 +00:00
|
|
|
#define TEST_MAX_INT 6
|
|
|
|
|
2007-11-26 19:18:49 +00:00
|
|
|
static void
|
2009-07-20 14:55:51 +00:00
|
|
|
evtag_int_test(void *ptr)
|
2005-08-22 01:34:34 +00:00
|
|
|
{
|
|
|
|
struct evbuffer *tmp = evbuffer_new();
|
2008-02-18 20:04:01 +00:00
|
|
|
ev_uint32_t integers[TEST_MAX_INT] = {
|
2005-08-22 01:34:34 +00:00
|
|
|
0xaf0, 0x1000, 0x1, 0xdeadbeef, 0x00, 0xbef000
|
|
|
|
};
|
2008-02-18 20:04:01 +00:00
|
|
|
ev_uint32_t integer;
|
2009-07-20 14:55:35 +00:00
|
|
|
ev_uint64_t big_int;
|
2005-08-22 01:34:34 +00:00
|
|
|
int i;
|
|
|
|
|
2009-07-20 14:55:51 +00:00
|
|
|
evtag_init();
|
|
|
|
|
2005-08-22 01:34:34 +00:00
|
|
|
for (i = 0; i < TEST_MAX_INT; i++) {
|
|
|
|
int oldlen, newlen;
|
2010-11-03 14:38:45 -07:00
|
|
|
oldlen = (int)EVBUFFER_LENGTH(tmp);
|
2009-07-20 14:55:35 +00:00
|
|
|
evtag_encode_int(tmp, integers[i]);
|
2010-11-03 14:38:45 -07:00
|
|
|
newlen = (int)EVBUFFER_LENGTH(tmp);
|
2009-07-20 14:55:35 +00:00
|
|
|
TT_BLATHER(("encoded 0x%08x with %d bytes",
|
2010-02-18 17:41:15 -05:00
|
|
|
(unsigned)integers[i], newlen - oldlen));
|
2009-07-20 14:55:35 +00:00
|
|
|
big_int = integers[i];
|
|
|
|
big_int *= 1000000000; /* 1 billion */
|
|
|
|
evtag_encode_int64(tmp, big_int);
|
2005-08-22 01:34:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < TEST_MAX_INT; i++) {
|
2010-02-18 17:41:15 -05:00
|
|
|
tt_int_op(evtag_decode_int(&integer, tmp), !=, -1);
|
|
|
|
tt_uint_op(integer, ==, integers[i]);
|
2009-07-20 14:55:35 +00:00
|
|
|
tt_int_op(evtag_decode_int64(&big_int, tmp), !=, -1);
|
|
|
|
tt_assert((big_int / 1000000000) == integers[i]);
|
2005-08-22 01:34:34 +00:00
|
|
|
}
|
|
|
|
|
2009-07-20 14:55:51 +00:00
|
|
|
tt_uint_op(EVBUFFER_LENGTH(tmp), ==, 0);
|
2009-01-31 18:36:47 +00:00
|
|
|
end:
|
2005-08-22 01:34:34 +00:00
|
|
|
evbuffer_free(tmp);
|
|
|
|
}
|
|
|
|
|
2007-11-26 19:18:49 +00:00
|
|
|
static void
|
2009-07-20 14:55:51 +00:00
|
|
|
evtag_fuzz(void *ptr)
|
2005-08-22 01:34:34 +00:00
|
|
|
{
|
2015-08-25 15:24:39 +02:00
|
|
|
unsigned char buffer[4096];
|
2005-08-22 01:34:34 +00:00
|
|
|
struct evbuffer *tmp = evbuffer_new();
|
|
|
|
struct timeval tv;
|
|
|
|
int i, j;
|
|
|
|
|
2006-02-26 20:18:35 +00:00
|
|
|
int not_failed = 0;
|
2009-07-20 14:55:51 +00:00
|
|
|
|
|
|
|
evtag_init();
|
|
|
|
|
2005-08-22 01:34:34 +00:00
|
|
|
for (j = 0; j < 100; j++) {
|
2010-10-14 13:16:41 -04:00
|
|
|
for (i = 0; i < (int)sizeof(buffer); i++)
|
2014-09-18 12:02:13 -04:00
|
|
|
buffer[i] = test_weakrand();
|
2005-08-22 01:34:34 +00:00
|
|
|
evbuffer_drain(tmp, -1);
|
|
|
|
evbuffer_add(tmp, buffer, sizeof(buffer));
|
|
|
|
|
2006-02-26 20:18:35 +00:00
|
|
|
if (evtag_unmarshal_timeval(tmp, 0, &tv) != -1)
|
|
|
|
not_failed++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The majority of decodes should fail */
|
2009-01-31 18:36:47 +00:00
|
|
|
tt_int_op(not_failed, <, 10);
|
2005-08-22 01:34:34 +00:00
|
|
|
|
|
|
|
/* Now insert some corruption into the tag length field */
|
|
|
|
evbuffer_drain(tmp, -1);
|
2007-11-07 06:01:57 +00:00
|
|
|
evutil_timerclear(&tv);
|
2005-08-22 01:34:34 +00:00
|
|
|
tv.tv_sec = 1;
|
|
|
|
evtag_marshal_timeval(tmp, 0, &tv);
|
|
|
|
evbuffer_add(tmp, buffer, sizeof(buffer));
|
|
|
|
|
2010-01-23 16:38:36 -05:00
|
|
|
((char *)EVBUFFER_DATA(tmp))[1] = '\xff';
|
2005-08-22 01:34:34 +00:00
|
|
|
if (evtag_unmarshal_timeval(tmp, 0, &tv) != -1) {
|
2010-02-18 17:41:15 -05:00
|
|
|
tt_abort_msg("evtag_unmarshal_timeval should have failed");
|
2005-08-22 01:34:34 +00:00
|
|
|
}
|
|
|
|
|
2009-01-31 18:36:47 +00:00
|
|
|
end:
|
2005-08-22 01:34:34 +00:00
|
|
|
evbuffer_free(tmp);
|
|
|
|
}
|
|
|
|
|
2007-12-12 04:39:42 +00:00
|
|
|
static void
|
2009-07-20 14:55:51 +00:00
|
|
|
evtag_tag_encoding(void *ptr)
|
2007-12-12 04:39:42 +00:00
|
|
|
{
|
|
|
|
struct evbuffer *tmp = evbuffer_new();
|
2008-02-18 20:04:01 +00:00
|
|
|
ev_uint32_t integers[TEST_MAX_INT] = {
|
2007-12-12 04:39:42 +00:00
|
|
|
0xaf0, 0x1000, 0x1, 0xdeadbeef, 0x00, 0xbef000
|
|
|
|
};
|
2008-02-18 20:04:01 +00:00
|
|
|
ev_uint32_t integer;
|
2007-12-12 04:39:42 +00:00
|
|
|
int i;
|
|
|
|
|
2009-07-20 14:55:51 +00:00
|
|
|
evtag_init();
|
|
|
|
|
2007-12-12 04:39:42 +00:00
|
|
|
for (i = 0; i < TEST_MAX_INT; i++) {
|
|
|
|
int oldlen, newlen;
|
2010-11-03 14:38:45 -07:00
|
|
|
oldlen = (int)EVBUFFER_LENGTH(tmp);
|
2007-12-13 06:14:18 +00:00
|
|
|
evtag_encode_tag(tmp, integers[i]);
|
2010-11-03 14:38:45 -07:00
|
|
|
newlen = (int)EVBUFFER_LENGTH(tmp);
|
2010-02-18 17:41:15 -05:00
|
|
|
TT_BLATHER(("encoded 0x%08x with %d bytes",
|
|
|
|
(unsigned)integers[i], newlen - oldlen));
|
2007-12-12 04:39:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < TEST_MAX_INT; i++) {
|
2010-02-18 17:41:15 -05:00
|
|
|
tt_int_op(evtag_decode_tag(&integer, tmp), !=, -1);
|
|
|
|
tt_uint_op(integer, ==, integers[i]);
|
2007-12-12 04:39:42 +00:00
|
|
|
}
|
|
|
|
|
2010-02-18 17:41:15 -05:00
|
|
|
tt_uint_op(EVBUFFER_LENGTH(tmp), ==, 0);
|
2009-07-20 14:55:51 +00:00
|
|
|
|
2009-01-31 18:36:47 +00:00
|
|
|
end:
|
2007-12-12 04:39:42 +00:00
|
|
|
evbuffer_free(tmp);
|
|
|
|
}
|
|
|
|
|
2009-10-29 16:35:20 +00:00
|
|
|
static void
|
|
|
|
evtag_test_peek(void *ptr)
|
|
|
|
{
|
|
|
|
struct evbuffer *tmp = evbuffer_new();
|
|
|
|
ev_uint32_t u32;
|
|
|
|
|
|
|
|
evtag_marshal_int(tmp, 30, 0);
|
|
|
|
evtag_marshal_string(tmp, 40, "Hello world");
|
|
|
|
|
|
|
|
tt_int_op(evtag_peek(tmp, &u32), ==, 1);
|
|
|
|
tt_int_op(u32, ==, 30);
|
|
|
|
tt_int_op(evtag_peek_length(tmp, &u32), ==, 0);
|
|
|
|
tt_int_op(u32, ==, 1+1+1);
|
|
|
|
tt_int_op(evtag_consume(tmp), ==, 0);
|
|
|
|
|
|
|
|
tt_int_op(evtag_peek(tmp, &u32), ==, 1);
|
|
|
|
tt_int_op(u32, ==, 40);
|
|
|
|
tt_int_op(evtag_peek_length(tmp, &u32), ==, 0);
|
|
|
|
tt_int_op(u32, ==, 1+1+11);
|
|
|
|
tt_int_op(evtag_payload_length(tmp, &u32), ==, 0);
|
|
|
|
tt_int_op(u32, ==, 11);
|
|
|
|
|
|
|
|
end:
|
|
|
|
evbuffer_free(tmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-05-08 05:33:15 +00:00
|
|
|
static void
|
2009-01-29 23:19:57 +00:00
|
|
|
test_methods(void *ptr)
|
2008-05-08 05:33:15 +00:00
|
|
|
{
|
2008-05-08 22:51:39 +00:00
|
|
|
const char **methods = event_get_supported_methods();
|
2009-01-29 23:19:57 +00:00
|
|
|
struct event_config *cfg = NULL;
|
|
|
|
struct event_base *base = NULL;
|
2008-05-08 05:56:20 +00:00
|
|
|
const char *backend;
|
2008-05-12 17:16:47 +00:00
|
|
|
int n_methods = 0;
|
2008-05-08 05:33:15 +00:00
|
|
|
|
2010-02-18 17:41:15 -05:00
|
|
|
tt_assert(methods);
|
2008-05-08 05:33:15 +00:00
|
|
|
|
2008-05-08 05:56:20 +00:00
|
|
|
backend = methods[0];
|
2008-05-08 05:33:15 +00:00
|
|
|
while (*methods != NULL) {
|
2009-01-29 23:19:57 +00:00
|
|
|
TT_BLATHER(("Support method: %s", *methods));
|
2008-05-08 05:33:15 +00:00
|
|
|
++methods;
|
2008-05-12 17:16:47 +00:00
|
|
|
++n_methods;
|
|
|
|
}
|
|
|
|
|
2008-05-08 05:56:20 +00:00
|
|
|
cfg = event_config_new();
|
|
|
|
assert(cfg != NULL);
|
|
|
|
|
2009-01-29 23:19:57 +00:00
|
|
|
tt_int_op(event_config_avoid_method(cfg, backend), ==, 0);
|
2009-07-25 03:35:32 +00:00
|
|
|
event_config_set_flag(cfg, EVENT_BASE_FLAG_IGNORE_ENV);
|
2008-05-08 05:56:20 +00:00
|
|
|
|
|
|
|
base = event_base_new_with_config(cfg);
|
2009-04-23 18:08:42 +00:00
|
|
|
if (n_methods > 1) {
|
|
|
|
tt_assert(base);
|
|
|
|
tt_str_op(backend, !=, event_base_get_method(base));
|
|
|
|
} else {
|
|
|
|
tt_assert(base == NULL);
|
|
|
|
}
|
2009-01-29 23:19:57 +00:00
|
|
|
|
|
|
|
end:
|
2010-02-18 17:41:15 -05:00
|
|
|
if (base)
|
|
|
|
event_base_free(base);
|
|
|
|
if (cfg)
|
|
|
|
event_config_free(cfg);
|
2009-01-29 23:19:57 +00:00
|
|
|
}
|
|
|
|
|
2009-04-21 18:46:11 +00:00
|
|
|
static void
|
|
|
|
test_version(void *arg)
|
|
|
|
{
|
|
|
|
const char *vstr;
|
|
|
|
ev_uint32_t vint;
|
|
|
|
int major, minor, patch, n;
|
|
|
|
|
|
|
|
vstr = event_get_version();
|
|
|
|
vint = event_get_version_number();
|
|
|
|
|
|
|
|
tt_assert(vstr);
|
|
|
|
tt_assert(vint);
|
|
|
|
|
|
|
|
tt_str_op(vstr, ==, LIBEVENT_VERSION);
|
|
|
|
tt_int_op(vint, ==, LIBEVENT_VERSION_NUMBER);
|
|
|
|
|
|
|
|
n = sscanf(vstr, "%d.%d.%d", &major, &minor, &patch);
|
|
|
|
tt_assert(3 == n);
|
2009-04-23 00:01:14 +00:00
|
|
|
tt_int_op((vint&0xffffff00), ==, ((major<<24)|(minor<<16)|(patch<<8)));
|
2009-04-21 18:46:11 +00:00
|
|
|
end:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
test_base_features(void *arg)
|
|
|
|
{
|
|
|
|
struct event_base *base = NULL;
|
|
|
|
struct event_config *cfg = NULL;
|
|
|
|
|
|
|
|
cfg = event_config_new();
|
|
|
|
|
|
|
|
tt_assert(0 == event_config_require_features(cfg, EV_FEATURE_ET));
|
|
|
|
|
|
|
|
base = event_base_new_with_config(cfg);
|
|
|
|
if (base) {
|
|
|
|
tt_int_op(EV_FEATURE_ET, ==,
|
|
|
|
event_base_get_features(base) & EV_FEATURE_ET);
|
|
|
|
} else {
|
|
|
|
base = event_base_new();
|
|
|
|
tt_int_op(0, ==, event_base_get_features(base) & EV_FEATURE_ET);
|
|
|
|
}
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (base)
|
|
|
|
event_base_free(base);
|
|
|
|
if (cfg)
|
|
|
|
event_config_free(cfg);
|
|
|
|
}
|
|
|
|
|
2012-02-29 15:07:31 -05:00
|
|
|
#ifdef EVENT__HAVE_SETENV
|
2009-12-29 16:38:03 -05:00
|
|
|
#define SETENV_OK
|
2012-02-29 15:07:31 -05:00
|
|
|
#elif !defined(EVENT__HAVE_SETENV) && defined(EVENT__HAVE_PUTENV)
|
2012-02-29 15:47:16 -05:00
|
|
|
static void setenv(const char *k, const char *v, int o_)
|
2009-04-30 18:05:33 +00:00
|
|
|
{
|
|
|
|
char b[256];
|
|
|
|
evutil_snprintf(b, sizeof(b), "%s=%s",k,v);
|
|
|
|
putenv(b);
|
|
|
|
}
|
2009-12-29 16:38:03 -05:00
|
|
|
#define SETENV_OK
|
|
|
|
#endif
|
|
|
|
|
2012-02-29 15:07:31 -05:00
|
|
|
#ifdef EVENT__HAVE_UNSETENV
|
2009-12-29 16:38:03 -05:00
|
|
|
#define UNSETENV_OK
|
2012-02-29 15:07:31 -05:00
|
|
|
#elif !defined(EVENT__HAVE_UNSETENV) && defined(EVENT__HAVE_PUTENV)
|
2009-04-30 18:05:33 +00:00
|
|
|
static void unsetenv(const char *k)
|
|
|
|
{
|
|
|
|
char b[256];
|
|
|
|
evutil_snprintf(b, sizeof(b), "%s=",k);
|
|
|
|
putenv(b);
|
|
|
|
}
|
2009-12-29 16:38:03 -05:00
|
|
|
#define UNSETENV_OK
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(SETENV_OK) && defined(UNSETENV_OK)
|
|
|
|
static void
|
|
|
|
methodname_to_envvar(const char *mname, char *buf, size_t buflen)
|
|
|
|
{
|
|
|
|
char *cp;
|
|
|
|
evutil_snprintf(buf, buflen, "EVENT_NO%s", mname);
|
|
|
|
for (cp = buf; *cp; ++cp) {
|
2012-02-29 15:07:33 -05:00
|
|
|
*cp = EVUTIL_TOUPPER_(*cp);
|
2009-12-29 16:38:03 -05:00
|
|
|
}
|
|
|
|
}
|
2009-04-30 18:05:33 +00:00
|
|
|
#endif
|
|
|
|
|
2009-04-28 19:08:27 +00:00
|
|
|
static void
|
|
|
|
test_base_environ(void *arg)
|
|
|
|
{
|
2009-12-29 16:38:03 -05:00
|
|
|
struct event_base *base = NULL;
|
|
|
|
struct event_config *cfg = NULL;
|
|
|
|
|
|
|
|
#if defined(SETENV_OK) && defined(UNSETENV_OK)
|
2009-04-28 19:08:27 +00:00
|
|
|
const char **basenames;
|
|
|
|
int i, n_methods=0;
|
2010-11-22 14:10:01 -05:00
|
|
|
char varbuf[128];
|
|
|
|
const char *defaultname, *ignoreenvname;
|
2009-04-28 19:08:27 +00:00
|
|
|
|
2010-04-21 12:25:29 -04:00
|
|
|
/* See if unsetenv works before we rely on it. */
|
|
|
|
setenv("EVENT_NOWAFFLES", "1", 1);
|
|
|
|
unsetenv("EVENT_NOWAFFLES");
|
|
|
|
if (getenv("EVENT_NOWAFFLES") != NULL) {
|
2012-02-29 15:07:31 -05:00
|
|
|
#ifndef EVENT__HAVE_UNSETENV
|
2010-04-21 12:25:29 -04:00
|
|
|
TT_DECLARE("NOTE", ("Can't fake unsetenv; skipping test"));
|
|
|
|
#else
|
|
|
|
TT_DECLARE("NOTE", ("unsetenv doesn't work; skipping test"));
|
|
|
|
#endif
|
|
|
|
tt_skip();
|
|
|
|
}
|
|
|
|
|
2009-04-28 19:08:27 +00:00
|
|
|
basenames = event_get_supported_methods();
|
|
|
|
for (i = 0; basenames[i]; ++i) {
|
|
|
|
methodname_to_envvar(basenames[i], varbuf, sizeof(varbuf));
|
|
|
|
unsetenv(varbuf);
|
|
|
|
++n_methods;
|
|
|
|
}
|
|
|
|
|
|
|
|
base = event_base_new();
|
|
|
|
tt_assert(base);
|
|
|
|
|
|
|
|
defaultname = event_base_get_method(base);
|
2009-07-14 18:49:42 +00:00
|
|
|
TT_BLATHER(("default is <%s>", defaultname));
|
2009-04-28 19:08:27 +00:00
|
|
|
event_base_free(base);
|
|
|
|
base = NULL;
|
|
|
|
|
|
|
|
/* Can we disable the method with EVENT_NOfoo ? */
|
2010-11-22 14:10:01 -05:00
|
|
|
if (!strcmp(defaultname, "epoll (with changelist)")) {
|
|
|
|
setenv("EVENT_NOEPOLL", "1", 1);
|
|
|
|
ignoreenvname = "epoll";
|
|
|
|
} else {
|
|
|
|
methodname_to_envvar(defaultname, varbuf, sizeof(varbuf));
|
|
|
|
setenv(varbuf, "1", 1);
|
|
|
|
ignoreenvname = defaultname;
|
|
|
|
}
|
2009-04-28 19:08:27 +00:00
|
|
|
|
2009-04-30 18:05:33 +00:00
|
|
|
/* Use an empty cfg rather than NULL so a failure doesn't exit() */
|
|
|
|
cfg = event_config_new();
|
|
|
|
base = event_base_new_with_config(cfg);
|
|
|
|
event_config_free(cfg);
|
|
|
|
cfg = NULL;
|
2009-04-28 19:08:27 +00:00
|
|
|
if (n_methods == 1) {
|
|
|
|
tt_assert(!base);
|
|
|
|
} else {
|
|
|
|
tt_assert(base);
|
|
|
|
tt_str_op(defaultname, !=, event_base_get_method(base));
|
|
|
|
event_base_free(base);
|
|
|
|
base = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Can we disable looking at the environment with IGNORE_ENV ? */
|
|
|
|
cfg = event_config_new();
|
|
|
|
event_config_set_flag(cfg, EVENT_BASE_FLAG_IGNORE_ENV);
|
|
|
|
base = event_base_new_with_config(cfg);
|
|
|
|
tt_assert(base);
|
2010-11-22 14:10:01 -05:00
|
|
|
tt_str_op(ignoreenvname, ==, event_base_get_method(base));
|
2009-12-29 16:38:03 -05:00
|
|
|
#else
|
|
|
|
tt_skip();
|
|
|
|
#endif
|
2009-04-28 19:08:27 +00:00
|
|
|
|
|
|
|
end:
|
|
|
|
if (base)
|
|
|
|
event_base_free(base);
|
|
|
|
if (cfg)
|
|
|
|
event_config_free(cfg);
|
|
|
|
}
|
|
|
|
|
2009-04-21 18:46:43 +00:00
|
|
|
static void
|
2010-03-05 12:47:46 -05:00
|
|
|
read_called_once_cb(evutil_socket_t fd, short event, void *arg)
|
2009-04-21 18:46:43 +00:00
|
|
|
{
|
|
|
|
tt_int_op(event, ==, EV_READ);
|
|
|
|
called += 1;
|
|
|
|
end:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2010-03-05 12:47:46 -05:00
|
|
|
timeout_called_once_cb(evutil_socket_t fd, short event, void *arg)
|
2009-04-21 18:46:43 +00:00
|
|
|
{
|
|
|
|
tt_int_op(event, ==, EV_TIMEOUT);
|
|
|
|
called += 100;
|
|
|
|
end:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
2011-12-07 11:49:52 -05:00
|
|
|
static void
|
|
|
|
immediate_called_twice_cb(evutil_socket_t fd, short event, void *arg)
|
|
|
|
{
|
|
|
|
tt_int_op(event, ==, EV_TIMEOUT);
|
|
|
|
called += 1000;
|
|
|
|
end:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
2009-04-21 18:46:43 +00:00
|
|
|
static void
|
|
|
|
test_event_once(void *ptr)
|
|
|
|
{
|
|
|
|
struct basic_test_data *data = ptr;
|
|
|
|
struct timeval tv;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
tv.tv_sec = 0;
|
|
|
|
tv.tv_usec = 50*1000;
|
|
|
|
called = 0;
|
|
|
|
r = event_base_once(data->base, data->pair[0], EV_READ,
|
|
|
|
read_called_once_cb, NULL, NULL);
|
|
|
|
tt_int_op(r, ==, 0);
|
2009-04-21 18:47:02 +00:00
|
|
|
r = event_base_once(data->base, -1, EV_TIMEOUT,
|
2009-04-21 18:46:43 +00:00
|
|
|
timeout_called_once_cb, NULL, &tv);
|
|
|
|
tt_int_op(r, ==, 0);
|
2009-04-21 18:47:02 +00:00
|
|
|
r = event_base_once(data->base, -1, 0, NULL, NULL, NULL);
|
|
|
|
tt_int_op(r, <, 0);
|
2011-12-07 11:49:52 -05:00
|
|
|
r = event_base_once(data->base, -1, EV_TIMEOUT,
|
|
|
|
immediate_called_twice_cb, NULL, NULL);
|
|
|
|
tt_int_op(r, ==, 0);
|
|
|
|
tv.tv_sec = 0;
|
|
|
|
tv.tv_usec = 0;
|
|
|
|
r = event_base_once(data->base, -1, EV_TIMEOUT,
|
|
|
|
immediate_called_twice_cb, NULL, &tv);
|
|
|
|
tt_int_op(r, ==, 0);
|
2009-04-21 18:46:43 +00:00
|
|
|
|
2011-07-12 13:05:36 -04:00
|
|
|
if (write(data->pair[1], TEST1, strlen(TEST1)+1) < 0) {
|
2011-10-03 12:45:36 -04:00
|
|
|
tt_fail_perror("write");
|
2011-07-12 13:05:36 -04:00
|
|
|
}
|
|
|
|
|
2016-03-11 01:27:52 +03:00
|
|
|
shutdown(data->pair[1], EVUTIL_SHUT_WR);
|
2009-04-21 18:46:43 +00:00
|
|
|
|
|
|
|
event_base_dispatch(data->base);
|
|
|
|
|
2011-12-07 11:49:52 -05:00
|
|
|
tt_int_op(called, ==, 2101);
|
2009-04-21 18:46:43 +00:00
|
|
|
end:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
2012-11-16 10:17:34 -05:00
|
|
|
static void
|
|
|
|
test_event_once_never(void *ptr)
|
|
|
|
{
|
|
|
|
struct basic_test_data *data = ptr;
|
|
|
|
struct timeval tv;
|
|
|
|
|
|
|
|
/* Have one trigger in 10 seconds (don't worry, because) */
|
|
|
|
tv.tv_sec = 10;
|
|
|
|
tv.tv_usec = 0;
|
|
|
|
called = 0;
|
2012-11-16 16:17:07 -05:00
|
|
|
event_base_once(data->base, -1, EV_TIMEOUT,
|
2012-11-16 10:17:34 -05:00
|
|
|
timeout_called_once_cb, NULL, &tv);
|
|
|
|
|
|
|
|
/* But shut down the base in 75 msec. */
|
|
|
|
tv.tv_sec = 0;
|
|
|
|
tv.tv_usec = 75*1000;
|
|
|
|
event_base_loopexit(data->base, &tv);
|
|
|
|
|
|
|
|
event_base_dispatch(data->base);
|
|
|
|
|
|
|
|
tt_int_op(called, ==, 0);
|
|
|
|
end:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
2009-04-21 18:47:02 +00:00
|
|
|
static void
|
|
|
|
test_event_pending(void *ptr)
|
|
|
|
{
|
|
|
|
struct basic_test_data *data = ptr;
|
|
|
|
struct event *r=NULL, *w=NULL, *t=NULL;
|
2012-01-24 15:30:31 -05:00
|
|
|
struct timeval tv, now, tv2;
|
2009-04-21 18:47:02 +00:00
|
|
|
|
|
|
|
tv.tv_sec = 0;
|
|
|
|
tv.tv_usec = 500 * 1000;
|
|
|
|
r = event_new(data->base, data->pair[0], EV_READ, simple_read_cb,
|
|
|
|
NULL);
|
|
|
|
w = event_new(data->base, data->pair[1], EV_WRITE, simple_write_cb,
|
|
|
|
NULL);
|
|
|
|
t = evtimer_new(data->base, timeout_cb, NULL);
|
|
|
|
|
2012-07-26 09:35:43 -04:00
|
|
|
tt_assert(r);
|
|
|
|
tt_assert(w);
|
|
|
|
tt_assert(t);
|
|
|
|
|
2009-04-21 18:47:02 +00:00
|
|
|
evutil_gettimeofday(&now, NULL);
|
|
|
|
event_add(r, NULL);
|
|
|
|
event_add(t, &tv);
|
|
|
|
|
|
|
|
tt_assert( event_pending(r, EV_READ, NULL));
|
|
|
|
tt_assert(!event_pending(w, EV_WRITE, NULL));
|
|
|
|
tt_assert(!event_pending(r, EV_WRITE, NULL));
|
|
|
|
tt_assert( event_pending(r, EV_READ|EV_WRITE, NULL));
|
|
|
|
tt_assert(!event_pending(r, EV_TIMEOUT, NULL));
|
|
|
|
tt_assert( event_pending(t, EV_TIMEOUT, NULL));
|
|
|
|
tt_assert( event_pending(t, EV_TIMEOUT, &tv2));
|
|
|
|
|
|
|
|
tt_assert(evutil_timercmp(&tv2, &now, >));
|
2012-01-24 14:59:37 -05:00
|
|
|
|
|
|
|
test_timeval_diff_eq(&now, &tv2, 500);
|
2009-04-21 18:47:02 +00:00
|
|
|
|
|
|
|
end:
|
|
|
|
if (r) {
|
|
|
|
event_del(r);
|
|
|
|
event_free(r);
|
|
|
|
}
|
|
|
|
if (w) {
|
|
|
|
event_del(w);
|
|
|
|
event_free(w);
|
|
|
|
}
|
|
|
|
if (t) {
|
|
|
|
event_del(t);
|
|
|
|
event_free(t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-24 11:38:29 -04:00
|
|
|
static void
|
|
|
|
dfd_cb(evutil_socket_t fd, short e, void *data)
|
|
|
|
{
|
|
|
|
*(int*)data = (int)e;
|
|
|
|
}
|
|
|
|
|
2016-07-15 02:27:23 +02:00
|
|
|
static void
|
|
|
|
test_event_closed_fd_poll(void *arg)
|
|
|
|
{
|
|
|
|
struct timeval tv;
|
|
|
|
struct event *e;
|
|
|
|
struct basic_test_data *data = (struct basic_test_data *)arg;
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
if (strcmp(event_base_get_method(data->base), "poll")) {
|
|
|
|
tinytest_set_test_skipped_();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
e = event_new(data->base, data->pair[0], EV_READ, dfd_cb, &i);
|
|
|
|
tt_assert(e);
|
|
|
|
|
|
|
|
tv.tv_sec = 0;
|
|
|
|
tv.tv_usec = 500 * 1000;
|
|
|
|
event_add(e, &tv);
|
|
|
|
tt_assert(event_pending(e, EV_READ, NULL));
|
|
|
|
close(data->pair[0]);
|
|
|
|
data->pair[0] = -1; /** avoids double-close */
|
|
|
|
event_base_loop(data->base, EVLOOP_ONCE);
|
|
|
|
tt_int_op(i, ==, EV_READ);
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (e) {
|
|
|
|
event_del(e);
|
|
|
|
event_free(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef _WIN32
|
|
|
|
/* You can't do this test on windows, since dup2 doesn't work on sockets */
|
|
|
|
|
2010-10-24 11:38:29 -04:00
|
|
|
/* Regression test for our workaround for a fun epoll/linux related bug
|
|
|
|
* where fd2 = dup(fd1); add(fd2); close(fd2); dup2(fd1,fd2); add(fd2)
|
|
|
|
* will get you an EEXIST */
|
|
|
|
static void
|
|
|
|
test_dup_fd(void *arg)
|
|
|
|
{
|
|
|
|
struct basic_test_data *data = arg;
|
|
|
|
struct event_base *base = data->base;
|
|
|
|
struct event *ev1=NULL, *ev2=NULL;
|
|
|
|
int fd, dfd=-1;
|
|
|
|
int ev1_got, ev2_got;
|
|
|
|
|
|
|
|
tt_int_op(write(data->pair[0], "Hello world",
|
|
|
|
strlen("Hello world")), >, 0);
|
|
|
|
fd = data->pair[1];
|
|
|
|
|
|
|
|
dfd = dup(fd);
|
|
|
|
tt_int_op(dfd, >=, 0);
|
|
|
|
|
|
|
|
ev1 = event_new(base, fd, EV_READ|EV_PERSIST, dfd_cb, &ev1_got);
|
|
|
|
ev2 = event_new(base, dfd, EV_READ|EV_PERSIST, dfd_cb, &ev2_got);
|
2024-04-10 15:47:57 +08:00
|
|
|
tt_assert(ev1);
|
|
|
|
tt_assert(ev2);
|
2010-10-24 11:38:29 -04:00
|
|
|
ev1_got = ev2_got = 0;
|
|
|
|
event_add(ev1, NULL);
|
|
|
|
event_add(ev2, NULL);
|
|
|
|
event_base_loop(base, EVLOOP_ONCE);
|
|
|
|
tt_int_op(ev1_got, ==, EV_READ);
|
|
|
|
tt_int_op(ev2_got, ==, EV_READ);
|
|
|
|
|
|
|
|
/* Now close and delete dfd then dispatch. We need to do the
|
|
|
|
* dispatch here so that when we add it later, we think there
|
|
|
|
* was an intermediate delete. */
|
|
|
|
close(dfd);
|
|
|
|
event_del(ev2);
|
|
|
|
ev1_got = ev2_got = 0;
|
|
|
|
event_base_loop(base, EVLOOP_ONCE);
|
|
|
|
tt_want_int_op(ev1_got, ==, EV_READ);
|
|
|
|
tt_int_op(ev2_got, ==, 0);
|
|
|
|
|
|
|
|
/* Re-duplicate the fd. We need to get the same duplicated
|
|
|
|
* value that we closed to provoke the epoll quirk. Also, we
|
|
|
|
* need to change the events to write, or else the old lingering
|
|
|
|
* read event will make the test pass whether the change was
|
|
|
|
* successful or not. */
|
|
|
|
tt_int_op(dup2(fd, dfd), ==, dfd);
|
|
|
|
event_free(ev2);
|
|
|
|
ev2 = event_new(base, dfd, EV_WRITE|EV_PERSIST, dfd_cb, &ev2_got);
|
2024-04-10 15:47:57 +08:00
|
|
|
tt_assert(ev2);
|
2010-10-24 11:38:29 -04:00
|
|
|
event_add(ev2, NULL);
|
|
|
|
ev1_got = ev2_got = 0;
|
|
|
|
event_base_loop(base, EVLOOP_ONCE);
|
|
|
|
tt_want_int_op(ev1_got, ==, EV_READ);
|
|
|
|
tt_int_op(ev2_got, ==, EV_WRITE);
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (ev1)
|
|
|
|
event_free(ev1);
|
|
|
|
if (ev2)
|
|
|
|
event_free(ev2);
|
2012-07-26 10:04:43 -04:00
|
|
|
if (dfd >= 0)
|
|
|
|
close(dfd);
|
2010-10-24 11:38:29 -04:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-02-29 15:07:31 -05:00
|
|
|
#ifdef EVENT__DISABLE_MM_REPLACEMENT
|
2009-11-18 21:16:47 +00:00
|
|
|
static void
|
|
|
|
test_mm_functions(void *arg)
|
|
|
|
{
|
2012-04-03 14:54:39 -04:00
|
|
|
tinytest_set_test_skipped_();
|
2009-11-18 21:16:47 +00:00
|
|
|
}
|
|
|
|
#else
|
2009-04-22 15:38:50 +00:00
|
|
|
static int
|
2012-02-29 15:47:16 -05:00
|
|
|
check_dummy_mem_ok(void *mem_)
|
2009-04-21 18:47:35 +00:00
|
|
|
{
|
2012-02-29 15:47:16 -05:00
|
|
|
char *mem = mem_;
|
2009-04-21 18:47:35 +00:00
|
|
|
mem -= 16;
|
|
|
|
return !memcmp(mem, "{[<guardedram>]}", 16);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *
|
|
|
|
dummy_malloc(size_t len)
|
|
|
|
{
|
|
|
|
char *mem = malloc(len+16);
|
|
|
|
memcpy(mem, "{[<guardedram>]}", 16);
|
|
|
|
return mem+16;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *
|
2012-02-29 15:47:16 -05:00
|
|
|
dummy_realloc(void *mem_, size_t len)
|
2009-04-21 18:47:35 +00:00
|
|
|
{
|
2012-02-29 15:47:16 -05:00
|
|
|
char *mem = mem_;
|
2009-04-21 18:47:35 +00:00
|
|
|
if (!mem)
|
|
|
|
return dummy_malloc(len);
|
2012-02-29 15:47:16 -05:00
|
|
|
tt_want(check_dummy_mem_ok(mem_));
|
2009-04-21 18:47:35 +00:00
|
|
|
mem -= 16;
|
|
|
|
mem = realloc(mem, len+16);
|
|
|
|
return mem+16;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-02-29 15:47:16 -05:00
|
|
|
dummy_free(void *mem_)
|
2009-04-21 18:47:35 +00:00
|
|
|
{
|
2012-02-29 15:47:16 -05:00
|
|
|
char *mem = mem_;
|
|
|
|
tt_want(check_dummy_mem_ok(mem_));
|
2009-04-21 18:47:35 +00:00
|
|
|
mem -= 16;
|
|
|
|
free(mem);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
test_mm_functions(void *arg)
|
|
|
|
{
|
|
|
|
struct event_base *b = NULL;
|
2009-04-21 18:48:05 +00:00
|
|
|
struct event_config *cfg = NULL;
|
2009-04-21 18:47:35 +00:00
|
|
|
event_set_mem_functions(dummy_malloc, dummy_realloc, dummy_free);
|
2009-04-21 18:48:05 +00:00
|
|
|
cfg = event_config_new();
|
|
|
|
event_config_avoid_method(cfg, "Nonesuch");
|
|
|
|
b = event_base_new_with_config(cfg);
|
2009-04-21 18:47:35 +00:00
|
|
|
tt_assert(b);
|
|
|
|
tt_assert(check_dummy_mem_ok(b));
|
|
|
|
end:
|
2009-04-21 18:48:05 +00:00
|
|
|
if (cfg)
|
|
|
|
event_config_free(cfg);
|
2009-04-21 18:47:35 +00:00
|
|
|
if (b)
|
|
|
|
event_base_free(b);
|
|
|
|
}
|
2009-11-18 21:16:47 +00:00
|
|
|
#endif
|
2009-04-21 18:47:35 +00:00
|
|
|
|
2009-10-30 22:43:30 +00:00
|
|
|
static void
|
2010-03-05 12:47:46 -05:00
|
|
|
many_event_cb(evutil_socket_t fd, short event, void *arg)
|
2009-10-30 22:43:30 +00:00
|
|
|
{
|
|
|
|
int *calledp = arg;
|
|
|
|
*calledp += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
test_many_events(void *arg)
|
|
|
|
{
|
2011-05-03 13:54:57 -04:00
|
|
|
/* Try 70 events that should all be ready at once. This will
|
2010-03-16 13:37:15 -04:00
|
|
|
* exercise the "resize" code on most of the backends, and will make
|
|
|
|
* sure that we can get past the 64-handle limit of some windows
|
|
|
|
* functions. */
|
|
|
|
#define MANY 70
|
2009-10-30 22:43:30 +00:00
|
|
|
|
|
|
|
struct basic_test_data *data = arg;
|
|
|
|
struct event_base *base = data->base;
|
2011-05-03 13:54:57 -04:00
|
|
|
int one_at_a_time = data->setup_data != NULL;
|
2009-10-30 22:43:30 +00:00
|
|
|
evutil_socket_t sock[MANY];
|
|
|
|
struct event *ev[MANY];
|
|
|
|
int called[MANY];
|
|
|
|
int i;
|
2011-05-03 14:22:48 -04:00
|
|
|
int loopflags = EVLOOP_NONBLOCK, evflags=0;
|
|
|
|
if (one_at_a_time) {
|
|
|
|
loopflags |= EVLOOP_ONCE;
|
|
|
|
evflags = EV_PERSIST;
|
|
|
|
}
|
2009-10-30 22:43:30 +00:00
|
|
|
|
|
|
|
memset(sock, 0xff, sizeof(sock));
|
|
|
|
memset(ev, 0, sizeof(ev));
|
|
|
|
memset(called, 0, sizeof(called));
|
|
|
|
|
|
|
|
for (i = 0; i < MANY; ++i) {
|
|
|
|
/* We need an event that will hit the backend, and that will
|
|
|
|
* be ready immediately. "Send a datagram" is an easy
|
|
|
|
* instance of that. */
|
|
|
|
sock[i] = socket(AF_INET, SOCK_DGRAM, 0);
|
|
|
|
tt_assert(sock[i] >= 0);
|
2018-11-04 00:59:33 +03:00
|
|
|
tt_assert(!evutil_make_socket_nonblocking(sock[i]));
|
2009-10-30 22:43:30 +00:00
|
|
|
called[i] = 0;
|
2011-05-03 14:22:48 -04:00
|
|
|
ev[i] = event_new(base, sock[i], EV_WRITE|evflags,
|
2011-05-03 13:54:57 -04:00
|
|
|
many_event_cb, &called[i]);
|
2024-04-10 15:47:57 +08:00
|
|
|
tt_assert(ev[i]);
|
2009-10-30 22:43:30 +00:00
|
|
|
event_add(ev[i], NULL);
|
2011-05-03 13:54:57 -04:00
|
|
|
if (one_at_a_time)
|
|
|
|
event_base_loop(base, EVLOOP_NONBLOCK|EVLOOP_ONCE);
|
2009-10-30 22:43:30 +00:00
|
|
|
}
|
|
|
|
|
2011-05-03 14:22:48 -04:00
|
|
|
event_base_loop(base, loopflags);
|
2009-10-30 22:43:30 +00:00
|
|
|
|
|
|
|
for (i = 0; i < MANY; ++i) {
|
2011-05-03 13:54:57 -04:00
|
|
|
if (one_at_a_time)
|
|
|
|
tt_int_op(called[i], ==, MANY - i + 1);
|
|
|
|
else
|
|
|
|
tt_int_op(called[i], ==, 1);
|
2009-10-30 22:43:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
end:
|
|
|
|
for (i = 0; i < MANY; ++i) {
|
|
|
|
if (ev[i])
|
|
|
|
event_free(ev[i]);
|
|
|
|
if (sock[i] >= 0)
|
2010-04-14 15:42:57 -04:00
|
|
|
evutil_closesocket(sock[i]);
|
2009-10-30 22:43:30 +00:00
|
|
|
}
|
|
|
|
#undef MANY
|
|
|
|
}
|
|
|
|
|
2010-06-21 12:23:32 -04:00
|
|
|
static void
|
|
|
|
test_struct_event_size(void *arg)
|
|
|
|
{
|
|
|
|
tt_int_op(event_get_struct_event_size(), <=, sizeof(struct event));
|
|
|
|
end:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
2013-04-26 17:46:33 -04:00
|
|
|
static void
|
|
|
|
test_get_assignment(void *arg)
|
|
|
|
{
|
|
|
|
struct basic_test_data *data = arg;
|
|
|
|
struct event_base *base = data->base;
|
|
|
|
struct event *ev1 = NULL;
|
|
|
|
const char *str = "foo";
|
|
|
|
|
|
|
|
struct event_base *b;
|
|
|
|
evutil_socket_t s;
|
|
|
|
short what;
|
|
|
|
event_callback_fn cb;
|
|
|
|
void *cb_arg;
|
|
|
|
|
|
|
|
ev1 = event_new(base, data->pair[1], EV_READ, dummy_read_cb, (void*)str);
|
|
|
|
event_get_assignment(ev1, &b, &s, &what, &cb, &cb_arg);
|
|
|
|
|
|
|
|
tt_ptr_op(b, ==, base);
|
2019-01-29 21:12:33 +03:00
|
|
|
tt_fd_op(s, ==, data->pair[1]);
|
2013-04-26 17:46:33 -04:00
|
|
|
tt_int_op(what, ==, EV_READ);
|
|
|
|
tt_ptr_op(cb, ==, dummy_read_cb);
|
|
|
|
tt_ptr_op(cb_arg, ==, str);
|
|
|
|
|
|
|
|
/* Now make sure this doesn't crash. */
|
|
|
|
event_get_assignment(ev1, NULL, NULL, NULL, NULL, NULL);
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (ev1)
|
|
|
|
event_free(ev1);
|
|
|
|
}
|
|
|
|
|
2013-04-26 13:50:22 -04:00
|
|
|
struct foreach_helper {
|
|
|
|
int count;
|
|
|
|
const struct event *ev;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
foreach_count_cb(const struct event_base *base, const struct event *ev, void *arg)
|
|
|
|
{
|
|
|
|
struct foreach_helper *h = event_get_callback_arg(ev);
|
|
|
|
struct timeval *tv = arg;
|
2013-04-26 19:14:05 -04:00
|
|
|
if (event_get_callback(ev) != timeout_cb)
|
|
|
|
return 0;
|
2013-04-26 13:50:22 -04:00
|
|
|
tt_ptr_op(event_get_base(ev), ==, base);
|
|
|
|
tt_int_op(tv->tv_sec, ==, 10);
|
|
|
|
h->ev = ev;
|
|
|
|
h->count++;
|
|
|
|
return 0;
|
|
|
|
end:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
foreach_find_cb(const struct event_base *base, const struct event *ev, void *arg)
|
|
|
|
{
|
|
|
|
const struct event **ev_out = arg;
|
|
|
|
struct foreach_helper *h = event_get_callback_arg(ev);
|
2013-04-26 19:14:05 -04:00
|
|
|
if (event_get_callback(ev) != timeout_cb)
|
|
|
|
return 0;
|
2013-04-26 13:50:22 -04:00
|
|
|
if (h->count == 99) {
|
|
|
|
*ev_out = ev;
|
|
|
|
return 101;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
test_event_foreach(void *arg)
|
|
|
|
{
|
|
|
|
struct basic_test_data *data = arg;
|
|
|
|
struct event_base *base = data->base;
|
|
|
|
struct event *ev[5];
|
|
|
|
struct foreach_helper visited[5];
|
|
|
|
int i;
|
|
|
|
struct timeval ten_sec = {10,0};
|
|
|
|
const struct event *ev_found = NULL;
|
|
|
|
|
|
|
|
for (i = 0; i < 5; ++i) {
|
|
|
|
visited[i].count = 0;
|
|
|
|
visited[i].ev = NULL;
|
|
|
|
ev[i] = event_new(base, -1, 0, timeout_cb, &visited[i]);
|
2024-04-10 15:47:57 +08:00
|
|
|
tt_assert(ev[i]);
|
2013-04-26 13:50:22 -04:00
|
|
|
}
|
|
|
|
|
2013-04-26 19:14:05 -04:00
|
|
|
tt_int_op(-1, ==, event_base_foreach_event(NULL, foreach_count_cb, NULL));
|
|
|
|
tt_int_op(-1, ==, event_base_foreach_event(base, NULL, NULL));
|
|
|
|
|
2013-04-26 13:50:22 -04:00
|
|
|
event_add(ev[0], &ten_sec);
|
|
|
|
event_add(ev[1], &ten_sec);
|
|
|
|
event_active(ev[1], EV_TIMEOUT, 1);
|
|
|
|
event_active(ev[2], EV_TIMEOUT, 1);
|
|
|
|
event_add(ev[3], &ten_sec);
|
|
|
|
/* Don't touch ev[4]. */
|
|
|
|
|
|
|
|
tt_int_op(0, ==, event_base_foreach_event(base, foreach_count_cb,
|
|
|
|
&ten_sec));
|
|
|
|
tt_int_op(1, ==, visited[0].count);
|
|
|
|
tt_int_op(1, ==, visited[1].count);
|
|
|
|
tt_int_op(1, ==, visited[2].count);
|
|
|
|
tt_int_op(1, ==, visited[3].count);
|
|
|
|
tt_ptr_op(ev[0], ==, visited[0].ev);
|
|
|
|
tt_ptr_op(ev[1], ==, visited[1].ev);
|
|
|
|
tt_ptr_op(ev[2], ==, visited[2].ev);
|
|
|
|
tt_ptr_op(ev[3], ==, visited[3].ev);
|
|
|
|
|
|
|
|
visited[2].count = 99;
|
|
|
|
tt_int_op(101, ==, event_base_foreach_event(base, foreach_find_cb,
|
|
|
|
&ev_found));
|
|
|
|
tt_ptr_op(ev_found, ==, ev[2]);
|
|
|
|
|
|
|
|
end:
|
|
|
|
for (i=0; i<5; ++i) {
|
|
|
|
event_free(ev[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-26 17:28:46 -04:00
|
|
|
static struct event_base *cached_time_base = NULL;
|
|
|
|
static int cached_time_reset = 0;
|
|
|
|
static int cached_time_sleep = 0;
|
|
|
|
static void
|
|
|
|
cache_time_cb(evutil_socket_t fd, short what, void *arg)
|
|
|
|
{
|
|
|
|
struct timeval *tv = arg;
|
|
|
|
tt_int_op(0, ==, event_base_gettimeofday_cached(cached_time_base, tv));
|
|
|
|
if (cached_time_sleep) {
|
|
|
|
struct timeval delay = { 0, 30*1000 };
|
|
|
|
evutil_usleep_(&delay);
|
|
|
|
}
|
|
|
|
if (cached_time_reset) {
|
|
|
|
event_base_update_cache_time(cached_time_base);
|
|
|
|
}
|
|
|
|
end:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
test_gettimeofday_cached(void *arg)
|
|
|
|
{
|
|
|
|
struct basic_test_data *data = arg;
|
|
|
|
struct event_config *cfg = NULL;
|
|
|
|
struct event_base *base = NULL;
|
|
|
|
struct timeval tv1, tv2, tv3, now;
|
|
|
|
struct event *ev1=NULL, *ev2=NULL, *ev3=NULL;
|
|
|
|
int cached_time_disable = strstr(data->setup_data, "disable") != NULL;
|
|
|
|
|
|
|
|
cfg = event_config_new();
|
|
|
|
if (cached_time_disable) {
|
|
|
|
event_config_set_flag(cfg, EVENT_BASE_FLAG_NO_CACHE_TIME);
|
|
|
|
}
|
|
|
|
cached_time_base = base = event_base_new_with_config(cfg);
|
2013-08-06 19:31:26 -04:00
|
|
|
tt_assert(base);
|
2013-04-26 17:28:46 -04:00
|
|
|
|
|
|
|
/* Try gettimeofday_cached outside of an event loop. */
|
|
|
|
evutil_gettimeofday(&now, NULL);
|
|
|
|
tt_int_op(0, ==, event_base_gettimeofday_cached(NULL, &tv1));
|
|
|
|
tt_int_op(0, ==, event_base_gettimeofday_cached(base, &tv2));
|
|
|
|
tt_int_op(timeval_msec_diff(&tv1, &tv2), <, 10);
|
|
|
|
tt_int_op(timeval_msec_diff(&tv1, &now), <, 10);
|
|
|
|
|
|
|
|
cached_time_reset = strstr(data->setup_data, "reset") != NULL;
|
|
|
|
cached_time_sleep = strstr(data->setup_data, "sleep") != NULL;
|
|
|
|
|
|
|
|
ev1 = event_new(base, -1, 0, cache_time_cb, &tv1);
|
|
|
|
ev2 = event_new(base, -1, 0, cache_time_cb, &tv2);
|
|
|
|
ev3 = event_new(base, -1, 0, cache_time_cb, &tv3);
|
|
|
|
|
|
|
|
event_active(ev1, EV_TIMEOUT, 1);
|
|
|
|
event_active(ev2, EV_TIMEOUT, 1);
|
|
|
|
event_active(ev3, EV_TIMEOUT, 1);
|
|
|
|
|
|
|
|
event_base_dispatch(base);
|
|
|
|
|
|
|
|
if (cached_time_reset && cached_time_sleep) {
|
|
|
|
tt_int_op(labs(timeval_msec_diff(&tv1,&tv2)), >, 10);
|
|
|
|
tt_int_op(labs(timeval_msec_diff(&tv2,&tv3)), >, 10);
|
|
|
|
} else if (cached_time_disable && cached_time_sleep) {
|
|
|
|
tt_int_op(labs(timeval_msec_diff(&tv1,&tv2)), >, 10);
|
|
|
|
tt_int_op(labs(timeval_msec_diff(&tv2,&tv3)), >, 10);
|
|
|
|
} else if (! cached_time_disable) {
|
|
|
|
tt_assert(evutil_timercmp(&tv1, &tv2, ==));
|
|
|
|
tt_assert(evutil_timercmp(&tv2, &tv3, ==));
|
|
|
|
}
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (ev1)
|
|
|
|
event_free(ev1);
|
|
|
|
if (ev2)
|
|
|
|
event_free(ev2);
|
|
|
|
if (ev3)
|
|
|
|
event_free(ev3);
|
|
|
|
if (base)
|
|
|
|
event_base_free(base);
|
|
|
|
if (cfg)
|
|
|
|
event_config_free(cfg);
|
|
|
|
}
|
|
|
|
|
2013-12-23 20:46:38 -05:00
|
|
|
static void
|
|
|
|
tabf_cb(evutil_socket_t fd, short what, void *arg)
|
|
|
|
{
|
|
|
|
int *ptr = arg;
|
|
|
|
*ptr = what;
|
|
|
|
*ptr += 0x10000;
|
|
|
|
}
|
|
|
|
|
2019-04-24 22:55:24 +02:00
|
|
|
static void
|
|
|
|
test_evmap_invalid_slots(void *arg)
|
|
|
|
{
|
|
|
|
struct basic_test_data *data = arg;
|
|
|
|
struct event_base *base = data->base;
|
|
|
|
struct event *ev1 = NULL, *ev2 = NULL;
|
|
|
|
int e1, e2;
|
|
|
|
#ifndef _WIN32
|
|
|
|
struct event *ev3 = NULL, *ev4 = NULL;
|
|
|
|
int e3, e4;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
ev1 = evsignal_new(base, -1, dummy_read_cb, (void *)base);
|
|
|
|
ev2 = evsignal_new(base, NSIG, dummy_read_cb, (void *)base);
|
|
|
|
tt_assert(ev1);
|
|
|
|
tt_assert(ev2);
|
|
|
|
e1 = event_add(ev1, NULL);
|
|
|
|
e2 = event_add(ev2, NULL);
|
|
|
|
tt_int_op(e1, !=, 0);
|
|
|
|
tt_int_op(e2, !=, 0);
|
|
|
|
#ifndef _WIN32
|
|
|
|
ev3 = event_new(base, INT_MAX, EV_READ, dummy_read_cb, (void *)base);
|
|
|
|
ev4 = event_new(base, INT_MAX / 2, EV_READ, dummy_read_cb, (void *)base);
|
|
|
|
tt_assert(ev3);
|
|
|
|
tt_assert(ev4);
|
|
|
|
e3 = event_add(ev3, NULL);
|
|
|
|
e4 = event_add(ev4, NULL);
|
|
|
|
tt_int_op(e3, !=, 0);
|
|
|
|
tt_int_op(e4, !=, 0);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
end:
|
|
|
|
event_free(ev1);
|
|
|
|
event_free(ev2);
|
|
|
|
#ifndef _WIN32
|
|
|
|
event_free(ev3);
|
|
|
|
event_free(ev4);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2013-12-23 20:46:38 -05:00
|
|
|
static void
|
|
|
|
test_active_by_fd(void *arg)
|
|
|
|
{
|
|
|
|
struct basic_test_data *data = arg;
|
|
|
|
struct event_base *base = data->base;
|
|
|
|
struct event *ev1 = NULL, *ev2 = NULL, *ev3 = NULL, *ev4 = NULL;
|
|
|
|
int e1,e2,e3,e4;
|
|
|
|
#ifndef _WIN32
|
|
|
|
struct event *evsig = NULL;
|
|
|
|
int es;
|
|
|
|
#endif
|
|
|
|
struct timeval tenmin = { 600, 0 };
|
|
|
|
|
|
|
|
/* Ensure no crash on nonexistent FD. */
|
|
|
|
event_base_active_by_fd(base, 1000, EV_READ);
|
|
|
|
|
|
|
|
/* Ensure no crash on bogus FD. */
|
|
|
|
event_base_active_by_fd(base, -1, EV_READ);
|
|
|
|
|
|
|
|
/* Ensure no crash on nonexistent/bogus signal. */
|
|
|
|
event_base_active_by_signal(base, 1000);
|
|
|
|
event_base_active_by_signal(base, -1);
|
|
|
|
|
|
|
|
event_base_assert_ok_(base);
|
|
|
|
|
|
|
|
e1 = e2 = e3 = e4 = 0;
|
|
|
|
ev1 = event_new(base, data->pair[0], EV_READ, tabf_cb, &e1);
|
|
|
|
ev2 = event_new(base, data->pair[0], EV_WRITE, tabf_cb, &e2);
|
|
|
|
ev3 = event_new(base, data->pair[1], EV_READ, tabf_cb, &e3);
|
|
|
|
ev4 = event_new(base, data->pair[1], EV_READ, tabf_cb, &e4);
|
2014-01-08 11:51:22 -05:00
|
|
|
tt_assert(ev1);
|
|
|
|
tt_assert(ev2);
|
|
|
|
tt_assert(ev3);
|
|
|
|
tt_assert(ev4);
|
2013-12-23 20:46:38 -05:00
|
|
|
#ifndef _WIN32
|
|
|
|
evsig = event_new(base, SIGHUP, EV_SIGNAL, tabf_cb, &es);
|
2014-01-08 11:51:22 -05:00
|
|
|
tt_assert(evsig);
|
2013-12-23 20:46:38 -05:00
|
|
|
event_add(evsig, &tenmin);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
event_add(ev1, &tenmin);
|
|
|
|
event_add(ev2, NULL);
|
|
|
|
event_add(ev3, NULL);
|
|
|
|
event_add(ev4, &tenmin);
|
|
|
|
|
|
|
|
|
|
|
|
event_base_assert_ok_(base);
|
|
|
|
|
|
|
|
/* Trigger 2, 3, 4 */
|
|
|
|
event_base_active_by_fd(base, data->pair[0], EV_WRITE);
|
|
|
|
event_base_active_by_fd(base, data->pair[1], EV_READ);
|
2014-12-09 21:43:18 -05:00
|
|
|
event_base_active_by_fd(base, data->pair[1], EV_TIMEOUT);
|
2013-12-23 20:46:38 -05:00
|
|
|
#ifndef _WIN32
|
|
|
|
event_base_active_by_signal(base, SIGHUP);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
event_base_assert_ok_(base);
|
|
|
|
|
|
|
|
event_base_loop(base, EVLOOP_ONCE);
|
|
|
|
|
|
|
|
tt_int_op(e1, ==, 0);
|
|
|
|
tt_int_op(e2, ==, EV_WRITE | 0x10000);
|
|
|
|
tt_int_op(e3, ==, EV_READ | 0x10000);
|
|
|
|
/* Mask out EV_WRITE here, since it could be genuinely writeable. */
|
2014-12-09 21:43:18 -05:00
|
|
|
tt_int_op((e4 & ~EV_WRITE), ==, EV_READ | EV_TIMEOUT | 0x10000);
|
2013-12-23 20:46:38 -05:00
|
|
|
#ifndef _WIN32
|
|
|
|
tt_int_op(es, ==, EV_SIGNAL | 0x10000);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (ev1)
|
|
|
|
event_free(ev1);
|
|
|
|
if (ev2)
|
|
|
|
event_free(ev2);
|
|
|
|
if (ev3)
|
|
|
|
event_free(ev3);
|
|
|
|
if (ev4)
|
|
|
|
event_free(ev4);
|
|
|
|
#ifndef _WIN32
|
|
|
|
if (evsig)
|
|
|
|
event_free(evsig);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2009-04-21 18:45:59 +00:00
|
|
|
struct testcase_t main_testcases[] = {
|
2010-02-18 17:41:15 -05:00
|
|
|
/* Some converted-over tests */
|
|
|
|
{ "methods", test_methods, TT_FORK, NULL, NULL },
|
2009-04-21 18:46:11 +00:00
|
|
|
{ "version", test_version, 0, NULL, NULL },
|
2009-10-27 06:47:25 +00:00
|
|
|
BASIC(base_features, TT_FORK|TT_NO_LOGS),
|
2009-04-28 19:08:27 +00:00
|
|
|
{ "base_environ", test_base_environ, TT_FORK, NULL, NULL },
|
2009-01-29 23:19:57 +00:00
|
|
|
|
2009-07-14 18:49:42 +00:00
|
|
|
BASIC(event_base_new, TT_FORK|TT_NEED_SOCKETPAIR),
|
|
|
|
BASIC(free_active_base, TT_FORK|TT_NEED_SOCKETPAIR),
|
|
|
|
|
2009-07-21 19:20:44 +00:00
|
|
|
BASIC(manipulate_active_events, TT_FORK|TT_NEED_BASE),
|
2012-03-13 21:42:40 +02:00
|
|
|
BASIC(event_new_selfarg, TT_FORK|TT_NEED_BASE),
|
|
|
|
BASIC(event_assign_selfarg, TT_FORK|TT_NEED_BASE),
|
2013-07-02 16:01:02 -04:00
|
|
|
BASIC(event_base_get_num_events, TT_FORK|TT_NEED_BASE),
|
2014-01-05 16:30:35 -05:00
|
|
|
BASIC(event_base_get_max_events, TT_FORK|TT_NEED_BASE),
|
2019-04-24 22:55:24 +02:00
|
|
|
BASIC(evmap_invalid_slots, TT_FORK|TT_NEED_BASE),
|
2009-07-21 19:20:44 +00:00
|
|
|
|
2009-10-27 04:25:45 +00:00
|
|
|
BASIC(bad_assign, TT_FORK|TT_NEED_BASE|TT_NO_LOGS),
|
2010-03-21 13:28:48 -04:00
|
|
|
BASIC(bad_reentrant, TT_FORK|TT_NEED_BASE|TT_NO_LOGS),
|
2018-11-20 11:46:44 +03:00
|
|
|
BASIC(active_later, TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR|TT_RETRIABLE),
|
2012-11-16 16:15:03 -05:00
|
|
|
BASIC(event_remove_timeout, TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR),
|
2024-10-27 16:41:12 +01:00
|
|
|
BASIC(event_timeout_lost, TT_FORK|TT_NEED_BASE),
|
2009-10-27 04:25:45 +00:00
|
|
|
|
2012-04-06 03:00:40 -04:00
|
|
|
/* These are still using the old API */
|
2010-02-18 17:41:15 -05:00
|
|
|
LEGACY(persistent_timeout, TT_FORK|TT_NEED_BASE),
|
2012-04-19 00:25:12 -04:00
|
|
|
{ "persistent_timeout_jump", test_persistent_timeout_jump, TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
|
2010-02-23 23:55:32 -05:00
|
|
|
{ "persistent_active_timeout", test_persistent_active_timeout,
|
2018-11-20 11:46:44 +03:00
|
|
|
TT_FORK|TT_NEED_BASE|TT_RETRIABLE, &basic_setup, NULL },
|
2010-02-18 17:41:15 -05:00
|
|
|
LEGACY(priorities, TT_FORK|TT_NEED_BASE),
|
2012-04-30 17:30:48 -04:00
|
|
|
BASIC(priority_active_inversion, TT_FORK|TT_NEED_BASE),
|
2020-01-23 21:34:18 +03:00
|
|
|
{ "common_timeout", test_common_timeout, TT_FORK|TT_NEED_BASE|TT_RETRIABLE,
|
2009-11-09 17:16:30 +00:00
|
|
|
&basic_setup, NULL },
|
2009-01-29 23:19:57 +00:00
|
|
|
|
2010-02-18 17:41:15 -05:00
|
|
|
/* These legacy tests may not all need all of these flags. */
|
|
|
|
LEGACY(simpleread, TT_ISOLATED),
|
|
|
|
LEGACY(simpleread_multiple, TT_ISOLATED),
|
|
|
|
LEGACY(simplewrite, TT_ISOLATED),
|
2020-04-09 00:14:26 +03:00
|
|
|
{ "simpleclose_rw", test_simpleclose_rw, TT_FORK, &basic_setup, NULL },
|
2020-04-09 00:30:57 +03:00
|
|
|
/* simpleclose */
|
|
|
|
{ "simpleclose_close", test_simpleclose,
|
|
|
|
TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE,
|
|
|
|
&basic_setup, (void *)"close" },
|
|
|
|
{ "simpleclose_shutdown", test_simpleclose,
|
|
|
|
TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE,
|
|
|
|
&basic_setup, (void *)"shutdown" },
|
|
|
|
/* simpleclose_*_persist */
|
|
|
|
{ "simpleclose_close_persist", test_simpleclose,
|
|
|
|
TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE,
|
|
|
|
&basic_setup, (void *)"close_persist" },
|
|
|
|
{ "simpleclose_shutdown_persist", test_simpleclose,
|
|
|
|
TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE,
|
|
|
|
&basic_setup, (void *)"shutdown_persist" },
|
|
|
|
/* simpleclose_*_et */
|
|
|
|
{ "simpleclose_close_et", test_simpleclose,
|
|
|
|
TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE,
|
|
|
|
&basic_setup, (void *)"close_ET" },
|
|
|
|
{ "simpleclose_shutdown_et", test_simpleclose,
|
|
|
|
TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE,
|
|
|
|
&basic_setup, (void *)"shutdown_ET" },
|
|
|
|
/* simpleclose_*_persist_et */
|
|
|
|
{ "simpleclose_close_persist_et", test_simpleclose,
|
|
|
|
TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE,
|
|
|
|
&basic_setup, (void *)"close_persist_ET" },
|
|
|
|
{ "simpleclose_shutdown_persist_et", test_simpleclose,
|
|
|
|
TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE,
|
|
|
|
&basic_setup, (void *)"shutdown_persist_ET" },
|
2010-02-18 17:41:15 -05:00
|
|
|
LEGACY(multiple, TT_ISOLATED),
|
|
|
|
LEGACY(persistent, TT_ISOLATED),
|
|
|
|
LEGACY(combined, TT_ISOLATED),
|
|
|
|
LEGACY(simpletimeout, TT_ISOLATED),
|
|
|
|
LEGACY(loopbreak, TT_ISOLATED),
|
|
|
|
LEGACY(loopexit, TT_ISOLATED),
|
2009-01-29 23:19:57 +00:00
|
|
|
LEGACY(loopexit_multiple, TT_ISOLATED),
|
2019-01-12 13:58:50 +03:00
|
|
|
{ "nonpersist_readd", test_nonpersist_readd, TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE, &basic_setup, NULL },
|
2009-01-29 23:19:57 +00:00
|
|
|
LEGACY(multiple_events_for_same_fd, TT_ISOLATED),
|
|
|
|
LEGACY(want_only_once, TT_ISOLATED),
|
2009-04-21 18:47:02 +00:00
|
|
|
{ "event_once", test_event_once, TT_ISOLATED, &basic_setup, NULL },
|
2012-11-16 10:17:34 -05:00
|
|
|
{ "event_once_never", test_event_once_never, TT_ISOLATED, &basic_setup, NULL },
|
2009-04-21 18:47:02 +00:00
|
|
|
{ "event_pending", test_event_pending, TT_ISOLATED, &basic_setup,
|
|
|
|
NULL },
|
2016-07-15 02:27:23 +02:00
|
|
|
{ "event_closed_fd_poll", test_event_closed_fd_poll, TT_ISOLATED, &basic_setup,
|
|
|
|
NULL },
|
|
|
|
|
2011-05-25 19:50:56 -04:00
|
|
|
#ifndef _WIN32
|
2010-10-24 11:38:29 -04:00
|
|
|
{ "dup_fd", test_dup_fd, TT_ISOLATED, &basic_setup, NULL },
|
|
|
|
#endif
|
2009-04-21 18:47:35 +00:00
|
|
|
{ "mm_functions", test_mm_functions, TT_FORK, NULL, NULL },
|
2011-05-03 13:54:57 -04:00
|
|
|
{ "many_events", test_many_events, TT_ISOLATED, &basic_setup, NULL },
|
|
|
|
{ "many_events_slow_add", test_many_events, TT_ISOLATED, &basic_setup, (void*)1 },
|
2004-07-30 05:00:44 +00:00
|
|
|
|
2010-06-21 12:23:32 -04:00
|
|
|
{ "struct_event_size", test_struct_event_size, 0, NULL, NULL },
|
2013-04-26 17:46:33 -04:00
|
|
|
BASIC(get_assignment, TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR),
|
2010-06-21 12:23:32 -04:00
|
|
|
|
2013-04-26 13:50:22 -04:00
|
|
|
BASIC(event_foreach, TT_FORK|TT_NEED_BASE),
|
2013-04-26 17:28:46 -04:00
|
|
|
{ "gettimeofday_cached", test_gettimeofday_cached, TT_FORK, &basic_setup, (void*)"" },
|
|
|
|
{ "gettimeofday_cached_sleep", test_gettimeofday_cached, TT_FORK, &basic_setup, (void*)"sleep" },
|
|
|
|
{ "gettimeofday_cached_reset", test_gettimeofday_cached, TT_FORK, &basic_setup, (void*)"sleep reset" },
|
|
|
|
{ "gettimeofday_cached_disabled", test_gettimeofday_cached, TT_FORK, &basic_setup, (void*)"sleep disable" },
|
|
|
|
{ "gettimeofday_cached_disabled_nosleep", test_gettimeofday_cached, TT_FORK, &basic_setup, (void*)"disable" },
|
2013-04-26 13:50:22 -04:00
|
|
|
|
2013-12-23 20:46:38 -05:00
|
|
|
BASIC(active_by_fd, TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR),
|
|
|
|
|
2019-02-24 17:25:31 +03:00
|
|
|
#ifndef _WIN32
|
2010-02-18 17:41:15 -05:00
|
|
|
LEGACY(fork, TT_ISOLATED),
|
2004-05-24 00:19:52 +00:00
|
|
|
#endif
|
2020-01-13 22:24:54 +03:00
|
|
|
|
2023-02-12 21:39:04 +01:00
|
|
|
#ifndef EVENT__DISABLE_THREAD_SUPPORT
|
2018-11-20 11:46:44 +03:00
|
|
|
LEGACY(del_wait, TT_ISOLATED|TT_NEED_THREADS|TT_RETRIABLE),
|
2018-04-24 00:59:11 +03:00
|
|
|
LEGACY(del_notify, TT_ISOLATED|TT_NEED_THREADS),
|
2024-10-20 23:52:33 +02:00
|
|
|
BASIC(del_timeout_notify, TT_NEED_THREADS|TT_FORK|TT_NEED_BASE),
|
2016-01-03 00:23:22 +03:00
|
|
|
#endif
|
|
|
|
|
2010-02-18 17:41:15 -05:00
|
|
|
END_OF_TESTCASES
|
2009-07-20 14:55:51 +00:00
|
|
|
};
|
2004-05-24 00:19:52 +00:00
|
|
|
|
2009-07-20 14:55:51 +00:00
|
|
|
struct testcase_t evtag_testcases[] = {
|
|
|
|
{ "int", evtag_int_test, TT_FORK, NULL, NULL },
|
|
|
|
{ "fuzz", evtag_fuzz, TT_FORK, NULL, NULL },
|
|
|
|
{ "encoding", evtag_tag_encoding, TT_FORK, NULL, NULL },
|
2009-10-29 16:35:20 +00:00
|
|
|
{ "peek", evtag_test_peek, 0, NULL, NULL },
|
2009-01-31 18:36:47 +00:00
|
|
|
|
2009-07-20 14:55:51 +00:00
|
|
|
END_OF_TESTCASES
|
2009-01-29 23:19:57 +00:00
|
|
|
};
|
|
|
|
|
test: retry signal tests with SIGALRM no OSX
By some reason even after first ALRM signal received and event loop
returned it is possible to recieve an ALRM one more time (at least one):
% yes signal/simple_signal.. | head -n 1000 | xargs -I{} -P10 sh -c 'EVENT_DEBUG_LOGGING_ALL= bin/regress --timeout 0 --verbose {} >& /tmp/test.$SECONDS.$RANDOM.log'
% cat /tmp/test.0.18384.log
signal/simple_signal: [forking] [debug] event_add: event: 0x16d70f368 (fd 14), call 0x102704ae8
[debug] evsig_ensure_saved_: evsignal (14) >= sh_old_max (0), resizing
OK /Users/ec2-user/libevent/test/regress.c:1086: assert(setitimer(ITIMER_REAL, &itv, NULL) == 0): 0 vs 0[debug] kq_dispatch: kevent reports 1
[debug] event_active: 0x16d70f368 (fd 14), res 8, callback 0x102704ae8
[debug] event_process_active: event: 0x16d70f368, call 0x102704ae8
[debug] event_del: 0x16d70f368 (fd 14), callback 0x102704ae8
[debug] event_base_loop: no events registered.
FAIL /Users/ec2-user/libevent/test/regress.c:1062: ALRM received not from event loop![debug] event_del: 0x16d70f368 (fd 14), callback 0x102704ae8
[debug] event_base_free_: 0 events freed
signal/simple_signal: exited with 0 (0)
[FAILED signal/simple_signal (0 retries)]
signal/simple_signal_re_order: [forking] [debug] event_add: event: 0x16d70f368 (fd 14), call 0x102704ae8
[debug] evsig_ensure_saved_: evsignal (14) >= sh_old_max (0), resizing
[debug] event_del: 0x16d70f368 (fd 14), callback 0x102704ae8
[debug] event_add: event: 0x16d70f368 (fd 14), call 0x102704ae8
OK /Users/ec2-user/libevent/test/regress.c:1086: assert(setitimer(ITIMER_REAL, &itv, NULL) == 0): 0 vs 0[debug] kq_dispatch: kevent reports 1
[debug] event_active: 0x16d70f368 (fd 14), res 8, callback 0x102704ae8
[debug] event_process_active: event: 0x16d70f368, call 0x102704ae8
[debug] event_del: 0x16d70f368 (fd 14), callback 0x102704ae8
[debug] event_base_loop: no events registered.
[debug] event_del: 0x16d70f368 (fd 14), callback 0x102704ae8
[debug] event_base_free_: 0 events freed
signal/simple_signal_re_order: exited with 0 (0)
1/2 TESTS FAILED. (0 skipped)
Also note, that the problem not only when I run two tests, but only one
as well:
% bin/regress --timeout 0 --repeat 1000 --verbose --no-fork signal/simple_signal >/tmp/test2.log 2>&1
signal/simple_signal:
OK /Users/ec2-user/libevent/test/regress.c:1086: assert(setitimer(ITIMER_REAL, &itv, NULL) == 0): 0 vs 0
signal/simple_signal:
OK /Users/ec2-user/libevent/test/regress.c:1086: assert(setitimer(ITIMER_REAL, &itv, NULL) == 0): 0 vs 0
FAIL /Users/ec2-user/libevent/test/regress.c:1062: ALRM received not from event loop!
I've tried to run under "ktrace trace -Ss -f C4,S0x010c -c" but of
course it does not fails under it (dtruss by some reason did not work
for me).
P.S. Also remove one TT_RETRIABLE for one test, since only setitimer()
causes this.
2024-10-28 22:20:10 +01:00
|
|
|
/* Apparently there is a bug in OSX that leads to subsequent ALRM signal
|
|
|
|
* delievered even though it_interval is set to 0, so let's retry the tests */
|
2024-10-28 08:34:12 +01:00
|
|
|
#if defined(__APPLE__)
|
2021-09-19 12:23:48 +03:00
|
|
|
#define RETRY_ON_DARWIN TT_RETRIABLE
|
|
|
|
#else
|
|
|
|
#define RETRY_ON_DARWIN 0
|
|
|
|
#endif
|
|
|
|
|
2009-01-29 23:19:57 +00:00
|
|
|
struct testcase_t signal_testcases[] = {
|
2011-05-25 19:50:56 -04:00
|
|
|
#ifndef _WIN32
|
2024-10-28 08:23:48 +01:00
|
|
|
LEGACY(simple_signal, TT_ISOLATED|RETRY_ON_DARWIN),
|
|
|
|
LEGACY(simple_signal_re_order, TT_ISOLATED|RETRY_ON_DARWIN),
|
2021-09-19 12:23:48 +03:00
|
|
|
LEGACY(multiplesignal, TT_ISOLATED|RETRY_ON_DARWIN),
|
2009-01-29 23:19:57 +00:00
|
|
|
LEGACY(immediatesignal, TT_ISOLATED),
|
2010-02-18 17:41:15 -05:00
|
|
|
LEGACY(signal_dealloc, TT_ISOLATED),
|
2024-02-18 16:06:28 +01:00
|
|
|
LEGACY(signal_timeout, TT_ISOLATED),
|
2009-01-29 23:19:57 +00:00
|
|
|
LEGACY(signal_pipeloss, TT_ISOLATED),
|
2010-09-15 01:08:39 -04:00
|
|
|
LEGACY(signal_switchbase, TT_ISOLATED|TT_NO_LOGS),
|
2009-01-29 23:19:57 +00:00
|
|
|
LEGACY(signal_restore, TT_ISOLATED),
|
|
|
|
LEGACY(signal_assert, TT_ISOLATED),
|
|
|
|
LEGACY(signal_while_processing, TT_ISOLATED),
|
test: retry signal tests with SIGALRM no OSX
By some reason even after first ALRM signal received and event loop
returned it is possible to recieve an ALRM one more time (at least one):
% yes signal/simple_signal.. | head -n 1000 | xargs -I{} -P10 sh -c 'EVENT_DEBUG_LOGGING_ALL= bin/regress --timeout 0 --verbose {} >& /tmp/test.$SECONDS.$RANDOM.log'
% cat /tmp/test.0.18384.log
signal/simple_signal: [forking] [debug] event_add: event: 0x16d70f368 (fd 14), call 0x102704ae8
[debug] evsig_ensure_saved_: evsignal (14) >= sh_old_max (0), resizing
OK /Users/ec2-user/libevent/test/regress.c:1086: assert(setitimer(ITIMER_REAL, &itv, NULL) == 0): 0 vs 0[debug] kq_dispatch: kevent reports 1
[debug] event_active: 0x16d70f368 (fd 14), res 8, callback 0x102704ae8
[debug] event_process_active: event: 0x16d70f368, call 0x102704ae8
[debug] event_del: 0x16d70f368 (fd 14), callback 0x102704ae8
[debug] event_base_loop: no events registered.
FAIL /Users/ec2-user/libevent/test/regress.c:1062: ALRM received not from event loop![debug] event_del: 0x16d70f368 (fd 14), callback 0x102704ae8
[debug] event_base_free_: 0 events freed
signal/simple_signal: exited with 0 (0)
[FAILED signal/simple_signal (0 retries)]
signal/simple_signal_re_order: [forking] [debug] event_add: event: 0x16d70f368 (fd 14), call 0x102704ae8
[debug] evsig_ensure_saved_: evsignal (14) >= sh_old_max (0), resizing
[debug] event_del: 0x16d70f368 (fd 14), callback 0x102704ae8
[debug] event_add: event: 0x16d70f368 (fd 14), call 0x102704ae8
OK /Users/ec2-user/libevent/test/regress.c:1086: assert(setitimer(ITIMER_REAL, &itv, NULL) == 0): 0 vs 0[debug] kq_dispatch: kevent reports 1
[debug] event_active: 0x16d70f368 (fd 14), res 8, callback 0x102704ae8
[debug] event_process_active: event: 0x16d70f368, call 0x102704ae8
[debug] event_del: 0x16d70f368 (fd 14), callback 0x102704ae8
[debug] event_base_loop: no events registered.
[debug] event_del: 0x16d70f368 (fd 14), callback 0x102704ae8
[debug] event_base_free_: 0 events freed
signal/simple_signal_re_order: exited with 0 (0)
1/2 TESTS FAILED. (0 skipped)
Also note, that the problem not only when I run two tests, but only one
as well:
% bin/regress --timeout 0 --repeat 1000 --verbose --no-fork signal/simple_signal >/tmp/test2.log 2>&1
signal/simple_signal:
OK /Users/ec2-user/libevent/test/regress.c:1086: assert(setitimer(ITIMER_REAL, &itv, NULL) == 0): 0 vs 0
signal/simple_signal:
OK /Users/ec2-user/libevent/test/regress.c:1086: assert(setitimer(ITIMER_REAL, &itv, NULL) == 0): 0 vs 0
FAIL /Users/ec2-user/libevent/test/regress.c:1062: ALRM received not from event loop!
I've tried to run under "ktrace trace -Ss -f C4,S0x010c -c" but of
course it does not fails under it (dtruss by some reason did not work
for me).
P.S. Also remove one TT_RETRIABLE for one test, since only setitimer()
causes this.
2024-10-28 22:20:10 +01:00
|
|
|
BASIC(signal_free_in_callback, TT_FORK|TT_NEED_BASE),
|
2008-12-19 22:42:51 +00:00
|
|
|
#endif
|
2010-02-18 17:41:15 -05:00
|
|
|
END_OF_TESTCASES
|
2009-01-29 23:19:57 +00:00
|
|
|
};
|
2008-05-08 05:33:15 +00:00
|
|
|
|