aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2012-08-06 13:39:28 +0200
committerLoïc Hoguin <[email protected]>2012-08-06 13:39:28 +0200
commit6b354c1124035c54b6648665aafbe7197b34bd0e (patch)
treed31bdd1e0e6cffe8f31e50b40516e63201c6046d /test
parent7d52280c2e3fcc9e1b89435c98ef96d4758aed7a (diff)
downloadranch-6b354c1124035c54b6648665aafbe7197b34bd0e.tar.gz
ranch-6b354c1124035c54b6648665aafbe7197b34bd0e.tar.bz2
ranch-6b354c1124035c54b6648665aafbe7197b34bd0e.zip
Make accept asynchronous
Ranch now accepts connection asynchronously through a separate process. The accept process is linked to the acceptor, calls accept and does nothing else but send the socket back to the acceptor. This allows us to receive messages in the acceptor to handle upgrades instead of polling. This will also allow us later to make acceptors system processes. Remove support for connection pools in favor of a simpler max_connections setting. Connections can be removed from the count, allowing us to have as many long-lived connections as we want while still limiting the number of short-lived ones. Add max_connections, max_connections with long-lived connections, and upgrade tests.
Diffstat (limited to 'test')
-rw-r--r--test/acceptor_SUITE.erl67
-rw-r--r--test/notify_and_wait_protocol.erl11
-rw-r--r--test/remove_conn_and_wait_protocol.erl17
3 files changed, 94 insertions, 1 deletions
diff --git a/test/acceptor_SUITE.erl b/test/acceptor_SUITE.erl
index c1313cc..389f375 100644
--- a/test/acceptor_SUITE.erl
+++ b/test/acceptor_SUITE.erl
@@ -29,6 +29,9 @@
%% tcp.
-export([tcp_echo/1]).
+-export([tcp_max_connections/1]).
+-export([tcp_max_connections_and_beyond/1]).
+-export([tcp_upgrade/1]).
%% ct.
@@ -37,7 +40,10 @@ all() ->
groups() ->
[{tcp, [
- tcp_echo
+ tcp_echo,
+ tcp_max_connections,
+ tcp_max_connections_and_beyond,
+ tcp_upgrade
]}, {ssl, [
ssl_echo
]}].
@@ -100,3 +106,62 @@ tcp_echo(_) ->
%% Make sure the listener stopped.
{'EXIT', _} = begin catch ranch:get_port(tcp_echo) end,
ok.
+
+tcp_max_connections(_) ->
+ {ok, _} = ranch:start_listener(tcp_max_connections, 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),
+ ok = connect_loop(Port, 11, 150),
+ 10 = ranch_server:count_connections(ListenerPid),
+ 10 = receive_loop(connected, 400),
+ 1 = receive_loop(connected, 1000).
+
+tcp_max_connections_and_beyond(_) ->
+ {ok, _} = ranch:start_listener(tcp_max_connections_and_beyond, 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),
+ 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,
+ ok = connect_loop(Port, 10, 0),
+ receive after 500 -> ok end,
+ 10 = ranch_server:count_connections(ListenerPid).
+
+tcp_upgrade(_) ->
+ receive after 20000 -> ok end,
+ {ok, _} = ranch:start_listener(tcp_upgrade, 1,
+ ranch_tcp, [{port, 0}],
+ notify_and_wait_protocol, [{msg, connected}, {pid, self()}]),
+ Port = ranch:get_port(tcp_upgrade),
+ ok = connect_loop(Port, 1, 0),
+ receive connected -> ok after 1000 -> error(timeout) end,
+ ranch:set_protocol_options(tcp_upgrade, [{msg, upgraded}, {pid, self()}]),
+ ok = connect_loop(Port, 1, 0),
+ receive upgraded -> ok after 1000 -> error(timeout) end.
+
+%% Utility functions.
+
+connect_loop(_, 0, _) ->
+ ok;
+connect_loop(Port, N, Sleep) ->
+ {ok, _} = gen_tcp:connect("localhost", Port,
+ [binary, {active, false}, {packet, raw}]),
+ receive after Sleep -> ok end,
+ connect_loop(Port, N - 1, Sleep).
+
+receive_loop(Message, Timeout) ->
+ receive_loop(Message, Timeout, 0).
+receive_loop(Message, Timeout, N) ->
+ receive Message ->
+ receive_loop(Message, Timeout, N + 1)
+ after Timeout ->
+ N
+ end.
diff --git a/test/notify_and_wait_protocol.erl b/test/notify_and_wait_protocol.erl
new file mode 100644
index 0000000..27542f2
--- /dev/null
+++ b/test/notify_and_wait_protocol.erl
@@ -0,0 +1,11 @@
+-module(notify_and_wait_protocol).
+-export([start_link/4]).
+-export([init/2]).
+
+start_link(_, _, _, [{msg, Msg}, {pid, TestPid}]) ->
+ Pid = spawn_link(?MODULE, init, [Msg, TestPid]),
+ {ok, Pid}.
+
+init(Msg, Pid) ->
+ Pid ! Msg,
+ receive after 2500 -> ok end.
diff --git a/test/remove_conn_and_wait_protocol.erl b/test/remove_conn_and_wait_protocol.erl
new file mode 100644
index 0000000..8fffca7
--- /dev/null
+++ b/test/remove_conn_and_wait_protocol.erl
@@ -0,0 +1,17 @@
+-module(remove_conn_and_wait_protocol).
+-export([start_link/4]).
+-export([init/2]).
+
+start_link(ListenerPid, _, _, [{remove, MaybeRemove}]) ->
+ Pid = spawn_link(?MODULE, init, [ListenerPid, MaybeRemove]),
+ {ok, Pid}.
+
+init(ListenerPid, MaybeRemove) ->
+ ranch:accept_ack(ListenerPid),
+ case MaybeRemove of
+ true ->
+ ranch_listener:remove_connection(ListenerPid);
+ false ->
+ ok
+ end,
+ receive after 2500 -> ok end.