aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/compress_SUITE.erl129
-rw-r--r--test/cowboy_test.erl51
-rw-r--r--test/handlers/compress_h.erl37
-rw-r--r--test/handlers/echo_h.erl2
-rw-r--r--test/handlers/resp_h.erl4
-rw-r--r--test/loop_handler_SUITE.erl16
-rw-r--r--test/req_SUITE.erl31
-rw-r--r--test/static_handler_SUITE.erl9
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);