From 228cebaf04f2c53b0bf09fb69b52be543cfc55ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Date: Tue, 5 May 2015 19:59:37 +0300 Subject: Add rfc7230 test suite and update others to recent Gun This is a large commit. The rfc7230 test suite adds many tests from the RFC7230 document. Gun has been updated quite a bit recently, which broke the Cowboy suites. This is now fixed with this commit. A new hook onfirstrequest has been added. It was very useful during debugging of the test suites. The initial process code has changed a little; more changes are expected with the switch to maps for options. --- test/http_SUITE.erl | 107 ++++++++++++++++++++++++---------------------------- 1 file changed, 50 insertions(+), 57 deletions(-) (limited to 'test/http_SUITE.erl') diff --git a/test/http_SUITE.erl b/test/http_SUITE.erl index 12b974c..314508b 100644 --- a/test/http_SUITE.erl +++ b/test/http_SUITE.erl @@ -16,11 +16,10 @@ -module(http_SUITE). -compile(export_all). --import(cowboy_test, [config/2]). +-import(ct_helper, [config/2]). -import(cowboy_test, [gun_open/1]). --import(cowboy_test, [gun_monitor_open/1]). --import(cowboy_test, [gun_monitor_open/2]). --import(cowboy_test, [gun_is_gone/2]). +-import(cowboy_test, [gun_open/2]). +-import(cowboy_test, [gun_down/1]). -import(cowboy_test, [raw_open/1]). -import(cowboy_test, [raw_send/2]). -import(cowboy_test, [raw_recv_head/1]). @@ -41,7 +40,7 @@ all() -> ]. groups() -> - Tests = cowboy_test:all(?MODULE) -- [ + Tests = ct_helper:all(?MODULE) -- [ onresponse_crash, onresponse_reply, onresponse_capitalize, parse_host, set_env_dispatch ], @@ -95,18 +94,14 @@ init_per_group(Name = https_compress, Config) -> init_per_group(onresponse, Config) -> {ok, _} = cowboy:start_http(onresponse, 100, [{port, 0}], [ {env, [{dispatch, init_dispatch(Config)}]}, - {max_keepalive, 50}, - {onresponse, fun do_onresponse_hook/4}, - {timeout, 500} + {onresponse, fun do_onresponse_hook/4} ]), Port = ranch:get_port(onresponse), [{type, tcp}, {port, Port}, {opts, []}|Config]; init_per_group(onresponse_capitalize, Config) -> {ok, _} = cowboy:start_http(onresponse_capitalize, 100, [{port, 0}], [ {env, [{dispatch, init_dispatch(Config)}]}, - {max_keepalive, 50}, - {onresponse, fun do_onresponse_capitalize_hook/4}, - {timeout, 500} + {onresponse, fun do_onresponse_capitalize_hook/4} ]), Port = ranch:get_port(onresponse_capitalize), [{type, tcp}, {port, Port}, {opts, []}|Config]; @@ -117,17 +112,13 @@ init_per_group(parse_host, Config) -> ]} ]), {ok, _} = cowboy:start_http(parse_host, 100, [{port, 0}], [ - {env, [{dispatch, Dispatch}]}, - {max_keepalive, 50}, - {timeout, 500} + {env, [{dispatch, Dispatch}]} ]), Port = ranch:get_port(parse_host), [{type, tcp}, {port, Port}, {opts, []}|Config]; init_per_group(set_env, Config) -> {ok, _} = cowboy:start_http(set_env, 100, [{port, 0}], [ - {env, [{dispatch, []}]}, - {max_keepalive, 50}, - {timeout, 500} + {env, [{dispatch, []}]} ]), Port = ranch:get_port(set_env), [{type, tcp}, {port, Port}, {opts, []}|Config]. @@ -342,26 +333,26 @@ echo_body_qs_max_length(Config) -> ok. error_init_after_reply(Config) -> - {ConnPid, MRef} = gun_monitor_open(Config), + ConnPid = gun_open(Config), Ref = gun:get(ConnPid, "/handler_errors?case=init_after_reply"), - {response, nofin, 200, _} = gun:await(ConnPid, Ref, MRef), - gun_is_gone(ConnPid, MRef). + {response, nofin, 200, _} = gun:await(ConnPid, Ref), + gun_down(ConnPid). headers_dupe(Config) -> - {ConnPid, MRef} = gun_monitor_open(Config), + ConnPid = gun_open(Config), Ref = gun:get(ConnPid, "/headers/dupe"), - {response, nofin, 200, Headers} = gun:await(ConnPid, Ref, MRef), + {response, nofin, 200, Headers} = gun:await(ConnPid, Ref), %% Ensure that only one connection header was received. [<<"close">>] = [V || {Name, V} <- Headers, Name =:= <<"connection">>], - gun_is_gone(ConnPid, MRef). + gun_down(ConnPid). http10_chunkless(Config) -> - {ConnPid, MRef} = gun_monitor_open(Config, [{http, [{version, 'HTTP/1.0'}]}]), + ConnPid = gun_open(Config, #{http_opts => #{version => 'HTTP/1.0'}}), Ref = gun:get(ConnPid, "/chunked_response"), - {response, nofin, 200, Headers} = gun:await(ConnPid, Ref, MRef), + {response, nofin, 200, Headers} = gun:await(ConnPid, Ref), false = lists:keyfind(<<"transfer-encoding">>, 1, Headers), - {ok, <<"chunked_handler\r\nworks fine!">>} = gun:await_body(ConnPid, Ref, MRef), - gun_is_gone(ConnPid, MRef). + {ok, <<"chunked_handler\r\nworks fine!">>} = gun:await_body(ConnPid, Ref), + gun_down(ConnPid). http10_hostless(Config) -> Name = http10_hostless, @@ -411,17 +402,17 @@ http10_keepalive_forced(Config) -> end. keepalive_max(Config) -> - {ConnPid, MRef} = gun_monitor_open(Config), + ConnPid = gun_open(Config), Refs = [gun:get(ConnPid, "/", [{<<"connection">>, <<"keep-alive">>}]) - || _ <- lists:seq(1, 49)], + || _ <- lists:seq(1, 99)], CloseRef = gun:get(ConnPid, "/", [{<<"connection">>, <<"keep-alive">>}]), _ = [begin - {response, nofin, 200, Headers} = gun:await(ConnPid, Ref, MRef), + {response, nofin, 200, Headers} = gun:await(ConnPid, Ref), {_, <<"keep-alive">>} = lists:keyfind(<<"connection">>, 1, Headers) end || Ref <- Refs], - {response, nofin, 200, Headers} = gun:await(ConnPid, CloseRef, MRef), + {response, nofin, 200, Headers} = gun:await(ConnPid, CloseRef), {_, <<"close">>} = lists:keyfind(<<"connection">>, 1, Headers), - gun_is_gone(ConnPid, MRef). + gun_down(ConnPid). keepalive_nl(Config) -> ConnPid = gun_open(Config), @@ -440,7 +431,7 @@ keepalive_stream_loop(Config) -> ConnPid = gun_open(Config), Refs = [begin Ref = gun:post(ConnPid, "/loop_stream_recv", - [{<<"transfer-encoding">>, <<"chunked">>}]), + [{<<"content-type">>, <<"application/octet-stream">>}]), _ = [gun:data(ConnPid, Ref, nofin, << ID:32 >>) || ID <- lists:seq(1, 250)], gun:data(ConnPid, Ref, fin, <<>>), @@ -481,9 +472,8 @@ multipart_chunked(Config) -> "\r\n--OHai--\r\n" "This is an epilogue." >>, - Ref = gun:post(ConnPid, "/multipart", [ - {<<"content-type">>, <<"multipart/x-makes-no-sense; boundary=OHai">>}, - {<<"transfer-encoding">>, <<"chunked">>}]), + Ref = gun:post(ConnPid, "/multipart", + [{<<"content-type">>, <<"multipart/x-makes-no-sense; boundary=OHai">>}]), gun:data(ConnPid, Ref, fin, Body), {response, nofin, 200, _} = gun:await(ConnPid, Ref), {ok, RespBody} = gun:await_body(ConnPid, Ref), @@ -614,10 +604,12 @@ rest_param_all(Config) -> %% Content-Type without param. Ref6 = gun:put(ConnPid, "/param_all", [{<<"content-type">>, <<"text/plain">>}]), + gun:data(ConnPid, Ref6, fin, "Hello world!"), {response, fin, 204, _} = gun:await(ConnPid, Ref6), %% Content-Type with param. Ref7 = gun:put(ConnPid, "/param_all", [{<<"content-type">>, <<"text/plain; charset=utf-8">>}]), + gun:data(ConnPid, Ref7, fin, "Hello world!"), {response, fin, 204, _} = gun:await(ConnPid, Ref7), ok. @@ -662,12 +654,13 @@ rest_keepalive(Config) -> rest_keepalive_post(Config) -> ConnPid = gun_open(Config), - Refs = [{ - gun:post(ConnPid, "/forbidden_post", - [{<<"content-type">>, <<"text/plain">>}]), - gun:post(ConnPid, "/simple_post", - [{<<"content-type">>, <<"text/plain">>}]) - } || _ <- lists:seq(1, 5)], + Refs = [begin + Ref1 = gun:post(ConnPid, "/forbidden_post", [{<<"content-type">>, <<"text/plain">>}]), + gun:data(ConnPid, Ref1, fin, "Hello world!"), + Ref2 = gun:post(ConnPid, "/simple_post", [{<<"content-type">>, <<"text/plain">>}]), + gun:data(ConnPid, Ref2, fin, "Hello world!"), + {Ref1, Ref2} + end || _ <- lists:seq(1, 5)], _ = [begin {response, fin, 403, Headers1} = gun:await(ConnPid, Ref1), {_, <<"keep-alive">>} = lists:keyfind(<<"connection">>, 1, Headers1), @@ -808,7 +801,7 @@ slowloris(Config) -> try [begin ok = raw_send(Client, [C]), - receive after 25 -> ok end + receive after 250 -> ok end end || C <- "GET / HTTP/1.1\r\nHost: localhost\r\n" "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US)\r\n" "Cookie: name=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\r\n\r\n"], @@ -894,11 +887,11 @@ stream_body_set_resp(Config) -> ok. stream_body_set_resp_close(Config) -> - {ConnPid, MRef} = gun_monitor_open(Config), + ConnPid = gun_open(Config), Ref = gun:get(ConnPid, "/stream_body/set_resp_close"), - {response, nofin, 200, _} = gun:await(ConnPid, Ref, MRef), - {ok, <<"stream_body_set_resp_close">>} = gun:await_body(ConnPid, Ref, MRef), - gun_is_gone(ConnPid, MRef). + {response, nofin, 200, _} = gun:await(ConnPid, Ref), + {ok, <<"stream_body_set_resp_close">>} = gun:await_body(ConnPid, Ref), + gun_down(ConnPid). stream_body_set_resp_chunked(Config) -> ConnPid = gun_open(Config), @@ -909,12 +902,12 @@ stream_body_set_resp_chunked(Config) -> ok. stream_body_set_resp_chunked10(Config) -> - {ConnPid, MRef} = gun_monitor_open(Config, [{http, [{version, 'HTTP/1.0'}]}]), + ConnPid = gun_open(Config, #{http_opts => #{version => 'HTTP/1.0'}}), Ref = gun:get(ConnPid, "/stream_body/set_resp_chunked"), - {response, nofin, 200, Headers} = gun:await(ConnPid, Ref, MRef), + {response, nofin, 200, Headers} = gun:await(ConnPid, Ref), false = lists:keyfind(<<"transfer-encoding">>, 1, Headers), - {ok, <<"stream_body_set_resp_chunked">>} = gun:await_body(ConnPid, Ref, MRef), - gun_is_gone(ConnPid, MRef). + {ok, <<"stream_body_set_resp_chunked">>} = gun:await_body(ConnPid, Ref), + gun_down(ConnPid). %% Undocumented hack: force chunked response to be streamed as HTTP/1.1. streamed_response(Config) -> @@ -933,8 +926,8 @@ streamed_response(Config) -> te_chunked(Config) -> Body = list_to_binary(io_lib:format("~p", [lists:seq(1, 100)])), ConnPid = gun_open(Config), - Ref = gun:post(ConnPid, "/echo/body", - [{<<"transfer-encoding">>, <<"chunked">>}], Body), + Ref = gun:post(ConnPid, "/echo/body", [{<<"content-type">>, <<"text/plain">>}]), + gun:data(ConnPid, Ref, fin, Body), {response, nofin, 200, _} = gun:await(ConnPid, Ref), {ok, Body} = gun:await_body(ConnPid, Ref), ok. @@ -957,7 +950,7 @@ te_chunked_chopped(Config) -> Body2 = iolist_to_binary(do_body_to_chunks(50, Body, [])), ConnPid = gun_open(Config), Ref = gun:post(ConnPid, "/echo/body", - [{<<"transfer-encoding">>, <<"chunked">>}]), + [{<<"content-type">>, <<"text/plain">>}]), _ = [begin ok = gun:dbg_send_raw(ConnPid, << C >>), receive after 10 -> ok end @@ -971,7 +964,7 @@ te_chunked_delayed(Config) -> Chunks = do_body_to_chunks(50, Body, []), ConnPid = gun_open(Config), Ref = gun:post(ConnPid, "/echo/body", - [{<<"transfer-encoding">>, <<"chunked">>}]), + [{<<"content-type">>, <<"text/plain">>}]), _ = [begin ok = gun:dbg_send_raw(ConnPid, Chunk), receive after 10 -> ok end @@ -985,7 +978,7 @@ te_chunked_split_body(Config) -> Chunks = do_body_to_chunks(50, Body, []), ConnPid = gun_open(Config), Ref = gun:post(ConnPid, "/echo/body", - [{<<"transfer-encoding">>, <<"chunked">>}]), + [{<<"content-type">>, <<"text/plain">>}]), _ = [begin case Chunk of <<"0\r\n\r\n">> -> @@ -1009,7 +1002,7 @@ te_chunked_split_crlf(Config) -> Chunks = do_body_to_chunks(50, Body, []), ConnPid = gun_open(Config), Ref = gun:post(ConnPid, "/echo/body", - [{<<"transfer-encoding">>, <<"chunked">>}]), + [{<<"content-type">>, <<"text/plain">>}]), _ = [begin %% Split in the newline just before the end of the chunk. Len = byte_size(Chunk) - (random:uniform(2) - 1), -- cgit v1.2.3