Skip to content

Commit

Permalink
Explicitly close the socket in some tests for speed ups
Browse files Browse the repository at this point in the history
The socket staying open meant that the graceful shut down
of the Cowboy listeners were waiting for the connections
to be closed gracefully (or a timeout). Closing explicitly
where it makes sense ensures we don't unnecessarily wait.

This commit removes a full minute in the run time of all
Cowboy test suites (minus examples).
  • Loading branch information
essen committed Dec 18, 2023
1 parent 2558ba6 commit 627a450
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 21 deletions.
41 changes: 30 additions & 11 deletions test/http2_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ idle_timeout(Config) ->
{ok, Socket} = do_handshake([{port, Port}|Config]),
timer:sleep(1000),
%% Receive a GOAWAY frame back with NO_ERROR.
{ok, << _:24, 7:8, _:72, 0:32 >>} = gen_tcp:recv(Socket, 17, 1000)
{ok, << _:24, 7:8, _:72, 0:32 >>} = gen_tcp:recv(Socket, 17, 1000),
gen_tcp:close(Socket)
after
cowboy:stop_listener(?FUNCTION_NAME)
end.
Expand All @@ -79,7 +80,8 @@ idle_timeout_infinity(Config) ->
{ok, Socket} = do_handshake([{port, Port}|Config]),
timer:sleep(1000),
%% Don't receive a GOAWAY frame.
{error, timeout} = gen_tcp:recv(Socket, 17, 1000)
{error, timeout} = gen_tcp:recv(Socket, 17, 1000),
gen_tcp:close(Socket)
after
cowboy:stop_listener(?FUNCTION_NAME)
end.
Expand Down Expand Up @@ -108,7 +110,8 @@ idle_timeout_reset_on_data(Config) ->
{ok, <<8:24, 6:8, 0:7, 1:1, 0:96>>} = gen_tcp:recv(Socket, 17, 1000),
%% The connection goes away soon after we stop sending data.
timer:sleep(1000),
{ok, << _:24, 7:8, _:72, 0:32 >>} = gen_tcp:recv(Socket, 17, 1000)
{ok, << _:24, 7:8, _:72, 0:32 >>} = gen_tcp:recv(Socket, 17, 1000),
gen_tcp:close(Socket)
after
cowboy:stop_listener(?FUNCTION_NAME)
end.
Expand All @@ -125,7 +128,8 @@ inactivity_timeout(Config) ->
{ok, Socket} = do_handshake([{port, Port}|Config]),
receive after 1000 -> ok end,
%% Receive a GOAWAY frame back with an INTERNAL_ERROR.
{ok, << _:24, 7:8, _:72, 2:32 >>} = gen_tcp:recv(Socket, 17, 1000)
{ok, << _:24, 7:8, _:72, 2:32 >>} = gen_tcp:recv(Socket, 17, 1000),
gen_tcp:close(Socket)
after
cowboy:stop_listener(?FUNCTION_NAME)
end.
Expand All @@ -149,7 +153,8 @@ initial_connection_window_size(Config) ->
{ok, << 4:8, 0:40, _:Len/binary >>} = gen_tcp:recv(Socket, 6 + Len, 1000),
%% Receive a WINDOW_UPDATE frame incrementing the connection window to 100000.
{ok, <<4:24, 8:8, 0:41, Size:31>>} = gen_tcp:recv(Socket, 13, 1000),
ConfiguredSize = Size + 65535
ConfiguredSize = Size + 65535,
gen_tcp:close(Socket)
after
cowboy:stop_listener(?FUNCTION_NAME)
end.
Expand Down Expand Up @@ -192,7 +197,8 @@ max_frame_size_sent(Config) ->
%% The DATA frames following must have lengths of 20000
%% and then 10000 due to the limit.
{ok, <<20000:24, 0:8, _:40, _:20000/unit:8>>} = gen_tcp:recv(Socket, 20009, 6000),
{ok, <<10000:24, 0:8, _:40, _:10000/unit:8>>} = gen_tcp:recv(Socket, 10009, 6000)
{ok, <<10000:24, 0:8, _:40, _:10000/unit:8>>} = gen_tcp:recv(Socket, 10009, 6000),
gen_tcp:close(Socket)
after
cowboy:stop_listener(?FUNCTION_NAME)
end.
Expand Down Expand Up @@ -236,7 +242,7 @@ preface_timeout_infinity(Config) ->
{'DOWN', Ref, process, Pid, Reason} ->
error(Reason)
after 1000 ->
ok
gen_tcp:close(Socket)
end
after
cowboy:stop_listener(?FUNCTION_NAME)
Expand Down Expand Up @@ -280,7 +286,7 @@ settings_timeout_infinity(Config) ->
{'DOWN', Ref, process, Pid, Reason} ->
error(Reason)
after 1000 ->
ok
gen_tcp:close(Socket)
end
after
cowboy:stop_listener(?FUNCTION_NAME)
Expand Down Expand Up @@ -366,20 +372,26 @@ graceful_shutdown_timeout(Config) ->

