]> granicus.if.org Git - libevent/commitdiff
test/regress_http: cover write during read
authorAzat Khuzhin <a3at.mail@gmail.com>
Wed, 9 Sep 2015 14:45:44 +0000 (17:45 +0300)
committerAzat Khuzhin <a3at.mail@gmail.com>
Wed, 9 Sep 2015 15:06:37 +0000 (18:06 +0300)
This is the regression for evhttp_write_buffer() where we reset readcb to avoid
illegal state:
http/write_during_read: [err] evhttp_read_cb: illegal connection state 7

If you will comment that this test will fail.

test/regress_http.c

index 75dd41ed6d62f5cd7c1ac7b3b2eca26d35209a82..c86ec95f48407aed67d6e43dd6a4d35f28bb25cd 100644 (file)
@@ -84,6 +84,7 @@ static char const BASIC_REQUEST_BODY[] = "This is funny";
 IMPL_HTTP_REQUEST_ERROR_CB(cancel, EVREQ_HTTP_REQUEST_CANCEL)
 
 static void http_basic_cb(struct evhttp_request *req, void *arg);
+static void http_large_cb(struct evhttp_request *req, void *arg);
 static void http_chunked_cb(struct evhttp_request *req, void *arg);
 static void http_post_cb(struct evhttp_request *req, void *arg);
 static void http_put_cb(struct evhttp_request *req, void *arg);
@@ -133,6 +134,7 @@ http_setup(ev_uint16_t *pport, struct event_base *base, int ipv6)
 
        /* Register a callback for certain types of requests */
        evhttp_set_cb(myhttp, "/test", http_basic_cb, base);
+       evhttp_set_cb(myhttp, "/large", http_large_cb, base);
        evhttp_set_cb(myhttp, "/chunked", http_chunked_cb, base);
        evhttp_set_cb(myhttp, "/streamed", http_chunked_cb, base);
        evhttp_set_cb(myhttp, "/postit", http_post_cb, base);
@@ -329,6 +331,19 @@ end:
        evbuffer_free(evb);
 }
 
+static void
+http_large_cb(struct evhttp_request *req, void *arg)
+{
+       struct evbuffer *evb = evbuffer_new();
+       int i;
+
+       for (i = 0; i < 1<<20; ++i) {
+               evbuffer_add_printf(evb, BASIC_REQUEST_BODY);
+       }
+       evhttp_send_reply(req, HTTP_OK, "Everything is fine", evb);
+       evbuffer_free(evb);
+}
+
 static char const* const CHUNKS[] = {
        "This is funny",
        "but not hilarious.",
@@ -3990,6 +4005,56 @@ http_set_family_ipv6_test(void *arg)
        http_ipv6_for_domain_test_impl(arg, AF_INET6);
 }
 
+static void
+http_write_during_read(evutil_socket_t fd, short what, void *arg)
+{
+       struct bufferevent *bev = arg;
+       struct timeval tv;
+
+       bufferevent_write(bev, "foobar", strlen("foobar"));
+
+       evutil_timerclear(&tv);
+       tv.tv_sec = 1;
+       event_base_loopexit(exit_base, &tv);
+}
+static void
+http_write_during_read_test(void *arg)
+{
+       struct basic_test_data *data = arg;
+       ev_uint16_t port = 0;
+       struct bufferevent *bev = NULL;
+       struct timeval tv;
+       int fd;
+       const char *http_request;
+
+       test_ok = 0;
+       exit_base = data->base;
+
+       http = http_setup(&port, data->base, 0);
+
+       fd = http_connect("127.0.0.1", port);
+       bev = bufferevent_socket_new(data->base, fd, 0);
+       bufferevent_setcb(bev, NULL, NULL, NULL, data->base);
+       bufferevent_disable(bev, EV_READ);
+
+       http_request =
+           "GET /large HTTP/1.1\r\n"
+           "Host: somehost\r\n"
+           "\r\n";
+
+       bufferevent_write(bev, http_request, strlen(http_request));
+       evutil_timerclear(&tv);
+       tv.tv_usec = 10000;
+       event_base_once(data->base, -1, EV_TIMEOUT, http_write_during_read, bev, &tv);
+
+       event_base_dispatch(data->base);
+
+       if (bev)
+               bufferevent_free(bev);
+       if (http)
+               evhttp_free(http);
+}
+
 #define HTTP_LEGACY(name)                                              \
        { #name, run_legacy_test_fn, TT_ISOLATED|TT_LEGACY, &legacy_setup, \
                    http_##name##_test }
@@ -4050,6 +4115,8 @@ struct testcase_t http_testcases[] = {
        HTTP(set_family_ipv4),
        HTTP(set_family_ipv6),
 
+       HTTP(write_during_read),
+
        END_OF_TESTCASES
 };