diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/send_errors_SUITE.erl | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/test/send_errors_SUITE.erl b/test/send_errors_SUITE.erl new file mode 100644 index 0000000..7a0fd02 --- /dev/null +++ b/test/send_errors_SUITE.erl @@ -0,0 +1,139 @@ +%% Copyright (c) 2020, Björn Svensson <[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(send_errors_SUITE). +-compile(export_all). +-compile(nowarn_export_all). + +-import(ct_helper, [doc/1]). +-import(gun_test, [http2_handshake/2]). + +suite() -> + [{timetrap, 180000}]. + +all() -> + [{group, gun}]. + +groups() -> + [{gun, [parallel], ct_helper:all(?MODULE)}]. + +init_per_suite(Config) -> + case os:type() of + {_, linux} -> Config; + _ -> {skip, "linux only due to socket juggling"} + end. + +end_per_suite(_) -> ok. + +%% Tests. + +http2_send_request_fail(_) -> + doc("Handle send failures of requests in http2."), + {ok, ListenSocket} = gen_tcp:listen(0, [binary, {active, false}]), + {ok, {_, Port}} = inet:sockname(ListenSocket), + %% Socket buffers needs to be smaller than local_window/ConnWindow + {ok, Pid} = gun:open("localhost", Port, #{ + protocols => [http2], + tcp_opts => [ + {send_timeout, 250}, + {send_timeout_close, true}, + {sndbuf, 2048}, + {nodelay, true} + ] + }), + {ok, ClientSocket} = gen_tcp:accept(ListenSocket, 5000), + inet:setopts(ClientSocket, [{recbuf, 512}]), + http2_handshake(ClientSocket, gen_tcp), + {ok, http2} = gun:await_up(Pid), + post_loop(Pid, 1000), %% Fill buffer + receive + {gun_error, Pid, _, {closed, {error, _}}} -> + gun:close(Pid); + Msg -> + error({fail, Msg}) + after 5000 -> + error(timeout) + end. + +http2_send_ping_fail(_) -> + doc("Handle send failures of ping in http2."), + {ok, ListenSocket} = gen_tcp:listen(0, [binary, {active, false}]), + {ok, {_, Port}} = inet:sockname(ListenSocket), + {ok, Pid} = gun:open("localhost", Port, #{ + protocols => [http2], + http2_opts => #{keepalive => 1}, + tcp_opts => [ + {send_timeout, 250}, + {send_timeout_close, true}, + {sndbuf, 256}, + {nodelay, true} + ] + }), + {ok, ClientSocket} = gen_tcp:accept(ListenSocket, 5000), + inet:setopts(ClientSocket, [{recbuf, 256}]), + http2_handshake(ClientSocket, gen_tcp), + {ok, http2} = gun:await_up(Pid), + receive + {gun_down, Pid, http2, {error, _}, []} -> + gun:close(Pid); + Msg -> + error({fail, Msg}) + after 5000 -> + error(timeout) + end. + +http2_send_ping_ack_fail(_) -> + doc("Handle send failures of ping ack in http2."), + {ok, ListenSocket} = gen_tcp:listen(0, [binary, {active, false}]), + {ok, {_, Port}} = inet:sockname(ListenSocket), + {ok, Pid} = gun:open("localhost", Port, #{ + protocols => [http2], + http2_opts => #{keepalive => infinity}, + tcp_opts => [ + {send_timeout, 250}, + {send_timeout_close, true}, + {sndbuf, 256}, + {nodelay, true} + ] + }), + {ok, ClientSocket} = gen_tcp:accept(ListenSocket, 5000), + inet:setopts(ClientSocket, [{recbuf, 256}]), + http2_handshake(ClientSocket, gen_tcp), + {ok, http2} = gun:await_up(Pid), + ping_loop(ClientSocket, 1800), %% Send pings triggering ping acks + receive + {gun_down, Pid, http2, {error, _}, []} -> + gun:close(Pid); + Msg -> + error({fail, Msg}) + after 5000 -> + error(timeout) + end. + +%% Helpers + +post_loop(_Pid, 0) -> + ok; +post_loop(Pid, Loops) -> + Body = <<0:1000>>, + gun:post(Pid, "/organizations/ninenines", + [{<<"content-type">>, "application/octet-stream"}], + Body), + post_loop(Pid, Loops - 1). + +ping_loop(_Socket, 0) -> + ok; +ping_loop(Socket, Loops) -> + gun_tcp:send(Socket, cow_http2:ping(0)), + ping_loop(Socket, Loops - 1). |