From: Azat Khuzhin Date: Wed, 9 Sep 2015 14:45:44 +0000 (+0300) Subject: test/regress_http: cover write during read X-Git-Tag: release-2.1.6-beta~90^2~50^2~1 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3d15aeb4fddb4ef150061eb1ddf11d66b5725960;p=libevent test/regress_http: cover write during read 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. --- diff --git a/test/regress_http.c b/test/regress_http.c index 75dd41ed..c86ec95f 100644 --- a/test/regress_http.c +++ b/test/regress_http.c @@ -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 };