summaryrefslogtreecommitdiffstats
path: root/third_party/libevent/test/regress_http.c
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libevent/test/regress_http.c')
-rw-r--r--third_party/libevent/test/regress_http.c122
1 files changed, 112 insertions, 10 deletions
diff --git a/third_party/libevent/test/regress_http.c b/third_party/libevent/test/regress_http.c
index 7dc763c..1e2a1eb 100644
--- a/third_party/libevent/test/regress_http.c
+++ b/third_party/libevent/test/regress_http.c
@@ -42,7 +42,7 @@
#include <sys/queue.h>
#ifndef WIN32
#include <sys/socket.h>
-#include <sys/signal.h>
+#include <signal.h>
#include <unistd.h>
#include <netdb.h>
#endif
@@ -70,6 +70,7 @@ void http_basic_cb(struct evhttp_request *req, void *arg);
static void http_chunked_cb(struct evhttp_request *req, void *arg);
void http_post_cb(struct evhttp_request *req, void *arg);
void http_dispatcher_cb(struct evhttp_request *req, void *arg);
+static void http_large_delay_cb(struct evhttp_request *req, void *arg);
static struct evhttp *
http_setup(short *pport, struct event_base *base)
@@ -94,6 +95,7 @@ http_setup(short *pport, struct event_base *base)
evhttp_set_cb(myhttp, "/test", http_basic_cb, NULL);
evhttp_set_cb(myhttp, "/chunked", http_chunked_cb, NULL);
evhttp_set_cb(myhttp, "/postit", http_post_cb, NULL);
+ evhttp_set_cb(myhttp, "/largedelay", http_large_delay_cb, NULL);
evhttp_set_cb(myhttp, "/", http_dispatcher_cb, NULL);
*pport = port;
@@ -375,6 +377,31 @@ http_basic_test(void)
fprintf(stdout, "OK\n");
}
+static struct evhttp_connection *delayed_client;
+
+static void
+http_delay_reply(int fd, short what, void *arg)
+{
+ struct evhttp_request *req = arg;
+
+ evhttp_send_reply(req, HTTP_OK, "Everything is fine", NULL);
+
+ ++test_ok;
+}
+
+static void
+http_large_delay_cb(struct evhttp_request *req, void *arg)
+{
+ struct timeval tv;
+ timerclear(&tv);
+ tv.tv_sec = 3;
+
+ event_once(-1, EV_TIMEOUT, http_delay_reply, req, &tv);
+
+ /* here we close the client connection which will cause an EOF */
+ evhttp_connection_fail(delayed_client, EVCON_HTTP_EOF);
+}
+
void http_request_done(struct evhttp_request *, void *);
void http_request_empty_done(struct evhttp_request *, void *);
@@ -819,6 +846,7 @@ http_failure_test(void)
static void
close_detect_done(struct evhttp_request *req, void *arg)
{
+ struct timeval tv;
if (req == NULL || req->response_code != HTTP_OK) {
fprintf(stderr, "FAILED\n");
@@ -826,7 +854,11 @@ close_detect_done(struct evhttp_request *req, void *arg)
}
test_ok = 1;
- event_loopexit(NULL);
+
+ timerclear(&tv);
+ tv.tv_sec = 3; /* longer than the http time out */
+
+ event_loopexit(&tv);
}
static void
@@ -853,7 +885,7 @@ close_detect_cb(struct evhttp_request *req, void *arg)
struct evhttp_connection *evcon = arg;
struct timeval tv;
- if (req->response_code != HTTP_OK) {
+ if (req != NULL && req->response_code != HTTP_OK) {
fprintf(stderr, "FAILED\n");
exit(1);
@@ -868,14 +900,15 @@ close_detect_cb(struct evhttp_request *req, void *arg)
static void
-http_close_detection(void)
+http_close_detection(int with_delay)
{
short port = -1;
struct evhttp_connection *evcon = NULL;
struct evhttp_request *req = NULL;
test_ok = 0;
- fprintf(stdout, "Testing Connection Close Detection: ");
+ fprintf(stdout, "Testing Connection Close Detection%s: ",
+ with_delay ? " (with delay)" : "");
http = http_setup(&port, NULL);
@@ -888,6 +921,8 @@ http_close_detection(void)
exit(1);
}
+ delayed_client = evcon;
+
/*
* At this point, we want to schedule a request to the HTTP
* server using our make request method.
@@ -899,7 +934,8 @@ http_close_detection(void)
evhttp_add_header(req->output_headers, "Host", "somehost");
/* We give ownership of the request to the connection */
- if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) {
+ if (evhttp_make_request(evcon,
+ req, EVHTTP_REQ_GET, with_delay ? "/largedelay" : "/test") == -1) {
fprintf(stdout, "FAILED\n");
exit(1);
}
@@ -911,6 +947,12 @@ http_close_detection(void)
exit(1);
}
+ /* at this point, the http server should have no connection */
+ if (TAILQ_FIRST(&http->connections) != NULL) {
+ fprintf(stdout, "FAILED (left connections)\n");
+ exit(1);
+ }
+
evhttp_connection_free(evcon);
evhttp_free(http);
@@ -953,13 +995,16 @@ http_bad_header_test(void)
if (evhttp_add_header(&headers, "One\r", "Two") != -1)
goto fail;
-
+ if (evhttp_add_header(&headers, "One", "Two") != 0)
+ goto fail;
+ if (evhttp_add_header(&headers, "One", "Two\r\n Three") != 0)
+ goto fail;
+ if (evhttp_add_header(&headers, "One\r", "Two") != -1)
+ goto fail;
if (evhttp_add_header(&headers, "One\n", "Two") != -1)
goto fail;
-
if (evhttp_add_header(&headers, "One", "Two\r") != -1)
goto fail;
-
if (evhttp_add_header(&headers, "One", "Two\n") != -1)
goto fail;
@@ -972,6 +1017,61 @@ fail:
exit(1);
}
+static int validate_header(
+ const struct evkeyvalq* headers,
+ const char *key, const char *value)
+{
+ const char *real_val = evhttp_find_header(headers, key);
+ if (real_val == NULL)
+ return (-1);
+ if (strcmp(real_val, value) != 0)
+ return (-1);
+ return (0);
+}
+
+static void
+http_parse_query_test(void)
+{
+ struct evkeyvalq headers;
+
+ fprintf(stdout, "Testing HTTP query parsing: ");
+
+ TAILQ_INIT(&headers);
+
+ evhttp_parse_query("http://www.test.com/?q=test", &headers);
+ if (validate_header(&headers, "q", "test") != 0)
+ goto fail;
+ evhttp_clear_headers(&headers);
+
+ evhttp_parse_query("http://www.test.com/?q=test&foo=bar", &headers);
+ if (validate_header(&headers, "q", "test") != 0)
+ goto fail;
+ if (validate_header(&headers, "foo", "bar") != 0)
+ goto fail;
+ evhttp_clear_headers(&headers);
+
+ evhttp_parse_query("http://www.test.com/?q=test+foo", &headers);
+ if (validate_header(&headers, "q", "test foo") != 0)
+ goto fail;
+ evhttp_clear_headers(&headers);
+
+ evhttp_parse_query("http://www.test.com/?q=test%0Afoo", &headers);
+ if (validate_header(&headers, "q", "test\nfoo") != 0)
+ goto fail;
+ evhttp_clear_headers(&headers);
+
+ evhttp_parse_query("http://www.test.com/?q=test%0Dfoo", &headers);
+ if (validate_header(&headers, "q", "test\rfoo") != 0)
+ goto fail;
+ evhttp_clear_headers(&headers);
+
+ fprintf(stdout, "OK\n");
+ return;
+fail:
+ fprintf(stdout, "FAILED\n");
+ exit(1);
+}
+
static void
http_base_test(void)
{
@@ -1358,10 +1458,12 @@ http_suite(void)
{
http_base_test();
http_bad_header_test();
+ http_parse_query_test();
http_basic_test();
http_connection_test(0 /* not-persistent */);
http_connection_test(1 /* persistent */);
- http_close_detection();
+ http_close_detection(0 /* with delay */);
+ http_close_detection(1 /* with delay */);
http_post_test();
http_failure_test();
http_highport_test();