graceful_shutdown_listener(Config) ->
doc("Check that connections are shut down gracefully when stopping a listener."),
TransOpts = #{
socket_opts => [{port, 0}],
shutdown => 1000 %% Shorter timeout to make the test case faster.
},
Dispatch = cowboy_router:compile([{"localhost", [
{"/delay_hello", delay_hello_h,
#{delay => 500, notify_received => self()}}
]}]),
ProtoOpts = #{
env => #{dispatch => Dispatch}
},
{ok, Listener} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], ProtoOpts),
{ok, Listener} = cowboy:start_clear(?FUNCTION_NAME, TransOpts, ProtoOpts),
Port = ranch:get_port(?FUNCTION_NAME),
ConnPid = gun_open([{type, tcp}, {protocol, http2}, {port, Port}|Config]),
Ref = gun:get(ConnPid, "/delay_hello"),
%% Shutdown listener while the handlers are working.
receive {request_received, <<"/delay_hello">>} -> ok end,
ListenerMonitorRef = monitor(process, Listener),
%% Note: This call does not complete quickly and will
%% prevent other cowboy:stop_listener/1 calls to complete.
ok = cowboy:stop_listener(?FUNCTION_NAME),
receive
{'DOWN', ListenerMonitorRef, process, Listener, _Reason} ->
Expand All @@ -393,6 +405,10 @@ graceful_shutdown_listener(Config) ->

graceful_shutdown_listener_timeout(Config) ->
doc("Check that connections are shut down when gracefully stopping a listener times out."),
TransOpts = #{
socket_opts => [{port, 0}],
shutdown => 1000 %% Shorter timeout to make the test case faster.
},
Dispatch = cowboy_router:compile([{"localhost", [
{"/long_delay_hello", delay_hello_h,
#{delay => 10000, notify_received => self()}}
Expand All @@ -402,13 +418,15 @@ graceful_shutdown_listener_timeout(Config) ->
goaway_initial_timeout => 200,
goaway_complete_timeout => 500
},
{ok, Listener} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], ProtoOpts),
{ok, Listener} = cowboy:start_clear(?FUNCTION_NAME, TransOpts, ProtoOpts),
Port = ranch:get_port(?FUNCTION_NAME),
ConnPid = gun_open([{type, tcp}, {protocol, http2}, {port, Port}|Config]),
Ref = gun:get(ConnPid, "/long_delay_hello"),
%% Shutdown listener while the handlers are working.
receive {request_received, <<"/long_delay_hello">>} -> ok end,
ListenerMonitorRef = monitor(process, Listener),
%% Note: This call does not complete quickly and will
%% prevent other cowboy:stop_listener/1 calls to complete.
ok = cowboy:stop_listener(?FUNCTION_NAME),
receive
{'DOWN', ListenerMonitorRef, process, Listener, _Reason} ->
Expand Down Expand Up @@ -482,7 +500,8 @@ send_timeout_close(Config) ->
end,
ok = WaitClosedFun(2000),
false = erlang:is_process_alive(StreamPid),
false = erlang:is_process_alive(ServerPid)
false = erlang:is_process_alive(ServerPid),
gen_tcp:close(ClientSocket)
after
cowboy:stop_listener(?FUNCTION_NAME)
end.
15 changes: 11 additions & 4 deletions test/http_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ idle_timeout_infinity(Config) ->
{'DOWN', Ref, process, Pid, Reason} ->
error(Reason)
after 1000 ->
ok
gun:close(ConnPid)
end
after
cowboy:stop_listener(?FUNCTION_NAME)
Expand Down Expand Up @@ -293,7 +293,7 @@ request_timeout_infinity(Config) ->
{'DOWN', Ref, process, Pid, Reason} ->
error(Reason)
after 1000 ->
ok
gun:close(ConnPid)
end
after
cowboy:stop_listener(?FUNCTION_NAME)
Expand Down Expand Up @@ -349,7 +349,8 @@ set_options_chunked_false_ignored(Config) ->
%% is not disabled for that second request.
StreamRef2 = gun:get(ConnPid, "/resp/stream_reply2/200"),
{response, nofin, 200, Headers} = gun:await(ConnPid, StreamRef2),
{_, <<"chunked">>} = lists:keyfind(<<"transfer-encoding">>, 1, Headers)
{_, <<"chunked">>} = lists:keyfind(<<"transfer-encoding">>, 1, Headers),
gun:close(ConnPid)
after
cowboy:stop_listener(?FUNCTION_NAME)
end.
Expand Down Expand Up @@ -492,6 +493,10 @@ graceful_shutdown_connection(Config) ->

graceful_shutdown_listener(Config) ->
doc("Check that connections are shut down gracefully when stopping a listener."),
TransOpts = #{
socket_opts => [{port, 0}],
shutdown => 1000 %% Shorter timeout to make the test case faster.
},
Dispatch = cowboy_router:compile([{"localhost", [
{"/delay_hello", delay_hello_h,
#{delay => 500, notify_received => self()}},
Expand All @@ -501,7 +506,7 @@ graceful_shutdown_listener(Config) ->
ProtoOpts = #{
env => #{dispatch => Dispatch}
},
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], ProtoOpts),
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, TransOpts, ProtoOpts),
Port = ranch:get_port(?FUNCTION_NAME),
ConnPid1 = gun_open([{type, tcp}, {protocol, http}, {port, Port}|Config]),
Ref1 = gun:get(ConnPid1, "/delay_hello"),
Expand All @@ -510,6 +515,8 @@ graceful_shutdown_listener(Config) ->
%% Shutdown listener while the handlers are working.
receive {request_received, <<"/delay_hello">>} -> ok end,
receive {request_received, <<"/long_delay_hello">>} -> ok end,
%% Note: This call does not complete quickly and will
%% prevent other cowboy:stop_listener/1 calls to complete.
ok = cowboy:stop_listener(?FUNCTION_NAME),
%% Check that the 1st request is handled before shutting down.
{response, nofin, 200, RespHeaders} = gun:await(ConnPid1, Ref1),
Expand Down
2 changes: 1 addition & 1 deletion test/rfc7231_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ expect(Config) ->
{<<"expect">>, <<"100-continue">>}
]),
{inform, 100, _} = gun:await(ConnPid, Ref),
ok.
gun:close(ConnPid).

