Browse Source

Add tests and more docs about separate supervisor/connection

Loïc Hoguin 9 years ago
parent
commit
c867ec582d
4 changed files with 65 additions and 3 deletions
  1. 9 2
      manual/ranch_protocol.md
  2. 2 1
      src/ranch_protocol.erl
  3. 38 0
      test/acceptor_SUITE.erl
  4. 16 0
      test/supervisor_separate.erl

+ 9 - 2
manual/ranch_protocol.md

@@ -12,7 +12,7 @@ None.
 Callbacks
 ---------
 
-### start_link(Ref, Socket, Transport, ProtoOpts) -> {ok, pid()}
+### start_link(Ref, Socket, Transport, ProtoOpts) -> {ok, pid()} | {ok, pid(), pid()}
 
 > Types:
 >  *  Ref = ranch:ref()
@@ -27,9 +27,16 @@ Callbacks
 > then return the new pid. This function will always be called
 > from inside a supervisor.
 >
+> This callback can also return two pids. The first pid is the
+> pid of the process that will be supervised. The second pid is
+> the pid of the process that will receive ownership of the
+> socket. This second process must be a child of the first. This
+> form is only available when `connection_type` is set to
+> `supervisor`.
+>
 > If any other value is returned, the supervisor will close the
 > socket and assume no process has been started.
 >
-> Do not perform any operation in this callback, as this would
+> Do not perform any operations in this callback, as this would
 > block the supervisor responsible for starting connection
 > processes and degrade performance severely.

+ 2 - 1
src/ranch_protocol.erl

@@ -20,4 +20,5 @@
 		Socket::any(),
 		Transport::module(),
 		ProtocolOptions::any())
-	-> {ok, ConnectionPid::pid()}.
+	-> {ok, ConnectionPid::pid()}
+	| {ok, SupPid::pid(), ConnectionPid::pid()}.

+ 38 - 0
test/acceptor_SUITE.erl

@@ -42,6 +42,8 @@ groups() ->
 	]}, {misc, [
 		misc_bad_transport
 	]}, {supervisor, [
+		connection_type_supervisor,
+		connection_type_supervisor_separate_from_connection,
 		supervisor_clean_child_restart,
 		supervisor_clean_conns_sup_restart,
 		supervisor_clean_restart,
@@ -298,6 +300,42 @@ tcp_upgrade(_) ->
 
 %% Supervisor tests
 
+connection_type_supervisor(_) ->
+	doc("The supervisor connection type must be reflected in the specifications."),
+	Name = connection_type_supervisor,
+	{ok, _} = ranch:start_listener(Name, 1,
+		ranch_tcp, [{connection_type, supervisor}],
+		echo_protocol, []),
+	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),
+	ConnsSup = ranch_server:get_connections_sup(Name),
+	[{echo_protocol, _, supervisor, [echo_protocol]}] = supervisor:which_children(ConnsSup),
+	ok = ranch:stop_listener(Name),
+	{error, closed} = gen_tcp:recv(Socket, 0, 1000),
+	%% Make sure the listener stopped.
+	{'EXIT', _} = begin catch ranch:get_port(Name) end,
+	ok.
+
+connection_type_supervisor_separate_from_connection(_) ->
+	doc("The supervisor connection type allows separate supervised and connection processes."),
+	Name = connection_type_supervisor,
+	{ok, _} = ranch:start_listener(Name, 1,
+		ranch_tcp, [{connection_type, supervisor}],
+		supervisor_separate, []),
+	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),
+	ConnsSup = ranch_server:get_connections_sup(Name),
+	[{supervisor_separate, _, supervisor, [supervisor_separate]}] = supervisor:which_children(ConnsSup),
+	ok = ranch:stop_listener(Name),
+	{error, closed} = gen_tcp:recv(Socket, 0, 1000),
+	%% Make sure the listener stopped.
+	{'EXIT', _} = begin catch ranch:get_port(Name) end,
+	ok.
+
 supervisor_clean_child_restart(_) ->
 	%% Then we verify that only parts of the supervision tree
 	%% restarted in the case of failure.

+ 16 - 0
test/supervisor_separate.erl

@@ -0,0 +1,16 @@
+-module(supervisor_separate).
+-behavior(supervisor).
+-behavior(ranch_protocol).
+
+-export([start_link/4]).
+-export([init/1]).
+
+start_link(Ref, Socket, Transport, Opts) ->
+	{ok, SupPid} = supervisor:start_link(?MODULE, []),
+	{ok, ConnPid} = supervisor:start_child(SupPid,
+		{echo_protocol, {echo_protocol, start_link, [Ref, Socket, Transport, Opts]},
+			temporary, 5000, worker, [echo_protocol]}),
+	{ok, SupPid, ConnPid}.
+
+init([]) ->
+	{ok, {{one_for_one, 1, 1}, []}}.