diff options
Diffstat (limited to 'test/regress_dns.c')
-rw-r--r-- | test/regress_dns.c | 244 |
1 files changed, 208 insertions, 36 deletions
diff --git a/test/regress_dns.c b/test/regress_dns.c index 4d90d671..e03c143c 100644 --- a/test/regress_dns.c +++ b/test/regress_dns.c @@ -24,8 +24,9 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "../util-internal.h" -#ifdef WIN32 +#ifdef _WIN32 #include <winsock2.h> #include <windows.h> #include <ws2tcpip.h> @@ -35,18 +36,18 @@ #include <sys/types.h> #include <sys/stat.h> -#ifdef _EVENT_HAVE_SYS_TIME_H +#ifdef EVENT__HAVE_SYS_TIME_H #include <sys/time.h> #endif #include <sys/queue.h> -#ifndef WIN32 +#ifndef _WIN32 #include <sys/socket.h> #include <signal.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #endif -#ifdef _EVENT_HAVE_NETINET_IN6_H +#ifdef EVENT__HAVE_NETINET_IN6_H #include <netinet/in6.h> #endif #ifdef HAVE_NETDB_H @@ -71,8 +72,6 @@ #include "regress.h" #include "regress_testutils.h" -#include "../util-internal.h" - static int dns_ok = 0; static int dns_got_cancel = 0; static int dns_err = 0; @@ -99,7 +98,7 @@ dns_gethostbyname_cb(int result, char type, int count, int ttl, switch (type) { case DNS_IPv6_AAAA: { -#if defined(_EVENT_HAVE_STRUCT_IN6_ADDR) && defined(_EVENT_HAVE_INET_NTOP) && defined(INET6_ADDRSTRLEN) +#if defined(EVENT__HAVE_STRUCT_IN6_ADDR) && defined(EVENT__HAVE_INET_NTOP) && defined(INET6_ADDRSTRLEN) struct in6_addr *in6_addrs = addresses; char buf[INET6_ADDRSTRLEN+1]; int i; @@ -320,7 +319,7 @@ dns_server_gethostbyname_cb(int result, char type, int count, int ttl, break; } case DNS_IPv6_AAAA: { -#if defined (_EVENT_HAVE_STRUCT_IN6_ADDR) && defined(_EVENT_HAVE_INET_NTOP) && defined(INET6_ADDRSTRLEN) +#if defined (EVENT__HAVE_STRUCT_IN6_ADDR) && defined(EVENT__HAVE_INET_NTOP) && defined(INET6_ADDRSTRLEN) struct in6_addr *in6_addrs = addresses; char buf[INET6_ADDRSTRLEN+1]; if (memcmp(&in6_addrs[0].s6_addr, "abcdefghijklmnop", 16) @@ -444,6 +443,7 @@ end: static int n_replies_left; static struct event_base *exit_base; +static struct evdns_server_port *exit_port; struct generic_dns_callback_result { int result; @@ -484,8 +484,14 @@ generic_dns_callback(int result, char type, int count, int ttl, void *addresses, res->addrs = res->addrs_buf; } - if (--n_replies_left == 0) - event_base_loopexit(exit_base, NULL); + --n_replies_left; + if (n_replies_left == 0) { + if (exit_port) { + evdns_close_server_port(exit_port); + exit_port = NULL; + } else + event_base_loopexit(exit_base, NULL); + } } static struct regress_dns_server_table search_table[] = { @@ -655,7 +661,7 @@ fail_server_cb(struct evdns_server_request *req, void *data) event_base_loopexit(exit_base, NULL); } - evutil_inet_pton(AF_INET, "16.32.64.128", &in); + tt_assert(evutil_inet_pton(AF_INET, "16.32.64.128", &in)); evdns_server_request_add_a_reply(req, question, 1, &in.s_addr, 100); tt_assert(! evdns_server_request_respond(req, 0)) @@ -665,7 +671,7 @@ end: } static void -dns_retry_test(void *arg) +dns_retry_test_impl(void *arg, int flags) { struct basic_test_data *data = arg; struct event_base *base = data->base; @@ -682,11 +688,11 @@ dns_retry_test(void *arg) tt_assert(port); evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum); - dns = evdns_base_new(base, 0); + dns = evdns_base_new(base, flags); tt_assert(!evdns_base_nameserver_ip_add(dns, buf)); - tt_assert(! evdns_base_set_option(dns, "timeout", "0.3")); + tt_assert(! evdns_base_set_option(dns, "timeout", "0.2")); tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "10")); - tt_assert(! evdns_base_set_option(dns, "initial-probe-timeout", "0.5")); + tt_assert(! evdns_base_set_option(dns, "initial-probe-timeout", "0.1")); evdns_base_resolve_ipv4(dns, "host.example.com", 0, generic_dns_callback, &r1); @@ -705,8 +711,8 @@ dns_retry_test(void *arg) /* Now try again, but this time have the server get treated as * failed, so we can send it a test probe. */ drop_count = 4; - tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "3")); - tt_assert(! evdns_base_set_option(dns, "attempts:", "4")); + tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "2")); + tt_assert(! evdns_base_set_option(dns, "attempts:", "3")); memset(&r1, 0, sizeof(r1)); evdns_base_resolve_ipv4(dns, "host.example.com", 0, @@ -737,6 +743,16 @@ end: if (port) evdns_close_server_port(port); } +static void +dns_retry_test(void *arg) +{ + dns_retry_test_impl(arg, 0); +} +static void +dns_retry_disable_when_inactive_test(void *arg) +{ + dns_retry_test_impl(arg, EVDNS_BASE_DISABLE_WHEN_INACTIVE); +} static struct regress_dns_server_table internal_error_table[] = { /* Error 4 (NOTIMPL) makes us reissue the request to another server @@ -754,7 +770,7 @@ static struct regress_dns_server_table reissue_table[] = { }; static void -dns_reissue_test(void *arg) +dns_reissue_test_impl(void *arg, int flags) { struct basic_test_data *data = arg; struct event_base *base = data->base; @@ -773,7 +789,7 @@ dns_reissue_test(void *arg) evutil_snprintf(buf1, sizeof(buf1), "127.0.0.1:%d", (int)portnum1); evutil_snprintf(buf2, sizeof(buf2), "127.0.0.1:%d", (int)portnum2); - dns = evdns_base_new(base, 0); + dns = evdns_base_new(base, flags); tt_assert(!evdns_base_nameserver_ip_add(dns, buf1)); tt_assert(! evdns_base_set_option(dns, "timeout:", "0.3")); tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "2")); @@ -806,6 +822,16 @@ end: if (port2) evdns_close_server_port(port2); } +static void +dns_reissue_test(void *arg) +{ + dns_reissue_test_impl(arg, 0); +} +static void +dns_reissue_disable_when_inactive_test(void *arg) +{ + dns_reissue_test_impl(arg, EVDNS_BASE_DISABLE_WHEN_INACTIVE); +} #if 0 static void @@ -820,21 +846,29 @@ dumb_bytes_fn(char *p, size_t n) #endif static void -dns_inflight_test(void *arg) +dns_inflight_test_impl(void *arg, int flags) { struct basic_test_data *data = arg; struct event_base *base = data->base; struct evdns_base *dns = NULL; + struct evdns_server_port *dns_port = NULL; ev_uint16_t portnum = 0; char buf[64]; + int disable_when_inactive = flags & EVDNS_BASE_DISABLE_WHEN_INACTIVE; struct generic_dns_callback_result r[20]; int i; - tt_assert(regress_dnsserver(base, &portnum, reissue_table)); + dns_port = regress_get_dnsserver(base, &portnum, NULL, + regress_dns_server_cb, reissue_table); + tt_assert(dns_port); + if (disable_when_inactive) { + exit_port = dns_port; + } + evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum); - dns = evdns_base_new(base, 0); + dns = evdns_base_new(base, flags); tt_assert(!evdns_base_nameserver_ip_add(dns, buf)); tt_assert(! evdns_base_set_option(dns, "max-inflight:", "3")); tt_assert(! evdns_base_set_option(dns, "randomize-case:", "0")); @@ -856,7 +890,65 @@ dns_inflight_test(void *arg) end: if (dns) evdns_base_free(dns, 0); + if (exit_port) { + evdns_close_server_port(exit_port); + exit_port = NULL; + } else if (! disable_when_inactive) { + evdns_close_server_port(dns_port); + } +} + +static void +dns_inflight_test(void *arg) +{ + dns_inflight_test_impl(arg, 0); +} + +static void +dns_disable_when_inactive_test(void *arg) +{ + dns_inflight_test_impl(arg, EVDNS_BASE_DISABLE_WHEN_INACTIVE); +} + +static void +dns_disable_when_inactive_no_ns_test(void *arg) +{ + struct basic_test_data *data = arg; + struct event_base *base = data->base, *inactive_base; + struct evdns_base *dns = NULL; + ev_uint16_t portnum = 0; + char buf[64]; + struct generic_dns_callback_result r; + + inactive_base = event_base_new(); + tt_assert(inactive_base); + + /** Create dns server with inactive base, to avoid replying to clients */ + tt_assert(regress_dnsserver(inactive_base, &portnum, search_table)); + evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum); + + dns = evdns_base_new(base, EVDNS_BASE_DISABLE_WHEN_INACTIVE); + tt_assert(!evdns_base_nameserver_ip_add(dns, buf)); + tt_assert(! evdns_base_set_option(dns, "timeout:", "0.1")); + + evdns_base_resolve_ipv4(dns, "foof.example.com", 0, generic_dns_callback, &r); + n_replies_left = 1; + exit_base = base; + + event_base_dispatch(base); + + tt_int_op(n_replies_left, ==, 0); + + tt_int_op(r.result, ==, DNS_ERR_TIMEOUT); + tt_int_op(r.count, ==, 0); + tt_ptr_op(r.addrs, ==, NULL); + +end: + if (dns) + evdns_base_free(dns, 0); regress_clean_dnsserver(); + if (inactive_base) + event_base_free(inactive_base); } /* === Test for bufferevent_socket_connect_hostname */ @@ -883,6 +975,8 @@ be_getaddrinfo_server_cb(struct evdns_server_request *req, void *data) struct in6_addr ans6; memset(&ans6, 0, sizeof(ans6)); + TT_BLATHER(("Got question about %s, type=%d", qname, qtype)); + if (qtype == EVDNS_TYPE_A && qclass == EVDNS_CLASS_INET && !evutil_ascii_strcasecmp(qname, "nobodaddy.example.com")) { @@ -983,10 +1077,13 @@ be_getaddrinfo_server_cb(struct evdns_server_request *req, void *data) TT_GRIPE(("Got weird request for %s",qname)); } } - if (added_any) + if (added_any) { + TT_BLATHER(("answering")); evdns_server_request_respond(req, 0); - else + } else { + TT_BLATHER(("saying nexist.")); evdns_server_request_respond(req, 3); + } } /* Implements a listener for connect_hostname test. */ @@ -1207,15 +1304,19 @@ test_getaddrinfo_async(void *arg) struct evdns_server_port *port = NULL; ev_uint16_t dns_port = 0; int n_dns_questions = 0; + struct evdns_base *dns_base; + + memset(a_out, 0, sizeof(a_out)); + memset(&local_outcome, 0, sizeof(local_outcome)); - struct evdns_base *dns_base = evdns_base_new(data->base, 0); + dns_base = evdns_base_new(data->base, 0); tt_assert(dns_base); /* for localhost */ evdns_base_load_hosts(dns_base, NULL); - memset(a_out, 0, sizeof(a_out)); - memset(&local_outcome, 0, sizeof(local_outcome)); + tt_assert(! evdns_base_set_option(dns_base, "timeout", "0.3")); + tt_assert(! evdns_base_set_option(dns_base, "getaddrinfo-allow-skew", "0.2")); n_gai_results_pending = 10000; /* don't think about exiting yet. */ @@ -1555,7 +1656,8 @@ test_getaddrinfo_async(void *arg) end: if (local_outcome.ai) evutil_freeaddrinfo(local_outcome.ai); - for (i=0;i<10;++i) { +#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) + for (i=0;i<(int)ARRAY_SIZE(a_out);++i) { if (a_out[i].ai) evutil_freeaddrinfo(a_out[i].ai); } @@ -1687,7 +1789,8 @@ testleak_setup(const struct testcase_t *testcase) allocated_chunks = 0; event_set_mem_functions(cnt_malloc, cnt_realloc, cnt_free); - event_enable_debug_mode(); + if (!libevent_tests_running_in_debug_mode) + event_enable_debug_mode(); /* not mm_calloc: we don't want to mess with the count. */ env = calloc(1, sizeof(struct testleak_env_t)); @@ -1705,7 +1808,7 @@ testleak_cleanup(const struct testcase_t *testcase, void *env_) int ok = 0; struct testleak_env_t *env = env_; tt_assert(env); -#ifdef _EVENT_DISABLE_DEBUG_MODE +#ifdef EVENT__DISABLE_DEBUG_MODE tt_int_op(allocated_chunks, ==, 0); #else /* FIXME: that's `1' because of event_debug_map_HT_GROW */ @@ -1748,6 +1851,57 @@ test_dbg_leak_cancel(void *env_) } static void +dbg_leak_resume(void *env_, int cancel, int send_err_shutdown) +{ + /* cancel, loop, free/dns, free/base */ + struct testleak_env_t *env = env_; + if (cancel) { + evdns_cancel_request(env->dns_base, env->req); + tt_assert(!evdns_base_resume(env->dns_base)); + } else { + /* TODO: No nameservers, request can't be processed, must be errored */ + tt_assert(!evdns_base_resume(env->dns_base)); + } + + /** + * Because we don't cancel request, + * and want our callback to recieve DNS_ERR_SHUTDOWN, + * we use deferred callback, and there was + * - one extra malloc(), + * @see reply_schedule_callback() + * - and one missing free + * @see request_finished() (req->handle->pending_cb = 1) + * than we don't need to count in testleak_cleanup() + * + * So just decrement allocated_chunks to 2, + * like we already take care about it. + */ + if (!cancel && send_err_shutdown) { + allocated_chunks -= 2; + } + + event_base_loop(env->base, EVLOOP_NONBLOCK); + +end: + evdns_base_free(env->dns_base, send_err_shutdown); + env->dns_base = 0; + + event_base_free(env->base); + env->base = 0; +} + +#define IMPL_DBG_LEAK_RESUME(name, cancel, send_err_shutdown) \ + static void \ + test_dbg_leak_##name##_(void *env_) \ + { \ + dbg_leak_resume(env_, cancel, send_err_shutdown); \ + } +IMPL_DBG_LEAK_RESUME(resume, 0, 0) +IMPL_DBG_LEAK_RESUME(cancel_and_resume, 1, 0) +IMPL_DBG_LEAK_RESUME(resume_send_err, 0, 1) +IMPL_DBG_LEAK_RESUME(cancel_and_resume_send_err, 1, 1) + +static void test_dbg_leak_shutdown(void *env_) { /* free/dns, loop, free/base */ @@ -1816,6 +1970,8 @@ end: evdns_base_free(dns_base, 1); if (server) evdns_close_server_port(server); + if (base) + event_base_free(base); if (fd >= 0) evutil_closesocket(fd); } @@ -1827,18 +1983,26 @@ end: struct testcase_t dns_testcases[] = { DNS_LEGACY(server, TT_FORK|TT_NEED_BASE), - DNS_LEGACY(gethostbyname, TT_FORK|TT_NEED_BASE|TT_NEED_DNS), - DNS_LEGACY(gethostbyname6, TT_FORK|TT_NEED_BASE|TT_NEED_DNS), - DNS_LEGACY(gethostbyaddr, TT_FORK|TT_NEED_BASE|TT_NEED_DNS), - { "resolve_reverse", dns_resolve_reverse, TT_FORK, NULL, NULL }, + DNS_LEGACY(gethostbyname, TT_FORK|TT_NEED_BASE|TT_NEED_DNS|TT_OFF_BY_DEFAULT), + DNS_LEGACY(gethostbyname6, TT_FORK|TT_NEED_BASE|TT_NEED_DNS|TT_OFF_BY_DEFAULT), + DNS_LEGACY(gethostbyaddr, TT_FORK|TT_NEED_BASE|TT_NEED_DNS|TT_OFF_BY_DEFAULT), + { "resolve_reverse", dns_resolve_reverse, TT_FORK|TT_OFF_BY_DEFAULT, NULL, NULL }, { "search", dns_search_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, { "search_cancel", dns_search_cancel_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, - { "retry", dns_retry_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, - { "reissue", dns_reissue_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, + { "retry", dns_retry_test, TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL }, + { "retry_disable_when_inactive", dns_retry_disable_when_inactive_test, + TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL }, + { "reissue", dns_reissue_test, TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL }, + { "reissue_disable_when_inactive", dns_reissue_disable_when_inactive_test, + TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL }, { "inflight", dns_inflight_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, { "bufferevent_connect_hostname", test_bufferevent_connect_hostname, TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, + { "disable_when_inactive", dns_disable_when_inactive_test, + TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, + { "disable_when_inactive_no_ns", dns_disable_when_inactive_no_ns_test, + TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, { "getaddrinfo_async", test_getaddrinfo_async, TT_FORK|TT_NEED_BASE, &basic_setup, (char*)"" }, @@ -1848,6 +2012,14 @@ struct testcase_t dns_testcases[] = { #ifdef EVENT_SET_MEM_FUNCTIONS_IMPLEMENTED { "leak_shutdown", test_dbg_leak_shutdown, TT_FORK, &testleak_funcs, NULL }, { "leak_cancel", test_dbg_leak_cancel, TT_FORK, &testleak_funcs, NULL }, + + { "leak_resume", test_dbg_leak_resume_, TT_FORK, &testleak_funcs, NULL }, + { "leak_cancel_and_resume", test_dbg_leak_cancel_and_resume_, + TT_FORK, &testleak_funcs, NULL }, + { "leak_resume_send_err", test_dbg_leak_resume_send_err_, + TT_FORK, &testleak_funcs, NULL }, + { "leak_cancel_and_resume_send_err", test_dbg_leak_cancel_and_resume_send_err_, + TT_FORK, &testleak_funcs, NULL }, #endif END_OF_TESTCASES |