http10_expect(Config) ->
case config(protocol, Config) of
Expand Down
12 changes: 8 additions & 4 deletions test/rfc7540_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -1374,7 +1374,8 @@ max_frame_size_allow_exactly_custom(Config0) ->
{ok, << Len2:24, 1:8, _:40 >>} = gen_tcp:recv(Socket, 9, 6000),
{ok, _} = gen_tcp:recv(Socket, Len2, 6000),
%% No errors follow due to our sending of a 25000 bytes frame.
{error, timeout} = gen_tcp:recv(Socket, 0, 1000)
{error, timeout} = gen_tcp:recv(Socket, 0, 1000),
gen_tcp:close(Socket)
after
cowboy:stop_listener(?FUNCTION_NAME)
end.
Expand Down Expand Up @@ -2742,7 +2743,8 @@ settings_initial_window_size(Config0) ->
{ok, << Len2:24, 1:8, _:40 >>} = gen_tcp:recv(Socket, 9, 6000),
{ok, _} = gen_tcp:recv(Socket, Len2, 6000),
%% No errors follow due to our sending of more than 65535 bytes of data.
{error, timeout} = gen_tcp:recv(Socket, 0, 1000)
{error, timeout} = gen_tcp:recv(Socket, 0, 1000),
gen_tcp:close(Socket)
after
cowboy:stop_listener(?FUNCTION_NAME)
end.
Expand Down Expand Up @@ -2833,7 +2835,8 @@ settings_initial_window_size_before_ack(Config0) ->
{ok, << Len2:24, 1:8, _:40 >>} = gen_tcp:recv(Socket, 9, 6000),
{ok, _} = gen_tcp:recv(Socket, Len2, 6000),
%% No errors follow due to our sending of more than 0 bytes of data.
{error, timeout} = gen_tcp:recv(Socket, 0, 1000)
{error, timeout} = gen_tcp:recv(Socket, 0, 1000),
gen_tcp:close(Socket)
after
cowboy:stop_listener(?FUNCTION_NAME)
end.
Expand Down Expand Up @@ -2866,7 +2869,8 @@ settings_max_frame_size(Config0) ->
{ok, << Len2:24, 1:8, _:40 >>} = gen_tcp:recv(Socket, 9, 6000),
{ok, _} = gen_tcp:recv(Socket, Len2, 6000),
%% No errors follow due to our sending of a 25000 bytes frame.
{error, timeout} = gen_tcp:recv(Socket, 0, 1000)
{error, timeout} = gen_tcp:recv(Socket, 0, 1000),
gen_tcp:close(Socket)
after
cowboy:stop_listener(?FUNCTION_NAME)
end.
Expand Down
2 changes: 1 addition & 1 deletion test/stream_handler_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ flow_after_body_fully_read(Config) ->
%% Receive a 200 response, sent after the second flow command,
%% confirming that the flow command was accepted.
{response, _, 200, _} = gun:await(ConnPid, Ref),
ok.
gun:close(ConnPid).

set_options_ignore_unknown(Config) ->
doc("Confirm that unknown options are ignored when using the set_options commands."),
Expand Down

0 comments on commit 627a450

Please sign in to comment.