]> granicus.if.org Git - libevent/commitdiff
test the server side of sending chunked replies
authorNiels Provos <provos@gmail.com>
Tue, 29 Apr 2008 02:33:27 +0000 (02:33 +0000)
committerNiels Provos <provos@gmail.com>
Tue, 29 Apr 2008 02:33:27 +0000 (02:33 +0000)
svn:r740

test/regress_http.c

index 75a5bbf03b0038107fec6c4db06792fefc4a3141..f75dd20c479132f3ef6f13ba47f48343d86b65d5 100644 (file)
@@ -67,6 +67,7 @@ static struct event_base *base;
 void http_suite(void);
 
 void http_basic_cb(struct evhttp_request *req, void *arg);
+void http_chunked_cb(struct evhttp_request *req, void *arg);
 void http_post_cb(struct evhttp_request *req, void *arg);
 void http_put_cb(struct evhttp_request *req, void *arg);
 void http_delete_cb(struct evhttp_request *req, void *arg);
@@ -93,6 +94,7 @@ http_setup(short *pport, struct event_base *base)
 
        /* Register a callback for certain types of requests */
        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, "/putit", http_put_cb, NULL);
        evhttp_set_cb(myhttp, "/deleteit", http_delete_cb, NULL);
@@ -165,15 +167,15 @@ http_readcb(struct bufferevent *bev, void *arg)
 {
        const char *what = "This is funny";
 
-       event_debug(("%s: %s\n", __func__, EVBUFFER_DATA(bev->input)));
+       event_debug(("%s: %s\n", __func__, EVBUFFER_DATA(EVBUFFER_INPUT(bev))));
        
-       if (evbuffer_find(bev->input,
+       if (evbuffer_find(EVBUFFER_INPUT(bev),
                (const unsigned char*) what, strlen(what)) != NULL) {
                struct evhttp_request *req = evhttp_request_new(NULL, NULL);
                int done;
 
                req->kind = EVHTTP_RESPONSE;
-               done = evhttp_parse_lines(req, bev->input);
+               done = evhttp_parse_lines(req, EVBUFFER_INPUT(bev));
 
                if (done == 1 &&
                    evhttp_find_header(req->input_headers,
@@ -191,7 +193,7 @@ http_readcb(struct bufferevent *bev, void *arg)
 static void
 http_writecb(struct bufferevent *bev, void *arg)
 {
-       if (EVBUFFER_LENGTH(bev->output) == 0) {
+       if (EVBUFFER_LENGTH(EVBUFFER_OUTPUT(bev)) == 0) {
                /* enable reading of the reply */
                bufferevent_enable(bev, EV_READ);
                test_ok++;
@@ -220,6 +222,33 @@ http_basic_cb(struct evhttp_request *req, void *arg)
        evbuffer_free(evb);
 }
 
+void
+http_chunked_cb(struct evhttp_request *req, void *arg)
+{
+       struct evbuffer *evb = evbuffer_new();
+       event_debug(("%s: called\n", __func__));
+
+       /* generate a chunked reply */
+       evhttp_send_reply_start(req, HTTP_OK, "Everything is fine");
+
+       /* first chunk */
+       evbuffer_add_printf(evb, "This is funny");
+       evhttp_send_reply_chunk(req, evb);
+
+       /* second chunk */
+       evbuffer_add_printf(evb, "but not hilarious.");
+       evhttp_send_reply_chunk(req, evb);
+
+       /* third and last chunk */
+       evbuffer_add_printf(evb, "bwv 1052");
+       evhttp_send_reply_chunk(req, evb);
+
+       /* finish request */
+       evhttp_send_reply_end(req);
+
+       evbuffer_free(evb);
+}
+
 static void
 http_basic_test(void)
 {
@@ -851,7 +880,8 @@ static void
 http_failure_readcb(struct bufferevent *bev, void *arg)
 {
        const char *what = "400 Bad Request";
-       if (evbuffer_find(bev->input, (const unsigned char*) what, strlen(what)) != NULL) {
+       if (evbuffer_find(EVBUFFER_INPUT(bev),
+               (const unsigned char*) what, strlen(what)) != NULL) {
                test_ok = 2;
                bufferevent_disable(bev, EV_READ);
                event_loopexit(NULL);
@@ -1139,7 +1169,7 @@ http_incomplete_writecb(struct bufferevent *bev, void *arg)
                /* terminate the write side to simulate EOF */
                shutdown(fd, SHUT_WR);
        }
-       if (EVBUFFER_LENGTH(bev->output) == 0) {
+       if (EVBUFFER_LENGTH(EVBUFFER_OUTPUT(bev)) == 0) {
                /* enable reading of the reply */
                bufferevent_enable(bev, EV_READ);
                test_ok++;
@@ -1207,6 +1237,162 @@ http_incomplete_test(int use_timeout)
        fprintf(stdout, "OK\n");
 }
 
+/*
+ * the server is going to reply with chunked data.
+ */
+
+static void
+http_chunked_readcb(struct bufferevent *bev, void *arg)
+{
+       /* nothing here */
+}
+
+static void
+http_chunked_errorcb(struct bufferevent *bev, short what, void *arg)
+{
+       if (!test_ok)
+               goto out;
+
+       test_ok = -1;
+
+       if ((what & EVBUFFER_EOF) != 0) {
+               struct evhttp_request *req = evhttp_request_new(NULL, NULL);
+               const char *header;
+               int done;
+               
+               req->kind = EVHTTP_RESPONSE;
+               done = evhttp_parse_lines(req, EVBUFFER_INPUT(bev));
+
+               if (done != 1)
+                       goto out;
+
+               header = evhttp_find_header(req->input_headers, "Transfer-Encoding");
+               if (header == NULL || strcmp(header, "chunked"))
+                       goto out;
+
+               header = evhttp_find_header(req->input_headers, "Connection");
+               if (header == NULL || strcmp(header, "close"))
+                       goto out;
+
+               header = evbuffer_readln(EVBUFFER_INPUT(bev), NULL, EVBUFFER_EOL_CRLF);
+               if (header == NULL)
+                       goto out;
+               /* 13 chars */
+               if (strcmp(header, "d"))
+                       goto out;
+               free((char*)header);
+
+               if (strncmp((char *)evbuffer_pullup(EVBUFFER_INPUT(bev), 13),
+                       "This is funny", 13))
+                       goto out;
+
+               evbuffer_drain(EVBUFFER_INPUT(bev), 13 + 2);
+
+               header = evbuffer_readln(EVBUFFER_INPUT(bev), NULL, EVBUFFER_EOL_CRLF);
+               if (header == NULL)
+                       goto out;
+               /* 18 chars */
+               if (strcmp(header, "12"))
+                       goto out;
+               free((char *)header);
+
+               if (strncmp((char *)evbuffer_pullup(EVBUFFER_INPUT(bev), 18),
+                       "but not hilarious.", 18))
+                       goto out;
+
+               evbuffer_drain(EVBUFFER_INPUT(bev), 18 + 2);
+
+               header = evbuffer_readln(EVBUFFER_INPUT(bev), NULL, EVBUFFER_EOL_CRLF);
+               if (header == NULL)
+                       goto out;
+               /* 8 chars */
+               if (strcmp(header, "8"))
+                       goto out;
+               free((char *)header);
+
+               if (strncmp((char *)evbuffer_pullup(EVBUFFER_INPUT(bev), 8),
+                       "bwv 1052.", 8))
+                       goto out;
+
+               evbuffer_drain(EVBUFFER_INPUT(bev), 8 + 2);
+
+               header = evbuffer_readln(EVBUFFER_INPUT(bev), NULL, EVBUFFER_EOL_CRLF);
+               if (header == NULL)
+                       goto out;
+               /* 0 chars */
+               if (strcmp(header, "0"))
+                       goto out;
+               free((char *)header);
+
+               test_ok = 2;
+       }
+
+out:
+       event_loopexit(NULL);
+}
+
+static void
+http_chunked_writecb(struct bufferevent *bev, void *arg)
+{
+       if (EVBUFFER_LENGTH(EVBUFFER_OUTPUT(bev)) == 0) {
+               /* enable reading of the reply */
+               bufferevent_enable(bev, EV_READ);
+               test_ok++;
+       }
+}
+
+static void
+http_chunked_test()
+{
+       struct bufferevent *bev;
+       int fd;
+       const char *http_request;
+       short port = -1;
+       struct timeval tv_start, tv_end;
+
+       test_ok = 0;
+       fprintf(stdout, "Testing Chunked HTTP Reply: ");
+
+       http = http_setup(&port, NULL);
+
+       fd = http_connect("127.0.0.1", port);
+
+       /* Stupid thing to send a request */
+       bev = bufferevent_new(fd, 
+           http_chunked_readcb, http_chunked_writecb,
+           http_chunked_errorcb, NULL);
+
+       http_request =
+           "GET /chunked HTTP/1.1\r\n"
+           "Host: somehost\r\n"
+           "Connection: close\r\n"
+           "\r\n";
+
+       bufferevent_write(bev, http_request, strlen(http_request));
+
+       gettimeofday(&tv_start, NULL);
+       
+       event_dispatch();
+
+       gettimeofday(&tv_end, NULL);
+       timersub(&tv_end, &tv_start, &tv_end);
+
+       evhttp_free(http);
+
+       if (tv_end.tv_sec >= 1) {
+               fprintf(stdout, "FAILED (time)\n");
+               exit (1);
+       }
+
+
+       if (test_ok != 2) {
+               fprintf(stdout, "FAILED\n");
+               exit(1);
+       }
+       
+       fprintf(stdout, "OK\n");
+}
+
 static void
 http_connection_retry_done(struct evhttp_request *req, void *arg)
 {
@@ -1450,5 +1636,7 @@ http_suite(void)
        http_incomplete_test(0 /* use_timeout */);
        http_incomplete_test(1 /* use_timeout */);
 
+       http_chunked_test();
+
        http_connection_retry();
 }