From d2bd3f357446d6d580db0fafd16377855cc81492 Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Mon, 8 Apr 2013 17:06:58 +0200 Subject: Add testcase to exercise reconnect behaviour --- lib/diameter/test/diameter_transport_SUITE.erl | 90 +++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 2 deletions(-) (limited to 'lib/diameter/test') diff --git a/lib/diameter/test/diameter_transport_SUITE.erl b/lib/diameter/test/diameter_transport_SUITE.erl index 893b7ba2f9..de097b886e 100644 --- a/lib/diameter/test/diameter_transport_SUITE.erl +++ b/lib/diameter/test/diameter_transport_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2011. All Rights Reserved. +%% Copyright Ericsson AB 2010-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -36,6 +36,7 @@ tcp_connect/1, sctp_accept/1, sctp_connect/1, + reconnect/1, reconnect/0, stop/1]). -export([accept/1, @@ -102,7 +103,8 @@ tc() -> [tcp_accept, tcp_connect, sctp_accept, - sctp_connect]. + sctp_connect, + reconnect]. init_per_suite(Config) -> [{sctp, have_sctp()} | Config]. @@ -164,6 +166,90 @@ connect(Prot) -> T = {Prot, make_ref()}, [] = ?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. + %% =========================================================================== %% =========================================================================== -- cgit v1.2.3