aboutsummaryrefslogtreecommitdiffstats
path: root/lib/diameter/test
diff options
context:
space:
mode:
Diffstat (limited to 'lib/diameter/test')
-rw-r--r--lib/diameter/test/diameter_transport_SUITE.erl88
1 files changed, 87 insertions, 1 deletions
diff --git a/lib/diameter/test/diameter_transport_SUITE.erl b/lib/diameter/test/diameter_transport_SUITE.erl
index dab0bc4215..97f4cec11f 100644
--- a/lib/diameter/test/diameter_transport_SUITE.erl
+++ b/lib/diameter/test/diameter_transport_SUITE.erl
@@ -36,6 +36,7 @@
tcp_connect/1,
sctp_accept/1,
sctp_connect/1,
+ reconnect/1, reconnect/0,
stop/1]).
-export([accept/1,
@@ -99,7 +100,8 @@ tc() ->
[tcp_accept,
tcp_connect,
sctp_accept,
- sctp_connect].
+ sctp_connect,
+ reconnect].
init_per_suite(Config) ->
[{sctp, have_sctp()} | Config].
@@ -162,6 +164,90 @@ connect(Prot) ->
[] = ?util:run([{?MODULE, [init, X, T]} || X <- [gen_accept, connect]]).
%% ===========================================================================
+%% reconnect/1
+%%
+%% Exercise reconnection behaviour: that a connecting transport
+%% doesn't try to establish a new connection until the old one is
+%% broken.
+
+reconnect() ->
+ [{timetrap, {minutes, 4}}].
+
+reconnect({listen, Ref}) ->
+ SvcName = make_ref(),
+ ok = start_service(SvcName),
+ LRef = ?util:listen(SvcName, tcp, [{watchdog_timer, 6000}]),
+ [_] = diameter_reg:wait({diameter_tcp, listener, {LRef, '_'}}),
+ true = diameter_reg:add_new({?MODULE, Ref, LRef}),
+
+ %% Wait for partner to request transport death: kill to force the
+ %% peer to reconnect.
+ TPid = abort(SvcName, LRef, Ref),
+
+ exit(TPid, kill),
+
+ abort(SvcName, LRef, Ref);
+
+reconnect({connect, Ref}) ->
+ SvcName = make_ref(),
+ true = diameter:subscribe(SvcName),
+ ok = start_service(SvcName),
+ [{{_, _, LRef}, Pid}] = diameter_reg:wait({?MODULE, Ref, '_'}),
+ CRef = ?util:connect(SvcName, tcp, LRef, [{reconnect_timer, 2000},
+ {watchdog_timer, 6000}]),
+
+ %% Tell partner to kill transport after seeing that there are no
+ %% reconnection attempts.
+ abort(SvcName, Pid, Ref),
+
+ %% Transport does down and is reestablished.
+ ?RECV(#diameter_event{service = SvcName, info = {down, CRef, _, _}}),
+ ?RECV(#diameter_event{service = SvcName, info = {reconnect, CRef, _}}),
+ ?RECV(#diameter_event{service = SvcName, info = {up, CRef, _, _, _}}),
+
+ %% Kill again.
+ abort(SvcName, Pid, Ref),
+
+ %% Wait for partner to die.
+ MRef = erlang:monitor(process, Pid),
+ ?RECV({'DOWN', MRef, process, _, _});
+
+reconnect(_) ->
+ Ref = make_ref(),
+ [] = ?util:run([{?MODULE, [reconnect, {T, Ref}]}
+ || T <- [listen, connect]]).
+
+start_service(SvcName) ->
+ OH = io_lib:format("~p-~p-~p", tuple_to_list(now())),
+ Opts = [{application, [{dictionary, diameter_gen_base_rfc6733},
+ {module, diameter_callback}]},
+ {'Origin-Host', OH},
+ {'Origin-Realm', OH ++ ".org"},
+ {'Vendor-Id', 0},
+ {'Product-Name', "x"},
+ {'Auth-Application-Id', [0]}],
+ diameter:start_service(SvcName, Opts).
+
+abort(SvcName, Pid, Ref)
+ when is_pid(Pid) ->
+ receive
+ #diameter_event{service = SvcName, info = {reconnect, _, _}} = E ->
+ erlang:error(E)
+ after 45000 ->
+ ok
+ end,
+ Pid ! {abort, Ref};
+
+abort(SvcName, LRef, Ref)
+ when is_reference(LRef) ->
+ ?RECV({abort, Ref}),
+ [[{ref, LRef}, {type, listen}, {options, _}, {accept, [_,_] = Ts} | _]]
+ %% assert on two accepting
+ = diameter:service_info(SvcName, transport),
+ [TPid] = [P || [{watchdog, {_,_,okay}}, {peer, {P,_}} | _] <- Ts],
+ TPid.
+
+%% ===========================================================================
%% ===========================================================================
%% have_sctp/0