From 84adefa331c4159d432d22840663c38f155cd4c1 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Fri, 20 Nov 2009 14:54:40 +0000 Subject: The R13B03 release. --- lib/megaco/test/megaco_test_generic_transport.erl | 354 ++++++++++++++++++++++ 1 file changed, 354 insertions(+) create mode 100644 lib/megaco/test/megaco_test_generic_transport.erl (limited to 'lib/megaco/test/megaco_test_generic_transport.erl') diff --git a/lib/megaco/test/megaco_test_generic_transport.erl b/lib/megaco/test/megaco_test_generic_transport.erl new file mode 100644 index 0000000000..10afa45baa --- /dev/null +++ b/lib/megaco/test/megaco_test_generic_transport.erl @@ -0,0 +1,354 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2007-2009. 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 +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: Generic megaco transport simulator module +%%---------------------------------------------------------------------- + +-module(megaco_test_generic_transport). + +-behaviour(gen_server). +-behaviour(megaco_transport). + +-export([ + start_transport/0, + listen/2, + connect/2, + start/1, + stop/0, + incomming_message/2 + ]). + +%% gen_server callbacks +-export([ + init/1, + handle_call/3, + handle_cast/2, + handle_info/2, + terminate/2, + code_change/3 + ]). + +%% megaco_transport callbacks +-export([ + send_message/2, + send_message/3, + resend_message/2 + ]). + +-record(state, {parent, + controller, + receive_handle}). + +-include_lib("megaco/include/megaco.hrl"). +%% -include("megaco_test_lib.hrl"). +-define(SERVER, ?MODULE). + + +%%------------------------------------------------------------------- +%% API +%%------------------------------------------------------------------- + +start(RH) -> + {ok, Pid} = start_transport(), + {ok, SendHandle, _} = connect(Pid, [{receive_handle, RH}]), + {ok, SendHandle}. + +start_transport() -> + %% GS_ARGS = [{debug,[trace]}], + GS_ARGS = [], + {ok, Pid} = gen_server:start_link({local, ?SERVER}, ?MODULE, [self()], GS_ARGS), + unlink(Pid), + {ok, Pid}. + +connect(Sup, Opts) -> + call({connect, Sup, Opts}). + +listen(Sup, Opts) -> + call({listen, Sup, Opts}). + +stop() -> + call(stop). + + +%%---------------------------------------------------------------------- +%% Megaco transport callback +%%---------------------------------------------------------------------- + +send_message(SendHandle, Bin) -> + call({transport, {send_message, SendHandle, Bin}}). + +send_message(SendHandle, Bin, Resend) -> + call({transport, {send_message, SendHandle, Bin, Resend}}). + +resend_message(SendHandle, Bin) -> + call({transport, {resend_message, SendHandle, Bin}}). + +incomming_message(Pid, Msg) -> + cast(Pid, {incomming_message, Msg}). + + +%%%------------------------------------------------------------------- +%%% Callback functions from gen_server +%%%------------------------------------------------------------------- + +%%-------------------------------------------------------------------- +%% Func: init/1 +%% Returns: {ok, State} | +%% {ok, State, Timeout} | +%% ignore | +%% {stop, Reason} +%%-------------------------------------------------------------------- +init([Parent]) -> + {ok, #state{parent = Parent}}. + + +%%-------------------------------------------------------------------- +%% Func: handle_call/3 +%% Returns: {reply, Reply, State} | +%% {reply, Reply, State, Timeout} | +%% {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, Reply, State} | (terminate/2 is called) +%% {stop, Reason, State} (terminate/2 is called) +%%-------------------------------------------------------------------- +handle_call({connect, _Sup, Opts}, _From, State) -> + d("handle_call(connect) -> entry with" + "~n Opts: ~p", [Opts]), + {value, {_, ReceiveHandle}} = lists:keysearch(receive_handle, 1, Opts), + {value, {_, Controller}} = lists:keysearch(port, 1, Opts), + SendHandle = self(), + ControlPid = self(), + Reply = {ok, SendHandle, ControlPid}, + {reply, Reply, State#state{controller = Controller, + receive_handle = ReceiveHandle}}; + +handle_call({listen, _Sup, Opts}, _From, State) -> + d("handle_call(listen) -> entry with" + "~n Opts: ~p", [Opts]), + {value, {_, ReceiveHandle}} = lists:keysearch(receive_handle, 1, Opts), + {value, {_, Controller}} = lists:keysearch(port, 1, Opts), + SendHandle = self(), + ControlPid = self(), + Reply = {ok, SendHandle, ControlPid}, + Controller ! {listen, ReceiveHandle, SendHandle, ControlPid}, + {reply, Reply, State#state{controller = Controller, + receive_handle = ReceiveHandle}}; + +handle_call(stop, _From, State) -> + d("handle_call(stop) -> entry"), + Reply = ok, + Reason = normal, + {stop, Reason, Reply, State}; + +handle_call({transport, Event}, _From, + #state{controller = Pid, receive_handle = RH} = State) -> + d("handle_call(transport) -> entry with" + "~n Event: ~p", [Event]), + Reply = handle_transport(Pid, RH, Event), + {reply, Reply, State}; + +handle_call(Req, From, State) -> + d("handle_call -> entry with" + "~n Req: ~p", [Req]), + Reply = {error, {unknown_request, Req}}, + Reason = {received_unexpected_request, Req, From}, + {stop, Reason, Reply, State}. + + +%%-------------------------------------------------------------------- +%% Func: handle_cast/2 +%% Returns: {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, State} (terminate/2 is called) +%%-------------------------------------------------------------------- +handle_cast({incomming_message, Msg}, + #state{receive_handle = RH} = State) -> + d("handle_cast(incomming_message) -> entry with" + "~n Msg: ~p", [Msg]), + handle_incomming_message(Msg, RH), + {noreply, State}; + +handle_cast(Msg, State) -> + d("handle_cast -> entry with" + "~n Msg: ~p", [Msg]), + Reason = {received_unexpected_message, Msg}, + {stop, Reason, State}. + + +%%-------------------------------------------------------------------- +%% Func: handle_info/2 +%% Returns: {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, State} (terminate/2 is called) +%%-------------------------------------------------------------------- +handle_info(Info, State) -> + d("handle_info -> entry with" + "~n Info: ~p", [Info]), + Reason = {received_unexpected_info, Info}, + {stop, Reason, State}. + + +%%-------------------------------------------------------------------- +%% Func: terminate/2 +%% Purpose: Shutdown the server +%% Returns: any (ignored by gen_server) +%%-------------------------------------------------------------------- +terminate(_Reason, _State) -> + ok. + + +%%---------------------------------------------------------------------- +%% Func: code_change/3 +%% Purpose: Convert process state when code is changed +%% Returns: {ok, NewState} +%%---------------------------------------------------------------------- + +code_change(_Vsn, State, _Extra) -> + {ok, State}. + + +%%%------------------------------------------------------------------- +%%% Internal functions +%%%------------------------------------------------------------------- + +handle_transport(Pid, + #megaco_receive_handle{encoding_mod = EM, + encoding_config = EC}, + {Event, SendHandle, Bin, Resend}) -> + Info = + case (catch EM:decode_message(EC, Bin)) of + {ok, MegMsg} -> + {message, MegMsg, Resend}; + Error -> + d("handle_transport -> decode failed" + "~n Error: ~p", [Error]), + {bad_message, Error, Bin} + end, + handle_transport(Pid, Event, SendHandle, Info); +handle_transport(Pid, + #megaco_receive_handle{encoding_mod = EM, + encoding_config = EC}, + {Event, SendHandle, Bin}) -> + Info = + case (catch EM:decode_message(EC, Bin)) of + {ok, MegMsg} -> + {message, MegMsg}; + Error -> + d("handle_transport -> decode failed" + "~n Error: ~p", [Error]), + {bad_message, Error, Bin} + end, + handle_transport(Pid, Event, SendHandle, Info). + +handle_transport(Pid, Event, SendHandle, Info) -> + Pid ! {transport_event, {Event, SendHandle, Info}, self()}, + receive + {transport_reply, Reply, Pid} -> + d("handle_transport -> received reply" + "~n Reply: ~p", [Reply]), + Reply + after 10000 -> + receive + Any -> + d("handle_transport -> received crap after timeout" + "~n Any: ~p", [Any]), + exit({timeout, Any}) + after 0 -> + d("handle_transport -> timeout"), + exit(timeout) + end + end. + + +%% This function is used to simulate incomming messages +handle_incomming_message(Msg, + #megaco_receive_handle{encoding_mod = EM, + encoding_config = EC} = RH) -> + Self = self(), + case EM:encode_message(EC, Msg) of + {ok, Bin} -> + ProcessMessage = + fun() -> + megaco:process_received_message(RH, Self, Self, Bin) + end, + spawn(ProcessMessage), + ok; + Error -> + d("handle_incomming_message -> encode failed" + "~n Error: ~p", [Error]), + exit(Error) + end. + + +%%------------------------------------------------------------------- + +call(Req) -> + call(Req, infinity). + +call(Req, Timeout) -> + case (catch gen_server:call(?SERVER, Req, Timeout)) of + {'EXIT', _} -> + {error, not_started}; + Res -> + Res + end. + +%% cast(Msg) -> +%% cast(whereis(?SERVER), Msg). + +cast(Pid, Msg) -> + d("cast -> entry with" + "~n Pid: ~p" + "~n Msg: ~p", [Pid, Msg]), + case (catch gen_server:cast(Pid, Msg)) of + {'EXIT', Reason} -> + d("cast -> failed casting" + "~n Reason: ~p", [Reason]), + {error, not_started}; + Res -> + Res + end. + + +%%------------------------------------------------------------------- + +d(F) -> + d(F, []). + +d(F, A) -> + print(now(), F, A). + + +print(Ts, F, A) -> + io:format("*** [~s] GENERIC TRANSPORT [~p] ***" + "~n " ++ F ++ "~n", + [format_timestamp(Ts), self() | A]). + +format_timestamp({_N1, _N2, N3} = Now) -> + {Date, Time} = calendar:now_to_datetime(Now), + {YYYY,MM,DD} = Date, + {Hour,Min,Sec} = Time, + FormatDate = + io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w", + [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]), + lists:flatten(FormatDate). + + -- cgit v1.2.3