aboutsummaryrefslogtreecommitdiffstats
path: root/lib/megaco/test/megaco_pending_limit_test.erl
diff options
context:
space:
mode:
authorErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
committerErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
commit84adefa331c4159d432d22840663c38f155cd4c1 (patch)
treebff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/megaco/test/megaco_pending_limit_test.erl
downloadotp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz
otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2
otp-84adefa331c4159d432d22840663c38f155cd4c1.zip
The R13B03 release.OTP_R13B03
Diffstat (limited to 'lib/megaco/test/megaco_pending_limit_test.erl')
-rw-r--r--lib/megaco/test/megaco_pending_limit_test.erl2158
1 files changed, 2158 insertions, 0 deletions
diff --git a/lib/megaco/test/megaco_pending_limit_test.erl b/lib/megaco/test/megaco_pending_limit_test.erl
new file mode 100644
index 0000000000..1ca29c195c
--- /dev/null
+++ b/lib/megaco/test/megaco_pending_limit_test.erl
@@ -0,0 +1,2158 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2003-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: Verify the application specifics of the Megaco application
+%% Testing the xxxOriginatingPendingLimit property of the
+%% root package
+%%----------------------------------------------------------------------
+-module(megaco_pending_limit_test).
+
+-export([t/0, t/1]).
+-export([init_per_testcase/2, fin_per_testcase/2]).
+-export([all/1,
+
+ sent/1,
+ sent_timer_late_reply/1,
+ sent_timer_exceeded/1,
+ sent_timer_exceeded_long/1,
+ sent_resend_late_reply/1,
+ sent_resend_exceeded/1,
+ sent_resend_exceeded_long/1,
+
+ recv/1,
+ recv_limit_exceeded1/1,
+ recv_limit_exceeded2/1,
+
+ tickets/1,
+ otp_4956/1,
+ otp_5310/1,
+ otp_5619/1
+
+ ]).
+
+-ifdef(megaco_hipe_special).
+-export([
+ %% Case: recv_limit_exceeded1
+ rle1_mgc_verify_service_change_req_msg/2,
+ rle1_mgc_verify_notify_req_msg/1,
+ rle1_mg_verify_handle_connect/1,
+ rle1_mg_verify_service_change_rep/1,
+ rle1_mg_verify_trans_rep/1,
+
+ %% Case: otp_4956
+ otp_4956_mgc_verify_handle_connect/1,
+ otp_4956_mgc_verify_service_change_req/2,
+ otp_4956_mgc_verify_notify_req1/1,
+ otp_4956_mgc_verify_notify_req2/1,
+ otp_4956_mgc_verify_handle_trans_req_abort/1,
+ otp_4956_mgc_verify_handle_disconnect/1,
+ otp_4956_mg_verify_service_change_rep_msg/1,
+ otp_4956_mg_verify_pending_msg/1,
+ otp_4956_mg_verify_pending_limit_msg/1,
+
+ %% Utility
+ encode_msg/3,
+ decode_msg/3
+ ]).
+-endif.
+
+-include("megaco_test_lib.hrl").
+-include_lib("megaco/include/megaco.hrl").
+-include_lib("megaco/include/megaco_message_v1.hrl").
+
+-define(TEST_VERBOSITY, debug).
+-define(MGC_VERBOSITY, debug).
+-define(MG_VERBOSITY, debug).
+
+-define(VERSION, 1).
+
+-define(A4444, ["11111111", "00000000", "00000000"]).
+-define(A4445, ["11111111", "00000000", "11111111"]).
+-define(A5555, ["11111111", "11111111", "00000000"]).
+-define(A5556, ["11111111", "11111111", "11111111"]).
+
+-define(MGC_START(Pid, Mid, ET, Conf, Verb),
+ megaco_test_mgc:start(Pid, Mid, ET, Conf, Verb)).
+-define(MGC_STOP(Pid), megaco_test_mgc:stop(Pid)).
+-define(MGC_GET_STATS(Pid, No), megaco_test_mgc:get_stats(Pid, No)).
+-define(MGC_RESET_STATS(Pid), megaco_test_mgc:reset_stats(Pid)).
+-define(MGC_REQ_IGNORE(Pid), megaco_test_mgc:request_ignore(Pid)).
+-define(MGC_REQ_PIGNORE(Pid), megaco_test_mgc:request_pending_ignore(Pid)).
+-define(MGC_REQ_DISC(Pid,To), megaco_test_mgc:request_discard(Pid,To)).
+-define(MGC_REQ_PEND(Pid,To), megaco_test_mgc:request_pending(Pid,To)).
+-define(MGC_REQ_HAND(Pid, To), megaco_test_mgc:request_handle(Pid, To)).
+-define(MGC_REQ_HANDS(Pid), megaco_test_mgc:request_handle_sloppy(Pid)).
+-define(MGC_UPDATE_UI(Pid,Tag,Val),
+ megaco_test_mgc:update_user_info(Pid,Tag,Val)).
+-define(MGC_UPDATE_CI(Pid,Tag,Val),
+ megaco_test_mgc:update_conn_info(Pid,Tag,Val)).
+-define(MGC_USER_INFO(Pid,Tag), megaco_test_mgc:user_info(Pid,Tag)).
+-define(MGC_CONN_INFO(Pid,Tag), megaco_test_mgc:conn_info(Pid,Tag)).
+-define(MGC_ACK_INFO(Pid,To), megaco_test_mgc:ack_info(Pid,To)).
+-define(MGC_ABORT_INFO(Pid,To), megaco_test_mgc:abort_info(Pid,To)).
+-define(MGC_DISCO(Pid,Reason), megaco_test_mgc:disconnect(Pid,Reason)).
+
+-define(MG_START(Pid, Mid, Enc, Transp, Conf, Verb),
+ megaco_test_mg:start(Pid, Mid, Enc, Transp, Conf, Verb)).
+-define(MG_STOP(Pid), megaco_test_mg:stop(Pid)).
+-define(MG_GET_STATS(Pid, No), megaco_test_mg:get_stats(Pid, No)).
+-define(MG_RESET_STATS(Pid), megaco_test_mg:reset_stats(Pid)).
+-define(MG_SERV_CHANGE(Pid), megaco_test_mg:service_change(Pid)).
+-define(MG_NOTIF_RAR(Pid), megaco_test_mg:notify_request_and_reply(Pid)).
+-define(MG_NOTIF_REQ(Pid), megaco_test_mg:notify_request(Pid)).
+-define(MG_NOTIF_AR(Pid), megaco_test_mg:await_notify_reply(Pid)).
+-define(MG_CANCEL(Pid,R), megaco_test_mg:cancel_request(Pid,R)).
+-define(MG_APPLY_LOAD(Pid,CntStart), megaco_test_mg:apply_load(Pid,CntStart)).
+-define(MG_UPDATE_UI(Pid,Tag,Val),
+ megaco_test_mg:update_user_info(Pid,Tag,Val)).
+-define(MG_UPDATE_CI(Pid,Tag,Val),
+ megaco_test_mg:update_conn_info(Pid,Tag,Val)).
+-define(MG_USER_INFO(Pid,Tag), megaco_test_mg:user_info(Pid,Tag)).
+-define(MG_CONN_INFO(Pid,Tag), megaco_test_mg:conn_info(Pid,Tag)).
+-define(MG_GRP_REQ(Pid,N), megaco_test_mg:group_requests(Pid,N)).
+-define(MG_ECC(Pid, M, T, F), megaco_test_mg:enable_test_code(Pid,M,T,F)).
+
+t() -> megaco_test_lib:t(?MODULE).
+t(Case) -> megaco_test_lib:t({?MODULE, Case}).
+
+
+%% Test server callbacks
+init_per_testcase(Case, Config) ->
+ process_flag(trap_exit, true),
+ megaco_test_lib:init_per_testcase(Case, Config).
+
+fin_per_testcase(Case, Config) ->
+ process_flag(trap_exit, false),
+ megaco_test_lib:fin_per_testcase(Case, Config).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+all(suite) ->
+ [
+ sent,
+ recv,
+
+ %% Tickets last
+ tickets
+ ].
+
+sent(suite) ->
+ [
+ sent_timer_late_reply,
+ sent_timer_exceeded,
+ sent_timer_exceeded_long,
+ sent_resend_late_reply,
+ sent_resend_exceeded,
+ sent_resend_exceeded_long
+
+ ].
+
+recv(suite) ->
+ [
+ recv_limit_exceeded1,
+ recv_limit_exceeded2
+ ].
+
+tickets(suite) ->
+ [
+ otp_4956,
+ otp_5310,
+ otp_5619
+ ].
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%% %%%
+%%% Sent pending test cases %%%
+%%% %%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+sent_timer_late_reply(suite) ->
+ [];
+sent_timer_late_reply(doc) ->
+ "...";
+sent_timer_late_reply(Config) when is_list(Config) ->
+ put(verbosity, ?TEST_VERBOSITY),
+ put(sname, "TEST"),
+ put(tc, sent_timer_late_reply),
+ i("starting"),
+
+ MgcNode = make_node_name(mgc),
+ MgNode = make_node_name(mg),
+ d("start nodes: "
+ "~n MgcNode: ~p"
+ "~n MgNode: ~p",
+ [MgcNode, MgNode]),
+ ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE),
+
+ %% Start the MGC and MGs
+ i("[MGC] start"),
+ ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}],
+ MgcConf = [{megaco_trace, false}],
+ {ok, Mgc} =
+ ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, MgcConf, ?MGC_VERBOSITY),
+
+ i("[MG] start"),
+ MgMid = {deviceName, "mg"},
+ MgConf = [{megaco_trace, io}],
+ {ok, Mg} = ?MG_START(MgNode, MgMid, text, tcp, MgConf, ?MG_VERBOSITY),
+
+ d("MG user info: ~p", [?MG_USER_INFO(Mg, all)]),
+
+ i("[MG] connect to the MGC (service change)"),
+ ServChRes = ?MG_SERV_CHANGE(Mg),
+ d("service change result: ~p", [ServChRes]),
+
+ d("MG conn info: ~p", [?MG_CONN_INFO(Mg, all)]),
+
+ d("[MGC] update connection info pending timer"),
+ PendingTimer = #megaco_incr_timer{wait_for = timer:seconds(5),
+ factor = 1},
+ ?MGC_UPDATE_CI(Mgc, pending_timer, PendingTimer),
+
+ d("[MGC] update connection info sent pending limit"),
+ PendingLimit = 5,
+ ?MGC_UPDATE_CI(Mgc, sent_pending_limit, PendingLimit),
+
+ d("[MGC] late reply to requests "
+ "(simulate that the request takes a long time)"),
+ {ok, _} = ?MGC_REQ_DISC(Mgc, 11000),
+
+ d("[MG] send the notify"),
+ {ok, Reply} = ?MG_NOTIF_RAR(Mg),
+ d("[MG] Reply: ~p", [Reply]),
+ case Reply of
+ {_Version, {ok, [_ActionReply]}} ->
+ ok;
+ _ ->
+ ?ERROR({unexpected_reply, Reply})
+ end,
+
+ %% Tell MG to stop
+ i("[MG] stop"),
+ ?MG_STOP(Mg),
+
+ %% Tell Mgc to stop
+ i("[MGC] stop"),
+ ?MGC_STOP(Mgc),
+
+ i("done", []),
+ ok.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+sent_timer_exceeded(suite) ->
+ [];
+sent_timer_exceeded(doc) ->
+ "...";
+sent_timer_exceeded(Config) when is_list(Config) ->
+ put(verbosity, ?TEST_VERBOSITY),
+ put(sname, "TEST"),
+ put(tc, sent_timer_exceeded),
+ i("starting"),
+
+ MgcNode = make_node_name(mgc),
+ MgNode = make_node_name(mg),
+ d("start nodes: "
+ "~n MgcNode: ~p"
+ "~n MgNode: ~p",
+ [MgcNode, MgNode]),
+ ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE),
+
+ %% Start the MGC and MGs
+ i("[MGC] start"),
+ ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}],
+ {ok, Mgc} =
+ ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, [], ?MGC_VERBOSITY),
+
+ i("[MG] start"),
+ MgMid = {deviceName, "mg"},
+ MgConfig = [],
+ {ok, Mg} = ?MG_START(MgNode, MgMid, text, tcp, MgConfig, ?MG_VERBOSITY),
+
+ d("MG user info: ~p", [?MG_USER_INFO(Mg, all)]),
+
+ i("[MG] connect to the MGC (service change)"),
+ ServChRes = ?MG_SERV_CHANGE(Mg),
+ d("service change result: ~p", [ServChRes]),
+
+ d("MG conn info: ~p", [?MG_CONN_INFO(Mg, all)]),
+
+ d("[MGC] update connection info pending timer"),
+ PendingTimer = #megaco_incr_timer{wait_for = timer:seconds(5),
+ factor = 1},
+ ?MGC_UPDATE_CI(Mgc, pending_timer, PendingTimer),
+
+ d("[MGC] update connection info sent pending limit"),
+ PendingLimit = 5,
+ ?MGC_UPDATE_CI(Mgc, sent_pending_limit, PendingLimit),
+
+ d("[MGC] no reply to requests "
+ "(simulate that the request takes a __long__ time)"),
+ ?MGC_REQ_IGNORE(Mgc),
+
+ d("sleep 5 seconds to align trace output"),
+ sleep(5000),
+
+ d("[MG] send the notify"),
+ {ok, {_ProtocolVersion, {error, ED}}} = ?MG_NOTIF_RAR(Mg),
+ d("[MG] ED: ~p", [ED]),
+ ErrorCode = ?megaco_number_of_transactionpending_exceeded,
+ ErrorCode = ED#'ErrorDescriptor'.errorCode,
+
+ %% Tell MG to stop
+ i("[MG] stop"),
+ ?MG_STOP(Mg),
+
+ %% Tell Mgc to stop
+ i("[MGC] stop"),
+ ?MGC_STOP(Mgc),
+
+ i("done", []),
+ ok.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+sent_timer_exceeded_long(suite) ->
+ [];
+sent_timer_exceeded_long(doc) ->
+ "...";
+sent_timer_exceeded_long(Config) when is_list(Config) ->
+ put(verbosity, ?TEST_VERBOSITY),
+ put(sname, "TEST"),
+ put(tc, sent_timer_exceeded_long),
+ i("starting"),
+
+ MgcNode = make_node_name(mgc),
+ MgNode = make_node_name(mg),
+ d("start nodes: "
+ "~n MgcNode: ~p"
+ "~n MgNode: ~p",
+ [MgcNode, MgNode]),
+ ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE),
+
+ %% Start the MGC and MGs
+ i("[MGC] start"),
+ ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}],
+ {ok, Mgc} =
+ ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, [], ?MGC_VERBOSITY),
+
+ i("[MG] start"),
+ MgMid = {deviceName, "mg"},
+ MgConfig = [],
+ {ok, Mg} = ?MG_START(MgNode, MgMid, text, tcp, MgConfig, ?MG_VERBOSITY),
+
+ d("MG user info: ~p", [?MG_USER_INFO(Mg, all)]),
+
+ i("[MG] connect to the MGC (service change)"),
+ ServChRes = ?MG_SERV_CHANGE(Mg),
+ d("service change result: ~p", [ServChRes]),
+
+ d("MG conn info: ~p", [?MG_CONN_INFO(Mg, all)]),
+
+ d("[MGC] update connection info pending timer"),
+ PendingTimer = #megaco_incr_timer{wait_for = timer:seconds(5),
+ factor = 1},
+ ?MGC_UPDATE_CI(Mgc, pending_timer, PendingTimer),
+
+ d("[MGC] update connection info sent pending limit"),
+ PendingLimit = 5,
+ ?MGC_UPDATE_CI(Mgc, sent_pending_limit, PendingLimit),
+
+ d("[MGC] long request with no reply ~n"
+ " (simulate that we know that this will "
+ "take a while, but takes even longer...)"),
+ ?MGC_REQ_PIGNORE(Mgc),
+
+ d("[MG] send the notify"),
+ {ok, {_ProtocolVersion, {error, ED}}} = ?MG_NOTIF_RAR(Mg),
+ d("[MG] ED: ~p", [ED]),
+ ErrorCode = ?megaco_number_of_transactionpending_exceeded,
+ ErrorCode = ED#'ErrorDescriptor'.errorCode,
+
+ %% Tell MG to stop
+ i("[MG] stop"),
+ ?MG_STOP(Mg),
+
+ %% Tell Mgc to stop
+ i("[MGC] stop"),
+ ?MGC_STOP(Mgc),
+
+ i("done", []),
+ ok.
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% This test case can only be run with the stack compiled with
+%% the MEGACO_TEST_CODE flag. Therefor there is no point in
+%% including this test case in the usual test suite
+-ifdef(MEGACO_TEST_CODE).
+sent_resend_late_reply(suite) ->
+ [];
+sent_resend_late_reply(doc) ->
+ "...";
+sent_resend_late_reply(Config) when is_list(Config) ->
+ put(verbosity, ?TEST_VERBOSITY),
+ put(sname, "TEST"),
+ put(tc, sent_resend_late_reply),
+ i("starting"),
+
+ MgcNode = make_node_name(mgc),
+ MgNode = make_node_name(mg),
+ d("start nodes: "
+ "~n MgcNode: ~p"
+ "~n MgNode: ~p",
+ [MgcNode, MgNode]),
+ ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE),
+
+ %% Start the MGC and MGs
+ i("[MGC] start"),
+ ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}],
+ {ok, Mgc} =
+ ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, [], ?MGC_VERBOSITY),
+
+ i("[MG] start"),
+ MgMid = {deviceName, "mg"},
+ MgConfig = [],
+ {ok, Mg} = ?MG_START(MgNode, MgMid, text, tcp, MgConfig, ?MG_VERBOSITY),
+
+ d("MG user info: ~p", [?MG_USER_INFO(Mg, all)]),
+
+ i("[MG] connect to the MGC (service change)"),
+ ServChRes = ?MG_SERV_CHANGE(Mg),
+ d("service change result: ~p", [ServChRes]),
+
+ d("MG conn info: ~p", [?MG_CONN_INFO(Mg, all)]),
+
+ d("[MGC] update connection info pending timer"),
+ PendingTimer = infinity,
+ %% PendingTimer = #megaco_incr_timer{wait_for = timer:seconds(5),
+ %% factor = 1},
+ ?MGC_UPDATE_CI(Mgc, pending_timer, PendingTimer),
+
+ d("[MGC] update connection info sent pending limit"),
+ PendingLimit = 5,
+ ?MGC_UPDATE_CI(Mgc, sent_pending_limit, PendingLimit),
+
+ d("[MG] update connection info request timer"),
+ RequestTimer = #megaco_incr_timer{wait_for = timer:seconds(5),
+ factor = 1},
+ ?MG_UPDATE_CI(Mg, request_timer, RequestTimer),
+
+ d("[MGC] no reply to requests "
+ "(simulate that the request takes a __long__ time)"),
+ ?MGC_REQ_IGNORE(Mgc),
+
+ d("[MG] set the 'init_request_timer' tag"),
+ EccRes = (catch ?MG_ECC(Mg, megaco_messenger,
+ init_request_timer, fun init_request_timer/1)),
+ d("[MG] EccRes: ~p", [EccRes]),
+
+ d("[MGC] late reply to requests "
+ "(simulate that the request takes a long time)"),
+ ?MGC_REQ_DISC(Mgc, 11000),
+
+ d("[MG] send the notify"),
+ {ok, Reply} = (catch ?MG_NOTIF_RAR(Mg)),
+ d("[MG] Reply: ~p", [Reply]),
+ {_Version, {ok, [_ActionReply]}} = Reply,
+
+ %% Tell MG to stop
+ i("[MG] stop"),
+ ?MG_STOP(Mg),
+
+ %% Tell Mgc to stop
+ i("[MGC] stop"),
+ ?MGC_STOP(Mgc),
+
+ i("done", []),
+ ok.
+
+-else.
+
+sent_resend_late_reply(suite) ->
+ [];
+sent_resend_late_reply(doc) ->
+ "...";
+sent_resend_late_reply(Config) when is_list(Config) ->
+ ?SKIP("included only if compiled with USE_MEGACO_TEST_CODE=true").
+
+-endif.
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% This test case can only be run with the stack compiled with
+%% the MEGACO_TEST_CODE flag. Therefor there is no point in
+%% including this test case in the usual test suite
+-ifdef(MEGACO_TEST_CODE).
+sent_resend_exceeded(suite) ->
+ [];
+sent_resend_exceeded(doc) ->
+ "...";
+sent_resend_exceeded(Config) when is_list(Config) ->
+ put(verbosity, ?TEST_VERBOSITY),
+ put(sname, "TEST"),
+ put(tc, sent_resend_exceeded),
+ i("starting"),
+
+ MgcNode = make_node_name(mgc),
+ MgNode = make_node_name(mg),
+ d("start nodes: "
+ "~n MgcNode: ~p"
+ "~n MgNode: ~p",
+ [MgcNode, MgNode]),
+ ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE),
+
+ %% Start the MGC and MGs
+ i("[MGC] start"),
+ ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}],
+ {ok, Mgc} =
+ ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, [], ?MGC_VERBOSITY),
+
+ i("[MG] start"),
+ MgMid = {deviceName, "mg"},
+ MgConfig = [],
+ {ok, Mg} = ?MG_START(MgNode, MgMid, text, tcp, MgConfig, ?MG_VERBOSITY),
+
+ d("MG user info: ~p", [?MG_USER_INFO(Mg, all)]),
+
+ i("[MG] connect to the MGC (service change)"),
+ ServChRes = ?MG_SERV_CHANGE(Mg),
+ d("service change result: ~p", [ServChRes]),
+
+ d("MG conn info: ~p", [?MG_CONN_INFO(Mg, all)]),
+
+ d("[MGC] update connection info pending timer"),
+ PendingTimer = infinity,
+ ?MGC_UPDATE_CI(Mgc, pending_timer, PendingTimer),
+
+ d("[MGC] update connection info sent pending limit"),
+ PendingLimit = 5,
+ ?MGC_UPDATE_CI(Mgc, sent_pending_limit, PendingLimit),
+
+ d("[MG] update connection info request timer"),
+ RequestTimer = #megaco_incr_timer{wait_for = timer:seconds(5),
+ factor = 1},
+ ?MG_UPDATE_CI(Mg, request_timer, RequestTimer),
+
+ d("[MGC] no reply to requests "
+ "(simulate that the request takes a __long__ time)"),
+ ?MGC_REQ_IGNORE(Mgc),
+
+ d("[MG] set the 'init_request_timer' tag"),
+ EccRes = (catch ?MG_ECC(Mg, megaco_messenger,
+ init_request_timer, fun init_request_timer/1)),
+ d("[MG] EccRes: ~p", [EccRes]),
+
+ d("[MG] send the notify"),
+ ED = (catch ?MG_NOTIF_RAR(Mg)),
+ d("[MG] ED: ~p", [ED]),
+ ErrorCode = ?megaco_number_of_transactionpending_exceeded,
+ #'ErrorDescriptor'{errorCode = ErrorCode} = ED,
+
+ %% Tell MG to stop
+ i("[MG] stop"),
+ ?MG_STOP(Mg),
+
+ %% Tell Mgc to stop
+ i("[MGC] stop"),
+ ?MGC_STOP(Mgc),
+
+ i("done", []),
+ ok.
+
+
+-else.
+
+sent_resend_exceeded(suite) ->
+ [];
+sent_resend_exceeded(doc) ->
+ "...";
+sent_resend_exceeded(Config) when is_list(Config) ->
+ ?SKIP("included only if compiled with USE_MEGACO_TEST_CODE=true").
+
+-endif.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% This test case can only be run with the stack compiled with
+%% the MEGACO_TEST_CODE flag. Therefor there is no point in
+%% including this test case in the usual test suite
+-ifdef(MEGACO_TEST_CODE).
+sent_resend_exceeded_long(suite) ->
+ [];
+sent_resend_exceeded_long(doc) ->
+ "...";
+sent_resend_exceeded_long(Config) when is_list(Config) ->
+ put(verbosity, ?TEST_VERBOSITY),
+ put(sname, "TEST"),
+ put(tc, sent_resend_exceeded_long),
+ i("starting"),
+
+ MgcNode = make_node_name(mgc),
+ MgNode = make_node_name(mg),
+ d("start nodes: "
+ "~n MgcNode: ~p"
+ "~n MgNode: ~p",
+ [MgcNode, MgNode]),
+ ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE),
+
+ %% Start the MGC and MGs
+ i("[MGC] start"),
+ ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}],
+ {ok, Mgc} =
+ ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, [], ?MGC_VERBOSITY),
+
+ i("[MG] start"),
+ MgMid = {deviceName, "mg"},
+ MgConfig = [],
+ {ok, Mg} = ?MG_START(MgNode, MgMid, text, tcp, MgConfig, ?MG_VERBOSITY),
+
+ d("MG user info: ~p", [?MG_USER_INFO(Mg, all)]),
+
+ i("[MG] connect to the MGC (service change)"),
+ ServChRes = ?MG_SERV_CHANGE(Mg),
+ d("service change result: ~p", [ServChRes]),
+
+ d("MG conn info: ~p", [?MG_CONN_INFO(Mg, all)]),
+
+ d("[MGC] update connection info pending timer"),
+ PendingTimer = infinity,
+ ?MGC_UPDATE_CI(Mgc, pending_timer, PendingTimer),
+
+ d("[MGC] update connection info sent pending limit"),
+ PendingLimit = 5,
+ ?MGC_UPDATE_CI(Mgc, sent_pending_limit, PendingLimit),
+
+ d("[MG] update connection info request timer"),
+ RequestTimer = #megaco_incr_timer{wait_for = timer:seconds(5),
+ factor = 1},
+ ?MG_UPDATE_CI(Mg, request_timer, RequestTimer),
+
+ d("[MGC] long request with no reply ~n"
+ " (simulate that we know that this will "
+ "take a while, but takes even longer...)"),
+ ?MGC_REQ_PIGNORE(Mgc),
+
+ d("[MG] set the 'init_request_timer' tag"),
+ EccRes = (catch ?MG_ECC(Mg, megaco_messenger,
+ init_request_timer, fun init_request_timer/1)),
+ d("[MG] EccRes: ~p", [EccRes]),
+
+ d("[MG] send the notify"),
+ ED = (catch ?MG_NOTIF_RAR(Mg)),
+ d("[MG] ED: ~p", [ED]),
+ ErrorCode = ?megaco_number_of_transactionpending_exceeded,
+ #'ErrorDescriptor'{errorCode = ErrorCode} = ED,
+
+ %% Tell MG to stop
+ i("[MG] stop"),
+ ?MG_STOP(Mg),
+
+ %% Tell Mgc to stop
+ i("[MGC] stop"),
+ ?MGC_STOP(Mgc),
+
+ i("done", []),
+ ok.
+
+
+-else.
+
+sent_resend_exceeded_long(suite) ->
+ [];
+sent_resend_exceeded_long(doc) ->
+ "...";
+sent_resend_exceeded_long(Config) when is_list(Config) ->
+ ?SKIP("included only if compiled with USE_MEGACO_TEST_CODE=true").
+
+-endif.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%% %%%
+%%% Received peinding test cases %%%
+%%% %%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+recv_limit_exceeded1(suite) ->
+ [];
+recv_limit_exceeded1(doc) ->
+ "Received pending limit exceeded (exactly)";
+recv_limit_exceeded1(Config) when is_list(Config) ->
+ put(verbosity, ?TEST_VERBOSITY),
+ put(sname, "TEST"),
+ put(tc, rle1),
+ i("starting"),
+
+ MgcNode = make_node_name(mgc),
+ MgNode = make_node_name(mg),
+ d("start nodes: "
+ "~n MgcNode: ~p"
+ "~n MgNode: ~p",
+ [MgcNode, MgNode]),
+ ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE),
+
+ d("[MGC] start the simulator "),
+ {ok, Mgc} = megaco_test_tcp_generator:start_link("MGC", MgcNode),
+
+ d("[MGC] create the event sequence"),
+ MgcEvSeq = rle1_mgc_event_sequence(text, tcp),
+
+ i("wait some time before starting the MGC simulation"),
+ sleep(1000),
+
+ d("[MGC] start the simulation"),
+ {ok, MgcId} = megaco_test_tcp_generator:exec(Mgc, MgcEvSeq),
+
+ i("wait some time before starting the MG simulator"),
+ sleep(1000),
+
+ d("[MG] start the simulator (generator)"),
+ {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode),
+
+ d("[MG] create the event sequence"),
+ MgEvSeq = rle1_mg_event_sequence(text, tcp),
+
+ i("wait some time before starting the MG simulation"),
+ sleep(1000),
+
+ d("[MG] start the simulation"),
+ {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq),
+
+ d("await the generator reply(s)"),
+ await_completion([MgcId, MgId]),
+
+ %% Tell Mgc to stop
+ i("[MGC] stop generator"),
+ megaco_test_tcp_generator:stop(Mgc),
+
+ %% Tell Mg to stop
+ i("[MG] stop generator"),
+ megaco_test_megaco_generator:stop(Mg),
+
+ i("done", []),
+ ok.
+
+
+%%
+%% MGC generator stuff
+%%
+-ifdef(megaco_hipe_special).
+-define(rle1_mgc_decode_msg_fun(Mod, Conf),
+ {?MODULE, decode_msg, [Mod, Conf]}).
+-define(rle1_mgc_encode_msg_fun(Mod, Conf),
+ {?MODULE, encode_msg, [Mod, Conf]}).
+-define(rle1_mgc_verify_service_change_req_msg_fun(Mid),
+ {?MODULE, rle1_mgc_verify_service_change_req_msg, [Mid]}).
+-define(rle1_mgc_verify_notify_req_msg_fun(),
+ {?MODULE, rle1_mgc_verify_notify_req_msg, []}).
+-else.
+-define(rle1_mgc_decode_msg_fun(Mod, Conf),
+ rle1_mgc_decode_msg_fun(Mod, Conf)).
+-define(rle1_mgc_encode_msg_fun(Mod, Conf),
+ rle1_mgc_encode_msg_fun(Mod, Conf)).
+-define(rle1_mgc_verify_service_change_req_msg_fun(Mid),
+ rle1_mgc_verify_service_change_req_msg_fun(Mid)).
+-define(rle1_mgc_verify_notify_req_msg_fun(),
+ rle1_mgc_verify_notify_req_msg_fun()).
+-endif.
+
+rle1_mgc_event_sequence(text, tcp) ->
+ Mid = {deviceName,"ctrl"},
+ EM = megaco_pretty_text_encoder,
+ EC = [],
+ rle1_mgc_event_sequence2(Mid, EM, EC).
+
+rle1_mgc_event_sequence2(Mid, EM, EC) ->
+ DecodeFun = ?rle1_mgc_decode_msg_fun(EM, EC),
+ EncodeFun = ?rle1_mgc_encode_msg_fun(EM, EC),
+ ServiceChangeReply =
+ rle1_mgc_service_change_reply_msg(Mid, 1, 0),
+ Pending = rle1_mgc_pending_msg(Mid,2),
+ ServiceChangeReqVerify =
+ ?rle1_mgc_verify_service_change_req_msg_fun(Mid),
+ NotifyReqVerify = ?rle1_mgc_verify_notify_req_msg_fun(),
+%% ServiceChangeReqVerify =
+%% rle1_mgc_verify_service_change_req_fun(Mid),
+%% NotifyReqVerify = rle1_mgc_verify_notify_request_fun(),
+ EvSeq =
+ [{debug, true},
+ {decode, DecodeFun},
+ {encode, EncodeFun},
+ {listen, 2944},
+ {expect_accept, any},
+ {expect_receive, "service-change-req",
+ {ServiceChangeReqVerify, 10000}},
+ {send, "service-change-reply", ServiceChangeReply},
+ {expect_receive, "notify-request", {NotifyReqVerify, 5000}},
+ {sleep, 100},
+ {send, "pending 1", Pending},
+ {sleep, 100},
+ {send, "pending 2", Pending},
+ {sleep, 100},
+ {send, "pending 3", Pending},
+ {sleep, 100},
+ {send, "pending 4", Pending},
+ {sleep, 100},
+ {send, "pending 5", Pending},
+ {sleep, 1000},
+ disconnect
+ ],
+ EvSeq.
+
+-ifndef(megaco_hipe_special).
+rle1_mgc_encode_msg_fun(Mod, Conf) ->
+ fun(M) ->
+ encode_msg(M, Mod, Conf)
+ end.
+
+rle1_mgc_decode_msg_fun(Mod, Conf) ->
+ fun(M) ->
+ decode_msg(M, Mod, Conf)
+ end.
+-endif.
+
+rle1_mgc_service_change_reply_msg(Mid, TransId, Cid) ->
+ SCRP = #'ServiceChangeResParm'{serviceChangeMgcId = Mid},
+ SCRPs = {serviceChangeResParms,SCRP},
+ Root = #megaco_term_id{id = ["root"]},
+ SCR = #'ServiceChangeReply'{terminationID = [Root],
+ serviceChangeResult = SCRPs},
+ CR = {serviceChangeReply, SCR},
+ rle1_mgc_msg(Mid, TransId, CR, Cid).
+
+rle1_mgc_msg(Mid, TransId, CR, Cid) ->
+ AR = #'ActionReply'{contextId = Cid,
+ commandReply = [CR]},
+ ARs = {actionReplies, [AR]},
+ TR = #'TransactionReply'{transactionId = TransId,
+ transactionResult = ARs},
+ Body = {transactions, [{transactionReply, TR}]},
+ Mess = #'Message'{version = 1,
+ mId = Mid,
+ messageBody = Body},
+ #'MegacoMessage'{mess = Mess}.
+
+rle1_mgc_pending_msg(Mid, TransId) ->
+ TP = #'TransactionPending'{transactionId = TransId},
+ Body = {transactions, [{transactionPending, TP}]},
+ Mess = #'Message'{version = 1,
+ mId = Mid,
+ messageBody = Body},
+ #'MegacoMessage'{mess = Mess}.
+
+-ifndef(megaco_hipe_special).
+rle1_mgc_verify_service_change_req_msg_fun(Mid) ->
+ fun(M) ->
+ rle1_mgc_verify_service_change_req_msg(M, Mid)
+ end.
+-endif.
+
+rle1_mgc_verify_service_change_req_msg(#'MegacoMessage'{mess = Mess} = M,
+ _Mid1) ->
+ io:format("rle1_mgc_verify_service_change_req_msg -> entry with"
+ "~n M: ~p"
+ "~n", [M]),
+ #'Message'{version = _V,
+ mId = _Mid2,
+ messageBody = Body} = Mess,
+ {transactions, [Trans]} = Body,
+ {transactionRequest, TR} = Trans,
+ #'TransactionRequest'{transactionId = _Tid,
+ actions = [AR]} = TR,
+ #'ActionRequest'{contextId = _Cid,
+ contextRequest = _CtxReq,
+ contextAttrAuditReq = _CtxAar,
+ commandRequests = [CR]} = AR,
+ #'CommandRequest'{command = Cmd,
+ optional = _Opt,
+ wildcardReturn = _WR} = CR,
+ {serviceChangeReq, SCR} = Cmd,
+ #'ServiceChangeRequest'{terminationID = _TermID,
+ serviceChangeParms = SCP} = SCR,
+ #'ServiceChangeParm'{serviceChangeMethod = restart,
+ serviceChangeReason = [[$9,$0,$1|_]]} = SCP,
+ {ok, M};
+rle1_mgc_verify_service_change_req_msg(M, _Mid) ->
+ {error, {invalid_message, M}}.
+
+-ifndef(megaco_hipe_special).
+rle1_mgc_verify_notify_req_msg_fun() ->
+ fun(M) ->
+ rle1_mgc_verify_notify_req_msg(M)
+ end.
+-endif.
+
+rle1_mgc_verify_notify_req_msg(#'MegacoMessage'{mess = Mess} = M) ->
+ io:format("rle1_mgc_verify_notify_req_msg -> entry with"
+ "~n M: ~p"
+ "~n", [M]),
+ #'Message'{messageBody = Body} = Mess,
+ {transactions, [Trans]} = Body,
+ {transactionRequest, TR} = Trans,
+ #'TransactionRequest'{actions = [AR]} = TR,
+ io:format("rle1_mgc_verify_notify_request_fun -> AR: "
+ "~n~p~n", [AR]),
+ #'ActionRequest'{commandRequests = [CR]} = AR,
+ #'CommandRequest'{command = Cmd} = CR,
+ {notifyReq, NR} = Cmd,
+ #'NotifyRequest'{observedEventsDescriptor = OED} = NR,
+ #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED,
+ #'ObservedEvent'{eventName = "al/of"} = OE,
+ {ok, M};
+rle1_mgc_verify_notify_req_msg(M) ->
+ {error, {invalid_message, M}}.
+
+% rle1_err_desc(T) ->
+% EC = ?megaco_internal_gateway_error,
+% ET = lists:flatten(io_lib:format("~w",[T])),
+% #'ErrorDescriptor'{errorCode = EC, errorText = ET}.
+
+
+%%
+%% MG generator stuff
+%%
+-ifdef(megaco_hipe_special).
+-define(rle1_mg_verify_handle_connect_fun(),
+ {?MODULE, rle1_mg_verify_handle_connect, []}).
+-define(rle1_mg_verify_service_change_rep_fun(),
+ {?MODULE, rle1_mg_verify_service_change_rep, []}).
+-define(rle1_mg_verify_trans_rep_fun(),
+ {?MODULE, rle1_mg_verify_trans_rep, []}).
+-else.
+-define(rle1_mg_verify_handle_connect_fun(),
+ fun rle1_mg_verify_handle_connect/1).
+-define(rle1_mg_verify_service_change_rep_fun(),
+ fun rle1_mg_verify_service_change_rep/1).
+-define(rle1_mg_verify_trans_rep_fun(),
+ fun rle1_mg_verify_trans_rep/1).
+-endif.
+
+rle1_mg_event_sequence(text, tcp) ->
+ Mid = {deviceName,"mg"},
+ RI = [
+ {port, 2944},
+ {encoding_module, megaco_pretty_text_encoder},
+ {encoding_config, []},
+ {transport_module, megaco_tcp}
+ ],
+ rle1_mg_event_sequence2(Mid, RI).
+
+rle1_mg_event_sequence2(Mid, RI) ->
+ ServiceChangeReq = [rle1_mg_service_change_request_ar(Mid, 1)],
+ Tid = #megaco_term_id{id = ["00000000","00000000","01101101"]},
+ NotifyReq = [rle1_mg_notify_request_ar(1, Tid, 1)],
+ ConnectVerify = ?rle1_mg_verify_handle_connect_fun(),
+ ServiceChangeReplyVerify = ?rle1_mg_verify_service_change_rep_fun(),
+ TransReplyVerify = ?rle1_mg_verify_trans_rep_fun(),
+%% ConnectVerify = fun rle1_mg_verify_handle_connect/1,
+%% ServiceChangeReplyVerify = fun rle1_mg_verify_service_change_reply/1,
+%% TransReplyVerify = fun rle1_mg_verify_trans_reply/1,
+ EvSeq = [
+ {debug, true},
+ megaco_start,
+ {megaco_start_user, Mid, RI, []},
+ {megaco_update_user_info, recv_pending_limit, 4},
+ start_transport,
+ {megaco_trace, disable}, %%100},
+ {megaco_system_info, users},
+ {megaco_system_info, connections},
+ connect,
+ {megaco_callback, handle_connect, ConnectVerify},
+ megaco_connect,
+ {megaco_cast, ServiceChangeReq, []},
+ {megaco_callback, handle_connect, ConnectVerify},
+ {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify},
+ {sleep, 1000},
+ {megaco_cast, NotifyReq, []},
+ {megaco_callback, handle_trans_reply, TransReplyVerify},
+ {sleep, 1000},
+ megaco_stop_user,
+ megaco_stop,
+ {sleep, 1000}
+ ],
+ EvSeq.
+
+
+rle1_mg_verify_handle_connect({handle_connect, CH, ?VERSION}) ->
+ io:format("rle1_mg_verify_handle_connect -> ok"
+ "~n CH: ~p~n", [CH]),
+ {ok, CH, ok};
+rle1_mg_verify_handle_connect(Else) ->
+ io:format("rle1_mg_verify_handle_connect -> unknown"
+ "~n Else: ~p~n", [Else]),
+ {error, Else, ok}.
+
+rle1_mg_verify_service_change_rep(
+ {handle_trans_reply, _CH, ?VERSION, {ok, [AR]}, _}) ->
+ io:format("rle1_mg_verify_service_change_rep -> ok"
+ "~n AR: ~p~n", [AR]),
+ case AR of
+ #'ActionReply'{commandReply = [SCR]} ->
+ case SCR of
+ {serviceChangeReply,
+ #'ServiceChangeReply'{terminationID = [Tid],
+ serviceChangeResult = Res}} ->
+ case Tid of
+ #megaco_term_id{contains_wildcards = false,
+ id = ["root"]} ->
+ case Res of
+ {serviceChangeResParms,
+ #'ServiceChangeResParm'{
+ serviceChangeMgcId = _RemoteMid}} ->
+ {ok, AR, ok};
+ {Tag, Val} ->
+ Err = {invalid_service_change_result,
+ Tag, Val},
+ {error, Err, ok}
+ end;
+ _ ->
+ Err = {invalid_termination_id, Tid},
+ {error, Err, ok}
+ end;
+ {Tag, Val} ->
+ Err = {invalid_command_reply, Tag, Val},
+ {error, Err, ok}
+ end;
+ _ ->
+ Err = {invalid_action_reply, AR},
+ {error, Err, ok}
+ end;
+rle1_mg_verify_service_change_rep(Else) ->
+ io:format("rle1_mg_verify_service_change_rep -> unknown"
+ "~n Else: ~p~n", [Else]),
+ {error, Else, ok}.
+
+rle1_mg_verify_trans_rep(
+ {handle_trans_reply, _CH, ?VERSION,
+ {error, exceeded_recv_pending_limit} = E, _}) ->
+ io:format("rle1_mg_verify_trans_rep -> expected error~n", []),
+ {ok, E , error};
+rle1_mg_verify_trans_rep(Else) ->
+ io:format("rle1_mg_verify_trans_rep -> unknown"
+ "~n Else: ~p~n", [Else]),
+ {error, Else, error}.
+
+rle1_mg_service_change_request_ar(_Mid, Cid) ->
+ Prof = cre_serviceChangeProf("resgw", 1),
+ SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof),
+ Root = #megaco_term_id{id = ["root"]},
+ SCR = cre_serviceChangeReq([Root], SCP),
+ CMD = cre_command(SCR),
+ CR = cre_cmdReq(CMD),
+ cre_actionReq(Cid, [CR]).
+
+rle1_mg_notify_request_ar(Rid, Tid, Cid) ->
+ TT = cre_timeNotation("19990729", "22000000"),
+ Ev = cre_obsEvent("al/of", TT),
+ EvsDesc = cre_obsEvsDesc(Rid, [Ev]),
+ NR = cre_notifyReq([Tid], EvsDesc),
+ CMD = cre_command(NR),
+ CR = cre_cmdReq(CMD),
+ cre_actionReq(Cid, [CR]).
+
+
+%% ---
+
+recv_limit_exceeded2(suite) ->
+ [];
+recv_limit_exceeded2(doc) ->
+ "Received pending limit exceeded";
+recv_limit_exceeded2(Config) when is_list(Config) ->
+ put(verbosity, ?TEST_VERBOSITY),
+ put(sname, "TEST"),
+ put(tc, rle2),
+ i("starting"),
+
+ _MgcNode = make_node_name(mgc),
+ _MgNode = make_node_name(mg),
+
+ ?SKIP(not_yet_implemented).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%% %%%
+%%% Ticket test cases %%%
+%%% %%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+otp_4956(suite) ->
+ [];
+otp_4956(Config) when is_list(Config) ->
+ put(verbosity, ?TEST_VERBOSITY),
+ put(sname, "TEST"),
+ put(tc, otp_4956),
+ i("starting"),
+
+ MgcNode = make_node_name(mgc),
+ MgNode = make_node_name(mg),
+ d("start nodes: "
+ "~n MgcNode: ~p"
+ "~n MgNode: ~p",
+ [MgcNode, MgNode]),
+ ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE),
+
+ d("[MGC] start the simulator "),
+ {ok, Mgc} = megaco_test_megaco_generator:start_link("MGC", MgcNode),
+
+ d("[MGC] create the event sequence"),
+ MgcEvSeq = otp_4956_mgc_event_sequence(text, tcp),
+
+ i("wait some time before starting the MGC simulation"),
+ sleep(1000),
+
+ d("[MGC] start the simulation"),
+ {ok, MgcId} = megaco_test_megaco_generator:exec(Mgc, MgcEvSeq),
+
+ i("wait some time before starting the MG simulator"),
+ sleep(1000),
+
+ d("[MG] start the simulator (generator)"),
+ {ok, Mg} = megaco_test_tcp_generator:start_link("MG", MgNode),
+
+ d("[MG] create the event sequence"),
+ MgEvSeq = otp_4956_mg_event_sequence(text, tcp),
+
+ i("wait some time before starting the MG simulation"),
+ sleep(1000),
+
+ d("[MG] start the simulation"),
+ {ok, MgId} = megaco_test_tcp_generator:exec(Mg, MgEvSeq),
+
+ d("await the generator reply(s)"),
+ await_completion([MgcId, MgId]),
+
+ %% Tell Mgc to stop
+ i("[MGC] stop generator"),
+ megaco_test_megaco_generator:stop(Mgc),
+
+ %% Tell Mg to stop
+ i("[MG] stop generator"),
+ megaco_test_tcp_generator:stop(Mg),
+
+ i("done", []),
+ ok.
+
+
+%%
+%% MGC generator stuff
+%%
+-ifdef(megaco_hipe_special).
+-define(otp_4956_mgc_verify_handle_connect_fun(),
+ {?MODULE, otp_4956_mgc_verify_handle_connect, []}).
+-define(otp_4956_mgc_verify_service_change_req_fun(Mid),
+ {?MODULE, otp_4956_mgc_verify_service_change_req, [Mid]}).
+-define(otp_4956_mgc_verify_notify_req1_fun(),
+ {?MODULE, otp_4956_mgc_verify_notify_req1, []}).
+-define(otp_4956_mgc_verify_notify_req2_fun(),
+ {?MODULE, otp_4956_mgc_verify_notify_req2, []}).
+-define(otp_4956_mgc_verify_handle_trans_req_abort_fun(),
+ {?MODULE, otp_4956_mgc_verify_handle_trans_req_abort, []}).
+-define(otp_4956_mgc_verify_handle_disconnect_fun(),
+ {?MODULE, otp_4956_mgc_verify_handle_disconnect, []}).
+-else.
+-define(otp_4956_mgc_verify_handle_connect_fun(),
+ otp_4956_mgc_verify_handle_connect_fun()).
+-define(otp_4956_mgc_verify_service_change_req_fun(Mid),
+ otp_4956_mgc_verify_service_change_req_fun(Mid)).
+-define(otp_4956_mgc_verify_notify_req1_fun(),
+ otp_4956_mgc_verify_notify_req1_fun()).
+-define(otp_4956_mgc_verify_notify_req2_fun(),
+ otp_4956_mgc_verify_notify_req2_fun()).
+-define(otp_4956_mgc_verify_handle_trans_req_abort_fun(),
+ otp_4956_mgc_verify_handle_trans_req_abort_fun()).
+-define(otp_4956_mgc_verify_handle_disconnect_fun(),
+ fun otp_4956_mgc_verify_handle_disconnect/1).
+-endif.
+
+otp_4956_mgc_event_sequence(text, tcp) ->
+ Mid = {deviceName,"ctrl"},
+ RI = [
+ {port, 2944},
+ {encoding_module, megaco_pretty_text_encoder},
+ {encoding_config, []},
+ {transport_module, megaco_tcp}
+ ],
+ ConnectVerify = ?otp_4956_mgc_verify_handle_connect_fun(),
+ ServiceChangeReqVerify = ?otp_4956_mgc_verify_service_change_req_fun(Mid),
+ NotifyReqVerify1 = ?otp_4956_mgc_verify_notify_req1_fun(),
+ NotifyReqVerify2 = ?otp_4956_mgc_verify_notify_req2_fun(),
+ ReqAbortVerify = ?otp_4956_mgc_verify_handle_trans_req_abort_fun(),
+ DiscoVerify = ?otp_4956_mgc_verify_handle_disconnect_fun(),
+%% ConnectVerify = otp_4956_mgc_verify_handle_connect_fun(),
+%% ServiceChangeReqVerify = otp_4956_mgc_verify_service_change_req_fun(Mid),
+%% NotifyReqVerify1 = otp_4956_mgc_verify_notify_request_fun1(),
+%% NotifyReqVerify2 = otp_4956_mgc_verify_notify_request_fun2(),
+%% ReqAbortVerify = otp_4956_mgc_verify_handle_trans_request_abort_fun(),
+%% DiscoVerify = fun otp_4956_mgc_verify_handle_disconnect/1,
+ EvSeq = [
+ {debug, true},
+ {megaco_trace, disable},
+ {megaco_trace, max},
+ megaco_start,
+ {megaco_start_user, Mid, RI, []},
+ {megaco_update_user_info, sent_pending_limit, 4},
+ start_transport,
+ listen,
+ {megaco_callback, handle_connect, ConnectVerify},
+ {megaco_conn_info, all},
+ {megaco_callback, handle_trans_request_sc, ServiceChangeReqVerify},
+ {megaco_callback, handle_trans_request_1, NotifyReqVerify1},
+ {megaco_callback, handle_trans_request_abort, ReqAbortVerify},
+ {megaco_callback, nocall, 1000},
+ {megaco_callback, handle_trans_request_6, NotifyReqVerify2},
+ {megaco_callback, handle_disconnect, DiscoVerify},
+ megaco_stop_user,
+ megaco_stop
+ ],
+ EvSeq.
+
+
+-ifndef(megaco_hipe_special).
+otp_4956_mgc_verify_handle_connect_fun() ->
+ fun(M) ->
+ otp_4956_mgc_verify_handle_connect(M)
+ end.
+-endif.
+
+otp_4956_mgc_verify_handle_connect({handle_connect, CH, ?VERSION}) ->
+ {ok, CH, ok};
+otp_4956_mgc_verify_handle_connect(Else) ->
+ {error, Else, ok}.
+
+-ifndef(megaco_hipe_special).
+otp_4956_mgc_verify_service_change_req_fun(Mid) ->
+ fun(Req) ->
+ otp_4956_mgc_verify_service_change_req(Req, Mid)
+ end.
+-endif.
+
+otp_4956_mgc_verify_service_change_req(
+ {handle_trans_request, _, ?VERSION, [AR]}, Mid) ->
+ io:format("otp_4956_mgc_verify_service_change_req -> ok"
+ "~n AR: ~p"
+ "~n", [AR]),
+ case AR of
+ #'ActionRequest'{commandRequests = [CR]} ->
+ case CR of
+ #'CommandRequest'{command = Cmd} ->
+ case Cmd of
+ {serviceChangeReq,
+ #'ServiceChangeRequest'{terminationID = [Tid],
+ serviceChangeParms = Parms}} ->
+ case Tid of
+ #megaco_term_id{contains_wildcards = false,
+ id = ["root"]} ->
+ case Parms of
+ #'ServiceChangeParm'{
+ serviceChangeMethod = restart,
+ serviceChangeReason = [[$9,$0,$1|_]]} ->
+ Reply =
+ {discard_ack,
+ [otp_4956_mgc_service_change_reply_ar(Mid, 1)]},
+ {ok, AR, Reply};
+ _ ->
+ Err = {invalid_SCP, Parms},
+ ED = otp_4956_err_desc(Parms),
+ ErrReply = {discard_ack,
+ ED},
+ {error, Err, ErrReply}
+ end;
+ _ ->
+ Err = {invalid_termination_id, Tid},
+ ED = otp_4956_err_desc(Tid),
+ ErrReply = {discard_ack, ED},
+ {error, Err, ErrReply}
+ end;
+ _ ->
+ Err = {invalid_command, Cmd},
+ ED = otp_4956_err_desc(Cmd),
+ ErrReply = {discard_ack, ED},
+ {error, Err, ErrReply}
+ end;
+ _ ->
+ Err = {invalid_command_request, CR},
+ ED = otp_4956_err_desc(CR),
+ ErrReply = {discard_ack, ED},
+ {error, Err, ErrReply}
+ end;
+ _ ->
+ Err = {invalid_action_request, AR},
+ ED = otp_4956_err_desc(AR),
+ ErrReply = {discard_ack, ED},
+ {error, Err, ErrReply}
+ end;
+otp_4956_mgc_verify_service_change_req(Else, _Mid) ->
+ ED = otp_4956_err_desc(Else),
+ ErrReply = {discard_ack, ED},
+ {error, Else, ErrReply}.
+
+-ifndef(megaco_hipe_special).
+otp_4956_mgc_verify_notify_req1_fun() ->
+ fun(Req) ->
+ otp_4956_mgc_verify_notify_req1(Req)
+ end.
+-endif.
+
+otp_4956_mgc_verify_notify_req1({handle_trans_request, _, ?VERSION, [AR]}) ->
+ io:format("otp_4956_mgc_verify_notify_req1 -> entry with"
+ "~n AR: ~p"
+ "~n", [AR]),
+ case AR of
+ #'ActionRequest'{contextId = Cid,
+ commandRequests = [CR]} ->
+ #'CommandRequest'{command = Cmd} = CR,
+ {notifyReq, NR} = Cmd,
+ #'NotifyRequest'{terminationID = [Tid],
+ observedEventsDescriptor = OED,
+ errorDescriptor = asn1_NOVALUE} = NR,
+ #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED,
+ #'ObservedEvent'{eventName = "al/of"} = OE,
+ Reply = {discard_ack, [otp_4956_mgc_notify_reply_ar(Cid, Tid)]},
+ {ok, 6500, AR, Reply};
+ _ ->
+ ED = otp_4956_err_desc(AR),
+ ErrReply = {discard_ack, ED},
+ {error, AR, ErrReply}
+ end;
+otp_4956_mgc_verify_notify_req1(Else) ->
+ io:format("otp_4956_mgc_verify_notify_req1 -> entry with"
+ "~n Else: ~p"
+ "~n", [Else]),
+ ED = otp_4956_err_desc(Else),
+ ErrReply = {discard_ack, ED},
+ {error, Else, ErrReply}.
+
+-ifndef(megaco_hipe_special).
+otp_4956_mgc_verify_notify_req2_fun() ->
+ fun(Ev) ->
+ otp_4956_mgc_verify_notify_req2(Ev)
+ end.
+-endif.
+
+otp_4956_mgc_verify_notify_req2({handle_trans_request, _, ?VERSION, [AR]}) ->
+ case AR of
+ #'ActionRequest'{contextId = _Cid,
+ commandRequests = [CR]} ->
+ #'CommandRequest'{command = Cmd} = CR,
+ {notifyReq, NR} = Cmd,
+ #'NotifyRequest'{terminationID = [_Tid],
+ observedEventsDescriptor = OED,
+ errorDescriptor = asn1_NOVALUE} = NR,
+ #'ObservedEventsDescriptor'{observedEventLst = [OE]} = OED,
+ #'ObservedEvent'{eventName = "al/of"} = OE,
+ Reply = ignore,
+ {ok, 100, AR, Reply};
+ _ ->
+ ED = otp_4956_err_desc(AR),
+ ErrReply = {discard_ack, ED},
+ {error, AR, ErrReply}
+ end;
+otp_4956_mgc_verify_notify_req2(Else) ->
+ ED = otp_4956_err_desc(Else),
+ ErrReply = {discard_ack, ED},
+ {error, Else, ErrReply}.
+
+-ifndef(megaco_hipe_special).
+otp_4956_mgc_verify_handle_trans_req_abort_fun() ->
+ fun(Req) ->
+ otp_4956_mgc_verify_handle_trans_req_abort(Req)
+ end.
+-endif.
+
+otp_4956_mgc_verify_handle_trans_req_abort({handle_trans_request_abort,
+ CH, ?VERSION, 2, Pid}) ->
+ io:format("otp_4956_mgc_verify_handle_trans_req_abort -> ok"
+ "~n CH: ~p"
+ "~n Pid: ~p"
+ "~n", [CH, Pid]),
+ {ok, {CH, Pid}, ok};
+otp_4956_mgc_verify_handle_trans_req_abort({handle_trans_request_abort,
+ CH, Version, TransId, Pid}) ->
+ io:format("otp_4956_mgc_verify_handle_trans_req_abort -> error"
+ "~n CH: ~p"
+ "~n Version: ~p"
+ "~n TransId: ~p"
+ "~n Pid: ~p"
+ "~n", [CH, Version, TransId, Pid]),
+ {error, {error, {invalid_version_trans_id, Version, TransId}}, ok};
+otp_4956_mgc_verify_handle_trans_req_abort(Else) ->
+ io:format("otp_4956_mgc_verify_handle_trans_req_abort -> error"
+ "~n Else: ~p"
+ "~n", [Else]),
+ {error, Else, ok}.
+
+otp_4956_mgc_verify_handle_disconnect({handle_disconnect, CH, ?VERSION, _R}) ->
+ io:format("otp_4956_mgc_verify_handle_disconnect -> ok"
+ "~n CH: ~p"
+ "~n _R: ~p"
+ "~n", [CH, _R]),
+ {ok, CH, ok};
+otp_4956_mgc_verify_handle_disconnect(Else) ->
+ io:format("otp_4956_mgc_verify_handle_disconnect -> unknown"
+ "~n Else: ~p~n", [Else]),
+ {error, Else, ok}.
+
+otp_4956_mgc_service_change_reply_ar(Mid, Cid) ->
+ SCRP = cre_serviceChangeResParm(Mid),
+ SCRes = cre_serviceChangeResult(SCRP),
+ Root = #megaco_term_id{id = ["root"]},
+ SCR = cre_serviceChangeReply([Root], SCRes),
+ CR = cre_cmdReply(SCR),
+ AR = cre_actionReply(Cid, [CR]),
+ AR.
+
+%% otp_4956_mgc_service_change_reply_msg(Mid, TransId, Cid) ->
+%% AR = otp_4956_mgc_service_change_reply_ar(Mid, Cid),
+%% TRes = cre_transResult([AR]),
+%% TR = cre_transReply(TransId, TRes),
+%% Trans = cre_transaction(TR),
+%% Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])),
+%% cre_megacoMessage(Mess).
+
+otp_4956_mgc_notify_reply_ar(Cid, TermId) ->
+ NR = cre_notifyReply([TermId]),
+ CR = cre_cmdReply(NR),
+ cre_actionReply(Cid, [CR]).
+
+%% otp_4956_mgc_notify_reply(Mid, TransId, Cid, TermId) ->
+%% AR = otp_4956_mgc_notify_reply_ar(Cid, TermId),
+%% TRes = cre_transResult([AR]),
+%% TR = cre_transReply(TransId, TRes),
+%% Trans = cre_transaction(TR),
+%% Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])),
+%% cre_megacoMessage(Mess).
+
+
+%%
+%% MG generator stuff
+%%
+-ifdef(megaco_hipe_special).
+-define(otp_4956_mg_decode_msg_fun(Mod, Conf),
+ {?MODULE, decode_msg, [Mod, Conf]}).
+-define(otp_4956_mg_encode_msg_fun(Mod, Conf),
+ {?MODULE, encode_msg, [Mod, Conf]}).
+-define(otp_4956_mg_verify_service_change_rep_msg_fun(),
+ {?MODULE, otp_4956_mg_verify_service_change_rep_msg, []}).
+-define(otp_4956_mg_verify_pending_msg_fun(),
+ {?MODULE, otp_4956_mg_verify_pending_msg, []}).
+-define(otp_4956_mg_verify_pending_limit_msg_fun(),
+ {?MODULE, otp_4956_mg_verify_pending_limit_msg, []}).
+-else.
+-define(otp_4956_mg_decode_msg_fun(Mod, Conf),
+ otp_4956_mg_decode_msg_fun(Mod, Conf)).
+-define(otp_4956_mg_encode_msg_fun(Mod, Conf),
+ otp_4956_mg_encode_msg_fun(Mod, Conf)).
+-define(otp_4956_mg_verify_service_change_rep_msg_fun(),
+ otp_4956_mg_verify_service_change_rep_msg_fun()).
+-define(otp_4956_mg_verify_pending_msg_fun(),
+ otp_4956_mg_verify_pending_msg_fun()).
+-define(otp_4956_mg_verify_pending_limit_msg_fun(),
+ otp_4956_mg_verify_pending_limit_msg_fun()).
+-endif.
+
+otp_4956_mg_event_sequence(text, tcp) ->
+ DecodeFun = ?otp_4956_mg_decode_msg_fun(megaco_pretty_text_encoder, []),
+ EncodeFun = ?otp_4956_mg_encode_msg_fun(megaco_pretty_text_encoder, []),
+ Mid = {deviceName,"mg"},
+ ServiceChangeReq = otp_4956_mg_service_change_request_msg(Mid, 1, 0),
+ TermId = #megaco_term_id{id = ["00000000","00000000","01101101"]},
+ NotifyReq = otp_4956_mg_notify_request_msg(Mid, 2, 1, TermId, 1),
+ ServiceChangeReplyVerifyFun = ?otp_4956_mg_verify_service_change_rep_msg_fun(),
+ PendingVerify = ?otp_4956_mg_verify_pending_msg_fun(),
+ PendingLimitVerify = ?otp_4956_mg_verify_pending_limit_msg_fun(),
+%% ServiceChangeReplyVerifyFun =
+%% otp_4956_mg_verify_service_change_rep_msg_fun(),
+%% PendingVerify = otp_4956_mg_verify_pending_msg_fun(),
+%% PendingLimitVerify = otp_4956_mg_verify_pending_limit_msg_fun(),
+ EvSeq = [{debug, true},
+ {decode, DecodeFun},
+ {encode, EncodeFun},
+ {connect, 2944},
+ {send, "service-change-request", ServiceChangeReq},
+ {expect_receive, "service-change-reply", {ServiceChangeReplyVerifyFun, 10000}},
+ {send, "notify request (first send)", NotifyReq},
+ {sleep, 100},
+ {send, "notify request (resend 1)", NotifyReq},
+ {expect_receive, "pending 1", {PendingVerify, 1000}},
+ {sleep, 1000},
+ {send, "notify request (resend 2)", NotifyReq},
+ {expect_receive, "pending 2", {PendingVerify, 1000}},
+ {sleep, 1000},
+ {send, "notify request (resend 3)", NotifyReq},
+ {expect_receive, "pending 3", {PendingVerify, 1000}},
+ {sleep, 1000},
+ {send, "notify request (resend 4)", NotifyReq},
+ {expect_receive, "pending 4", {PendingVerify, 1000}},
+ {sleep, 1000},
+ {send, "notify request (resend 5)", NotifyReq},
+ {expect_receive, "pending limit exceeded",
+ {PendingLimitVerify, 1000}},
+ {sleep, 4000},
+ {send, "notify request (resend 6)", NotifyReq},
+ {expect_nothing, 4000},
+ disconnect
+ ],
+ EvSeq.
+
+-ifndef(megaco_hipe_special).
+otp_4956_mg_encode_msg_fun(Mod, Conf) ->
+ fun(M) ->
+ encode_msg(M, Mod, Conf)
+ end.
+
+otp_4956_mg_decode_msg_fun(Mod, Conf) ->
+ fun(M) ->
+ decode_msg(M, Mod, Conf)
+ end.
+-endif.
+
+-ifndef(megaco_hipe_special).
+otp_4956_mg_verify_service_change_rep_msg_fun() ->
+ fun(M) ->
+ otp_4956_mg_verify_service_change_rep_msg(M)
+ end.
+-endif.
+
+otp_4956_mg_verify_service_change_rep_msg(
+ #'MegacoMessage'{mess = Mess} = M) ->
+ io:format("otp_4956_mg_verify_service_change_rep_msg -> "
+ "ok so far~n",[]),
+ #'Message'{version = _V,
+ mId = _MgMid,
+ messageBody = Body} = Mess,
+ {transactions, [Trans]} = Body,
+ {transactionReply, TR} = Trans,
+ #'TransactionReply'{transactionId = _Tid,
+ immAckRequired = asn1_NOVALUE,
+ transactionResult = Res} = TR,
+ {actionReplies, [AR]} = Res,
+ #'ActionReply'{contextId = _Cid,
+ errorDescriptor = asn1_NOVALUE,
+ contextReply = _CtxReq,
+ commandReply = [CR]} = AR,
+ {serviceChangeReply, SCR} = CR,
+ #'ServiceChangeReply'{terminationID = _TermID,
+ serviceChangeResult = SCRes} = SCR,
+ {serviceChangeResParms, SCRP} = SCRes,
+ #'ServiceChangeResParm'{serviceChangeMgcId = _MgcMid} = SCRP,
+ {ok, M};
+otp_4956_mg_verify_service_change_rep_msg(M) ->
+ {error, {invalid_message, M}}.
+
+-ifndef(megaco_hipe_special).
+otp_4956_mg_verify_pending_msg_fun() ->
+ fun(M) ->
+ otp_4956_mg_verify_pending_msg(M)
+ end.
+-endif.
+
+otp_4956_mg_verify_pending_msg(#'MegacoMessage'{mess = Mess} = M) ->
+ io:format("otp_4956_mg_verify_pending_msg -> entry with"
+ "~n Mess. ~p"
+ "~n", [Mess]),
+ #'Message'{messageBody = Body} = Mess,
+ {transactions, [Trans]} = Body,
+ {transactionPending, TP} = Trans,
+ #'TransactionPending'{transactionId = _Id} = TP,
+ io:format("otp_4956_mg_verify_pending_msg -> done~n", []),
+ {ok, M};
+otp_4956_mg_verify_pending_msg(M) ->
+ io:format("otp_4956_mg_verify_pending_msg -> entry with"
+ "~n M: ~p"
+ "~n", [M]),
+ {error, {invalid_message, M}}.
+
+-ifndef(megaco_hipe_special).
+otp_4956_mg_verify_pending_limit_msg_fun() ->
+ fun(M) ->
+ otp_4956_mg_verify_pending_limit_msg(M)
+ end.
+-endif.
+
+otp_4956_mg_verify_pending_limit_msg(#'MegacoMessage'{mess = Mess} = M) ->
+ io:format("otp_4956_mg_verify_pending_limit_msg -> entry with"
+ "~n Mess: ~p"
+ "~n", [Mess]),
+ #'Message'{messageBody = Body} = Mess,
+ {transactions, [Trans]} = Body,
+ {transactionReply, TR} = Trans,
+ case element(4, TR) of
+ {transactionError, ED} ->
+ EC = ?megaco_number_of_transactionpending_exceeded,
+ #'ErrorDescriptor'{errorCode = EC} = ED,
+ {ok, M};
+ _ ->
+ {error, {invalid_transactionReply, TR}}
+ end;
+otp_4956_mg_verify_pending_limit_msg(M) ->
+ io:format("otp_4956_mg_verify_pending_limit_msg -> entry with"
+ "~n M: ~p"
+ "~n", [M]),
+ {error, {invalid_message, M}}.
+
+otp_4956_mg_service_change_request_ar(_Mid, Cid) ->
+ Prof = cre_serviceChangeProf("resgw", 1),
+ SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof),
+ Root = #megaco_term_id{id = ["root"]},
+ SCR = cre_serviceChangeReq([Root], SCP),
+ CMD = cre_command(SCR),
+ CR = cre_cmdReq(CMD),
+ cre_actionReq(Cid, [CR]).
+
+otp_4956_mg_service_change_request_msg(Mid, TransId, Cid) ->
+ AR = otp_4956_mg_service_change_request_ar(Mid, Cid),
+ TR = cre_transReq(TransId, [AR]),
+ Trans = cre_transaction(TR),
+ Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+otp_4956_mg_notify_request_ar(Rid, Tid, Cid) ->
+ TT = cre_timeNotation("19990729", "22000000"),
+ Ev = cre_obsEvent("al/of", TT),
+ EvsDesc = cre_obsEvsDesc(Rid, [Ev]),
+ NR = cre_notifyReq([Tid], EvsDesc),
+ CMD = cre_command(NR),
+ CR = cre_cmdReq(CMD),
+ cre_actionReq(Cid, [CR]).
+
+otp_4956_mg_notify_request_msg(Mid, TransId, Rid, TermId, Cid) ->
+ AR = otp_4956_mg_notify_request_ar(Rid, TermId, Cid),
+ TR = cre_transReq(TransId, [AR]),
+ Trans = cre_transaction(TR),
+ Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+
+otp_4956_err_desc(T) ->
+ EC = ?megaco_internal_gateway_error,
+ ET = lists:flatten(io_lib:format("~w",[T])),
+ #'ErrorDescriptor'{errorCode = EC, errorText = ET}.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+otp_5310(suite) ->
+ [];
+otp_5310(doc) ->
+ "...";
+otp_5310(Config) when is_list(Config) ->
+ put(verbosity, ?TEST_VERBOSITY),
+ put(sname, "TEST"),
+ put(tc, otp_5310),
+ i("starting"),
+
+ MgcNode = make_node_name(mgc),
+ MgNode = make_node_name(mg),
+ d("start nodes: "
+ "~n MgcNode: ~p"
+ "~n MgNode: ~p",
+ [MgcNode, MgNode]),
+ ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE),
+
+ %% Start the MGC and MGs
+ i("[MGC] start"),
+ ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}],
+ {ok, Mgc} =
+ ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, [], ?MGC_VERBOSITY),
+
+ i("[MG] start"),
+ MgMid = {deviceName, "mg"},
+ MgConfig = [],
+ {ok, Mg} = ?MG_START(MgNode, MgMid, text, tcp, MgConfig, ?MG_VERBOSITY),
+
+ d("MG user info: ~p", [?MG_USER_INFO(Mg, all)]),
+
+ i("[MG] connect to the MGC (service change)"),
+ ServChRes = ?MG_SERV_CHANGE(Mg),
+ d("service change result: ~p", [ServChRes]),
+
+ d("MG conn info: ~p", [?MG_CONN_INFO(Mg, all)]),
+
+ d("[MGC] update connection info pending timer"),
+ PendingTimer = #megaco_incr_timer{wait_for = timer:seconds(1),
+ factor = 1},
+ ?MGC_UPDATE_CI(Mgc, pending_timer, PendingTimer),
+
+ d("[MGC] update connection info originating pending limit"),
+ PendingLimit = 3,
+ ?MGC_UPDATE_CI(Mgc, orig_pending_limit, PendingLimit),
+
+ ConnReps1 = ?MGC_CONN_INFO(Mgc, replies),
+ d("[MGC] ConnReps1: ~p", [ConnReps1]),
+ case filter_aborted1(ConnReps1, []) of
+ [{_, []}] ->
+ ok;
+ ConnFlt1 ->
+ ?ERROR({unexpected_reply_state, conn_info, ConnReps1, ConnFlt1})
+ end,
+ UserReps1 = ?MGC_USER_INFO(Mgc, replies),
+ d("[MGC] UserReps1: ~p", [UserReps1]),
+ case filter_aborted1(UserReps1, []) of
+ [{_, []}] ->
+ ok;
+ UserFlt1 ->
+ ?ERROR({unexpected_reply_state, user_info, UserReps1, UserFlt1})
+ end,
+
+ %% Instruct the MGC to never reply to requests
+ d("[MGC] don't reply to requests"),
+ ?MGC_REQ_IGNORE(Mgc),
+
+ %% We want to know when the abort comes...
+ d("[MGC] request abort inform"),
+ ?MGC_ABORT_INFO(Mgc, self()),
+
+ %% Make MG send a request
+ d("[MG] send the notify"),
+ {ok, {_ProtocolVersion, {error, ED}}} = ?MG_NOTIF_RAR(Mg),
+ d("[MG] ED: ~p", [ED]),
+ ErrorCode = ?megaco_number_of_transactionpending_exceeded,
+ ErrorCode = ED#'ErrorDescriptor'.errorCode,
+
+ %% Wait for the MGC to get aborted
+ d("[MGC] await the abort callback"),
+ {ok, TransId} = await_aborted(Mgc),
+ d("[MGC] aborted transaction: ~p", [TransId]),
+
+ %% Make sure we have one in aborted state
+ d("[MGC] how many is aborted (should be == 1)?"),
+ ConnReps2 = ?MGC_CONN_INFO(Mgc, replies),
+ case filter_aborted1(ConnReps2, []) of
+ [{_, [TransId]}] ->
+ ok;
+ [{_, []}] ->
+ ok; % has already been cleaned up...
+ ConnFlt2 ->
+ ?ERROR({unexpected_reply_state, conn_info, ConnReps2, ConnFlt2})
+ end,
+ d("[MGC] ConnReps2: ~p", [ConnReps2]),
+ UserReps2 = ?MGC_USER_INFO(Mgc, replies),
+ d("[MGC] UserReps2: ~p", [UserReps2]),
+ case filter_aborted1(UserReps2, []) of
+ [{_, [TransId]}] ->
+ ok;
+ [{_, []}] ->
+ ok; % has already been cleaned up...
+ UserFlt2 ->
+ ?ERROR({unexpected_reply_state, user_info, UserReps2, UserFlt2})
+ end,
+
+ %% do disconnect and the do cancel in the handle function
+ d("[MGC] disconnect"),
+ DiscoRes = ?MGC_DISCO(Mgc, cancel),
+ d("[MGC] DiscoRes: ~p", [DiscoRes]),
+
+ %% check number of reply records (should be no in aborted).
+ d("[MGC] check number of replies in aborted state (should be == 1)"),
+ ConnReps3 = ?MGC_CONN_INFO(Mgc, replies),
+ d("[MGC] ConnReps3: ~p", [ConnReps3]),
+ UserReps3 = ?MGC_USER_INFO(Mgc, replies),
+ d("[MGC] UserReps3: ~p", [UserReps3]),
+
+ %% Tell MG to stop
+ i("[MG] stop"),
+ ?MG_STOP(Mg),
+
+ %% Tell Mgc to stop
+ i("[MGC] stop"),
+ ?MGC_STOP(Mgc),
+
+ i("done", []),
+ ok.
+
+await_aborted(Mgc) ->
+ d("await_aborted"),
+ receive
+ {abort_received, Mgc, TransId} ->
+ {ok, TransId}
+ after 10000 ->
+ d("await_aborted - timeout"),
+ {error, timeout}
+ end.
+
+filter_aborted1([], Acc) ->
+ lists:reverse(Acc);
+filter_aborted1([{CH, Ab}|T], Acc) ->
+ filter_aborted1(T, [{CH, filter_aborted2(Ab, [])}|Acc]).
+
+filter_aborted2([], Aborted) ->
+ lists:reverse(Aborted);
+filter_aborted2([{TransId, aborted, _}|T], Aborted) ->
+ filter_aborted2(T, [TransId|Aborted]);
+filter_aborted2([{TransId, State, _}|T], Aborted) ->
+ d("Transaction ~w actually in state ~w", [TransId, State]),
+ filter_aborted2(T, Aborted);
+filter_aborted2([_|T], Aborted) ->
+ filter_aborted2(T, Aborted).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% The timeout times is a little odd in this test case. The (short)
+%% request timer is longer then the (long) request timer. This is
+%% simply to produce the effect that we want regarding max_retries =
+%% infinity_restartable. Also the pending timeout has to be shorter
+%% then "short" + "long" and longer then "long"
+
+otp_5619(suite) ->
+ [];
+otp_5619(doc) ->
+ "...";
+otp_5619(Config) when is_list(Config) ->
+ put(verbosity, ?TEST_VERBOSITY),
+ put(sname, "TEST"),
+ put(tc, otp_5619),
+ i("starting"),
+
+ MgcNode = make_node_name(mgc),
+ MgNode = make_node_name(mg),
+ d("start nodes: "
+ "~n MgcNode: ~p"
+ "~n MgNode: ~p",
+ [MgcNode, MgNode]),
+ ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE),
+
+ %% Start the MGC and MGs
+ i("[MGC] start"),
+ MgcMid = {deviceName, "ctrl"},
+ ET = [{text, tcp}, {text, udp}, {binary, tcp}, {binary, udp}],
+ {ok, Mgc} = ?MGC_START(MgcNode, MgcMid, ET, [], ?MGC_VERBOSITY),
+
+ i("[MG] start"),
+ MgMid = {deviceName, "mg"},
+ MgConfig = [],
+ {ok, Mg} = ?MG_START(MgNode, MgMid, text, tcp, MgConfig, ?MG_VERBOSITY),
+
+ d("MG user info: ~p", [?MG_USER_INFO(Mg, all)]),
+ d("MG conn info: ~p", [?MG_CONN_INFO(Mg, all)]),
+
+ i("[MG] connect to the MGC (service change)"),
+ ServChRes = ?MG_SERV_CHANGE(Mg),
+ d("service change result: ~p", [ServChRes]),
+
+ d("[MG] update connection info long request timer"),
+ LongReqTmr = #megaco_incr_timer{wait_for = timer:seconds(1),
+ factor = 1,
+ max_retries = infinity_restartable},
+ ?MG_UPDATE_CI(Mg, long_request_timer, LongReqTmr),
+
+ d("MG conn info: ~p", [?MG_CONN_INFO(Mg, all)]),
+
+ d("MGC conn info: ~p", [?MGC_CONN_INFO(Mgc, all)]),
+
+ d("[MGC] update connection info pending timer"),
+ PendingTimer = #megaco_incr_timer{wait_for = timer:seconds(3),
+ factor = 1},
+ ?MGC_UPDATE_CI(Mgc, pending_timer, PendingTimer),
+
+ d("[MGC] update connection info sent pending limit"),
+ PendingLimit = 5,
+ ?MGC_UPDATE_CI(Mgc, sent_pending_limit, PendingLimit),
+
+ d("MGC conn info: ~p", [?MG_CONN_INFO(Mgc, all)]),
+
+
+ d("[MGC] late reply to requests "
+ "(simulate that the request takes a long time)"),
+ {ok, _} = ?MGC_REQ_DISC(Mgc, 11000),
+
+
+ d("[MG] send the notify and await the timeout"),
+ {ok, Reply} = ?MG_NOTIF_RAR(Mg),
+ case Reply of
+ {_Version, {error, timeout}} ->
+ d("[MG] expected reply (timeout) received~n", []);
+ _ ->
+ ?ERROR({unexpected_reply, Reply})
+ end,
+
+
+ %% Tell MG to stop
+ i("[MG] stop~n"),
+ ?MG_STOP(Mg),
+
+ %% Tell Mgc to stop
+ i("[MGC] stop~n"),
+ ?MGC_STOP(Mgc),
+
+ i("done", []),
+ ok.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+%%
+%% Common message creation functions
+%%
+
+cre_serviceChangeParm(M,R,P) ->
+ #'ServiceChangeParm'{serviceChangeMethod = M,
+ serviceChangeReason = R,
+ serviceChangeProfile = P}.
+
+cre_serviceChangeReq(Tid, Parms) ->
+ #'ServiceChangeRequest'{terminationID = Tid,
+ serviceChangeParms = Parms}.
+
+cre_timeNotation(D,T) ->
+ #'TimeNotation'{date = D, time = T}.
+
+cre_obsEvent(Name, Not) ->
+ #'ObservedEvent'{eventName = Name,
+ timeNotation = Not}.
+%% cre_obsEvent(Name, Not, Par) ->
+%% #'ObservedEvent'{eventName = Name,
+%% timeNotation = Not,
+%% eventParList = Par}.
+
+cre_obsEvsDesc(Id, EvList) ->
+ #'ObservedEventsDescriptor'{requestId = Id,
+ observedEventLst = EvList}.
+
+cre_notifyReq(Tid, EvsDesc) ->
+ #'NotifyRequest'{terminationID = Tid,
+ observedEventsDescriptor = EvsDesc}.
+
+cre_command(R) when is_record(R, 'NotifyRequest') ->
+ {notifyReq, R};
+cre_command(R) when is_record(R, 'ServiceChangeRequest') ->
+ {serviceChangeReq, R}.
+
+cre_cmdReq(Cmd) ->
+ #'CommandRequest'{command = Cmd}.
+
+cre_actionReq(CtxId, CmdReqs) when is_list(CmdReqs) ->
+ #'ActionRequest'{contextId = CtxId,
+ commandRequests = CmdReqs}.
+
+cre_transReq(TransId, ARs) when is_list(ARs) ->
+ #'TransactionRequest'{transactionId = TransId,
+ actions = ARs}.
+
+%% --
+
+cre_serviceChangeResParm(Mid) ->
+ cre_serviceChangeResParm(Mid, ?VERSION).
+
+cre_serviceChangeResParm(Mid, V) ->
+ #'ServiceChangeResParm'{serviceChangeMgcId = Mid,
+ serviceChangeVersion = V}.
+
+cre_serviceChangeResult(SCRP) when is_record(SCRP, 'ServiceChangeResParm') ->
+ {serviceChangeResParms, SCRP};
+cre_serviceChangeResult(ED) when is_record(ED, 'ErrorDescriptor') ->
+ {errorDescriptor, ED}.
+
+cre_serviceChangeReply(Tid, Res) ->
+ #'ServiceChangeReply'{terminationID = Tid,
+ serviceChangeResult = Res}.
+
+cre_cmdReply(R) when is_record(R, 'NotifyReply') ->
+ {notifyReply, R};
+cre_cmdReply(R) when is_record(R, 'ServiceChangeReply') ->
+ {serviceChangeReply, R}.
+
+cre_notifyReply(Tid) ->
+ #'NotifyReply'{terminationID = Tid}.
+
+cre_actionReply(CtxId, CmdRep) ->
+ #'ActionReply'{contextId = CtxId,
+ commandReply = CmdRep}.
+
+%% cre_transResult(ED) when record(ED, 'ErrorDescriptor') ->
+%% {transactionError, ED};
+%% cre_transResult([AR|_] = ARs) when record(AR, 'ActionReply') ->
+%% {actionReplies, ARs}.
+
+%% cre_transReply(TransId, Res) ->
+%% #'TransactionReply'{transactionId = TransId,
+%% transactionResult = Res}.
+
+%% --
+
+cre_serviceChangeProf(Name, Ver) when is_list(Name) andalso is_integer(Ver) ->
+ #'ServiceChangeProfile'{profileName = Name,
+ version = Ver}.
+
+cre_transaction(Trans) when is_record(Trans, 'TransactionRequest') ->
+ {transactionRequest, Trans};
+cre_transaction(Trans) when is_record(Trans, 'TransactionPending') ->
+ {transactionPending, Trans};
+cre_transaction(Trans) when is_record(Trans, 'TransactionReply') ->
+ {transactionReply, Trans};
+cre_transaction(Trans) when is_record(Trans, 'TransactionAck') ->
+ {transactionResponseAck, Trans}.
+
+cre_transactions(Trans) when is_list(Trans) ->
+ {transactions, Trans}.
+
+cre_message(Version, Mid, Body) ->
+ #'Message'{version = Version,
+ mId = Mid,
+ messageBody = Body}.
+
+cre_megacoMessage(Mess) ->
+ #'MegacoMessage'{mess = Mess}.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Transform a short timer to a long one.
+%% The purpose of this is to trick the stack
+%% to keep re-sending the request, even after
+%% having received the first pending (which
+%% indicates that the other side _IS_
+%% working on the request).
+-ifdef(MEGACO_TEST_CODE).
+
+init_request_timer({short, Ref}) ->
+ {long, Ref};
+init_request_timer(O) ->
+ O.
+
+-endif.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+encode_msg(M, Mod, Conf) ->
+ Mod:encode_message(Conf, M).
+
+%% encode_msg(M, Mod, Conf, Ver) ->
+%% Mod:encode_message(Conf, Ver, M).
+
+decode_msg(M, Mod, Conf) ->
+ Mod:decode_message(Conf, M).
+
+%% decode_msg(M, Mod, Conf, Ver) ->
+%% Mod:decode_message(Conf, Ver, M).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+%% tim() ->
+%% {A,B,C} = erlang:now(),
+%% A*1000000000+B*1000+(C div 1000).
+
+
+make_node_name(Name) ->
+ case string:tokens(atom_to_list(node()), [$@]) of
+ [_,Host] ->
+ list_to_atom(lists:concat([atom_to_list(Name) ++ "@" ++ Host]));
+ _ ->
+ exit("Test node must be started with '-sname'")
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+await_completion(Ids) ->
+ case megaco_test_generator_lib:await_completion(Ids) of
+ {ok, Reply} ->
+ d("OK => Reply: ~n~p", [Reply]),
+ ok;
+ {error, Reply} ->
+ d("ERROR => Reply: ~n~p", [Reply]),
+ ?ERROR({failed, Reply})
+ end.
+
+%% await_completion(Ids, Timeout) ->
+%% case megaco_test_generator_lib:await_completion(Ids, Timeout) of
+%% {ok, Reply} ->
+%% d("OK => Reply: ~n~p", [Reply]),
+%% ok;
+%% {error, Reply} ->
+%% d("ERROR => Reply: ~n~p", [Reply]),
+%% ?ERROR({failed, Reply})
+%% end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+sleep(X) -> receive after X -> ok end.
+
+%% error_msg(F,A) -> error_logger:error_msg(F ++ "~n",A).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+i(F) ->
+ i(F, []).
+
+i(F, A) ->
+ print(info, get(verbosity), now(), get(tc), "INF", F, A).
+
+
+d(F) ->
+ d(F, []).
+
+d(F, A) ->
+ print(debug, get(verbosity), now(), get(tc), "DBG", F, A).
+
+
+printable(_, debug) -> true;
+printable(info, info) -> true;
+printable(_,_) -> false.
+
+print(Severity, Verbosity, Ts, Tc, P, F, A) ->
+ print(printable(Severity,Verbosity), Ts, Tc, P, F, A).
+
+print(true, Ts, Tc, P, F, A) ->
+ io:format("*** [~s] ~s ~p ~s:~w ***"
+ "~n " ++ F ++ "~n",
+ [format_timestamp(Ts), P, self(), get(sname), Tc | A]);
+print(_, _, _, _, _, _) ->
+ ok.
+
+%% print(F, A) ->
+%% io:format("*** [~s] ***"
+%% "~n " ++ F ++ "~n",
+%% [format_timestamp(now()) | A]).
+
+format_timestamp(Now) -> megaco:format_timestamp(Now).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% random_init() ->
+%% {A,B,C} = now(),
+%% random:seed(A,B,C).
+
+%% random() ->
+%% 10 * random:uniform(50).
+
+%% apply_load_timer() ->
+%% erlang:send_after(random(), self(), apply_load_timeout).
+
+
+