diff options
author | Loïc Hoguin <[email protected]> | 2017-01-22 10:50:39 +0100 |
---|---|---|
committer | Loïc Hoguin <[email protected]> | 2017-01-22 10:50:39 +0100 |
commit | 3e05ab8f82ac69da7c55d1b28284c32ea63186c4 (patch) | |
tree | cc13546e9579d572d7d926aeab73847a4fc56ca5 /test | |
parent | 3b91523a3c84a882dcc83f0591b919a939cb72c2 (diff) | |
download | cowboy-3e05ab8f82ac69da7c55d1b28284c32ea63186c4.tar.gz cowboy-3e05ab8f82ac69da7c55d1b28284c32ea63186c4.tar.bz2 cowboy-3e05ab8f82ac69da7c55d1b28284c32ea63186c4.zip |
Add experimental cowboy_compress_h stream handler
Currently marked as experimental because it can't be tweaked
(just enabled/disabled) and because it is not documented yet.
Diffstat (limited to 'test')
-rw-r--r-- | test/compress_SUITE.erl | 129 | ||||
-rw-r--r-- | test/cowboy_test.erl | 51 | ||||
-rw-r--r-- | test/handlers/compress_h.erl | 37 | ||||
-rw-r--r-- | test/handlers/echo_h.erl | 2 | ||||
-rw-r--r-- | test/handlers/resp_h.erl | 4 | ||||
-rw-r--r-- | test/loop_handler_SUITE.erl | 16 | ||||
-rw-r--r-- | test/req_SUITE.erl | 31 | ||||
-rw-r--r-- | test/static_handler_SUITE.erl | 9 |
8 files changed, 237 insertions, 42 deletions
diff --git a/test/compress_SUITE.erl b/test/compress_SUITE.erl new file mode 100644 index 0000000..2bd002d --- /dev/null +++ b/test/compress_SUITE.erl @@ -0,0 +1,129 @@ +%% Copyright (c) 2017, Loïc Hoguin <[email protected]> +%% +%% Permission to use, copy, modify, and/or distribute this software for any +%% purpose with or without fee is hereby granted, provided that the above +%% copyright notice and this permission notice appear in all copies. +%% +%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +-module(compress_SUITE). +-compile(export_all). + +-import(ct_helper, [config/2]). +-import(ct_helper, [doc/1]). +-import(cowboy_test, [gun_open/1]). + +%% ct. + +all() -> + [ + {group, http_compress}, + {group, https_compress}, + {group, h2_compress}, + {group, h2c_compress} + ]. + +groups() -> + cowboy_test:common_groups(ct_helper:all(?MODULE)). + +init_per_group(Name, Config) -> + cowboy_test:init_common_groups(Name, Config, ?MODULE). + +end_per_group(Name, _) -> + cowboy:stop_listener(Name). + +%% Routes. + +init_dispatch(Config) -> + cowboy_router:compile([{"[...]", [ + {"/reply/:what", compress_h, reply}, + {"/stream_reply/:what", compress_h, stream_reply} + ]}]). + +%% Internal. + +do_get(Path, ReqHeaders, Config) -> + ConnPid = gun_open(Config), + Ref = gun:get(ConnPid, Path, ReqHeaders), + {response, IsFin, Status, RespHeaders} = gun:await(ConnPid, Ref), + {ok, Body} = case IsFin of + nofin -> gun:await_body(ConnPid, Ref); + fin -> {ok, <<>>} + end, + gun:close(ConnPid), + {Status, RespHeaders, Body}. + +%% Tests. + +gzip_accept_encoding_missing(Config) -> + doc("Don't send accept-encoding; get an uncompressed response."), + {200, Headers, _} = do_get("/reply/large", + [], Config), + false = lists:keyfind(<<"content-encoding">>, 1, Headers), + {_, <<"100000">>} = lists:keyfind(<<"content-length">>, 1, Headers), + ok. + +gzip_accept_encoding_no_gzip(Config) -> + doc("Send accept-encoding: compress (unsupported by Cowboy); get an uncompressed response."), + {200, Headers, _} = do_get("/reply/large", + [{<<"accept-encoding">>, <<"compress">>}], Config), + false = lists:keyfind(<<"content-encoding">>, 1, Headers), + {_, <<"100000">>} = lists:keyfind(<<"content-length">>, 1, Headers), + ok. + +gzip_reply_content_encoding(Config) -> + doc("Reply with content-encoding header; get an uncompressed response."), + {200, Headers, _} = do_get("/reply/content-encoding", + [{<<"accept-encoding">>, <<"gzip">>}], Config), + %% We set the content-encoding to compress; without actually compressing. + {_, <<"compress">>} = lists:keyfind(<<"content-encoding">>, 1, Headers), + {_, <<"100000">>} = lists:keyfind(<<"content-length">>, 1, Headers), + ok. + +gzip_reply_large_body(Config) -> + doc("Reply a large body; get a gzipped response."), + {200, Headers, GzBody} = do_get("/reply/large", + [{<<"accept-encoding">>, <<"gzip">>}], Config), + {_, <<"gzip">>} = lists:keyfind(<<"content-encoding">>, 1, Headers), + {_, Length} = lists:keyfind(<<"content-length">>, 1, Headers), + ct:log("Original length: 100000; compressed: ~s.", [Length]), + _ = zlib:gunzip(GzBody), + ok. + +gzip_reply_sendfile(Config) -> + doc("Reply using sendfile; get an uncompressed response."), + {200, Headers, Body} = do_get("/reply/sendfile", + [{<<"accept-encoding">>, <<"gzip">>}], Config), + false = lists:keyfind(<<"content-encoding">>, 1, Headers), + ct:log("Body received:~n~p~n", [Body]), + ok. + +gzip_reply_small_body(Config) -> + doc("Reply a small body; get an uncompressed response."), + {200, Headers, _} = do_get("/reply/small", + [{<<"accept-encoding">>, <<"gzip">>}], Config), + false = lists:keyfind(<<"content-encoding">>, 1, Headers), + {_, <<"100">>} = lists:keyfind(<<"content-length">>, 1, Headers), + ok. + +gzip_stream_reply(Config) -> + doc("Stream reply; get a gzipped response."), + {200, Headers, GzBody} = do_get("/stream_reply/large", + [{<<"accept-encoding">>, <<"gzip">>}], Config), + {_, <<"gzip">>} = lists:keyfind(<<"content-encoding">>, 1, Headers), + _ = zlib:gunzip(GzBody), + ok. + +gzip_stream_reply_content_encoding(Config) -> + doc("Stream reply with content-encoding header; get an uncompressed response."), + {200, Headers, Body} = do_get("/stream_reply/content-encoding", + [{<<"accept-encoding">>, <<"gzip">>}], Config), + {_, <<"compress">>} = lists:keyfind(<<"content-encoding">>, 1, Headers), + 100000 = iolist_size(Body), + ok. diff --git a/test/cowboy_test.erl b/test/cowboy_test.erl index bb74ad0..a219878 100644 --- a/test/cowboy_test.erl +++ b/test/cowboy_test.erl @@ -43,10 +43,11 @@ common_all() -> {group, http}, {group, https}, {group, h2}, - {group, h2c}%, -%% @todo -% {group, http_compress}, -% {group, https_compress} + {group, h2c}, + {group, http_compress}, + {group, https_compress}, + {group, h2_compress}, + {group, h2c_compress} ]. common_groups(Tests) -> @@ -54,31 +55,51 @@ common_groups(Tests) -> {http, [parallel], Tests}, {https, [parallel], Tests}, {h2, [parallel], Tests}, - {h2c, [parallel], Tests}%, -%% @todo -% {http_compress, [parallel], Tests}, -% {https_compress, [parallel], Tests} + {h2c, [parallel], Tests}, + {http_compress, [parallel], Tests}, + {https_compress, [parallel], Tests}, + {h2_compress, [parallel], Tests}, + {h2c_compress, [parallel], Tests} ]. init_common_groups(Name = http, Config, Mod) -> - init_http(Name, #{env => #{dispatch => Mod:init_dispatch(Config)}}, Config); + init_http(Name, #{ + env => #{dispatch => Mod:init_dispatch(Config)} + }, Config); init_common_groups(Name = https, Config, Mod) -> - init_https(Name, #{env => #{dispatch => Mod:init_dispatch(Config)}}, Config); + init_https(Name, #{ + env => #{dispatch => Mod:init_dispatch(Config)} + }, Config); init_common_groups(Name = h2, Config, Mod) -> - init_http2(Name, #{env => #{dispatch => Mod:init_dispatch(Config)}}, Config); + init_http2(Name, #{ + env => #{dispatch => Mod:init_dispatch(Config)} + }, Config); init_common_groups(Name = h2c, Config, Mod) -> - Config1 = init_http(Name, #{env => #{dispatch => Mod:init_dispatch(Config)}}, Config), + Config1 = init_http(Name, #{ + env => #{dispatch => Mod:init_dispatch(Config)} + }, Config), lists:keyreplace(protocol, 1, Config1, {protocol, http2}); init_common_groups(Name = http_compress, Config, Mod) -> init_http(Name, #{ env => #{dispatch => Mod:init_dispatch(Config)}, - compress => true + stream_handlers => [cowboy_compress_h, cowboy_stream_h] }, Config); init_common_groups(Name = https_compress, Config, Mod) -> init_https(Name, #{ env => #{dispatch => Mod:init_dispatch(Config)}, - compress => true - }, Config). + stream_handlers => [cowboy_compress_h, cowboy_stream_h] + }, Config); +init_common_groups(Name = h2_compress, Config, Mod) -> + init_http2(Name, #{ + env => #{dispatch => Mod:init_dispatch(Config)}, + stream_handlers => [cowboy_compress_h, cowboy_stream_h] + }, Config); +init_common_groups(Name = h2c_compress, Config, Mod) -> + Config1 = init_http(Name, #{ + env => #{dispatch => Mod:init_dispatch(Config)}, + stream_handlers => [cowboy_compress_h, cowboy_stream_h] + }, Config), + lists:keyreplace(protocol, 1, Config1, {protocol, http2}). %% Support functions for testing using Gun. diff --git a/test/handlers/compress_h.erl b/test/handlers/compress_h.erl new file mode 100644 index 0000000..5787b66 --- /dev/null +++ b/test/handlers/compress_h.erl @@ -0,0 +1,37 @@ +%% This module sends a response body of varying sizes to test +%% the cowboy_compress_h stream handler. + +-module(compress_h). + +-export([init/2]). + +init(Req0, State=reply) -> + Req = case cowboy_req:binding(what, Req0) of + <<"small">> -> + cowboy_req:reply(200, #{}, lists:duplicate(100, $a), Req0); + <<"large">> -> + cowboy_req:reply(200, #{}, lists:duplicate(100000, $a), Req0); + <<"content-encoding">> -> + cowboy_req:reply(200, #{<<"content-encoding">> => <<"compress">>}, + lists:duplicate(100000, $a), Req0); + <<"sendfile">> -> + AppFile = code:where_is_file("cowboy.app"), + Size = filelib:file_size(AppFile), + cowboy_req:reply(200, #{}, {sendfile, 0, Size, AppFile}, Req0) + end, + {ok, Req, State}; +init(Req0, State=stream_reply) -> + Req = case cowboy_req:binding(what, Req0) of + <<"large">> -> + stream_reply(#{}, Req0); + <<"content-encoding">> -> + stream_reply(#{<<"content-encoding">> => <<"compress">>}, Req0) + end, + {ok, Req, State}. + +stream_reply(Headers, Req0) -> + Data = lists:duplicate(10000, $a), + Req = cowboy_req:stream_reply(200, Headers, Req0), + _ = [cowboy_req:stream_body(Data, nofin, Req) || _ <- lists:seq(1,9)], + cowboy_req:stream_body(Data, fin, Req), + Req. diff --git a/test/handlers/echo_h.erl b/test/handlers/echo_h.erl index fb7d8a8..5042ca8 100644 --- a/test/handlers/echo_h.erl +++ b/test/handlers/echo_h.erl @@ -79,5 +79,5 @@ read_body(Req0, Acc) -> value_to_iodata(V) when is_integer(V) -> integer_to_binary(V); value_to_iodata(V) when is_atom(V) -> atom_to_binary(V, latin1); -value_to_iodata(V) when is_list(V); is_tuple(V); is_map(V) -> io_lib:format("~p", [V]); +value_to_iodata(V) when is_list(V); is_tuple(V); is_map(V) -> io_lib:format("~999999p", [V]); value_to_iodata(V) -> V. diff --git a/test/handlers/resp_h.erl b/test/handlers/resp_h.erl index 658c5f8..5e6696e 100644 --- a/test/handlers/resp_h.erl +++ b/test/handlers/resp_h.erl @@ -28,7 +28,7 @@ do(<<"set_resp_header">>, Req0, Opts) -> do(<<"set_resp_headers">>, Req0, Opts) -> Req = cowboy_req:set_resp_headers(#{ <<"content-type">> => <<"text/plain">>, - <<"content-encoding">> => <<"gzip">> + <<"content-encoding">> => <<"compress">> }, Req0), {ok, cowboy_req:reply(200, #{}, "OK", Req), Opts}; do(<<"resp_header_defined">>, Req0, Opts) -> @@ -44,7 +44,7 @@ do(<<"resp_headers">>, Req0, Opts) -> Req1 = cowboy_req:set_resp_header(<<"server">>, <<"nginx">>, Req0), Req = cowboy_req:set_resp_headers(#{ <<"content-type">> => <<"text/plain">>, - <<"content-encoding">> => <<"gzip">> + <<"content-encoding">> => <<"compress">> }, Req1), Headers = cowboy_req:resp_headers(Req), true = maps:is_key(<<"server">>, Headers), diff --git a/test/loop_handler_SUITE.erl b/test/loop_handler_SUITE.erl index 7e26d60..5feb032 100644 --- a/test/loop_handler_SUITE.erl +++ b/test/loop_handler_SUITE.erl @@ -47,41 +47,45 @@ init_dispatch(_) -> long_polling(Config) -> doc("Simple long-polling."), ConnPid = gun_open(Config), - Ref = gun:get(ConnPid, "/long_polling"), + Ref = gun:get(ConnPid, "/long_polling", [{<<"accept-encoding">>, <<"gzip">>}]), {response, fin, 102, _} = gun:await(ConnPid, Ref), ok. long_polling_body(Config) -> doc("Long-polling with a body that falls within the configurable limits."), ConnPid = gun_open(Config), - Ref = gun:post(ConnPid, "/long_polling", [], << 0:5000/unit:8 >>), + Ref = gun:post(ConnPid, "/long_polling", [{<<"accept-encoding">>, <<"gzip">>}], + << 0:5000/unit:8 >>), {response, fin, 102, _} = gun:await(ConnPid, Ref), ok. long_polling_body_too_large(Config) -> doc("Long-polling with a body that exceeds the configurable limits."), ConnPid = gun_open(Config), - Ref = gun:post(ConnPid, "/long_polling", [], << 0:100000/unit:8 >>), + Ref = gun:post(ConnPid, "/long_polling", [{<<"accept-encoding">>, <<"gzip">>}], + << 0:100000/unit:8 >>), {response, fin, 500, _} = gun:await(ConnPid, Ref), ok. long_polling_pipeline(Config) -> doc("Pipeline of long-polling calls."), ConnPid = gun_open(Config), - Refs = [gun:get(ConnPid, "/long_polling") || _ <- lists:seq(1, 2)], + Refs = [gun:get(ConnPid, "/long_polling", [{<<"accept-encoding">>, <<"gzip">>}]) + || _ <- lists:seq(1, 2)], _ = [{response, fin, 102, _} = gun:await(ConnPid, Ref) || Ref <- Refs], ok. loop_body(Config) -> doc("Check that a loop handler can read the request body in info/3."), ConnPid = gun_open(Config), - Ref = gun:post(ConnPid, "/loop_body", [], << 0:100000/unit:8 >>), + Ref = gun:post(ConnPid, "/loop_body", [{<<"accept-encoding">>, <<"gzip">>}], + << 0:100000/unit:8 >>), {response, fin, 200, _} = gun:await(ConnPid, Ref), ok. loop_timeout(Config) -> doc("Ensure that the loop handler timeout results in a 204 response."), ConnPid = gun_open(Config), - Ref = gun:get(ConnPid, "/loop_timeout"), + Ref = gun:get(ConnPid, "/loop_timeout", [{<<"accept-encoding">>, <<"gzip">>}]), {response, fin, 204, _} = gun:await(ConnPid, Ref), ok. diff --git a/test/req_SUITE.erl b/test/req_SUITE.erl index 769daf3..8f10ca3 100644 --- a/test/req_SUITE.erl +++ b/test/req_SUITE.erl @@ -25,14 +25,7 @@ all() -> cowboy_test:common_all(). groups() -> - AllTests = ct_helper:all(?MODULE), - [ - {http, [parallel], AllTests}, - {https, [parallel], AllTests}, - {h2, [parallel], AllTests}, - {h2c, [parallel], AllTests} - %% @todo With compression enabled. - ]. + cowboy_test:common_groups(ct_helper:all(?MODULE)). init_per_suite(Config) -> ct_helper:create_static_dir(config(priv_dir, Config) ++ "/static"), @@ -74,30 +67,31 @@ do_body(Method, Path, Config) -> do_body(Method, Path, Headers, Config) -> do_body(Method, Path, Headers, <<>>, Config). -do_body(Method, Path, Headers, Body, Config) -> +do_body(Method, Path, Headers0, Body, Config) -> ConnPid = gun_open(Config), + Headers = [{<<"accept-encoding">>, <<"gzip">>}|Headers0], Ref = case Body of <<>> -> gun:request(ConnPid, Method, Path, Headers); _ -> gun:request(ConnPid, Method, Path, Headers, Body) end, - {response, IsFin, 200, _} = gun:await(ConnPid, Ref), + {response, IsFin, 200, RespHeaders} = gun:await(ConnPid, Ref), {ok, RespBody} = case IsFin of nofin -> gun:await_body(ConnPid, Ref); fin -> {ok, <<>>} end, gun:close(ConnPid), - RespBody. + do_decode(RespHeaders, RespBody). do_get(Path, Config) -> ConnPid = gun_open(Config), - Ref = gun:get(ConnPid, Path, []), - {response, IsFin, Status, Headers} = gun:await(ConnPid, Ref), + Ref = gun:get(ConnPid, Path, [{<<"accept-encoding">>, <<"gzip">>}]), + {response, IsFin, Status, RespHeaders} = gun:await(ConnPid, Ref), {ok, RespBody} = case IsFin of nofin -> gun:await_body(ConnPid, Ref); fin -> {ok, <<>>} end, gun:close(ConnPid), - {Status, Headers, RespBody}. + {Status, RespHeaders, do_decode(RespHeaders, RespBody)}. do_get_body(Path, Config) -> do_get_body(Path, [], Config). @@ -105,6 +99,12 @@ do_get_body(Path, Config) -> do_get_body(Path, Headers, Config) -> do_body("GET", Path, Headers, Config). +do_decode(Headers, Body) -> + case lists:keyfind(<<"content-encoding">>, 1, Headers) of + {_, <<"gzip">>} -> zlib:gunzip(Body); + _ -> Body + end. + %% Tests: Request. binding(Config) -> @@ -129,7 +129,8 @@ header(Config) -> headers(Config) -> doc("Request headers."), - << "#{<<\"header\">> => <<\"value\">>", _/bits >> + %% We always send accept-encoding with this test suite's requests. + <<"#{<<\"accept-encoding\">> => <<\"gzip\">>,<<\"header\">> => <<\"value\">>", _/bits>> = do_get_body("/headers", [{<<"header">>, "value"}], Config), ok. diff --git a/test/static_handler_SUITE.erl b/test/static_handler_SUITE.erl index 15fd473..78926ee 100644 --- a/test/static_handler_SUITE.erl +++ b/test/static_handler_SUITE.erl @@ -39,8 +39,11 @@ groups() -> {http, [parallel], GroupTests}, {https, [parallel], GroupTests}, {h2, [parallel], GroupTests}, - {h2c, [parallel], GroupTests} - %% @todo With compression enabled. + {h2c, [parallel], GroupTests}, + {http_compress, [parallel], GroupTests}, + {https_compress, [parallel], GroupTests}, + {h2_compress, [parallel], GroupTests}, + {h2c_compress, [parallel], GroupTests} ]. init_per_suite(Config) -> @@ -171,7 +174,7 @@ do_get(Path, Config) -> do_get(Path, ReqHeaders, Config) -> ConnPid = gun_open(Config), - Ref = gun:get(ConnPid, Path, ReqHeaders), + Ref = gun:get(ConnPid, Path, [{<<"accept-encoding">>, <<"gzip">>}|ReqHeaders]), {response, IsFin, Status, RespHeaders} = gun:await(ConnPid, Ref), {ok, Body} = case IsFin of nofin -> gun:await_body(ConnPid, Ref); |