]> granicus.if.org Git - libevent/commitdiff
Add a stress test for getaddrinfo_cancel
authorNick Mathewson <nickm@torproject.org>
Mon, 22 Nov 2010 21:24:09 +0000 (16:24 -0500)
committerNick Mathewson <nickm@torproject.org>
Mon, 22 Nov 2010 21:24:09 +0000 (16:24 -0500)
test/regress_dns.c

index 55f1158bf6755ac1f5347c4b4bb4a71c3a626c06..c69370efbf2c9c4d1d3caad389a4fdc697f8c92a 100644 (file)
@@ -1543,6 +1543,136 @@ end:
                evdns_base_free(dns_base, 0);
 }
 
+struct gaic_request_status {
+       int magic;
+       struct event_base *base;
+       struct evdns_base *dns_base;
+       struct evdns_getaddrinfo_request *request;
+       struct event cancel_event;
+       int canceled;
+};
+
+#define GAIC_MAGIC 0x1234abcd
+
+static int pending = 0;
+
+static void
+gaic_cancel_request_cb(evutil_socket_t fd, short what, void *arg)
+{
+       struct gaic_request_status *status = arg;
+
+       tt_assert(status->magic == GAIC_MAGIC);
+       status->canceled = 1;
+       evdns_getaddrinfo_cancel(status->request);
+       return;
+end:
+       event_base_loopexit(status->base, NULL);
+}
+
+static void
+gaic_server_cb(struct evdns_server_request *req, void *arg)
+{
+       ev_uint32_t answer = 0x7f000001;
+       tt_assert(req->nquestions);
+       evdns_server_request_add_a_reply(req, req->questions[0]->name, 1,
+           &answer, 100);
+       evdns_server_request_respond(req, 0);
+       return;
+end:
+       evdns_server_request_respond(req, DNS_ERR_REFUSED);
+}
+
+
+static void
+gaic_getaddrinfo_cb(int result, struct evutil_addrinfo *res, void *arg)
+{
+       struct gaic_request_status *status = arg;
+       struct event_base *base = status->base;
+       tt_assert(status->magic == GAIC_MAGIC);
+
+       if (result == EVUTIL_EAI_CANCEL) {
+               tt_assert(status->canceled);
+       }
+       event_del(&status->cancel_event);
+
+       memset(status, 0xf0, sizeof(*status));
+       free(status);
+
+end:
+       if (--pending <= 0)
+               event_base_loopexit(base, NULL);
+}
+
+static void
+gaic_launch(struct event_base *base, struct evdns_base *dns_base)
+{
+       struct gaic_request_status *status = calloc(1,sizeof(*status));
+       struct timeval tv = { 0, 10000 };
+       status->magic = GAIC_MAGIC;
+       status->base = base;
+       status->dns_base = dns_base;
+       event_assign(&status->cancel_event, base, -1, 0, gaic_cancel_request_cb,
+           status);
+       status->request = evdns_getaddrinfo(dns_base,
+           "foobar.bazquux.example.com", "80", NULL, gaic_getaddrinfo_cb,
+           status);
+       event_add(&status->cancel_event, &tv);
+       ++pending;
+}
+
+static void
+test_getaddrinfo_async_cancel_stress(void *arg)
+{
+       struct basic_test_data *data = arg;
+       struct event_base *base = data->base;
+       struct evdns_base *dns_base = NULL;
+       struct evdns_server_port *server = NULL;
+       evutil_socket_t fd = -1;
+       struct sockaddr_in sin;
+       struct sockaddr_storage ss;
+       ev_socklen_t slen;
+       int i;
+
+       base = event_base_new();
+       dns_base = evdns_base_new(base, 0);
+
+       memset(&sin, 0, sizeof(sin));
+       sin.sin_family = AF_INET;
+       sin.sin_port = 0;
+       sin.sin_addr.s_addr = htonl(0x7f000001);
+       if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+               tt_abort_perror("socket");
+       }
+       evutil_make_socket_nonblocking(fd);
+       if (bind(fd, (struct sockaddr*)&sin, sizeof(sin))<0) {
+               tt_abort_perror("bind");
+       }
+       server = evdns_add_server_port_with_base(base, fd, 0, gaic_server_cb,
+           base);
+
+       memset(&ss, 0, sizeof(ss));
+       slen = sizeof(ss);
+       if (getsockname(fd, (struct sockaddr*)&ss, &slen)<0) {
+               tt_abort_perror("getsockname");
+       }
+       evdns_base_nameserver_sockaddr_add(dns_base,
+           (struct sockaddr*)&ss, slen, 0);
+
+       for (i = 0; i < 1000; ++i) {
+               gaic_launch(base, dns_base);
+       }
+
+       event_base_dispatch(base);
+
+end:
+       if (dns_base)
+               evdns_base_free(dns_base, 1);
+       if (server)
+               evdns_close_server_port(server);
+       if (fd >= 0)
+               evutil_closesocket(fd);
+}
+
 
 #define DNS_LEGACY(name, flags)                                               \
        { #name, run_legacy_test_fn, flags|TT_LEGACY, &legacy_setup,   \
@@ -1565,6 +1695,8 @@ struct testcase_t dns_testcases[] = {
 
        { "getaddrinfo_async", test_getaddrinfo_async,
          TT_FORK|TT_NEED_BASE, &basic_setup, (char*)"" },
+       { "getaddrinfo_cancel_stress", test_getaddrinfo_async_cancel_stress,
+         TT_FORK|TT_NEED_BASE, &basic_setup, (char*)"" },
 
        END_OF_TESTCASES
 };