mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-06 18:58:09 -04:00
Convert and expand free_active_base/event_base_new tests to avoid dbl-free. Patch from Zack Weinberg
svn:r1342
This commit is contained in:
parent
6b4b77a265
commit
e224321c64
120
test/regress.c
120
test/regress.c
@ -99,6 +99,13 @@ static struct timeval tcalled;
|
||||
#define read(fd,buf,len) recv((fd),(buf),(len),0)
|
||||
#endif
|
||||
|
||||
struct basic_cb_args
|
||||
{
|
||||
struct event_base *eb;
|
||||
struct event *ev;
|
||||
unsigned int callcount;
|
||||
};
|
||||
|
||||
static void
|
||||
simple_read_cb(int fd, short event, void *arg)
|
||||
{
|
||||
@ -118,6 +125,45 @@ simple_read_cb(int fd, short event, void *arg)
|
||||
called++;
|
||||
}
|
||||
|
||||
static void
|
||||
basic_read_cb(int fd, short event, void *data)
|
||||
{
|
||||
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++) {
|
||||
case 0: /* first call: expect to read data; cycle */
|
||||
if (len > 0)
|
||||
return;
|
||||
|
||||
tt_fail_msg("EOF before data read");
|
||||
break;
|
||||
|
||||
case 1: /* second call: expect EOF; stop */
|
||||
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
|
||||
dummy_read_cb(int fd, short event, void *arg)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
simple_write_cb(int fd, short event, void *arg)
|
||||
{
|
||||
@ -893,43 +939,62 @@ test_signal_while_processing(void)
|
||||
#endif
|
||||
|
||||
static void
|
||||
test_free_active_base(void)
|
||||
test_free_active_base(void *ptr)
|
||||
{
|
||||
struct basic_test_data *data = ptr;
|
||||
struct event_base *base1;
|
||||
struct event ev1;
|
||||
setup_test("Free active base: ");
|
||||
|
||||
base1 = event_init();
|
||||
event_set(&ev1, pair[1], EV_READ, simple_read_cb, &ev1);
|
||||
event_base_set(base1, &ev1);
|
||||
event_add(&ev1, NULL);
|
||||
/* event_del(&ev1); */
|
||||
event_base_free(base1);
|
||||
test_ok = 1;
|
||||
cleanup_test();
|
||||
event_base_free(global_base);
|
||||
global_base = event_init();
|
||||
if (base1) {
|
||||
struct event ev1;
|
||||
event_assign(&ev1, base1, data->pair[1], EV_READ,
|
||||
dummy_read_cb, NULL);
|
||||
event_add(&ev1, NULL);
|
||||
event_base_free(base1); /* should not crash */
|
||||
} else {
|
||||
tt_fail_msg("failed to create event_base for test");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
test_event_base_new(void)
|
||||
test_event_base_new(void *ptr)
|
||||
{
|
||||
struct event_base *base;
|
||||
struct basic_test_data *data = ptr;
|
||||
struct event_base *base = 0;
|
||||
struct event ev1;
|
||||
setup_test("Event base new: ");
|
||||
struct basic_cb_args args;
|
||||
|
||||
write(pair[0], TEST1, strlen(TEST1)+1);
|
||||
shutdown(pair[0], SHUT_WR);
|
||||
int towrite = strlen(TEST1)+1;
|
||||
int len = write(data->pair[0], TEST1, towrite);
|
||||
|
||||
if (len < 0)
|
||||
tt_abort_perror("initial write");
|
||||
else if (len != towrite)
|
||||
tt_abort_printf(("initial write fell short (%d of %d bytes)",
|
||||
len, towrite));
|
||||
|
||||
if (shutdown(data->pair[0], SHUT_WR))
|
||||
tt_abort_perror("initial write shutdown");
|
||||
|
||||
base = event_base_new();
|
||||
event_set(&ev1, pair[1], EV_READ, simple_read_cb, &ev1);
|
||||
event_base_set(base, &ev1);
|
||||
event_add(&ev1, NULL);
|
||||
if (!base)
|
||||
tt_abort_msg("failed to create event base");
|
||||
|
||||
event_base_dispatch(base);
|
||||
args.eb = base;
|
||||
args.ev = &ev1;
|
||||
args.callcount = 0;
|
||||
event_assign(&ev1, base, data->pair[1],
|
||||
EV_READ|EV_PERSIST, basic_read_cb, &args);
|
||||
|
||||
event_base_free(base);
|
||||
test_ok = 1;
|
||||
cleanup_test();
|
||||
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);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1484,6 +1549,7 @@ test_base_environ(void *arg)
|
||||
tt_assert(base);
|
||||
|
||||
defaultname = event_base_get_method(base);
|
||||
TT_BLATHER(("default is <%s>", defaultname));
|
||||
event_base_free(base);
|
||||
base = NULL;
|
||||
|
||||
@ -1676,13 +1742,13 @@ struct testcase_t main_testcases[] = {
|
||||
{ "base_features", test_base_features, TT_FORK, NULL, NULL },
|
||||
{ "base_environ", test_base_environ, TT_FORK, NULL, NULL },
|
||||
|
||||
BASIC(event_base_new, TT_FORK|TT_NEED_SOCKETPAIR),
|
||||
BASIC(free_active_base, TT_FORK|TT_NEED_SOCKETPAIR),
|
||||
|
||||
/* These are still using the old API */
|
||||
LEGACY(persistent_timeout, TT_FORK|TT_NEED_BASE),
|
||||
LEGACY(priorities, TT_FORK|TT_NEED_BASE),
|
||||
|
||||
LEGACY(free_active_base, TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR),
|
||||
LEGACY(event_base_new, TT_FORK|TT_NEED_SOCKETPAIR),
|
||||
|
||||
/* These legacy tests may not all need all of these flags. */
|
||||
LEGACY(simpleread, TT_ISOLATED),
|
||||
LEGACY(simpleread_multiple, TT_ISOLATED),
|
||||
|
@ -79,6 +79,9 @@ void run_legacy_test_fn(void *ptr);
|
||||
/* All the flags that a legacy test needs. */
|
||||
#define TT_ISOLATED TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE
|
||||
|
||||
#define BASIC(name,flags) \
|
||||
{ #name, test_## name, flags, &basic_setup, NULL }
|
||||
|
||||
#define LEGACY(name,flags) \
|
||||
{ #name, run_legacy_test_fn, flags|TT_LEGACY, &legacy_setup, \
|
||||
test_## name }
|
||||
|
Loading…
x
Reference in New Issue
Block a user