📄 megaco_call_flow_test.erl
字号:
Stat7 = ?SP("rtp/delay","40"), Statistics = [Stat, Stat2, Stat3, Stat4, Stat5, Stat6, Stat7], Audits = [{mediaDescriptor, Media}, {packagesDescriptor, [PackagesItem, PackagesItem2]}, {statisticsDescriptor, Statistics}], Reply = {auditResult, #'AuditResult'{terminationID = #megaco_term_id{id = ?A5556}, terminationAuditResult = Audits}}, reply(Mid, 50007, ?megaco_null_context_id, [{auditValueReply, Reply}]).%%----------------------------------------------------------------------%% 22. When the MGC receives an onhook signal from one of the MGs, it%% brings down the call. In this example, the user at MG2 hangs up first.%%%% MG2 to MGC:%% MEGACO/1 [125.125.125.111]:55555%% Transaction = 50008 {%% Context = 5000 {%% Notify = A5555 {ObservedEvents =1235 {%% 19990729T24020002:al/on}%% }%% }%% }%%----------------------------------------------------------------------msg22a() -> msg22a(?MG2_MID).msg22a(Mid) -> TimeStamp = #'TimeNotation'{date = "19990729", time = "24020002"}, Event = #'ObservedEvent'{eventName = "al/on", timeNotation = TimeStamp, eventParList = []}, Desc = #'ObservedEventsDescriptor'{requestId = 1235, observedEventLst = [Event]}, NotifyReq = #'NotifyRequest'{terminationID = [#megaco_term_id{id = ?A5555}], observedEventsDescriptor = Desc}, CmdReq = #'CommandRequest'{command = {notifyReq, NotifyReq}}, request(Mid, 50008, 5000, [CmdReq]).%%----------------------------------------------------------------------%% MGC to MG2:%% MEGACO/1 [123.123.123.4]:55555%% Reply = 50008 {%% Context = - {Notify = A5555}%% }%%----------------------------------------------------------------------msg22b() -> msg22b(?MGC_MID).msg22b(Mid) -> Reply = #'NotifyReply'{terminationID = [#megaco_term_id{id = ?A5555}]}, reply(Mid, 50008, ?megaco_null_context_id, [{notifyReply, Reply}]).%%----------------------------------------------------------------------%% 23. The MGC now sends both MGs a Subtract to take down the call. Only%% the subtracts to MG2 are shown here. Each termination has its own%% set of statistics that it gathers. An MGC may not need to request%% both to be returned. A5555 is a physical termination, and A5556 is%% an RTP termination.%%%% MGC to MG2:%%%% MEGACO/1 [123.123.123.4]:55555%% Transaction = 50009 {%% Context = 5000 {%% Subtract = A5555 {Audit{Statistics}},%% Subtract = A5556 {Audit{Statistics}}%% }%% }%%----------------------------------------------------------------------msg23a() -> msg23a(?MGC_MID).msg23a(Mid) -> CommonAuditDesc = #'AuditDescriptor'{auditToken = [statsToken]}, SubReq = #'SubtractRequest'{terminationID = [#megaco_term_id{id = ?A5555}], auditDescriptor = CommonAuditDesc}, SubReq2 = #'SubtractRequest'{terminationID = [#megaco_term_id{id = ?A5556}], auditDescriptor = CommonAuditDesc}, CmdReq = #'CommandRequest'{command = {subtractReq, SubReq}}, CmdReq2 = #'CommandRequest'{command = {subtractReq, SubReq2}}, request(Mid, 50009, 5000, [CmdReq, CmdReq2]).%%%%----------------------------------------------------------------------%% MG2 to MGC:%%%% MEGACO/1 [125.125.125.111]:55555%% Reply = 50009 {%% Context = 5000 {%% Subtract = A5555 {%% Statistics {%% nt/os=45123, ; Octets Sent%% nt/dur=40 ; in seconds%% }%% },%% Subtract = A5556 {%% Statistics {%% rtp/ps=1245, ; packets sent%% nt/os=62345, ; octets sent%% rtp/pr=780, ; packets received%% nt/or=45123, ; octets received%% rtp/pl=10, ; % packets lost%% rtp/jit=27,%% rtp/delay=48 ; average latency%% }%% }%% }%% }%%----------------------------------------------------------------------msg23b() -> msg23b(?MG2_MID).msg23b(Mid) -> Stat11 = ?SP("nt/os","45123"), Stat12 = ?SP("nt/dur", "40"), Stats1 = [Stat11, Stat12], Reply1 = #'AmmsReply'{terminationID = [#megaco_term_id{id = ?A5555}], terminationAudit = [{statisticsDescriptor, Stats1}]}, Stat21 = ?SP("rtp/ps","1245"), Stat22 = ?SP("nt/os", "62345"), Stat23 = ?SP("rtp/pr", "780"), Stat24 = ?SP("nt/or", "45123"), Stat25 = ?SP("rtp/pl", "10"), Stat26 = ?SP("rtp/jit", "27"), Stat27 = ?SP("rtp/delay","48"), Stats2 = [Stat21, Stat22, Stat23, Stat24, Stat25, Stat26, Stat27], Reply2 = #'AmmsReply'{terminationID = [#megaco_term_id{id = ?A5556}], terminationAudit = [{statisticsDescriptor, Stats2}]}, reply(Mid, 50009, 5000, [{subtractReply, Reply1}, {subtractReply, Reply2}]).%%----------------------------------------------------------------------%% 24. The MGC now sets up both MG1 and MG2 to be ready to detect the%% next off-hook event. See step 1. Note that this could be the%% default state of a termination in the null context, and if this%% were the case, no message need be sent from the MGC to the%% MG. Once a termination returns to the null context, it goes back%% to the default termination values for that termination.%%----------------------------------------------------------------------%% BUGBUG: Example missing in spec%%----------------------------------------------------------------------%% Testing%%----------------------------------------------------------------------messages() -> [{Slogan, catch ?MODULE:Slogan()} || Slogan <- names()].encoders() -> [ {megaco_pretty_text_encoder, [], []}, {megaco_compact_text_encoder, [], []}, {megaco_binary_encoder, [], [native]}, %% {megaco_ber_encoder, [], [native]}, %% {megaco_ber_bin_encoder, [], [native]}, {megaco_per_encoder, [], [native]}, {megaco_erl_dist_encoder, [], []}, {megaco_erl_dist_encoder, [compressed], [compressed]} ].pretty_mod({Mod, Opt, _Opt2}) -> case Mod of megaco_pretty_text_encoder when Opt == [flex] -> pretty_flex; megaco_compact_text_encoder when Opt == [flex] -> compact_flex; megaco_pretty_text_encoder -> pretty_text; megaco_compact_text_encoder -> compact_text; megaco_binary_encoder -> asn1_ber; megaco_ber_encoder -> asn1_ber_old; megaco_ber_bin_encoder -> asn1_ber_bin; megaco_per_encoder -> asn1_per; megaco_erl_dist_encoder when Opt == [] -> standard_erl; megaco_erl_dist_encoder when Opt == [compressed] -> compressed_erl; Ugly -> Ugly end.%%----------------------------------------------------------------------%% Run specific encoder for all test cases%%----------------------------------------------------------------------pretty_text() -> Default = [], Encoder = {megaco_pretty_text_encoder, Default, Default}, All = [encode(Slogan, Msg, Encoder) || {Slogan, Msg} <- messages()], compute_res(All).compact_text() -> Default = [], Encoder = {megaco_compact_text_encoder, Default, Default}, All = [encode(Slogan, Msg, Encoder) || {Slogan, Msg} <- messages()], compute_res(All).pretty_flex() -> Default = [flex], Encoder = {megaco_pretty_text_encoder, Default, Default}, All = [encode(Slogan, Msg, Encoder) || {Slogan, Msg} <- messages()], compute_res(All).compact_flex() -> Default = [flex], Encoder = {megaco_compact_text_encoder, Default, Default}, All = [encode(Slogan, Msg, Encoder) || {Slogan, Msg} <- messages()], compute_res(All).bin() -> Default = [], Native = [native], Encoder = {megaco_binary_encoder, Default, Native}, All = [encode(Slogan, Msg, Encoder) || {Slogan, Msg} <- messages()], compute_res(All).asn1_ber() -> Default = [], Native = [native], Encoder = {megaco_ber_encoder, Default, Native}, All = [encode(Slogan, Msg, Encoder) || {Slogan, Msg} <- messages()], compute_res(All).asn1_ber_bin() -> Default = [], Native = [native], Encoder = {megaco_ber_bin_encoder, Default, Native}, All = [encode(Slogan, Msg, Encoder) || {Slogan, Msg} <- messages()], compute_res(All).asn1_per() -> Default = [], Native = [native], Encoder = {megaco_per_encoder, Default, Native}, All = [encode(Slogan, Msg, Encoder) || {Slogan, Msg} <- messages()], compute_res(All).standard_erl() -> Config = [], Encoder = {megaco_erl_dist_encoder, Config, Config}, All = [encode(Slogan, Msg, Encoder) || {Slogan, Msg} <- messages()], compute_res(All).compressed_erl() -> Config = [compressed], Encoder = {megaco_erl_dist_encoder, Config, Config}, All = [encode(Slogan, Msg, Encoder) || {Slogan, Msg} <- messages()], compute_res(All).encode(Slogan, DecodedMsg, {Mod, Opt, _Opt2} = _Encoder) -> Main = "==================================================", Sub = "--------------------------------------------------", case catch Mod:encode_message(Opt, DecodedMsg) of {ok, EncodedMsg} when binary(EncodedMsg) -> Sz = size(EncodedMsg), ok = io:format("~w ~s ~w bytes~n", [Slogan, Main, Sz]), catch io:format("~n~s~n", [(catch binary_to_list(EncodedMsg))]), case catch Mod:decode_message(Opt, EncodedMsg) of {ok, ReDecodedMsg} -> fmt(Slogan, DecodedMsg, ReDecodedMsg); {error, {Line, _, Reason}} when integer(Line)-> ?ERROR([{Slogan, Line, decode_failed}, {error, Reason}, {encoded, EncodedMsg}, DecodedMsg]), io:format("~n~w <ERROR> #~w: ~w~n", [Slogan, Line, Reason]); Other -> ?ERROR([{Slogan, 0, decode_failed}, Other, {encoded, EncodedMsg}, DecodedMsg]), io:format("~n~w <ERROR> ~w~n", [Slogan, Other]) end, Sz; Other -> ?ERROR([{Slogan, encode_failed}, Other, DecodedMsg]), ok = io:format("~w ~s~n~p~n<ERROR> ~s~n~p~n", [Slogan, Main, DecodedMsg, Sub, Other]), {Slogan, {encode_message, Other}} end.fmt(_Slogan, Msg, Msg) -> ok;fmt(Slogan, {'MegacoMessage', A, {'Message', V, MID, {transactions, [{T, Old}]}}}, {'MegacoMessage', A, {'Message', V, MID, {transactions, [{T, New}]}}}) -> fmt(Slogan, Old, New);fmt(Slogan, Old, New) -> PrettyOld = lists:flatten(io_lib:format("~p", [Old])), PrettyNew = lists:flatten(io_lib:format("~p", [New])), fmt_diff(Slogan, Old, New, PrettyOld, PrettyNew, []).fmt_diff(Slogan, Old, New, [H | OldRest], [H | NewRest], Common) -> fmt_diff(Slogan, Old, New, OldRest, NewRest, [H | Common]);fmt_diff(Slogan, Old, New, OldRest, NewRest, Common) -> RevCommon = lists:reverse(Common), ?ERROR([{Slogan, decode_mismatch}, {old, Old}, {new, New}]), Sub = "--------------------------------------------------", io:format("~n~w COMMON ~s~n~s~n", [Slogan, Sub, RevCommon]), io:format("~n~w OLD ~s~n~s~n", [Slogan, Sub, OldRest]), io:format("~n~w NEW ~s~n~s~n", [Slogan, Sub, NewRest]).compute_res(All) -> compute_res(All, [], 0).compute_res([H | T], Bad, Sum) when integer(H) -> compute_res(T, Bad, Sum + H);compute_res([H | T], Bad, Sum) -> compute_res(T, [H | Bad], Sum);compute_res([], Bad, Sum) -> ok = io:format("#bytes: ~w; errors: ~p~n", [Sum, Bad]).%%----------------------------------------------------------------------%% Compute sizes of encoded messages%%----------------------------------------------------------------------msg_sizes() -> Encoders = encoders(), msg_sizes(Encoders).%% Returns a list of {MessageSlogan, MessageSizes} where%% MessageSizes is the result from msg_sizes/2msg_sizes(Encoders) -> [{S, msg_sizes(Msg, Encoders)} || {S, Msg} <- messages()].%% Returns a list of {Encoder, Res} tuples%% where Res either is the message size (integer)%% or an error atommsg_sizes(DecodedMsg, Encoders) -> [abs_msg_size(DecodedMsg, E) || E <- Encoders].abs_msg_size(DecodedMsg, {Mod, Opt, _Opt2} = Encoder) -> case catch Mod:encode_message(Opt, DecodedMsg) of {ok, EncodedMsg} when binary(EncodedMsg) -> {Encoder, size(EncodedMsg)}; Error -> {Encoder, {bad_encoder, Error}} end.%%----------------------------------------------------------------------%% Compute time for encoding messages%%----------------------------------------------------------------------encoding_times() -> Encoders = encoders(), encoding_times(Encoders).%% Returns a list of {MessageSlogan, EncodingTimes} where%% EncodingTimes is the result from encoding_times/2encoding_times(Encoders) -> [{Slogan, encoding_times(Msg, Encoders)} || {Slogan, Msg} <- messages()].%% Returns a list of {Encoder, Res} tuples%% where Res either is the encoding time (integer)%% or an error atomencoding_times(DecodedMsg, Encoders) -> [{E, encoding_time(encoding_msg(DecodedMsg, E))} || E <- Encoders].encoding_msg(DecodedMsg, {Mod, Opt, Opt2} = Encoder) -> {ok, EncodedMsg} = Mod:encode_message(Opt, DecodedMsg), {ok, DecodedMsg2} = Mod:decode_message(Opt2, EncodedMsg), {Encoder, DecodedMsg2}.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -