aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorHaibo Huang <hhb@google.com>2020-07-14 18:31:56 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2020-07-14 18:31:56 +0000
commit884d7a39094e590c9dc58f865b068f40694c6a49 (patch)
tree53915fc3eafdda183ab94c84e85ad7d7107afc6a /test
parentc4d7c4bdab4c5587b42073d60fb6aca6e335d76e (diff)
parent023ea039b9fada42e0cbbefcd75858a855a6130a (diff)
downloadplatform_external_libevent-master.tar.gz
platform_external_libevent-master.tar.bz2
platform_external_libevent-master.zip
Upgrade libevent to release-2.1.12-stable am: f0077b80a0 am: 023ea039b9HEADmaster
Original change: https://android-review.googlesource.com/c/platform/external/libevent/+/1360893 Change-Id: Iee716ec96a55737a04463c7b84c929c2e6418c54
Diffstat (limited to 'test')
-rw-r--r--test/bench.c33
-rw-r--r--test/regress.c106
-rw-r--r--test/regress.gen.c66
-rw-r--r--test/regress.gen.h2
-rw-r--r--test/regress.h1
-rw-r--r--test/regress_buffer.c98
-rw-r--r--test/regress_bufferevent.c60
-rw-r--r--test/regress_dns.c119
-rw-r--r--test/regress_et.c2
-rw-r--r--test/regress_finalize.c48
-rw-r--r--test/regress_http.c65
-rw-r--r--test/regress_main.c57
-rw-r--r--test/regress_ssl.c13
-rw-r--r--test/regress_testutils.c2
-rw-r--r--test/regress_thread.h33
-rw-r--r--test/regress_util.c107
-rw-r--r--test/test-changelist.c4
-rw-r--r--test/test-closed.c1
-rw-r--r--test/test-eof.c4
-rw-r--r--test/test-init.c2
-rw-r--r--test/test-ratelim.c87
-rw-r--r--test/test-time.c25
-rw-r--r--test/test-weof.c4
-rw-r--r--test/tinytest.c125
-rw-r--r--test/tinytest_macros.h4
25 files changed, 867 insertions, 201 deletions
diff --git a/test/bench.c b/test/bench.c
index 3a6886d..f2af4d3 100644
--- a/test/bench.c
+++ b/test/bench.c
@@ -70,6 +70,7 @@ static int writes, failures;
static evutil_socket_t *pipes;
static int num_pipes, num_active, num_writes;
static struct event *events;
+static struct event_base *base;
static void
@@ -105,11 +106,11 @@ run_once(void)
for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2) {
if (event_initialized(&events[i]))
event_del(&events[i]);
- event_set(&events[i], cp[0], EV_READ | EV_PERSIST, read_cb, (void *)(ev_intptr_t) i);
+ event_assign(&events[i], base, cp[0], EV_READ | EV_PERSIST, read_cb, (void *)(ev_intptr_t) i);
event_add(&events[i], NULL);
}
- event_loop(EVLOOP_ONCE | EVLOOP_NONBLOCK);
+ event_base_loop(base, EVLOOP_ONCE | EVLOOP_NONBLOCK);
fired = 0;
space = num_pipes / num_active;
@@ -123,7 +124,7 @@ run_once(void)
int xcount = 0;
evutil_gettimeofday(&ts, NULL);
do {
- event_loop(EVLOOP_ONCE | EVLOOP_NONBLOCK);
+ event_base_loop(base, EVLOOP_ONCE | EVLOOP_NONBLOCK);
xcount++;
} while (count != fired);
evutil_gettimeofday(&te, NULL);
@@ -147,6 +148,9 @@ main(int argc, char **argv)
int i, c;
struct timeval *tv;
evutil_socket_t *cp;
+ const char **methods;
+ const char *method = NULL;
+ struct event_config *cfg = NULL;
#ifdef _WIN32
WSADATA WSAData;
@@ -155,7 +159,7 @@ main(int argc, char **argv)
num_pipes = 100;
num_active = 1;
num_writes = num_pipes;
- while ((c = getopt(argc, argv, "n:a:w:")) != -1) {
+ while ((c = getopt(argc, argv, "n:a:w:m:l")) != -1) {
switch (c) {
case 'n':
num_pipes = atoi(optarg);
@@ -166,6 +170,16 @@ main(int argc, char **argv)
case 'w':
num_writes = atoi(optarg);
break;
+ case 'm':
+ method = optarg;
+ break;
+ case 'l':
+ methods = event_get_supported_methods();
+ fprintf(stdout, "Using Libevent %s. Available methods are:\n",
+ event_get_version());
+ for (i = 0; methods[i] != NULL; ++i)
+ printf(" %s\n", methods[i]);
+ exit(0);
default:
fprintf(stderr, "Illegal argument \"%c\"\n", c);
exit(1);
@@ -187,7 +201,16 @@ main(int argc, char **argv)
exit(1);
}
- event_init();
+ if (method != NULL) {
+ cfg = event_config_new();
+ methods = event_get_supported_methods();
+ for (i = 0; methods[i] != NULL; ++i)
+ if (strcmp(methods[i], method))
+ event_config_avoid_method(cfg, methods[i]);
+ base = event_base_new_with_config(cfg);
+ event_config_free(cfg);
+ } else
+ base = event_base_new();
for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2) {
#ifdef USE_PIPES
diff --git a/test/regress.c b/test/regress.c
index 0ebadcb..08c30fa 100644
--- a/test/regress.c
+++ b/test/regress.c
@@ -31,10 +31,6 @@
#include <windows.h>
#endif
-#ifdef EVENT__HAVE_PTHREADS
-#include <pthread.h>
-#endif
-
#include "event2/event-config.h"
#include <sys/types.h>
@@ -73,6 +69,7 @@
#include "time-internal.h"
#include "regress.h"
+#include "regress_thread.h"
#ifndef _WIN32
#include "regress.gen.h"
@@ -390,7 +387,7 @@ record_event_cb(evutil_socket_t s, short what, void *ptr)
}
static void
-test_simpleclose(void *ptr)
+test_simpleclose_rw(void *ptr)
{
/* Test that a close of FD is detected as a read and as a write. */
struct event_base *base = event_base_new();
@@ -472,6 +469,56 @@ end:
event_base_free(base);
}
+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")) {
+ tt_assert(!evutil_closesocket(pair[1]));
+ /* 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));
+ }
+
+ tt_int_op(event_base_loop(base, EVLOOP_NONBLOCK), ==, !persist);
+ tt_int_op(got_event, ==, (events & ~EV_PERSIST));
+
+end:
+ if (ev)
+ event_free(ev);
+}
static void
test_multiple(void)
@@ -979,7 +1026,7 @@ test_fork(void)
evutil_closesocket(child_pair[1]);
}
-#ifdef EVENT__HAVE_PTHREADS
+#ifdef EVTHREAD_USE_PTHREADS_IMPLEMENTED
static void* del_wait_thread(void *arg)
{
struct timeval tv_start, tv_end;
@@ -1007,14 +1054,14 @@ static void
test_del_wait(void)
{
struct event ev;
- pthread_t thread;
+ 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);
- pthread_create(&thread, NULL, del_wait_thread, NULL);
+ THREAD_START(thread, del_wait_thread, NULL);
if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) {
tt_fail_perror("write");
@@ -1033,7 +1080,7 @@ test_del_wait(void)
test_timeval_diff_eq(&tv_start, &tv_end, 270);
}
- pthread_join(thread, NULL);
+ THREAD_JOIN(thread);
tt_int_op(test_ok, ==, 1);
@@ -1051,14 +1098,14 @@ static void
test_del_notify(void)
{
struct event ev;
- pthread_t thread;
+ THREAD_T thread;
test_ok = 1;
event_set(&ev, -1, EV_READ, null_cb, &ev);
event_add(&ev, NULL);
- pthread_create(&thread, NULL, test_del_notify_thread, NULL);
+ THREAD_START(thread, test_del_notify_thread, NULL);
{
struct timeval delay = { 0, 1000 };
@@ -1066,7 +1113,7 @@ test_del_notify(void)
}
event_del(&ev);
- pthread_join(thread, NULL);
+ THREAD_JOIN(thread);
}
#endif
@@ -3464,8 +3511,35 @@ struct testcase_t main_testcases[] = {
LEGACY(simpleread, TT_ISOLATED),
LEGACY(simpleread_multiple, TT_ISOLATED),
LEGACY(simplewrite, TT_ISOLATED),
- { "simpleclose", test_simpleclose, TT_FORK, &basic_setup,
- NULL },
+ { "simpleclose_rw", test_simpleclose_rw, TT_FORK, &basic_setup, NULL },
+ /* 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" },
LEGACY(multiple, TT_ISOLATED),
LEGACY(persistent, TT_ISOLATED),
LEGACY(combined, TT_ISOLATED),
@@ -3505,8 +3579,8 @@ struct testcase_t main_testcases[] = {
#ifndef _WIN32
LEGACY(fork, TT_ISOLATED),
#endif
-#ifdef EVENT__HAVE_PTHREADS
- /** TODO: support win32 */
+
+#ifdef EVTHREAD_USE_PTHREADS_IMPLEMENTED
LEGACY(del_wait, TT_ISOLATED|TT_NEED_THREADS|TT_RETRIABLE),
LEGACY(del_notify, TT_ISOLATED|TT_NEED_THREADS),
#endif
diff --git a/test/regress.gen.c b/test/regress.gen.c
index 09f4674..611ec8a 100644
--- a/test/regress.gen.c
+++ b/test/regress.gen.c
@@ -1,3 +1,4 @@
+
/*
* Automatically generated from ../test/regress.rpc
* by event_rpcgen.py/0.1. DO NOT EDIT THIS FILE.
@@ -91,7 +92,8 @@ msg_run_expand_to_hold_more(struct msg *msg)
return -1;
msg->run_data = new_data;
msg->run_num_allocated = tobe_allocated;
- return 0;}
+ return 0;
+}
struct run*
msg_run_add(struct msg *msg)
@@ -173,7 +175,7 @@ msg_attack_assign(struct msg *msg,
int
msg_run_assign(struct msg *msg, int off,
- const struct run* value)
+ const struct run* value)
{
if (!msg->run_set || off < 0 || off >= msg->run_length)
return (-1);
@@ -193,7 +195,8 @@ msg_run_assign(struct msg *msg, int off,
had_error = 1;
goto done;
}
- done:if (tmp != NULL)
+ done:
+ if (tmp != NULL)
evbuffer_free(tmp);
if (had_error) {
run_clear(msg->run_data[off]);
@@ -300,7 +303,7 @@ msg_free(struct msg *tmp)
}
void
-msg_marshal(struct evbuffer *evbuf, const struct msg *tmp){
+msg_marshal(struct evbuffer *evbuf, const struct msg *tmp) {
evtag_marshal_string(evbuf, MSG_FROM_NAME, tmp->from_name_data);
evtag_marshal_string(evbuf, MSG_TO_NAME, tmp->to_name_data);
if (tmp->attack_set) {
@@ -317,7 +320,7 @@ msg_marshal(struct evbuffer *evbuf, const struct msg *tmp){
}
int
-msg_unmarshal(struct msg *tmp, struct evbuffer *evbuf)
+msg_unmarshal(struct msg *tmp, struct evbuffer *evbuf)
{
ev_uint32_t tag;
while (evbuffer_get_length(evbuf) > 0) {
@@ -349,7 +352,8 @@ msg_unmarshal(struct msg *tmp, struct evbuffer *evbuf)
tmp->attack_data = kill_new();
if (tmp->attack_data == NULL)
return (-1);
- if (evtag_unmarshal_kill(evbuf, MSG_ATTACK, tmp->attack_data) == -1) {
+ if (evtag_unmarshal_kill(evbuf, MSG_ATTACK,
+ tmp->attack_data) == -1) {
event_warnx("%s: failed to unmarshal attack", __func__);
return (-1);
}
@@ -364,7 +368,8 @@ msg_unmarshal(struct msg *tmp, struct evbuffer *evbuf)
tmp->run_data[tmp->run_length] = run_new();
if (tmp->run_data[tmp->run_length] == NULL)
return (-1);
- if (evtag_unmarshal_run(evbuf, MSG_RUN, tmp->run_data[tmp->run_length]) == -1) {
+ if (evtag_unmarshal_run(evbuf, MSG_RUN,
+ tmp->run_data[tmp->run_length]) == -1) {
event_warnx("%s: failed to unmarshal run", __func__);
return (-1);
}
@@ -401,7 +406,8 @@ msg_complete(struct msg *msg)
}
int
-evtag_unmarshal_msg(struct evbuffer *evbuf, ev_uint32_t need_tag, struct msg *msg)
+evtag_unmarshal_msg(struct evbuffer *evbuf, ev_uint32_t need_tag,
+ struct msg *msg)
{
ev_uint32_t tag;
int res = -1;
@@ -422,13 +428,14 @@ evtag_unmarshal_msg(struct evbuffer *evbuf, ev_uint32_t need_tag, struct msg *ms
}
void
-evtag_marshal_msg(struct evbuffer *evbuf, ev_uint32_t tag, const struct msg *msg)
+evtag_marshal_msg(struct evbuffer *evbuf, ev_uint32_t tag,
+ const struct msg *msg)
{
struct evbuffer *buf_ = evbuffer_new();
assert(buf_ != NULL);
msg_marshal(buf_, msg);
evtag_marshal_buffer(evbuf, tag, buf_);
- evbuffer_free(buf_);
+ evbuffer_free(buf_);
}
/*
@@ -489,7 +496,8 @@ kill_how_often_expand_to_hold_more(struct kill *msg)
return -1;
msg->how_often_data = new_data;
msg->how_often_num_allocated = tobe_allocated;
- return 0;}
+ return 0;
+}
ev_uint32_t *
kill_how_often_add(struct kill *msg, const ev_uint32_t value)
@@ -532,7 +540,7 @@ kill_action_assign(struct kill *msg,
int
kill_how_often_assign(struct kill *msg, int off,
- const ev_uint32_t value)
+ const ev_uint32_t value)
{
if (!msg->how_often_set || off < 0 || off >= msg->how_often_length)
return (-1);
@@ -612,7 +620,7 @@ kill_free(struct kill *tmp)
}
void
-kill_marshal(struct evbuffer *evbuf, const struct kill *tmp){
+kill_marshal(struct evbuffer *evbuf, const struct kill *tmp) {
evtag_marshal_string(evbuf, KILL_WEAPON, tmp->weapon_data);
evtag_marshal_string(evbuf, KILL_ACTION, tmp->action_data);
if (tmp->how_often_set) {
@@ -626,7 +634,7 @@ kill_marshal(struct evbuffer *evbuf, const struct kill *tmp){
}
int
-kill_unmarshal(struct kill *tmp, struct evbuffer *evbuf)
+kill_unmarshal(struct kill *tmp, struct evbuffer *evbuf)
{
ev_uint32_t tag;
while (evbuffer_get_length(evbuf) > 0) {
@@ -686,7 +694,8 @@ kill_complete(struct kill *msg)
}
int
-evtag_unmarshal_kill(struct evbuffer *evbuf, ev_uint32_t need_tag, struct kill *msg)
+evtag_unmarshal_kill(struct evbuffer *evbuf, ev_uint32_t need_tag,
+ struct kill *msg)
{
ev_uint32_t tag;
int res = -1;
@@ -707,13 +716,14 @@ evtag_unmarshal_kill(struct evbuffer *evbuf, ev_uint32_t need_tag, struct kill *
}
void
-evtag_marshal_kill(struct evbuffer *evbuf, ev_uint32_t tag, const struct kill *msg)
+evtag_marshal_kill(struct evbuffer *evbuf, ev_uint32_t tag,
+ const struct kill *msg)
{
struct evbuffer *buf_ = evbuffer_new();
assert(buf_ != NULL);
kill_marshal(buf_, msg);
evtag_marshal_buffer(evbuf, tag, buf_);
- evbuffer_free(buf_);
+ evbuffer_free(buf_);
}
/*
@@ -794,7 +804,8 @@ run_notes_expand_to_hold_more(struct run *msg)
return -1;
msg->notes_data = new_data;
msg->notes_num_allocated = tobe_allocated;
- return 0;}
+ return 0;
+}
char * *
run_notes_add(struct run *msg, const char * value)
@@ -831,7 +842,8 @@ run_other_numbers_expand_to_hold_more(struct run *msg)
return -1;
msg->other_numbers_data = new_data;
msg->other_numbers_num_allocated = tobe_allocated;
- return 0;}
+ return 0;
+}
ev_uint32_t *
run_other_numbers_add(struct run *msg, const ev_uint32_t value)
@@ -884,7 +896,7 @@ run_fixed_bytes_assign(struct run *msg, const ev_uint8_t *value)
int
run_notes_assign(struct run *msg, int off,
- const char * value)
+ const char * value)
{
if (!msg->notes_set || off < 0 || off >= msg->notes_length)
return (-1);
@@ -911,7 +923,7 @@ run_large_number_assign(struct run *msg, const ev_uint64_t value)
int
run_other_numbers_assign(struct run *msg, int off,
- const ev_uint32_t value)
+ const ev_uint32_t value)
{
if (!msg->other_numbers_set || off < 0 || off >= msg->other_numbers_length)
return (-1);
@@ -1047,7 +1059,7 @@ run_free(struct run *tmp)
}
void
-run_marshal(struct evbuffer *evbuf, const struct run *tmp){
+run_marshal(struct evbuffer *evbuf, const struct run *tmp) {
evtag_marshal_string(evbuf, RUN_HOW, tmp->how_data);
if (tmp->some_bytes_set) {
evtag_marshal(evbuf, RUN_SOME_BYTES, tmp->some_bytes_data, tmp->some_bytes_length);
@@ -1075,7 +1087,7 @@ run_marshal(struct evbuffer *evbuf, const struct run *tmp){
}
int
-run_unmarshal(struct run *tmp, struct evbuffer *evbuf)
+run_unmarshal(struct run *tmp, struct evbuffer *evbuf)
{
ev_uint32_t tag;
while (evbuffer_get_length(evbuf) > 0) {
@@ -1172,7 +1184,8 @@ run_complete(struct run *msg)
}
int
-evtag_unmarshal_run(struct evbuffer *evbuf, ev_uint32_t need_tag, struct run *msg)
+evtag_unmarshal_run(struct evbuffer *evbuf, ev_uint32_t need_tag,
+ struct run *msg)
{
ev_uint32_t tag;
int res = -1;
@@ -1193,12 +1206,13 @@ evtag_unmarshal_run(struct evbuffer *evbuf, ev_uint32_t need_tag, struct run *ms
}
void
-evtag_marshal_run(struct evbuffer *evbuf, ev_uint32_t tag, const struct run *msg)
+evtag_marshal_run(struct evbuffer *evbuf, ev_uint32_t tag,
+ const struct run *msg)
{
struct evbuffer *buf_ = evbuffer_new();
assert(buf_ != NULL);
run_marshal(buf_, msg);
evtag_marshal_buffer(evbuf, tag, buf_);
- evbuffer_free(buf_);
+ evbuffer_free(buf_);
}
diff --git a/test/regress.gen.h b/test/regress.gen.h
index 5a657f5..b3683bd 100644
--- a/test/regress.gen.h
+++ b/test/regress.gen.h
@@ -1,3 +1,4 @@
+
/*
* Automatically generated from ../test/regress.rpc
*/
@@ -5,6 +6,7 @@
#ifndef EVENT_RPCOUT____TEST_REGRESS_RPC_
#define EVENT_RPCOUT____TEST_REGRESS_RPC_
+
#include <event2/util.h> /* for ev_uint*_t */
#include <event2/rpc.h>
struct msg;
diff --git a/test/regress.h b/test/regress.h
index 643b82b..43cb4ea 100644
--- a/test/regress.h
+++ b/test/regress.h
@@ -95,6 +95,7 @@ extern int libevent_tests_running_in_debug_mode;
#define TT_NO_LOGS (TT_FIRST_USER_FLAG<<5)
#define TT_ENABLE_IOCP_FLAG (TT_FIRST_USER_FLAG<<6)
#define TT_ENABLE_IOCP (TT_ENABLE_IOCP_FLAG|TT_NEED_THREADS)
+#define TT_ENABLE_DEBUG_MODE (TT_ENABLE_IOCP_FLAG<<7)
/* All the flags that a legacy test needs. */
#define TT_ISOLATED TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE
diff --git a/test/regress_buffer.c b/test/regress_buffer.c
index 8ac4b6e..f259b92 100644
--- a/test/regress_buffer.c
+++ b/test/regress_buffer.c
@@ -426,6 +426,36 @@ test_evbuffer_remove_buffer_with_empty3(void *ptr)
}
static void
+test_evbuffer_pullup_with_empty(void *ptr)
+{
+ struct evbuffer *buf = NULL;
+
+ buf = evbuffer_new();
+ evbuffer_add(buf, "foo", 3);
+ evbuffer_add_reference(buf, NULL, 0, NULL, NULL);
+ evbuffer_validate(buf);
+ tt_int_op(evbuffer_get_length(buf), ==, 3);
+ tt_mem_op(evbuffer_pullup(buf, -1), ==, "foo", 3);
+
+ evbuffer_free(buf);
+ buf = evbuffer_new();
+ evbuffer_validate(buf);
+ tt_int_op(evbuffer_get_length(buf), ==, 0);
+ tt_int_op(evbuffer_pullup(buf, -1), ==, NULL);
+
+ evbuffer_free(buf);
+ buf = evbuffer_new();
+ evbuffer_add(buf, "foo", 3);
+ evbuffer_add_reference(buf, NULL, 0, NULL, NULL);
+ evbuffer_validate(buf);
+ tt_mem_op(evbuffer_pullup(buf, 3), ==, "foo", 3);
+
+ end:
+ if (buf)
+ evbuffer_free(buf);
+}
+
+static void
test_evbuffer_remove_buffer_with_empty_front(void *ptr)
{
struct evbuffer *buf1 = NULL, *buf2 = NULL;
@@ -2327,7 +2357,7 @@ test_evbuffer_empty_reference_prepend_buffer(void *ptr)
tt_assert(!strncmp((char *)evbuffer_pullup(buf2, -1), "foo", 3));
evbuffer_validate(buf2);
- tt_assert(!strncmp((char *)evbuffer_pullup(buf1, -1), "", 0));
+ tt_assert(evbuffer_pullup(buf1, -1) == NULL);
evbuffer_validate(buf2);
end:
@@ -2494,28 +2524,37 @@ end:
static void
test_evbuffer_freeze(void *ptr)
{
- struct evbuffer *buf = NULL, *tmp_buf=NULL;
+ struct basic_test_data *testdata = ptr;
+ evutil_socket_t *pair = testdata->pair;
+ struct evbuffer *buf = NULL, *buf_two = NULL, *tmp_buf = NULL;
const char string[] = /* Year's End, Richard Wilbur */
"I've known the wind by water banks to shake\n"
"The late leaves down, which frozen where they fell\n"
"And held in ice as dancers in a spell\n"
"Fluttered all winter long into a lake...";
- const int start = !strcmp(ptr, "start");
+ const int start = !strcmp(testdata->setup_data, "start");
+ const char tmpfilecontent[] = "file_freeze_test_file";
char *cp;
char charbuf[128];
+ char *tmpfilename = NULL;
+ int fd = -1;
int r;
- size_t orig_length;
+ size_t orig_length, len;
struct evbuffer_iovec v[1];
if (!start)
- tt_str_op(ptr, ==, "end");
+ tt_str_op(testdata->setup_data, ==, "end");
buf = evbuffer_new();
+ buf_two = evbuffer_new();
tmp_buf = evbuffer_new();
tt_assert(tmp_buf);
evbuffer_add(buf, string, strlen(string));
+ evbuffer_add(buf_two, "abc", 3);
+ evbuffer_add(tmp_buf, "xyz", 3);
evbuffer_freeze(buf, start); /* Freeze the start or the end.*/
+ evbuffer_freeze(buf_two, start);
#define FREEZE_EQ(a, startcase, endcase) \
do { \
@@ -2544,7 +2583,22 @@ test_evbuffer_freeze(void *ptr)
FREEZE_EQ(r, 0, -1);
r = evbuffer_add_printf(buf, "Hello %s", "world");
FREEZE_EQ(r, 11, -1);
- /* TODO: test add_buffer, add_file, read */
+
+ r = evbuffer_add_buffer(buf, tmp_buf);
+ FREEZE_EQ(r, 0, -1);
+ len = strlen(tmpfilecontent);
+ fd = regress_make_tmpfile(tmpfilecontent, len, &tmpfilename);
+ r = evbuffer_add_file(buf, fd, 0, len);
+ FREEZE_EQ(r, 0, -1);
+
+ if (start)
+ evbuffer_add(tmp_buf, "xyz", 3);
+
+ tt_assert(evbuffer_get_length(tmp_buf));
+ len = evbuffer_get_length(tmp_buf);
+ evbuffer_write(tmp_buf, pair[0]);
+ r = evbuffer_read(buf, pair[1], -1);
+ FREEZE_EQ(r, len, -1);
if (!start)
tt_int_op(orig_length, ==, evbuffer_get_length(buf));
@@ -2562,7 +2616,24 @@ test_evbuffer_freeze(void *ptr)
FREEZE_EQ(cp==NULL, 1, 0);
if (cp)
free(cp);
- /* TODO: Test remove_buffer, add_buffer, write, prepend_buffer */
+
+ evbuffer_add(tmp_buf, "xyz", 3);
+ tt_assert(evbuffer_get_length(tmp_buf));
+ r = evbuffer_remove_buffer(buf, tmp_buf, 3);
+ FREEZE_EQ(r, -1, 3);
+ r = evbuffer_drain(buf, 3);
+ FREEZE_EQ(r, -1, 0);
+ r = evbuffer_prepend_buffer(buf, tmp_buf);
+ FREEZE_EQ(r, -1, 0);
+
+ len = evbuffer_get_length(buf);
+ r = evbuffer_write(buf, pair[0]);
+ evbuffer_read(tmp_buf, pair[1], -1);
+ FREEZE_EQ(r, -1, len);
+ len = evbuffer_get_length(buf_two);
+ r = evbuffer_write_atmost(buf_two, pair[0], -1);
+ evbuffer_read(tmp_buf, pair[1], -1);
+ FREEZE_EQ(r, -1, len);
if (start)
tt_int_op(orig_length, ==, evbuffer_get_length(buf));
@@ -2571,8 +2642,16 @@ end:
if (buf)
evbuffer_free(buf);
+ if (buf_two)
+ evbuffer_free(buf_two);
+
if (tmp_buf)
evbuffer_free(tmp_buf);
+
+ if (tmpfilename) {
+ unlink(tmpfilename);
+ free(tmpfilename);
+ }
}
static void
@@ -2756,11 +2835,12 @@ struct testcase_t evbuffer_testcases[] = {
{ "empty_reference_prepend_buffer", test_evbuffer_empty_reference_prepend_buffer, TT_FORK, NULL, NULL },
{ "peek", test_evbuffer_peek, 0, NULL, NULL },
{ "peek_first_gt", test_evbuffer_peek_first_gt, 0, NULL, NULL },
- { "freeze_start", test_evbuffer_freeze, 0, &nil_setup, (void*)"start" },
- { "freeze_end", test_evbuffer_freeze, 0, &nil_setup, (void*)"end" },
+ { "freeze_start", test_evbuffer_freeze, TT_NEED_SOCKETPAIR, &basic_setup, (void*)"start" },
+ { "freeze_end", test_evbuffer_freeze, TT_NEED_SOCKETPAIR, &basic_setup, (void*)"end" },
{ "add_iovec", test_evbuffer_add_iovec, 0, NULL, NULL},
{ "copyout", test_evbuffer_copyout, 0, NULL, NULL},
{ "file_segment_add_cleanup_cb", test_evbuffer_file_segment_add_cleanup_cb, 0, NULL, NULL },
+ { "pullup_with_empty", test_evbuffer_pullup_with_empty, 0, NULL, NULL },
#define ADDFILE_TEST(name, parameters) \
{ name, test_evbuffer_add_file, TT_FORK|TT_NEED_BASE, \
diff --git a/test/regress_bufferevent.c b/test/regress_bufferevent.c
index d4208c2..c276a0e 100644
--- a/test/regress_bufferevent.c
+++ b/test/regress_bufferevent.c
@@ -29,6 +29,19 @@
/* The old tests here need assertions to work. */
#undef NDEBUG
+/**
+ * - clang supports __has_feature
+ * - gcc supports __SANITIZE_ADDRESS__
+ *
+ * Let's set __SANITIZE_ADDRESS__ if __has_feature(address_sanitizer)
+ */
+#ifndef __has_feature
+#define __has_feature(x) 0
+#endif
+#if !defined(__SANITIZE_ADDRESS__) && __has_feature(address_sanitizer)
+#define __SANITIZE_ADDRESS__
+#endif
+
#ifdef _WIN32
#include <winsock2.h>
#include <windows.h>
@@ -203,7 +216,7 @@ static void test_bufferevent_pair_flush_normal(void) { test_bufferevent_impl(1,
static void test_bufferevent_pair_flush_flush(void) { test_bufferevent_impl(1, BEV_FLUSH); }
static void test_bufferevent_pair_flush_finished(void) { test_bufferevent_impl(1, BEV_FINISHED); }
-#if defined(EVTHREAD_USE_PTHREADS_IMPLEMENTED)
+#if defined(EVTHREAD_USE_PTHREADS_IMPLEMENTED) && !defined(__SANITIZE_ADDRESS__)
/**
* Trace lock/unlock/alloc/free for locks.
* (More heavier then evthread_debug*)
@@ -788,15 +801,28 @@ end:
}
static void
+close_socket_cb(evutil_socket_t fd, short what, void *arg)
+{
+ evutil_socket_t *fdp = arg;
+ if (*fdp >= 0) {
+ evutil_closesocket(*fdp);
+ *fdp = -1;
+ }
+}
+
+static void
test_bufferevent_connect_fail_eventcb(void *arg)
{
struct basic_test_data *data = arg;
int flags = BEV_OPT_CLOSE_ON_FREE | (long)data->setup_data;
+ struct event close_listener_event;
struct bufferevent *bev = NULL;
struct evconnlistener *lev = NULL;
struct sockaddr_in localhost;
+ struct timeval close_timeout = { 0, 300000 };
ev_socklen_t slen = sizeof(localhost);
evutil_socket_t fake_listener = -1;
+ int r;
fake_listener = fake_listener_create(&localhost);
@@ -809,10 +835,22 @@ test_bufferevent_connect_fail_eventcb(void *arg)
bufferevent_enable(bev, EV_READ|EV_WRITE);
tt_int_op(n_events_invoked, ==, 0);
tt_int_op(n_reads_invoked, ==, 0);
+
/** @see also test_bufferevent_connect_fail() */
- bufferevent_socket_connect(bev, (struct sockaddr *)&localhost, slen);
+ r = bufferevent_socket_connect(bev, (struct sockaddr *)&localhost, slen);
+ /* XXXX we'd like to test the '0' case everywhere, but FreeBSD tells
+ * detects the error immediately, which is not really wrong of it. */
+ tt_want(r == 0 || r == -1);
+
tt_int_op(n_events_invoked, ==, 0);
tt_int_op(n_reads_invoked, ==, 0);
+
+ /* Close the listener socket after a delay. This should trigger
+ "connection refused" on some other platforms, including OSX. */
+ evtimer_assign(&close_listener_event, data->base, close_socket_cb,
+ &fake_listener);
+ event_add(&close_listener_event, &close_timeout);
+
event_base_dispatch(data->base);
tt_int_op(n_events_invoked, ==, 1);
tt_int_op(n_reads_invoked, ==, 0);
@@ -847,23 +885,13 @@ want_fail_eventcb(struct bufferevent *bev, short what, void *ctx)
}
static void
-close_socket_cb(evutil_socket_t fd, short what, void *arg)
-{
- evutil_socket_t *fdp = arg;
- if (*fdp >= 0) {
- evutil_closesocket(*fdp);
- *fdp = -1;
- }
-}
-
-static void
test_bufferevent_connect_fail(void *arg)
{
struct basic_test_data *data = (struct basic_test_data *)arg;
struct bufferevent *bev=NULL;
struct event close_listener_event;
int close_listener_event_added = 0;
- struct timeval one_second = { 1, 0 };
+ struct timeval close_timeout = { 0, 300000 };
struct sockaddr_in localhost;
ev_socklen_t slen = sizeof(localhost);
evutil_socket_t fake_listener = -1;
@@ -882,11 +910,11 @@ test_bufferevent_connect_fail(void *arg)
* detects the error immediately, which is not really wrong of it. */
tt_want(r == 0 || r == -1);
- /* Close the listener socket after a second. This should trigger
+ /* Close the listener socket after a delay. This should trigger
"connection refused" on some other platforms, including OSX. */
evtimer_assign(&close_listener_event, data->base, close_socket_cb,
&fake_listener);
- event_add(&close_listener_event, &one_second);
+ event_add(&close_listener_event, &close_timeout);
close_listener_event_added = 1;
event_base_dispatch(data->base);
@@ -1336,7 +1364,7 @@ struct testcase_t bufferevent_testcases[] = {
LEGACY(bufferevent_pair_flush_normal, TT_ISOLATED),
LEGACY(bufferevent_pair_flush_flush, TT_ISOLATED),
LEGACY(bufferevent_pair_flush_finished, TT_ISOLATED),
-#if defined(EVTHREAD_USE_PTHREADS_IMPLEMENTED)
+#if defined(EVTHREAD_USE_PTHREADS_IMPLEMENTED) && !defined(__SANITIZE_ADDRESS__)
{ "bufferevent_pair_release_lock", test_bufferevent_pair_release_lock,
TT_FORK|TT_ISOLATED|TT_NEED_THREADS|TT_NEED_BASE|TT_LEGACY|TT_NO_LOGS,
&basic_setup, NULL },
diff --git a/test/regress_dns.c b/test/regress_dns.c
index d2084b7..9a8bff4 100644
--- a/test/regress_dns.c
+++ b/test/regress_dns.c
@@ -1265,27 +1265,9 @@ test_bufferevent_connect_hostname(void *arg)
int n_accept=0, n_dns=0;
char buf[128];
int emfile = data->setup_data && !strcmp(data->setup_data, "emfile");
- int success = BEV_EVENT_CONNECTED;
- int default_error = 0;
unsigned i;
int ret;
- if (emfile) {
- success = BEV_EVENT_ERROR;
-#if defined(__linux__)
- /* on linux glibc/musl reports EAI_SYSTEM, when getaddrinfo() cannot
- * open file for resolving service. */
- default_error = EVUTIL_EAI_SYSTEM;
-#elif defined(__sun__)
- /* on solaris it returns EAI_FAIL */
- default_error = EVUTIL_EAI_FAIL;
- /** the DP_POLL can also fail with EINVAL under EMFILE */
-#else
- /* on osx/freebsd it returns EAI_NONAME */
- default_error = EVUTIL_EAI_NONAME;
-#endif
- }
-
be_connect_hostname_base = data->base;
/* Bind an address and figure out what port it's on. */
@@ -1376,12 +1358,16 @@ test_bufferevent_connect_hostname(void *arg)
tt_int_op(be_outcome[0].what, ==, BEV_EVENT_ERROR);
tt_int_op(be_outcome[0].dnserr, ==, EVUTIL_EAI_NONAME);
- tt_int_op(be_outcome[1].what, ==, success);
+ tt_int_op(be_outcome[1].what, ==, !emfile ? BEV_EVENT_CONNECTED : BEV_EVENT_ERROR);
tt_int_op(be_outcome[1].dnserr, ==, 0);
- tt_int_op(be_outcome[2].what, ==, success);
+ tt_int_op(be_outcome[2].what, ==, !emfile ? BEV_EVENT_CONNECTED : BEV_EVENT_ERROR);
tt_int_op(be_outcome[2].dnserr, ==, 0);
- tt_int_op(be_outcome[3].what, ==, success);
- tt_int_op(be_outcome[3].dnserr, ==, default_error);
+ tt_int_op(be_outcome[3].what, ==, !emfile ? BEV_EVENT_CONNECTED : BEV_EVENT_ERROR);
+ if (!emfile) {
+ tt_int_op(be_outcome[3].dnserr, ==, 0);
+ } else {
+ tt_int_op(be_outcome[3].dnserr, !=, 0);
+ }
if (expect_err) {
tt_int_op(be_outcome[4].what, ==, BEV_EVENT_ERROR);
tt_int_op(be_outcome[4].dnserr, ==, expect_err);
@@ -1822,7 +1808,8 @@ struct gaic_request_status {
#define GAIC_MAGIC 0x1234abcd
-static int pending = 0;
+static int gaic_pending = 0;
+static int gaic_freed = 0;
static void
gaic_cancel_request_cb(evutil_socket_t fd, short what, void *arg)
@@ -1867,7 +1854,13 @@ gaic_getaddrinfo_cb(int result, struct evutil_addrinfo *res, void *arg)
free(status);
end:
- if (--pending <= 0)
+ if (res)
+ {
+ TT_BLATHER(("evutil_freeaddrinfo(%p)", res));
+ evutil_freeaddrinfo(res);
+ ++gaic_freed;
+ }
+ if (--gaic_pending <= 0)
event_base_loopexit(base, NULL);
}
@@ -1885,7 +1878,7 @@ gaic_launch(struct event_base *base, struct evdns_base *dns_base)
"foobar.bazquux.example.com", "80", NULL, gaic_getaddrinfo_cb,
status);
event_add(&status->cancel_event, &tv);
- ++pending;
+ ++gaic_pending;
}
#ifdef EVENT_SET_MEM_FUNCTIONS_IMPLEMENTED
@@ -2108,6 +2101,9 @@ test_getaddrinfo_async_cancel_stress(void *ptr)
event_base_dispatch(base);
+ // at least some was canceled via external event
+ tt_int_op(gaic_freed, !=, 1000);
+
end:
if (dns_base)
evdns_base_free(dns_base, 1);
@@ -2124,6 +2120,7 @@ dns_client_fail_requests_test(void *arg)
{
struct basic_test_data *data = arg;
struct event_base *base = data->base;
+ int limit_inflight = data->setup_data && !strcmp(data->setup_data, "limit-inflight");
struct evdns_base *dns = NULL;
struct evdns_server_port *dns_port = NULL;
ev_uint16_t portnum = 0;
@@ -2141,6 +2138,9 @@ dns_client_fail_requests_test(void *arg)
dns = evdns_base_new(base, EVDNS_BASE_DISABLE_WHEN_INACTIVE);
tt_assert(!evdns_base_nameserver_ip_add(dns, buf));
+ if (limit_inflight)
+ tt_assert(!evdns_base_set_option(dns, "max-inflight:", "11"));
+
for (i = 0; i < 20; ++i)
evdns_base_resolve_ipv4(dns, "foof.example.com", 0, generic_dns_callback, &r[i]);
@@ -2372,6 +2372,71 @@ end:
evdns_base_free(dns_base, 0);
}
+static void
+test_set_option(void *arg)
+{
+#define SUCCESS 0
+#define FAIL -1
+ struct basic_test_data *data = arg;
+ struct evdns_base *dns_base;
+ size_t i;
+ /* Option names are allowed to have ':' at the end.
+ * So all test option names come in pairs.
+ */
+ const char *int_options[] = {
+ "ndots", "ndots:",
+ "max-timeouts", "max-timeouts:",
+ "max-inflight", "max-inflight:",
+ "attempts", "attempts:",
+ "randomize-case", "randomize-case:",
+ "so-rcvbuf", "so-rcvbuf:",
+ "so-sndbuf", "so-sndbuf:",
+ };
+ const char *timeval_options[] = {
+ "timeout", "timeout:",
+ "getaddrinfo-allow-skew", "getaddrinfo-allow-skew:",
+ "initial-probe-timeout", "initial-probe-timeout:",
+ };
+ const char *addr_port_options[] = {
+ "bind-to", "bind-to:",
+ };
+
+ dns_base = evdns_base_new(data->base, 0);
+ tt_assert(dns_base);
+
+ for (i = 0; i < ARRAY_SIZE(int_options); ++i) {
+ tt_assert(SUCCESS == evdns_base_set_option(dns_base, int_options[i], "0"));
+ tt_assert(SUCCESS == evdns_base_set_option(dns_base, int_options[i], "1"));
+ tt_assert(SUCCESS == evdns_base_set_option(dns_base, int_options[i], "10000"));
+ tt_assert(FAIL == evdns_base_set_option(dns_base, int_options[i], "foo"));
+ tt_assert(FAIL == evdns_base_set_option(dns_base, int_options[i], "3.14"));
+ }
+
+ for (i = 0; i < ARRAY_SIZE(timeval_options); ++i) {
+ tt_assert(SUCCESS == evdns_base_set_option(dns_base, timeval_options[i], "1"));
+ tt_assert(SUCCESS == evdns_base_set_option(dns_base, timeval_options[i], "0.001"));
+ tt_assert(SUCCESS == evdns_base_set_option(dns_base, timeval_options[i], "3.14"));
+ tt_assert(SUCCESS == evdns_base_set_option(dns_base, timeval_options[i], "10000"));
+ tt_assert(FAIL == evdns_base_set_option(dns_base, timeval_options[i], "0"));
+ tt_assert(FAIL == evdns_base_set_option(dns_base, timeval_options[i], "foo"));
+ }
+
+ for (i = 0; i < ARRAY_SIZE(addr_port_options); ++i) {
+ tt_assert(SUCCESS == evdns_base_set_option(dns_base, addr_port_options[i], "8.8.8.8:80"));
+ tt_assert(SUCCESS == evdns_base_set_option(dns_base, addr_port_options[i], "1.2.3.4"));
+ tt_assert(SUCCESS == evdns_base_set_option(dns_base, addr_port_options[i], "::1:82"));
+ tt_assert(SUCCESS == evdns_base_set_option(dns_base, addr_port_options[i], "3::4"));
+ tt_assert(FAIL == evdns_base_set_option(dns_base, addr_port_options[i], "3.14"));
+ tt_assert(FAIL == evdns_base_set_option(dns_base, addr_port_options[i], "foo"));
+ }
+
+#undef SUCCESS
+#undef FAIL
+end:
+ if (dns_base)
+ evdns_base_free(dns_base, 0);
+}
+
#define DNS_LEGACY(name, flags) \
{ #name, run_legacy_test_fn, flags|TT_LEGACY, &legacy_setup, \
dns_##name }
@@ -2432,6 +2497,8 @@ struct testcase_t dns_testcases[] = {
{ "client_fail_requests", dns_client_fail_requests_test,
TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL },
+ { "client_fail_waiting_requests", dns_client_fail_requests_test,
+ TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, (char*)"limit-inflight" },
{ "client_fail_requests_getaddrinfo",
dns_client_fail_requests_getaddrinfo_test,
TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL },
@@ -2443,6 +2510,8 @@ struct testcase_t dns_testcases[] = {
{ "set_SO_RCVBUF_SO_SNDBUF", test_set_so_rcvbuf_so_sndbuf,
TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
+ { "set_options", test_set_option,
+ TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
END_OF_TESTCASES
};
diff --git a/test/regress_et.c b/test/regress_et.c
index 5fa87a3..1b1f819 100644
--- a/test/regress_et.c
+++ b/test/regress_et.c
@@ -102,7 +102,7 @@ test_edgetriggered(void *data_)
"support edge-triggering", event_base_get_method(base),
supports_et?"":"not "));
- /* Initalize one event */
+ /* Initialize one event */
ev = event_new(base, pair[1], EV_READ|EV_ET|EV_PERSIST, read_cb, &ev);
tt_assert(ev != NULL);
tt_int_op(event_add(ev, NULL), ==, 0);
diff --git a/test/regress_finalize.c b/test/regress_finalize.c
index 552210f..9e57188 100644
--- a/test/regress_finalize.c
+++ b/test/regress_finalize.c
@@ -290,6 +290,53 @@ end:
;
}
+static void
+event_finalize_callback_free(struct event *ev, void *arg)
+{
+ struct event_base *base = arg;
+ int err;
+ if (base) {
+ err = event_assign(ev, base, -1, EV_TIMEOUT, NULL, NULL);
+ tt_int_op(err, ==, 0);
+ test_ok += 1;
+ } else {
+ free(ev);
+ test_ok += 1;
+ }
+
+end:
+ ;
+}
+static void
+test_fin_debug_use_after_free(void *arg)
+{
+ struct basic_test_data *data = arg;
+ struct event_base *base = data->base;
+ struct event *ev;
+
+ tt_ptr_op(ev = event_new(base, -1, EV_TIMEOUT, NULL, base), !=, NULL);
+ tt_int_op(event_add(ev, NULL), ==, 0);
+ tt_int_op(event_finalize(0, ev, event_finalize_callback_free), ==, 0);
+
+ // Dispatch base to trigger callbacks
+ event_base_dispatch(base);
+ event_base_assert_ok_(base);
+ tt_int_op(test_ok, ==, 1);
+
+ // Now add again, since we did event_assign in event_finalize_callback_free
+ // This used to fail in event_debug_assert_is_setup_
+ tt_int_op(event_add(ev, NULL), ==, 0);
+
+ // Finalize and dispatch again
+ tt_int_op(event_finalize(0, ev, event_finalize_callback_free), ==, 0);
+ event_base_dispatch(base);
+ event_base_assert_ok_(base);
+ tt_int_op(test_ok, ==, 2);
+
+end:
+ ;
+}
+
#if 0
static void
timer_callback_3(evutil_socket_t *fd, short what, void *arg)
@@ -339,6 +386,7 @@ struct testcase_t finalize_testcases[] = {
TEST(cb_invoked, TT_FORK|TT_NEED_BASE),
TEST(free_finalize, TT_FORK),
TEST(within_cb, TT_FORK|TT_NEED_BASE),
+ TEST(debug_use_after_free, TT_FORK|TT_NEED_BASE|TT_ENABLE_DEBUG_MODE),
// TEST(many, TT_FORK|TT_NEED_BASE),
diff --git a/test/regress_http.c b/test/regress_http.c
index 8f30b57..4493907 100644
--- a/test/regress_http.c
+++ b/test/regress_http.c
@@ -66,6 +66,8 @@
#include "regress.h"
#include "regress_testutils.h"
+#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
+
/* set if a test needs to call loopexit on a base */
static struct event_base *exit_base;
@@ -230,6 +232,8 @@ evbuffer_datacmp(struct evbuffer *buf, const char *s)
return -1;
d = evbuffer_pullup(buf, s_sz);
+ if (!d)
+ d = (unsigned char *)"";
if ((r = memcmp(d, s, s_sz)))
return r;
@@ -457,9 +461,9 @@ http_chunked_cb(struct evhttp_request *req, void *arg)
}
static struct bufferevent *
-create_bev(struct event_base *base, evutil_socket_t fd, int ssl_mask)
+create_bev(struct event_base *base, evutil_socket_t fd, int ssl_mask, int flags_)
{
- int flags = BEV_OPT_DEFER_CALLBACKS;
+ int flags = BEV_OPT_DEFER_CALLBACKS | flags_;
struct bufferevent *bev = NULL;
if (!ssl_mask) {
@@ -522,7 +526,7 @@ http_basic_test_impl(void *arg, int ssl, const char *request_line)
fd = http_connect("127.0.0.1", port);
/* Stupid thing to send a request */
- bev = create_bev(data->base, fd, ssl);
+ bev = create_bev(data->base, fd, ssl, BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb(bev, http_readcb, http_half_writecb,
http_errorcb, data->base);
out = bufferevent_get_output(bev);
@@ -538,12 +542,11 @@ http_basic_test_impl(void *arg, int ssl, const char *request_line)
/* connect to the second port */
bufferevent_free(bev);
- evutil_closesocket(fd);
fd = http_connect("127.0.0.1", port2);
/* Stupid thing to send a request */
- bev = create_bev(data->base, fd, ssl);
+ bev = create_bev(data->base, fd, ssl, BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb(bev, http_readcb, http_writecb,
http_errorcb, data->base);
out = bufferevent_get_output(bev);
@@ -560,12 +563,11 @@ http_basic_test_impl(void *arg, int ssl, const char *request_line)
/* Connect to the second port again. This time, send an absolute uri. */
bufferevent_free(bev);
- evutil_closesocket(fd);
fd = http_connect("127.0.0.1", port2);
/* Stupid thing to send a request */
- bev = create_bev(data->base, fd, ssl);
+ bev = create_bev(data->base, fd, ssl, BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb(bev, http_readcb, http_writecb,
http_errorcb, data->base);
@@ -1283,6 +1285,7 @@ http_autofree_connection_test(void *arg)
struct evhttp_connection *evcon = NULL;
struct evhttp_request *req[2] = { NULL };
struct evhttp *http = http_setup(&port, data->base, 0);
+ size_t i;
test_ok = 0;
@@ -1297,19 +1300,14 @@ http_autofree_connection_test(void *arg)
req[1] = evhttp_request_new(http_request_empty_done, data->base);
/* Add the information that we care about */
- evhttp_add_header(evhttp_request_get_output_headers(req[0]), "Host", "somehost");
- evhttp_add_header(evhttp_request_get_output_headers(req[0]), "Connection", "close");
- evhttp_add_header(evhttp_request_get_output_headers(req[0]), "Empty", "itis");
- evhttp_add_header(evhttp_request_get_output_headers(req[1]), "Host", "somehost");
- evhttp_add_header(evhttp_request_get_output_headers(req[1]), "Connection", "close");
- evhttp_add_header(evhttp_request_get_output_headers(req[1]), "Empty", "itis");
+ for (i = 0; i < ARRAY_SIZE(req); ++i) {
+ evhttp_add_header(evhttp_request_get_output_headers(req[i]), "Host", "somehost");
+ evhttp_add_header(evhttp_request_get_output_headers(req[i]), "Connection", "close");
+ evhttp_add_header(evhttp_request_get_output_headers(req[i]), "Empty", "itis");
- /* We give ownership of the request to the connection */
- if (evhttp_make_request(evcon, req[0], EVHTTP_REQ_GET, "/test") == -1) {
- tt_abort_msg("couldn't make request");
- }
- if (evhttp_make_request(evcon, req[1], EVHTTP_REQ_GET, "/test") == -1) {
- tt_abort_msg("couldn't make request");
+ if (evhttp_make_request(evcon, req[i], EVHTTP_REQ_GET, "/test") == -1) {
+ tt_abort_msg("couldn't make request");
+ }
}
/*
@@ -1320,7 +1318,8 @@ http_autofree_connection_test(void *arg)
evhttp_connection_free_on_completion(evcon);
evcon = NULL;
- event_base_dispatch(data->base);
+ for (i = 0; i < ARRAY_SIZE(req); ++i)
+ event_base_dispatch(data->base);
/* at this point, the http server should have no connection */
tt_assert(TAILQ_FIRST(&http->connections) == NULL);
@@ -3119,7 +3118,7 @@ http_incomplete_test_(struct basic_test_data *data, int use_timeout, int ssl)
tt_assert(fd != EVUTIL_INVALID_SOCKET);
/* Stupid thing to send a request */
- bev = create_bev(data->base, fd, ssl);
+ bev = create_bev(data->base, fd, ssl, 0);
bufferevent_setcb(bev,
http_incomplete_readcb, http_incomplete_writecb,
http_incomplete_errorcb, use_timeout ? NULL : &fd);
@@ -3319,7 +3318,7 @@ static void
http_chunk_out_test_impl(void *arg, int ssl)
{
struct basic_test_data *data = arg;
- struct bufferevent *bev;
+ struct bufferevent *bev = NULL;
evutil_socket_t fd;
const char *http_request;
ev_uint16_t port = 0;
@@ -3336,7 +3335,7 @@ http_chunk_out_test_impl(void *arg, int ssl)
tt_assert(fd != EVUTIL_INVALID_SOCKET);
/* Stupid thing to send a request */
- bev = create_bev(data->base, fd, ssl);
+ bev = create_bev(data->base, fd, ssl, BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb(bev,
http_chunked_readcb, http_chunked_writecb,
http_chunked_errorcb, data->base);
@@ -3354,6 +3353,7 @@ http_chunk_out_test_impl(void *arg, int ssl)
event_base_dispatch(data->base);
bufferevent_free(bev);
+ bev = NULL;
evutil_gettimeofday(&tv_end, NULL);
evutil_timersub(&tv_end, &tv_start, &tv_end);
@@ -3363,7 +3363,7 @@ http_chunk_out_test_impl(void *arg, int ssl)
tt_int_op(test_ok, ==, 2);
/* now try again with the regular connection object */
- bev = create_bev(data->base, -1, ssl);
+ bev = create_bev(data->base, -1, ssl, BEV_OPT_CLOSE_ON_FREE);
evcon = evhttp_connection_base_bufferevent_new(
data->base, NULL, bev, "127.0.0.1", port);
tt_assert(evcon);
@@ -3371,14 +3371,13 @@ http_chunk_out_test_impl(void *arg, int ssl)
/* make two requests to check the keepalive behavior */
for (i = 0; i < 2; i++) {
test_ok = 0;
- req = evhttp_request_new(http_chunked_request_done,data->base);
+ req = evhttp_request_new(http_chunked_request_done, data->base);
/* Add the information that we care about */
evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
/* We give ownership of the request to the connection */
- if (evhttp_make_request(evcon, req,
- EVHTTP_REQ_GET, "/chunked") == -1) {
+ if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/chunked") == -1) {
tt_abort_msg("Couldn't make request");
}
@@ -3409,7 +3408,7 @@ http_stream_out_test_impl(void *arg, int ssl)
test_ok = 0;
exit_base = data->base;
- bev = create_bev(data->base, -1, ssl);
+ bev = create_bev(data->base, -1, ssl, 0);
evcon = evhttp_connection_base_bufferevent_new(
data->base, NULL, bev, "127.0.0.1", port);
tt_assert(evcon);
@@ -3609,7 +3608,7 @@ http_connection_fail_test_impl(void *arg, int ssl)
/* auto detect a port */
evhttp_free(http);
- bev = create_bev(data->base, -1, ssl);
+ bev = create_bev(data->base, -1, ssl, 0);
/* Pick an unroutable address. This administratively scoped multicast
* address should do when working with TCP. */
evcon = evhttp_connection_base_bufferevent_new(
@@ -3681,7 +3680,7 @@ http_simple_test_impl(void *arg, int ssl, int dirty, const char *uri)
exit_base = data->base;
test_ok = 0;
- bev = create_bev(data->base, -1, ssl);
+ bev = create_bev(data->base, -1, ssl, 0);
#ifdef EVENT__HAVE_OPENSSL
bufferevent_openssl_set_allow_dirty_shutdown(bev, dirty);
#endif
@@ -3728,7 +3727,7 @@ http_connection_retry_test_basic(void *arg, const char *addr, struct evdns_base
/* auto detect a port */
evhttp_free(http);
- bev = create_bev(data->base, -1, ssl);
+ bev = create_bev(data->base, -1, ssl, 0);
evcon = evhttp_connection_base_bufferevent_new(data->base, dns_base, bev, addr, hs.port);
tt_assert(evcon);
if (dns_base)
@@ -4516,7 +4515,7 @@ http_write_during_read_test_impl(void *arg, int ssl)
fd = http_connect("127.0.0.1", port);
tt_assert(fd != EVUTIL_INVALID_SOCKET);
- bev = create_bev(data->base, fd, 0);
+ bev = create_bev(data->base, fd, 0, 0);
bufferevent_setcb(bev, NULL, NULL, NULL, data->base);
bufferevent_disable(bev, EV_READ);
@@ -4588,7 +4587,7 @@ static void http_run_bev_request(struct event_base *base, int port,
tt_assert(fd != EVUTIL_INVALID_SOCKET);
/* Stupid thing to send a request */
- bev = create_bev(base, fd, 0);
+ bev = create_bev(base, fd, 0, 0);
bufferevent_setcb(bev, http_readcb, http_writecb,
http_errorcb, base);
out = bufferevent_get_output(bev);
diff --git a/test/regress_main.c b/test/regress_main.c
index c937282..2665612 100644
--- a/test/regress_main.c
+++ b/test/regress_main.c
@@ -33,6 +33,14 @@
#include <fcntl.h>
#endif
+/* move_pthread_to_realtime_scheduling_class() */
+#ifdef EVENT__HAVE_MACH_MACH_H
+#include <mach/mach.h>
+#endif
+#ifdef EVENT__HAVE_MACH_MACH_TIME_H
+#include <mach/mach_time.h>
+#endif
+
#if defined(__APPLE__) && defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__)
#if (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1060 && \
__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070)
@@ -81,10 +89,12 @@
#include "event2/event-config.h"
#include "regress.h"
+#include "regress_thread.h"
#include "tinytest.h"
#include "tinytest_macros.h"
#include "../iocp-internal.h"
#include "../event-internal.h"
+#include "../evthread-internal.h"
struct evutil_weakrand_state test_weakrand_state;
@@ -186,6 +196,45 @@ ignore_log_cb(int s, const char *msg)
{
}
+/**
+ * Put into the real time scheduling class for better timers latency.
+ * https://developer.apple.com/library/archive/technotes/tn2169/_index.html#//apple_ref/doc/uid/DTS40013172-CH1-TNTAG6000
+ */
+#if defined(__APPLE__)
+static void move_pthread_to_realtime_scheduling_class(pthread_t pthread)
+{
+ mach_timebase_info_data_t info;
+ mach_timebase_info(&info);
+
+ const uint64_t NANOS_PER_MSEC = 1000000ULL;
+ double clock2abs =
+ ((double)info.denom / (double)info.numer) * NANOS_PER_MSEC;
+
+ thread_time_constraint_policy_data_t policy;
+ policy.period = 0;
+ policy.computation = (uint32_t)(5 * clock2abs); // 5 ms of work
+ policy.constraint = (uint32_t)(10 * clock2abs);
+ policy.preemptible = FALSE;
+
+ int kr = thread_policy_set(pthread_mach_thread_np(pthread),
+ THREAD_TIME_CONSTRAINT_POLICY,
+ (thread_policy_t)&policy,
+ THREAD_TIME_CONSTRAINT_POLICY_COUNT);
+ if (kr != KERN_SUCCESS) {
+ mach_error("thread_policy_set:", kr);
+ exit(1);
+ }
+}
+
+void thread_setup(THREAD_T pthread)
+{
+ move_pthread_to_realtime_scheduling_class(pthread);
+}
+#else /** \__APPLE__ */
+void thread_setup(THREAD_T pthread) {}
+#endif /** \!__APPLE__ */
+
+
void *
basic_test_setup(const struct testcase_t *testcase)
{
@@ -193,11 +242,19 @@ basic_test_setup(const struct testcase_t *testcase)
evutil_socket_t spair[2] = { -1, -1 };
struct basic_test_data *data = NULL;
+ thread_setup(THREAD_SELF());
+
#ifndef _WIN32
if (testcase->flags & TT_ENABLE_IOCP_FLAG)
return (void*)TT_SKIP;
#endif
+ if (testcase->flags & TT_ENABLE_DEBUG_MODE &&
+ !libevent_tests_running_in_debug_mode) {
+ event_enable_debug_mode();
+ libevent_tests_running_in_debug_mode = 1;
+ }
+
if (testcase->flags & TT_NEED_THREADS) {
if (!(testcase->flags & TT_FORK))
return NULL;
diff --git a/test/regress_ssl.c b/test/regress_ssl.c
index 68c2811..37dc334 100644
--- a/test/regress_ssl.c
+++ b/test/regress_ssl.c
@@ -148,9 +148,9 @@ ssl_getcert(EVP_PKEY *key)
X509_set_issuer_name(x509, name);
X509_NAME_free(name);
- X509_time_adj(X509_get_notBefore(x509), 0, &now);
+ X509_time_adj(X509_getm_notBefore(x509), 0, &now);
now += 3600;
- X509_time_adj(X509_get_notAfter(x509), 0, &now);
+ X509_time_adj(X509_getm_notAfter(x509), 0, &now);
X509_set_pubkey(x509, key);
tt_assert(0 != X509_sign(x509, key, EVP_sha1()));
@@ -469,8 +469,8 @@ regress_bufferevent_openssl(void *arg)
type = (enum regress_openssl_type)data->setup_data;
if (type & REGRESS_OPENSSL_RENEGOTIATE) {
- if (SSLeay() >= 0x10001000 &&
- SSLeay() < 0x1000104f) {
+ if (OPENSSL_VERSION_NUMBER >= 0x10001000 &&
+ OPENSSL_VERSION_NUMBER < 0x1000104f) {
/* 1.0.1 up to 1.0.1c has a bug where TLS1.1 and 1.2
* can't renegotiate with themselves. Disable. */
disable_tls_11_and_12 = 1;
@@ -974,6 +974,7 @@ regress_bufferevent_openssl_wm(void *arg)
tt_int_op(client.get, ==, client.limit);
tt_int_op(server.get, ==, server.limit);
+
end:
free(payload);
evbuffer_free(client.data);
@@ -981,6 +982,10 @@ end:
evconnlistener_free(listener);
bufferevent_free(client.bev);
bufferevent_free(server.bev);
+
+ /* XXX: by some reason otherise there is a leak */
+ if (!(type & REGRESS_OPENSSL_FILTER))
+ event_base_loop(base, EVLOOP_ONCE);
}
struct testcase_t ssl_testcases[] = {
diff --git a/test/regress_testutils.c b/test/regress_testutils.c
index 959347e..b0ce7db 100644
--- a/test/regress_testutils.c
+++ b/test/regress_testutils.c
@@ -110,7 +110,7 @@ regress_get_dnsserver(struct event_base *base,
memset(&my_addr, 0, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(*portnum);
- my_addr.sin_addr.s_addr = htonl(0x7f000001UL);
+ my_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
if (bind(sock, (struct sockaddr*)&my_addr, sizeof(my_addr)) < 0) {
evutil_closesocket(sock);
tt_abort_perror("bind");
diff --git a/test/regress_thread.h b/test/regress_thread.h
index db0d8d1..a954fef 100644
--- a/test/regress_thread.h
+++ b/test/regress_thread.h
@@ -27,23 +27,30 @@
#ifndef REGRESS_THREAD_H_INCLUDED_
#define REGRESS_THREAD_H_INCLUDED_
-#ifdef EVENT__HAVE_PTHREADS
+#if defined(_WIN32) /** _WIN32 */
+#define THREAD_T void * /* HANDLE */
+#define THREAD_FN unsigned __stdcall
+#define THREAD_RETURN() return (0)
+#define THREAD_SELF() GetCurrentThreadId()
+#define THREAD_START(threadvar, fn, arg) do { \
+ uintptr_t threadhandle = _beginthreadex(NULL,0,fn,(arg),0,NULL); \
+ (threadvar) = (THREAD_T)threadhandle; \
+ thread_setup(threadvar); \
+} while (0)
+#define THREAD_JOIN(th) WaitForSingleObject(th, INFINITE)
+#else /* !_WIN32 */
#include <pthread.h>
#define THREAD_T pthread_t
#define THREAD_FN void *
#define THREAD_RETURN() return (NULL)
-#define THREAD_START(threadvar, fn, arg) \
- pthread_create(&(threadvar), NULL, fn, arg)
+#define THREAD_SELF() pthread_self()
+#define THREAD_START(threadvar, fn, arg) do { \
+ if (!pthread_create(&(threadvar), NULL, fn, arg)) \
+ thread_setup(threadvar); \
+} while (0)
#define THREAD_JOIN(th) pthread_join(th, NULL)
-#else
-#define THREAD_T HANDLE
-#define THREAD_FN unsigned __stdcall
-#define THREAD_RETURN() return (0)
-#define THREAD_START(threadvar, fn, arg) do { \
- uintptr_t threadhandle = _beginthreadex(NULL,0,fn,(arg),0,NULL); \
- (threadvar) = (HANDLE) threadhandle; \
- } while (0)
-#define THREAD_JOIN(th) WaitForSingleObject(th, INFINITE)
-#endif
+#endif /* \!_WIN32 */
+
+void thread_setup(THREAD_T pthread);
#endif
diff --git a/test/regress_util.c b/test/regress_util.c
index 3da2070..45caa27 100644
--- a/test/regress_util.c
+++ b/test/regress_util.c
@@ -211,6 +211,65 @@ regress_ipv6_parse(void *ptr)
#endif
}
+static struct ipv6_entry_scope {
+ const char *addr;
+ ev_uint32_t res[4];
+ unsigned scope;
+ enum entry_status status;
+} ipv6_entries_scope[] = {
+ { "2001:DB8::", { 0x20010db8, 0, 0 }, 0, NORMAL },
+ { "2001:DB8::%0", { 0x20010db8, 0, 0, 0 }, 0, NORMAL },
+ { "2001:DB8::%1", { 0x20010db8, 0, 0, 0 }, 1, NORMAL },
+ { "foobar.", { 0, 0, 0, 0 }, 0, BAD },
+ { "2001:DB8::%does-not-exist", { 0, 0, 0, 0 }, 0, BAD },
+ { NULL, { 0, 0, 0, 0, }, 0, BAD },
+};
+static void
+regress_ipv6_parse_scope(void *ptr)
+{
+#ifdef AF_INET6
+ int i, j;
+ unsigned if_scope;
+
+ for (i = 0; ipv6_entries_scope[i].addr; ++i) {
+ struct ipv6_entry_scope *ent = &ipv6_entries_scope[i];
+ struct in6_addr in6;
+ int r;
+ r = evutil_inet_pton_scope(AF_INET6, ent->addr, &in6,
+ &if_scope);
+ if (r == 0) {
+ if (ent->status != BAD)
+ TT_FAIL(("%s did not parse, but it's a good address!",
+ ent->addr));
+ continue;
+ }
+ if (ent->status == BAD) {
+ TT_FAIL(("%s parsed, but we expected an error", ent->addr));
+ continue;
+ }
+ for (j = 0; j < 4; ++j) {
+ /* Can't use s6_addr32 here; some don't have it. */
+ ev_uint32_t u =
+ ((ev_uint32_t)in6.s6_addr[j*4 ] << 24) |
+ ((ev_uint32_t)in6.s6_addr[j*4+1] << 16) |
+ ((ev_uint32_t)in6.s6_addr[j*4+2] << 8) |
+ ((ev_uint32_t)in6.s6_addr[j*4+3]);
+ if (u != ent->res[j]) {
+ TT_FAIL(("%s did not parse as expected.", ent->addr));
+ continue;
+ }
+ }
+ if (if_scope != ent->scope) {
+ TT_FAIL(("%s did not parse as expected.", ent->addr));
+ continue;
+ }
+ }
+#else
+ TT_BLATHER(("Skipping IPv6 address parsing."));
+#endif
+}
+
+
static struct sa_port_ent {
const char *parse;
int safamily;
@@ -926,6 +985,16 @@ end:
}
static void
+test_EVUTIL_IS_(void *arg)
+{
+ tt_int_op(EVUTIL_ISDIGIT_('0'), ==, 1);
+ tt_int_op(EVUTIL_ISDIGIT_('a'), ==, 0);
+ tt_int_op(EVUTIL_ISDIGIT_('\xff'), ==, 0);
+end:
+ ;
+}
+
+static void
test_evutil_getaddrinfo(void *arg)
{
struct evutil_addrinfo *ai = NULL, *a;
@@ -1121,6 +1190,41 @@ end:
evutil_freeaddrinfo(ai);
}
+static void
+test_evutil_getaddrinfo_AI_ADDRCONFIG(void *arg)
+{
+ struct evutil_addrinfo *ai = NULL;
+ struct evutil_addrinfo hints;
+ int r;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = EVUTIL_AI_PASSIVE|EVUTIL_AI_ADDRCONFIG;
+
+ /* IPv4 */
+ r = evutil_getaddrinfo("127.0.0.1", "80", &hints, &ai);
+ tt_int_op(r, ==, 0);
+ tt_assert(ai);
+ tt_ptr_op(ai->ai_next, ==, NULL);
+ test_ai_eq(ai, "127.0.0.1:80", SOCK_STREAM, IPPROTO_TCP);
+ evutil_freeaddrinfo(ai);
+ ai = NULL;
+
+ /* IPv6 */
+ r = evutil_getaddrinfo("::1", "80", &hints, &ai);
+ tt_int_op(r, ==, 0);
+ tt_assert(ai);
+ tt_ptr_op(ai->ai_next, ==, NULL);
+ test_ai_eq(ai, "[::1]:80", SOCK_STREAM, IPPROTO_TCP);
+ evutil_freeaddrinfo(ai);
+ ai = NULL;
+
+end:
+ if (ai)
+ evutil_freeaddrinfo(ai);
+}
+
#ifdef _WIN32
static void
test_evutil_loadsyslib(void *arg)
@@ -1539,6 +1643,7 @@ end:
struct testcase_t util_testcases[] = {
{ "ipv4_parse", regress_ipv4_parse, 0, NULL, NULL },
{ "ipv6_parse", regress_ipv6_parse, 0, NULL, NULL },
+ { "ipv6_parse_scope", regress_ipv6_parse_scope, 0, NULL, NULL },
{ "sockaddr_port_parse", regress_sockaddr_port_parse, 0, NULL, NULL },
{ "sockaddr_port_format", regress_sockaddr_port_format, 0, NULL, NULL },
{ "sockaddr_predicates", test_evutil_sockaddr_predicates, 0,NULL,NULL },
@@ -1551,8 +1656,10 @@ struct testcase_t util_testcases[] = {
{ "upcast", test_evutil_upcast, 0, NULL, NULL },
{ "integers", test_evutil_integers, 0, NULL, NULL },
{ "rand", test_evutil_rand, TT_FORK, NULL, NULL },
+ { "EVUTIL_IS_", test_EVUTIL_IS_, 0, NULL, NULL },
{ "getaddrinfo", test_evutil_getaddrinfo, TT_FORK, NULL, NULL },
{ "getaddrinfo_live", test_evutil_getaddrinfo_live, TT_FORK|TT_OFF_BY_DEFAULT, NULL, NULL },
+ { "getaddrinfo_AI_ADDRCONFIG", test_evutil_getaddrinfo_AI_ADDRCONFIG, TT_FORK|TT_OFF_BY_DEFAULT, NULL, NULL },
#ifdef _WIN32
{ "loadsyslib", test_evutil_loadsyslib, TT_FORK, NULL, NULL },
#endif
diff --git a/test/test-changelist.c b/test/test-changelist.c
index 6e2466d..fd1a17f 100644
--- a/test/test-changelist.c
+++ b/test/test-changelist.c
@@ -182,11 +182,11 @@ main(int argc, char **argv)
if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1)
return (1);
- /* Initalize the event library */
+ /* Initialize the event library */
if (!(base = event_base_new()))
return (1);
- /* Initalize a timeout to terminate the test */
+ /* Initialize a timeout to terminate the test */
timeout = evtimer_new(base,timeout_cb,&timeout);
/* and watch for writability on one end of the pipe */
ev = event_new(base,pair[1],EV_WRITE | EV_PERSIST, write_cb, &ev);
diff --git a/test/test-closed.c b/test/test-closed.c
index 1dd9885..9e60504 100644
--- a/test/test-closed.c
+++ b/test/test-closed.c
@@ -104,6 +104,7 @@ main(int argc, char **argv)
event_base_dispatch(base);
/* Finalize library */
+ event_free(ev);
event_base_free(base);
return 0;
}
diff --git a/test/test-eof.c b/test/test-eof.c
index 284ead7..de2fd88 100644
--- a/test/test-eof.c
+++ b/test/test-eof.c
@@ -102,10 +102,10 @@ main(int argc, char **argv)
return (1);
shutdown(pair[0], EVUTIL_SHUT_WR);
- /* Initalize the event library */
+ /* Initialize the event library */
event_init();
- /* Initalize one event */
+ /* Initialize one event */
event_set(&ev, pair[1], EV_READ | EV_TIMEOUT, read_cb, &ev);
event_add(&ev, &timeout);
diff --git a/test/test-init.c b/test/test-init.c
index 92fbc6b..aea49ee 100644
--- a/test/test-init.c
+++ b/test/test-init.c
@@ -57,7 +57,7 @@ main(int argc, char **argv)
(void) WSAStartup(wVersionRequested, &wsaData);
#endif
- /* Initalize the event library */
+ /* Initialize the event library */
event_init();
return (0);
diff --git a/test/test-ratelim.c b/test/test-ratelim.c
index 9ee989b..34112e3 100644
--- a/test/test-ratelim.c
+++ b/test/test-ratelim.c
@@ -50,6 +50,10 @@
#include "event2/listener.h"
#include "event2/thread.h"
+#ifndef MIN
+#define MIN(a,b) (((a)<(b))?(a):(b))
+#endif
+
static struct evutil_weakrand_state weakrand_state;
static int cfg_verbose = 0;
@@ -85,6 +89,18 @@ struct client_state {
};
static const struct timeval *ms100_common=NULL;
+/* Timers bias for slow CPUs, affects:
+ * - cfg_connlimit_tolerance (--check-connlimit)
+ * - cfg_grouplimit_tolerance (--check-grouplimit)
+ * - cfg_stddev_tolerance (--check-stddev)
+ */
+static int timer_bias_events;
+static struct timeval timer_bias_start;
+double timer_bias_spend;
+/* Real cost is less (approximately ~5 usec),
+ * this macros adjusted to make the bias less */
+#define TIMER_MAX_COST_USEC 10
+
/* info from check_bucket_levels_cb */
static int total_n_bev_checks = 0;
static ev_int64_t total_rbucket_level=0;
@@ -244,6 +260,64 @@ group_drain_cb(evutil_socket_t fd, short events, void *arg)
bufferevent_rate_limit_group_decrement_write(ratelim_group, cfg_group_drain);
}
+static void
+timer_bias_cb(evutil_socket_t fd, short events, void *arg)
+{
+ struct event *event = arg;
+ struct timeval end;
+ struct timeval diff;
+
+ /** XXX: use rdtsc? (portability issues?) */
+ evutil_gettimeofday(&end, NULL);
+ evutil_timersub(&end, &timer_bias_start, &diff);
+ timer_bias_spend += diff.tv_sec + diff.tv_usec * 1e6;
+ timer_bias_start = end;
+
+ if (++timer_bias_events == 100)
+ event_del(event);
+}
+static double
+timer_bias_calculate(void)
+{
+ struct event_config *cfg = NULL;
+ struct event_base *base = NULL;
+ struct event *timer = NULL;
+ struct timeval tv = { 0, 1 };
+ int done = 0;
+
+ cfg = event_config_new();
+ if (!cfg)
+ goto err;
+ if (event_config_set_flag(cfg, EVENT_BASE_FLAG_PRECISE_TIMER))
+ goto err;
+ base = event_base_new_with_config(cfg);
+ if (!base)
+ goto err;
+
+ timer = event_new(base, -1, EV_PERSIST, timer_bias_cb, event_self_cbarg());
+ if (!timer || event_add(timer, &tv)) {
+ goto err;
+ }
+
+ evutil_gettimeofday(&timer_bias_start, NULL);
+ event_base_dispatch(base);
+ done = 1;
+
+err:
+ if (cfg)
+ event_config_free(cfg);
+ if (timer)
+ event_free(timer);
+ if (base)
+ event_base_free(base);
+
+ if (done)
+ return MIN(timer_bias_spend / 1e6 / timer_bias_events / TIMER_MAX_COST_USEC, 5);
+
+ fprintf(stderr, "Couldn't create event for CPU cycle counter bias\n");
+ return -1;
+}
+
static int
test_ratelimiting(void)
{
@@ -266,6 +340,7 @@ test_ratelimiting(void)
struct event_config *base_cfg;
struct event *periodic_level_check;
struct event *group_drain_event=NULL;
+ double timer_bias;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
@@ -275,6 +350,16 @@ test_ratelimiting(void)
if (0)
event_enable_debug_mode();
+ timer_bias = timer_bias_calculate();
+ if (timer_bias > 1) {
+ fprintf(stderr, "CPU is slow, timers bias is %f\n", timer_bias);
+ cfg_connlimit_tolerance *= timer_bias;
+ cfg_grouplimit_tolerance *= timer_bias;
+ cfg_stddev_tolerance *= timer_bias;
+ } else {
+ printf("CPU is fast enough, timers bias is %f\n", timer_bias);
+ }
+
base_cfg = event_config_new();
#ifdef _WIN32
@@ -376,7 +461,7 @@ test_ratelimiting(void)
ratelim_group = NULL; /* So no more responders get added */
event_free(periodic_level_check);
if (group_drain_event)
- event_del(group_drain_event);
+ event_free(group_drain_event);
for (i = 0; i < cfg_n_connections; ++i) {
bufferevent_free(bevs[i]);
diff --git a/test/test-time.c b/test/test-time.c
index c4d031e..a8b3846 100644
--- a/test/test-time.c
+++ b/test/test-time.c
@@ -81,8 +81,10 @@ time_cb(evutil_socket_t fd, short event, void *arg)
int
main(int argc, char **argv)
{
+ struct event_base *base;
struct timeval tv;
int i;
+
#ifdef _WIN32
WORD wVersionRequested;
WSADATA wsaData;
@@ -94,23 +96,28 @@ main(int argc, char **argv)
evutil_weakrand_seed_(&weakrand_state, 0);
- /* Initalize the event library */
- event_init();
+ if (getenv("EVENT_DEBUG_LOGGING_ALL")) {
+ event_enable_debug_logging(EVENT_DBG_ALL);
+ }
- for (i = 0; i < NEVENT; i++) {
- ev[i] = malloc(sizeof(struct event));
+ base = event_base_new();
- /* Initalize one event */
- evtimer_set(ev[i], time_cb, ev[i]);
+ for (i = 0; i < NEVENT; i++) {
+ ev[i] = evtimer_new(base, time_cb, event_self_cbarg());
tv.tv_sec = 0;
tv.tv_usec = rand_int(50000);
evtimer_add(ev[i], &tv);
}
- event_dispatch();
+ i = event_base_dispatch(base);
+ printf("event_base_dispatch=%d, called=%d, EVENT=%d\n",
+ i, called, NEVENT);
- printf("%d, %d\n", called, NEVENT);
- return (called < NEVENT);
+ if (i == 1 && called >= NEVENT) {
+ return EXIT_SUCCESS;
+ } else {
+ return EXIT_FAILURE;
+ }
}
diff --git a/test/test-weof.c b/test/test-weof.c
index 52c7afb..68e7cd4 100644
--- a/test/test-weof.c
+++ b/test/test-weof.c
@@ -99,10 +99,10 @@ main(int argc, char **argv)
if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1)
return (1);
- /* Initalize the event library */
+ /* Initialize the event library */
event_init();
- /* Initalize one event */
+ /* Initialize one event */
event_set(&ev, pair[1], EV_WRITE, write_cb, &ev);
event_add(&ev, NULL);
diff --git a/test/tinytest.c b/test/tinytest.c
index a94fb9d..85dfe74 100644
--- a/test/tinytest.c
+++ b/test/tinytest.c
@@ -60,12 +60,8 @@
#include "tinytest_macros.h"
#define LONGEST_TEST_NAME 16384
-
-#ifndef _WIN32
#define DEFAULT_TESTCASE_TIMEOUT 30U
-#else
-#define DEFAULT_TESTCASE_TIMEOUT 0U
-#endif
+#define MAGIC_EXITCODE 42
static int in_tinytest_main = 0; /**< true if we're in tinytest_main().*/
static int n_ok = 0; /**< Number of tests that have passed */
@@ -86,33 +82,73 @@ const char *cur_test_prefix = NULL; /**< prefix of the current test group */
/** Name of the current test, if we haven't logged is yet. Used for --quiet */
const char *cur_test_name = NULL;
+static void usage(struct testgroup_t *groups, int list_groups)
+ __attribute__((noreturn));
+static int process_test_option(struct testgroup_t *groups, const char *test);
+
#ifdef _WIN32
/* Copy of argv[0] for win32. */
static char commandname[MAX_PATH+1];
-#endif
-static void usage(struct testgroup_t *groups, int list_groups)
- __attribute__((noreturn));
-static int process_test_option(struct testgroup_t *groups, const char *test);
+struct timeout_thread_args {
+ const testcase_fn *fn;
+ void *env;
+};
+static DWORD WINAPI
+timeout_thread_proc_(LPVOID arg)
+{
+ struct timeout_thread_args *args = arg;
+ (*(args->fn))(args->env);
+ ExitThread(cur_test_outcome == FAIL ? 1 : 0);
+}
+
+static enum outcome
+testcase_run_in_thread_(const struct testcase_t *testcase, void *env)
+{
+ /* We will never run testcase in a new thread when the
+ timeout is set to zero */
+ assert(opt_timeout);
+ DWORD ret, tid;
+ HANDLE handle;
+ struct timeout_thread_args args = {
+ &(testcase->fn),
+ env
+ };
+
+ handle =CreateThread(NULL, 0, timeout_thread_proc_,
+ (LPVOID)&args, 0, &tid);
+ ret = WaitForSingleObject(handle, opt_timeout * 1000U);
+ if (ret == WAIT_OBJECT_0) {
+ ret = 0;
+ if (!GetExitCodeThread(handle, &ret)) {
+ printf("GetExitCodeThread failed\n");
+ ret = 1;
+ }
+ } else if (ret == WAIT_TIMEOUT) {
+ printf("timeout\n");
+ } else {
+ printf("Wait failed\n");
+ }
+ CloseHandle(handle);
+ if (ret == 0)
+ return OK;
+ else if (ret == MAGIC_EXITCODE)
+ return SKIP;
+ else
+ return FAIL;
+}
+#else
static unsigned int testcase_set_timeout_(void)
{
- if (!opt_timeout)
- return 0;
-#ifndef _WIN32
return alarm(opt_timeout);
-#else
- /** TODO: win32 support */
- fprintf(stderr, "You cannot set alarm on windows\n");
- exit(1);
-#endif
}
+
static unsigned int testcase_reset_timeout_(void)
{
-#ifndef _WIN32
return alarm(0);
-#endif
}
+#endif
static enum outcome
testcase_run_bare_(const struct testcase_t *testcase)
@@ -129,9 +165,17 @@ testcase_run_bare_(const struct testcase_t *testcase)
cur_test_outcome = OK;
{
- testcase_set_timeout_();
- testcase->fn(env);
- testcase_reset_timeout_();
+ if (opt_timeout) {
+#ifdef _WIN32
+ cur_test_outcome = testcase_run_in_thread_(testcase, env);
+#else
+ testcase_set_timeout_();
+ testcase->fn(env);
+ testcase_reset_timeout_();
+#endif
+ } else {
+ testcase->fn(env);
+ }
}
outcome = cur_test_outcome;
@@ -143,7 +187,6 @@ testcase_run_bare_(const struct testcase_t *testcase)
return outcome;
}
-#define MAGIC_EXITCODE 42
#ifndef NO_FORKING
@@ -164,7 +207,7 @@ testcase_run_forked_(const struct testgroup_t *group,
char buffer[LONGEST_TEST_NAME+256];
STARTUPINFOA si;
PROCESS_INFORMATION info;
- DWORD exitcode;
+ DWORD ret;
if (!in_tinytest_main) {
printf("\nERROR. On Windows, testcase_run_forked_ must be"
@@ -174,7 +217,7 @@ testcase_run_forked_(const struct testgroup_t *group,
if (opt_verbosity>0)
printf("[forking] ");
- snprintf(buffer, sizeof(buffer), "%s --RUNNING-FORKED %s %s%s",
+ snprintf(buffer, sizeof(buffer), "%s --RUNNING-FORKED %s --timeout 0 %s%s",
commandname, verbosity_flag, group->prefix, testcase->name);
memset(&si, 0, sizeof(si));
@@ -185,15 +228,23 @@ testcase_run_forked_(const struct testgroup_t *group,
0, NULL, NULL, &si, &info);
if (!ok) {
printf("CreateProcess failed!\n");
- return 0;
+ return FAIL;
+ }
+ ret = WaitForSingleObject(info.hProcess,
+ (opt_timeout ? opt_timeout * 1000U : INFINITE));
+
+ if (ret == WAIT_OBJECT_0) {
+ GetExitCodeProcess(info.hProcess, &ret);
+ } else if (ret == WAIT_TIMEOUT) {
+ printf("timeout\n");
+ } else {
+ printf("Wait failed\n");
}
- WaitForSingleObject(info.hProcess, INFINITE);
- GetExitCodeProcess(info.hProcess, &exitcode);
CloseHandle(info.hProcess);
CloseHandle(info.hThread);
- if (exitcode == 0)
+ if (ret == 0)
return OK;
- else if (exitcode == MAGIC_EXITCODE)
+ else if (ret == MAGIC_EXITCODE)
return SKIP;
else
return FAIL;
@@ -228,7 +279,7 @@ testcase_run_forked_(const struct testgroup_t *group,
return FAIL; /* unreachable */
} else {
/* parent */
- int status, r;
+ int status, r, exitcode;
char b[1];
/* Close this now, so that if the other side closes it,
* our read fails. */
@@ -236,12 +287,20 @@ testcase_run_forked_(const struct testgroup_t *group,
r = (int)read(outcome_pipe[0], b, 1);
if (r == 0) {
printf("[Lost connection!] ");
- return 0;
+ return FAIL;
} else if (r != 1) {
perror("read outcome from pipe");
}
waitpid(pid, &status, 0);
+ exitcode = WEXITSTATUS(status);
close(outcome_pipe[0]);
+ if (opt_verbosity>1)
+ printf("%s%s: exited with %i (%i)\n", group->prefix, testcase->name, exitcode, status);
+ if (exitcode != 0)
+ {
+ printf("[atexit failure!] ");
+ return FAIL;
+ }
return b[0]=='Y' ? OK : (b[0]=='S' ? SKIP : FAIL);
}
#endif
@@ -520,7 +579,7 @@ tinytest_set_test_failed_(void)
printf("%s%s: ", cur_test_prefix, cur_test_name);
cur_test_name = NULL;
}
- cur_test_outcome = 0;
+ cur_test_outcome = FAIL;
}
void
diff --git a/test/tinytest_macros.h b/test/tinytest_macros.h
index e34e74e..e01f5d5 100644
--- a/test/tinytest_macros.h
+++ b/test/tinytest_macros.h
@@ -113,8 +113,8 @@
#define tt_assert_test_fmt_type(a,b,str_test,type,test,printf_type,printf_fmt, \
setup_block,cleanup_block,die_on_fail) \
TT_STMT_BEGIN \
- type val1_ = (a); \
- type val2_ = (b); \
+ type val1_ = (type)(a); \
+ type val2_ = (type)(b); \
int tt_status_ = (test); \
if (!tt_status_ || tinytest_get_verbosity_()>1) { \
printf_type print_; \