diff options
Diffstat (limited to 'test/acceptor_SUITE.erl')
-rw-r--r-- | test/acceptor_SUITE.erl | 278 |
1 files changed, 168 insertions, 110 deletions
diff --git a/test/acceptor_SUITE.erl b/test/acceptor_SUITE.erl index 8a8979f..02a5d79 100644 --- a/test/acceptor_SUITE.erl +++ b/test/acceptor_SUITE.erl @@ -41,6 +41,7 @@ -export([tcp_max_connections_and_beyond/1]). -export([tcp_set_max_connections/1]). -export([tcp_infinity_max_connections/1]). +-export([tcp_clean_set_max_connections/1]). -export([tcp_upgrade/1]). %% supervisor. @@ -62,6 +63,7 @@ groups() -> tcp_infinity_max_connections, tcp_max_connections_and_beyond, tcp_set_max_connections, + tcp_clean_set_max_connections, tcp_upgrade ]}, {ssl, [ ssl_accept_error, @@ -111,201 +113,255 @@ misc_bad_transport(_) -> %% ssl. ssl_accept_error(Config) -> - {ok, _} = ranch:start_listener(ssl_accept_error, 1, + Name = ssl_accept_error, + {ok, ListenerSup} = ranch:start_listener(Name, 1, ranch_ssl, [{port, 0}, {certfile, ?config(data_dir, Config) ++ "cert.pem"}], echo_protocol, []), - Port = ranch:get_port(ssl_accept_error), - [AcceptorPid] = ets:lookup_element(ranch_server, - {acceptors, ssl_accept_error}, 2), + Port = ranch:get_port(Name), + ListenerSupChildren = supervisor:which_children(ListenerSup), + {_, AcceptorsSup, _, _} + = lists:keyfind(ranch_acceptors_sup, 1, ListenerSupChildren), + [{{acceptor, _, _}, AcceptorPid, _, _}] + = supervisor:which_children(AcceptorsSup), true = is_process_alive(AcceptorPid), {ok, Socket} = gen_tcp:connect("localhost", Port, [binary, {active, false}, {packet, raw}]), ok = gen_tcp:close(Socket), receive after 500 -> ok end, - true = is_process_alive(AcceptorPid). + true = is_process_alive(AcceptorPid), + ranch:stop_listener(Name). ssl_accept_socket(Config) -> %%% XXX we can't do the spawn to test the controlling process change %%% because of the bug in ssl + Name = ssl_accept_socket, {ok, S} = ssl:listen(0, [{certfile, ?config(data_dir, Config) ++ "cert.pem"}, binary, {active, false}, {packet, raw}, {reuseaddr, true}]), - {ok, _} = ranch:start_listener(ssl_accept_socket, 1, + {ok, _} = ranch:start_listener(Name, 1, ranch_ssl, [{socket, S}], echo_protocol, []), - Port = ranch:get_port(ssl_accept_socket), + Port = ranch:get_port(Name), {ok, Socket} = ssl:connect("localhost", Port, [binary, {active, false}, {packet, raw}, {certfile, ?config(data_dir, Config) ++ "cert.pem"}]), ok = ssl:send(Socket, <<"TCP Ranch is working!">>), {ok, <<"TCP Ranch is working!">>} = ssl:recv(Socket, 21, 1000), - ok = ranch:stop_listener(ssl_accept_socket), + ok = ranch:stop_listener(Name), {error, closed} = ssl:recv(Socket, 0, 1000), %% Make sure the listener stopped. - {'EXIT', _} = begin catch ranch:get_port(ssl_accept_socket) end, + {'EXIT', _} = begin catch ranch:get_port(Name) end, ok. ssl_active_echo(Config) -> - {ok, _} = ranch:start_listener(ssl_active_echo, 1, + Name = ssl_active_echo, + {ok, _} = ranch:start_listener(Name, 1, ranch_ssl, [{port, 0}, {certfile, ?config(data_dir, Config) ++ "cert.pem"}], active_echo_protocol, []), - Port = ranch:get_port(ssl_active_echo), + Port = ranch:get_port(Name), {ok, Socket} = ssl:connect("localhost", Port, [binary, {active, false}, {packet, raw}, {certfile, ?config(data_dir, Config) ++ "cert.pem"}]), ok = ssl:send(Socket, <<"SSL Ranch is working!">>), {ok, <<"SSL Ranch is working!">>} = ssl:recv(Socket, 21, 1000), - ok = ranch:stop_listener(ssl_active_echo), + ok = ranch:stop_listener(Name), {error, closed} = ssl:recv(Socket, 0, 1000), %% Make sure the listener stopped. - {'EXIT', _} = begin catch ranch:get_port(ssl_active_echo) end, + {'EXIT', _} = begin catch ranch:get_port(Name) end, ok. ssl_echo(Config) -> - {ok, _} = ranch:start_listener(ssl_echo, 1, + Name = ssl_echo, + {ok, _} = ranch:start_listener(Name, 1, ranch_ssl, [{port, 0}, {certfile, ?config(data_dir, Config) ++ "cert.pem"}], echo_protocol, []), - Port = ranch:get_port(ssl_echo), + Port = ranch:get_port(Name), {ok, Socket} = ssl:connect("localhost", Port, [binary, {active, false}, {packet, raw}, {certfile, ?config(data_dir, Config) ++ "cert.pem"}]), ok = ssl:send(Socket, <<"SSL Ranch is working!">>), {ok, <<"SSL Ranch is working!">>} = ssl:recv(Socket, 21, 1000), - ok = ranch:stop_listener(ssl_echo), + ok = ranch:stop_listener(Name), {error, closed} = ssl:recv(Socket, 0, 1000), %% Make sure the listener stopped. - {'EXIT', _} = begin catch ranch:get_port(ssl_echo) end, + {'EXIT', _} = begin catch ranch:get_port(Name) end, ok. %% tcp. tcp_accept_socket(_) -> + Name = tcp_accept_socket, Ref = make_ref(), Parent = self(), spawn(fun() -> - {ok, S} = gen_tcp:listen(0, [binary, {active, false}, {packet, raw}, - {reuseaddr, true}]), - {ok, _} = ranch:start_listener(tcp_accept_socket, 1, - ranch_tcp, [{socket, S}], echo_protocol, []), - Parent ! Ref - end), + {ok, S} = gen_tcp:listen(0, [binary, {active, false}, {packet, raw}, + {reuseaddr, true}]), + {ok, _} = ranch:start_listener(Name, 1, + ranch_tcp, [{socket, S}], echo_protocol, []), + Parent ! Ref + end), receive Ref -> ok end, - - Port = ranch:get_port(tcp_accept_socket), + Port = ranch:get_port(Name), {ok, Socket} = gen_tcp:connect("localhost", Port, [binary, {active, false}, {packet, raw}]), ok = gen_tcp:send(Socket, <<"TCP Ranch is working!">>), {ok, <<"TCP Ranch is working!">>} = gen_tcp:recv(Socket, 21, 1000), - ok = ranch:stop_listener(tcp_accept_socket), + ok = ranch:stop_listener(Name), {error, closed} = gen_tcp:recv(Socket, 0, 1000), %% Make sure the listener stopped. - {'EXIT', _} = begin catch ranch:get_port(tcp_accept_socket) end, + {'EXIT', _} = begin catch ranch:get_port(Name) end, ok. tcp_active_echo(_) -> - {ok, _} = ranch:start_listener(tcp_active_echo, 1, + Name = tcp_active_echo, + {ok, _} = ranch:start_listener(Name, 1, ranch_tcp, [{port, 0}], active_echo_protocol, []), - Port = ranch:get_port(tcp_active_echo), + Port = ranch:get_port(Name), {ok, Socket} = gen_tcp:connect("localhost", Port, [binary, {active, false}, {packet, raw}]), ok = gen_tcp:send(Socket, <<"TCP Ranch is working!">>), {ok, <<"TCP Ranch is working!">>} = gen_tcp:recv(Socket, 21, 1000), - ok = ranch:stop_listener(tcp_active_echo), + ok = ranch:stop_listener(Name), {error, closed} = gen_tcp:recv(Socket, 0, 1000), %% Make sure the listener stopped. - {'EXIT', _} = begin catch ranch:get_port(tcp_active_echo) end, + {'EXIT', _} = begin catch ranch:get_port(Name) end, ok. tcp_echo(_) -> - {ok, _} = ranch:start_listener(tcp_echo, 1, + Name = tcp_echo, + {ok, _} = ranch:start_listener(Name, 1, ranch_tcp, [{port, 0}], echo_protocol, []), - Port = ranch:get_port(tcp_echo), + Port = ranch:get_port(Name), {ok, Socket} = gen_tcp:connect("localhost", Port, [binary, {active, false}, {packet, raw}]), ok = gen_tcp:send(Socket, <<"TCP Ranch is working!">>), {ok, <<"TCP Ranch is working!">>} = gen_tcp:recv(Socket, 21, 1000), - ok = ranch:stop_listener(tcp_echo), + ok = ranch:stop_listener(Name), {error, closed} = gen_tcp:recv(Socket, 0, 1000), %% Make sure the listener stopped. - {'EXIT', _} = begin catch ranch:get_port(tcp_echo) end, + {'EXIT', _} = begin catch ranch:get_port(Name) end, ok. tcp_max_connections(_) -> - {ok, _} = ranch:start_listener(tcp_max_connections, 1, + Name = tcp_max_connections, + {ok, _} = ranch:start_listener(Name, 1, ranch_tcp, [{port, 0}, {max_connections, 10}], notify_and_wait_protocol, [{msg, connected}, {pid, self()}]), - Port = ranch:get_port(tcp_max_connections), - %% @todo We'll probably want a more direct interface to count_connections. - ListenerPid = ranch_server:lookup_listener(tcp_max_connections), + Port = ranch:get_port(Name), ok = connect_loop(Port, 11, 150), - 10 = ranch_server:count_connections(ListenerPid), + 10 = ranch_server:count_connections(Name), 10 = receive_loop(connected, 400), - 1 = receive_loop(connected, 1000). + 1 = receive_loop(connected, 1000), + ranch:stop_listener(Name). tcp_max_connections_and_beyond(_) -> - {ok, _} = ranch:start_listener(tcp_max_connections_and_beyond, 1, + Name = tcp_max_connections_and_beyond, + {ok, _} = ranch:start_listener(Name, 1, ranch_tcp, [{port, 0}, {max_connections, 10}], remove_conn_and_wait_protocol, [{remove, true}]), - Port = ranch:get_port(tcp_max_connections_and_beyond), - %% @todo We'll probably want a more direct interface to count_connections. - ListenerPid = ranch_server:lookup_listener(tcp_max_connections_and_beyond), + Port = ranch:get_port(Name), ok = connect_loop(Port, 10, 0), - 0 = ranch_server:count_connections(ListenerPid), - ranch:set_protocol_options(tcp_max_connections_and_beyond, - [{remove, false}]), - receive after 500 -> ok end, + receive after 250 -> ok end, + 0 = ranch_server:count_connections(Name), + 10 = length(supervisor:which_children( + ranch_server:get_connections_sup(Name))), + Counts = supervisor:count_children( + ranch_server:get_connections_sup(Name)), + {_, 1} = lists:keyfind(specs, 1, Counts), + {_, 0} = lists:keyfind(supervisors, 1, Counts), + {_, 10} = lists:keyfind(active, 1, Counts), + {_, 10} = lists:keyfind(workers, 1, Counts), + ranch:set_protocol_options(Name, [{remove, false}]), + receive after 250 -> ok end, ok = connect_loop(Port, 10, 0), - receive after 500 -> ok end, - 10 = ranch_server:count_connections(ListenerPid). + receive after 250 -> ok end, + 10 = ranch_server:count_connections(Name), + 20 = length(supervisor:which_children( + ranch_server:get_connections_sup(Name))), + Counts2 = supervisor:count_children( + ranch_server:get_connections_sup(Name)), + {_, 20} = lists:keyfind(active, 1, Counts2), + {_, 20} = lists:keyfind(workers, 1, Counts2), + ranch:stop_listener(Name). tcp_set_max_connections(_) -> - {ok, _} = ranch:start_listener(tcp_set_max_connections, 1, + Name = tcp_set_max_connections, + {ok, _} = ranch:start_listener(Name, 1, ranch_tcp, [{port, 0}, {max_connections, 10}], notify_and_wait_protocol, [{msg, connected}, {pid, self()}]), - Port = ranch:get_port(tcp_set_max_connections), - %% @todo We'll probably want a more direct interface to count_connections. - ListenerPid = ranch_server:lookup_listener(tcp_set_max_connections), + Port = ranch:get_port(Name), ok = connect_loop(Port, 20, 0), - 10 = ranch_server:count_connections(ListenerPid), + 10 = ranch_server:count_connections(Name), 10 = receive_loop(connected, 1000), - 10 = ranch:get_max_connections(tcp_set_max_connections), - ranch:set_max_connections(tcp_set_max_connections, 20), + 10 = ranch:get_max_connections(Name), + ranch:set_max_connections(Name, 20), 10 = receive_loop(connected, 1000), - 20 = ranch:get_max_connections(tcp_set_max_connections). + 20 = ranch:get_max_connections(Name), + ranch:stop_listener(Name). tcp_infinity_max_connections(_) -> - {ok, _} = ranch:start_listener(tcp_infinity_max_connections, 1, + Name = tcp_infinity_max_connections, + {ok, _} = ranch:start_listener(Name, 1, ranch_tcp, [{port, 0}, {max_connections, 10}], notify_and_wait_protocol, [{msg, connected}, {pid, self()}]), - Port = ranch:get_port(tcp_infinity_max_connections), - %% @todo We'll probably want a more direct interface to count_connections. - ListenerPid = ranch_server:lookup_listener(tcp_infinity_max_connections), + Port = ranch:get_port(Name), ok = connect_loop(Port, 20, 0), - 10 = ranch_server:count_connections(ListenerPid), + 10 = ranch_server:count_connections(Name), 10 = receive_loop(connected, 1000), - 10 = ranch:get_max_connections(tcp_infinity_max_connections), - ranch:set_max_connections(tcp_infinity_max_connections, infinity), - 0 = ranch_server:count_connections(ListenerPid), - infinity = ranch:get_max_connections(tcp_infinity_max_connections), - ranch:set_max_connections(tcp_infinity_max_connections, 10), - 0 = ranch_server:count_connections(ListenerPid), + 10 = ranch_server:count_connections(Name), + 10 = ranch:get_max_connections(Name), + ranch:set_max_connections(Name, infinity), + receive after 250 -> ok end, + 20 = ranch_server:count_connections(Name), + infinity = ranch:get_max_connections(Name), + ranch:set_max_connections(Name, 10), + 20 = ranch_server:count_connections(Name), 10 = receive_loop(connected, 1000), - 10 = ranch_server:count_connections(ListenerPid). % count could be off + ranch:stop_listener(Name). + +tcp_clean_set_max_connections(_) -> + %% This is a regression test to check that setting max connections does not + %% cause any processes to crash. + Name = tcp_clean_set_max_connections, + {ok, ListSupPid} = ranch:start_listener(Name, 4, ranch_tcp, + [{port, 0}, {max_connections, 4}], + notify_and_wait_protocol, [{msg, connected}, {pid, self()}]), + Children = supervisor:which_children(ListSupPid), + {_, AccSupPid, _, _} = lists:keyfind(ranch_acceptors_sup, 1, Children), + 1 = erlang:trace(ListSupPid, true, [procs]), + 1 = erlang:trace(AccSupPid, true, [procs]), + Port = ranch:get_port(tcp_clean_set_max_connections), + N = 20, + ok = connect_loop(Port, N*5, 0), + %% Randomly set max connections. + [spawn(ranch, set_max_connections, [tcp_clean_set_max_connections, Max]) || + Max <- lists:flatten(lists:duplicate(N, [6, 4, 8, infinity]))], + receive + {trace, _, spawn, _, _} -> + error(dirty_set_max_connections) + after + 2000 -> ok + end, + _ = erlang:trace(all, false, [all]), + ok = clean_traces(), + ranch:stop_listener(Name). tcp_upgrade(_) -> - {ok, _} = ranch:start_listener(tcp_upgrade, 1, + Name = tcp_upgrade, + {ok, _} = ranch:start_listener(Name, 1, ranch_tcp, [{port, 0}], notify_and_wait_protocol, [{msg, connected}, {pid, self()}]), - Port = ranch:get_port(tcp_upgrade), + Port = ranch:get_port(Name), ok = connect_loop(Port, 1, 0), receive connected -> ok after 1000 -> error(timeout) end, - ranch:set_protocol_options(tcp_upgrade, [{msg, upgraded}, {pid, self()}]), + ranch:set_protocol_options(Name, [{msg, upgraded}, {pid, self()}]), ok = connect_loop(Port, 1, 0), - receive upgraded -> ok after 1000 -> error(timeout) end. + receive upgraded -> ok after 1000 -> error(timeout) end, + ranch:stop_listener(Name). %% Supervisor tests @@ -313,22 +369,21 @@ supervisor_clean_restart(_) -> %% There we verify that mature listener death will not let %% whole supervisor down and also the supervisor itself will %% restart everything properly. - Ref = supervisor_clean_restart, + Name = supervisor_clean_restart, NbAcc = 4, - {ok, Pid} = ranch:start_listener(Ref, + {ok, Pid} = ranch:start_listener(Name, NbAcc, ranch_tcp, [{port, 0}], echo_protocol, []), %% Trace supervisor spawns. 1 = erlang:trace(Pid, true, [procs, set_on_spawn]), - ListenerPid0 = ranch_server:lookup_listener(Ref), - erlang:exit(ListenerPid0, kill), + ConnsSup0 = ranch_server:get_connections_sup(Name), + erlang:exit(ConnsSup0, kill), receive after 1000 -> ok end, %% Verify that supervisor is alive true = is_process_alive(Pid), %% ...but children are dead. - false = is_process_alive(ListenerPid0), + false = is_process_alive(ConnsSup0), %% Receive traces from newly started children - ListenerPid = receive {trace, Pid, spawn, Pid1, _} -> Pid1 end, - _ConnSupPid = receive {trace, Pid, spawn, Pid2, _} -> Pid2 end, + ConnsSup = receive {trace, Pid, spawn, Pid2, _} -> Pid2 end, AccSupPid = receive {trace, Pid, spawn, Pid3, _} -> Pid3 end, %% ...and its acceptors. [receive {trace, AccSupPid, spawn, _Pid, _} -> ok end || @@ -339,22 +394,24 @@ supervisor_clean_restart(_) -> error(invalid_restart) after 1000 -> ok end, %% Verify that new children registered themselves properly. - ListenerPid = ranch_server:lookup_listener(Ref), + ConnsSup = ranch_server:get_connections_sup(Name), _ = erlang:trace(all, false, [all]), - ok = clean_traces(). + ok = clean_traces(), + ranch:stop_listener(Name). supervisor_clean_child_restart(_) -> %% Then we verify that only parts of the supervision tree %% restarted in the case of failure. - Ref = supervisor_clean_child_restart, + Name = supervisor_clean_child_restart, %% Trace socket allocations. _ = erlang:trace(new, true, [call]), - 1 = erlang:trace_pattern({ranch_tcp, listen, 1}, [{'_', [], [{return_trace}]}], [global]), - {ok, Pid} = ranch:start_listener(Ref, + 1 = erlang:trace_pattern({ranch_tcp, listen, 1}, + [{'_', [], [{return_trace}]}], [global]), + {ok, Pid} = ranch:start_listener(Name, 1, ranch_tcp, [{port, 0}], echo_protocol, []), %% Trace supervisor spawns. 1 = erlang:trace(Pid, true, [procs, set_on_spawn]), - ListenerPid0 = ranch_server:lookup_listener(Ref), + ConnsSup = ranch_server:get_connections_sup(Name), %% Manually shut the listening socket down. LSocket = receive {trace, _, return_from, {ranch_tcp, listen, 1}, {ok, Socket}} -> @@ -366,31 +423,31 @@ supervisor_clean_child_restart(_) -> receive after 1000 -> ok end, %% Verify that supervisor and its first two children are alive. true = is_process_alive(Pid), - true = is_process_alive(ListenerPid0), + true = is_process_alive(ConnsSup), %% Check that acceptors_sup is restarted properly. AccSupPid = receive {trace, Pid, spawn, Pid1, _} -> Pid1 end, - AccPid = receive {trace, AccSupPid, spawn, Pid2, _} -> Pid2 end, - receive {trace, AccPid, spawn, _, _} -> ok end, + receive {trace, AccSupPid, spawn, _, _} -> ok end, %% No more traces then. receive {trace, _, spawn, _, _} -> error(invalid_restart) after 1000 -> ok end, %% Verify that children still registered right. - ListenerPid0 = ranch_server:lookup_listener(Ref), + ConnsSup = ranch_server:get_connections_sup(Name), _ = erlang:trace_pattern({ranch_tcp, listen, 1}, false, []), _ = erlang:trace(all, false, [all]), ok = clean_traces(), - ok. + ranch:stop_listener(Name). supervisor_conns_alive(_) -> %% And finally we make sure that in the case of partial failure %% live connections are not being killed. - Ref = supervisor_conns_alive, + Name = supervisor_conns_alive, _ = erlang:trace(new, true, [call]), - 1 = erlang:trace_pattern({ranch_tcp, listen, 1}, [{'_', [], [{return_trace}]}], [global]), - {ok, _} = ranch:start_listener(Ref, - 1, ranch_tcp, [{port, 0}], remove_conn_and_wait_protocol, [{remove, false}]), - ok, + 1 = erlang:trace_pattern({ranch_tcp, listen, 1}, + [{'_', [], [{return_trace}]}], [global]), + {ok, _} = ranch:start_listener(Name, 1, + ranch_tcp, [{port, 0}], + remove_conn_and_wait_protocol, [{remove, false}]), %% Get the listener socket LSocket = receive {trace, _, return_from, {ranch_tcp, listen, 1}, {ok, S}} -> @@ -398,7 +455,7 @@ supervisor_conns_alive(_) -> after 0 -> error(lsocket_unknown) end, - TcpPort = ranch:get_port(Ref), + TcpPort = ranch:get_port(Name), {ok, Socket} = gen_tcp:connect("localhost", TcpPort, [binary, {active, true}, {packet, raw}]), %% Shut the socket down @@ -408,17 +465,8 @@ supervisor_conns_alive(_) -> ok = gen_tcp:send(Socket, <<"poke">>), receive {tcp_closed, _} -> ok end, _ = erlang:trace(all, false, [all]), - ok = clean_traces(). - -clean_traces() -> - receive - {trace, _, _, _} -> - clean_traces(); - {trace, _, _, _, _} -> - clean_traces() - after 0 -> - ok - end. + ok = clean_traces(), + ranch:stop_listener(Name). %% Utility functions. @@ -438,3 +486,13 @@ receive_loop(Message, Timeout, N) -> after Timeout -> N end. + +clean_traces() -> + receive + {trace, _, _, _} -> + clean_traces(); + {trace, _, _, _, _} -> + clean_traces() + after 0 -> + ok + end. |