1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2003-2020. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20
21%%
22%%----------------------------------------------------------------------
23%% Purpose: Verify the application specifics of the Megaco application
24%%----------------------------------------------------------------------
25-module(megaco_mreq_SUITE).
26
27-export([
28 	 suite/0, all/0, groups/0,
29         init_per_suite/1, end_per_suite/1,
30         init_per_group/2, end_per_group/2,
31         init_per_testcase/2, end_per_testcase/2,
32
33         req_and_rep/1,
34         req_and_pending/1,
35         req_and_cancel/1
36
37        ]).
38
39-include_lib("megaco/include/megaco.hrl").
40-include_lib("megaco/include/megaco_message_v1.hrl").
41-include("megaco_test_lib.hrl").
42
43-define(TEST_VERBOSITY, debug).
44-define(MGC_VERBOSITY,  debug).
45-define(MG_VERBOSITY,   debug).
46
47-define(LOAD_COUNTER_START, 10).
48-define(A4444, ["11111111", "00000000", "00000000"]).
49-define(A4445, ["11111111", "00000000", "11111111"]).
50-define(A5555, ["11111111", "11111111", "00000000"]).
51-define(A5556, ["11111111", "11111111", "11111111"]).
52
53-define(MGC_START(Pid, Mid, ET, Verb),
54	megaco_test_mgc:start(Pid, Mid, ET, Verb)).
55-define(MGC_STOP(Pid), megaco_test_mgc:stop(Pid)).
56-define(MGC_GET_STATS(Pid, No), megaco_test_mgc:get_stats(Pid, No)).
57-define(MGC_RESET_STATS(Pid), megaco_test_mgc:reset_stats(Pid)).
58-define(MGC_REQ_DISC(Pid,To), megaco_test_mgc:request_discard(Pid,To)).
59-define(MGC_REQ_PEND(Pid,To), megaco_test_mgc:request_pending(Pid,To)).
60-define(MGC_REQ_HAND(Pid), megaco_test_mgc:request_handle(Pid)).
61
62-define(MG_START(Pid, Mid, Enc, Transp, Verb),
63	megaco_test_mg:start(Pid, Mid, Enc, Transp, Verb)).
64-define(MG_STOP(Pid),                megaco_test_mg:stop(Pid)).
65-define(MG_GET_STATS(Pid),           megaco_test_mg:get_stats(Pid)).
66-define(MG_RESET_STATS(Pid),         megaco_test_mg:reset_stats(Pid)).
67-define(MG_SERV_CHANGE(Pid),         megaco_test_mg:service_change(Pid)).
68-define(MG_NOTIF_RAR(Pid),           megaco_test_mg:notify_request_and_reply(Pid)).
69-define(MG_NOTIF_REQ(Pid),           megaco_test_mg:notify_request(Pid)).
70-define(MG_NOTIF_AR(Pid),            megaco_test_mg:await_notify_reply(Pid)).
71-define(MG_CANCEL(Pid,R),            megaco_test_mg:cancel_request(Pid,R)).
72-define(MG_APPLY_LOAD(Pid,CntStart), megaco_test_mg:apply_load(Pid,CntStart)).
73
74
75%%======================================================================
76%% Common Test interface functions
77%%======================================================================
78
79suite() ->
80    [{ct_hooks, [ts_install_cth]}].
81
82all() ->
83    [
84     req_and_rep,
85     req_and_pending,
86     req_and_cancel
87    ].
88
89groups() ->
90    [].
91
92
93
94%%
95%% -----
96%%
97
98init_per_suite(suite) ->
99    [];
100init_per_suite(doc) ->
101    [];
102init_per_suite(Config0) when is_list(Config0) ->
103
104    ?ANNOUNCE_SUITE_INIT(),
105
106    p("init_per_suite -> entry with"
107      "~n      Config: ~p"
108      "~n      Nodes:  ~p", [Config0, erlang:nodes()]),
109
110    case ?LIB:init_per_suite(Config0) of
111        {skip, _} = SKIP ->
112            SKIP;
113
114        Config1 when is_list(Config1) ->
115
116            %% We need a (local) monitor on this node also
117            megaco_test_sys_monitor:start(),
118
119            p("init_per_suite -> end when"
120              "~n      Config: ~p"
121              "~n      Nodes:  ~p", [Config1, erlang:nodes()]),
122
123            Config1
124    end.
125
126end_per_suite(suite) -> [];
127end_per_suite(doc) -> [];
128end_per_suite(Config0) when is_list(Config0) ->
129
130    p("end_per_suite -> entry with"
131      "~n      Config: ~p"
132      "~n      Nodes:  ~p", [Config0, erlang:nodes()]),
133
134    megaco_test_sys_monitor:stop(),
135    Config1 = ?LIB:end_per_suite(Config0),
136
137    p("end_per_suite -> end when"
138      "~n      Nodes:  ~p", [erlang:nodes()]),
139
140    Config1.
141
142
143%%
144%% -----
145%%
146
147init_per_group(_GroupName, Config) ->
148    Config.
149
150end_per_group(_GroupName, Config) ->
151    Config.
152
153
154
155init_per_testcase(Case, Config) ->
156    process_flag(trap_exit, true),
157
158    p("init_per_suite -> entry with"
159      "~n      Config: ~p"
160      "~n      Nodes:  ~p", [Config, erlang:nodes()]),
161
162    megaco_test_global_sys_monitor:reset_events(),
163    megaco_test_lib:init_per_testcase(Case, Config).
164
165end_per_testcase(Case, Config) ->
166    process_flag(trap_exit, false),
167
168    p("end_per_suite -> entry with"
169      "~n      Config: ~p"
170      "~n      Nodes:  ~p", [Config, erlang:nodes()]),
171
172    p("system events during test: "
173      "~n   ~p", [megaco_test_global_sys_monitor:events()]),
174
175    megaco_test_lib:end_per_testcase(Case, Config).
176
177
178
179%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
180
181req_and_rep(suite) ->
182    [];
183req_and_rep(doc) ->
184    [];
185req_and_rep(Config) when is_list(Config) ->
186    Pre = fun() ->
187                  MgcNode = make_node_name(mgc),
188                  Mg1Node = make_node_name(mg1),
189                  Mg2Node = make_node_name(mg2),
190                  Mg3Node = make_node_name(mg3),
191                  Mg4Node = make_node_name(mg4),
192                  d("try start nodes: "
193                    "~n      MgcNode: ~p"
194                    "~n      Mg1Node: ~p"
195                    "~n      Mg2Node: ~p"
196                    "~n      Mg3Node: ~p"
197                    "~n      Mg4Node: ~p",
198                    [MgcNode, Mg1Node, Mg2Node, Mg3Node, Mg4Node]),
199                  Nodes = [MgcNode, Mg1Node, Mg2Node, Mg3Node, Mg4Node],
200                  ok    = ?START_NODES(Nodes),
201                  Nodes
202          end,
203    Case = fun do_req_and_rep/1,
204    Post = fun(Nodes) ->
205                   d("stop nodes (in the reverse order):"
206                     "~n       ~p", [Nodes]),
207                   ?STOP_NODES(lists:reverse(Nodes))
208           end,
209    try_tc(req_and_rep, Pre, Case, Post).
210
211do_req_and_rep([MgcNode, Mg1Node, Mg2Node, Mg3Node, Mg4Node]) ->
212    %% Start the MGC and MGs
213    i("start the MGC"),
214    ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}],
215    {ok, Mgc} =
216	?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, ?MGC_VERBOSITY),
217
218    i("start and connect the MGs"),
219    MgConf0 = [{Mg1Node, "mg1", text,   tcp, ?MG_VERBOSITY},
220	       {Mg2Node, "mg2", text,   udp, ?MG_VERBOSITY},
221	       {Mg3Node, "mg3", binary, tcp, ?MG_VERBOSITY},
222	       {Mg4Node, "mg4", binary, udp, ?MG_VERBOSITY}],
223    MgConf = rar_connect_mg(MgConf0, []),
224
225    %% Collect the (initial) MGs statistics
226    Stats1 = rar_get_mg_stats(MgConf, []),
227    d("stats for the MGs: "
228      "~n      ~p", [Stats1]),
229
230    %% Collect and check the MGC statistics
231    i("collect and check the MGC stats"),
232    {ok, MgcStats1} = ?MGC_GET_STATS(Mgc, 1),
233    d("stats (1) for Mgc: "
234      "~n      ~p"
235      "~n", [MgcStats1]),
236
237
238    sleep(1000),
239
240
241    %% And apply some load
242    i("apply traffic load"),
243    ok = rar_apply_load(MgConf),
244
245    %% Await completion of load part and the collect traffic
246    i("await load completion"),
247    ok = rar_await_load_complete(MgConf),
248
249
250    sleep(1000),
251
252
253    i("collect the MGs statistics"),
254    Stats2 = rar_get_mg_stats(MgConf, []),
255    d("stats for MGs: "
256      "~n      ~p", [Stats2]),
257
258    i("collect the MGC statistics"),
259    {ok, MgcStats2} = ?MGC_GET_STATS(Mgc, 1),
260    d("stats (1) for Mgc: "
261      "~n      ~p"
262      "~n", [MgcStats2]),
263
264
265    sleep(1000),
266
267
268    %% Reset counters
269    i("reset the MGs statistics"),
270    rar_reset_mg_stats(MgConf),
271    Stats3 = rar_get_mg_stats(MgConf, []),
272    d("stats for the MGs: "
273      "~n      ~p", [Stats3]),
274
275    i("reset the MGC statistics"),
276    rar_reset_mgc_stats(Mgc),
277    {ok, MgcStats3} = ?MGC_GET_STATS(Mgc, 1),
278    d("stats (1) for Mgc: "
279      "~n      ~p"
280      "~n", [MgcStats3]),
281
282
283    sleep(1000),
284
285
286    %% Tell MGs to stop
287    i("stop the MGs"),
288    rar_stop_mg(MgConf),
289
290
291    sleep(1000),
292
293
294    %% Collect the statistics
295    i("collect the MGC statistics"),
296    {ok, MgcStats4} = ?MGC_GET_STATS(Mgc, 1),
297    d("stats (1) for Mgc: "
298      "~n      ~p", [MgcStats4]),
299    {ok, MgcStats5} = ?MGC_GET_STATS(Mgc, 2),
300    d("stats (2) for Mgc: "
301      "~n      ~p"
302      "~n", [MgcStats5]),
303
304    %% Tell Mgc to stop
305    i("stop the MGC"),
306    ?MGC_STOP(Mgc),
307
308    i("done", []),
309    ok.
310
311
312rar_connect_mg([], Acc) ->
313    lists:reverse(Acc);
314rar_connect_mg([{Node, Name, Coding, Trans, Verb}|Mg], Acc) ->
315    Pid = rar_connect_mg(Node, Name, Coding, Trans, Verb),
316    rar_connect_mg(Mg, [{Name, Pid}|Acc]).
317
318rar_connect_mg(Node, Name, Coding, Trans, Verb) ->
319    Mid = {deviceName, Name},
320    {ok, Pid} = ?MG_START(Node, Mid, Coding, Trans, Verb),
321
322    %% Ask the MGs to do a service change
323    Res = ?MG_SERV_CHANGE(Pid),
324    d("rar_connect_mg -> (~s) service change result: ~p", [Name,Res]),
325
326    Pid.
327
328
329rar_stop_mg(MGs) ->
330    [?MG_STOP(Pid) || {_Name, Pid} <- MGs].
331
332
333rar_get_mg_stats([], Acc) ->
334    lists:reverse(Acc);
335rar_get_mg_stats([{Name, Pid}|Mgs], Acc) ->
336    {ok, Stats} = ?MG_GET_STATS(Pid),
337    d("rar_get_mg_stats -> stats for ~s: "
338      "~n      ~p"
339      "~n", [Name, Stats]),
340    rar_get_mg_stats(Mgs, [{Name, Stats}|Acc]).
341
342
343rar_apply_load([]) ->
344    ok;
345rar_apply_load([{_, MG}|MGs]) ->
346    ?MG_APPLY_LOAD(MG,?LOAD_COUNTER_START),
347    rar_apply_load(MGs).
348
349
350rar_reset_mg_stats([]) ->
351    ok;
352rar_reset_mg_stats([{Name, Pid}|MGs]) ->
353    d("rar_reset_mg_stats -> resetting ~s", [Name]),
354    ?MG_RESET_STATS(Pid),
355    rar_reset_mg_stats(MGs).
356
357rar_reset_mgc_stats(Mgc) ->
358    d("rar_reset_mgc_stats -> resetting ~p", [Mgc]),
359    ?MGC_RESET_STATS(Mgc).
360
361
362rar_await_load_complete([]) ->
363    ok;
364rar_await_load_complete(MGs0) ->
365    receive
366	{load_complete, Pid} ->
367	    d("received load_complete from ~p", [Pid]),
368	    MGs1 = lists:keydelete(Pid, 2, MGs0),
369	    rar_await_load_complete(lists:delete(Pid, MGs1));
370	{'EXIT', Pid, Reason} ->
371	    e("exit signal from ~p: ~p", [Pid, Reason]),
372	    case lists:keymember(Pid, 2, MGs0) of
373		true ->
374		    exit({mg_exit, Pid, Reason});
375		false ->
376		    MGs1 = lists:keydelete(Pid, 2, MGs0),
377		    rar_await_load_complete(lists:delete(Pid, MGs1))
378	    end
379    end.
380
381
382%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
383
384req_and_pending(suite) ->
385    [];
386req_and_pending(doc) ->
387    [];
388req_and_pending(Config) when is_list(Config) ->
389    Pre = fun() ->
390                  MgcNode = make_node_name(mgc),
391                  MgNode  = make_node_name(mg),
392                  d("try starting nodes: "
393                    "~n      MgcNode: ~p"
394                    "~n      MgNode:  ~p", [MgcNode, MgNode]),
395                  Nodes = [MgcNode, MgNode],
396                  ok    = ?START_NODES(Nodes),
397                  Nodes
398          end,
399    Case = fun do_req_and_pending/1,
400    Post = fun(Nodes) ->
401                   d("stop nodes (in the reverse order):"
402                     "~n       ~p", [Nodes]),
403                   ?STOP_NODES(lists:reverse(Nodes))
404           end,
405    try_tc(req_and_pending, Pre, Case, Post).
406
407do_req_and_pending([MgcNode, MgNode]) ->
408
409    %% Start the MGC and MGs
410    i("try start the MGC"),
411    ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}],
412    {ok, Mgc} =
413	?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, ?MGC_VERBOSITY),
414
415    i("try start the MG"),
416    {ok, Mg} =
417	?MG_START(MgNode, {deviceName, "mg"}, text, tcp, ?MG_VERBOSITY),
418
419    i("connect MG (to MFC)"),
420    Res1 = ?MG_SERV_CHANGE(Mg),
421    d("service change result: ~p", [Res1]),
422
423    sleep(1000),
424
425    i("[MGC] change request action to pending"),
426    {ok, _} = ?MGC_REQ_PEND(Mgc, 3500),
427
428    i("[MG] send notify request"),
429    {ok, Res2} = ?MG_NOTIF_RAR(Mg),
430    d("notify reply: ~p", [Res2]),
431
432    sleep(1000),
433
434    %% Tell MG to stop
435    i("stop the MG"),
436    ?MG_STOP(Mg),
437
438    %% Tell Mgc to stop
439    i("stop the MGC"),
440    ?MGC_STOP(Mgc),
441
442    i("done", []),
443    ok.
444
445
446
447%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
448
449req_and_cancel(suite) ->
450    [];
451req_and_cancel(doc) ->
452    [];
453req_and_cancel(Config) when is_list(Config) ->
454    Pre = fun() ->
455                  MgcNode = make_node_name(mgc),
456                  MgNode  = make_node_name(mg),
457                  d("try start nodes: "
458                    "~n      MgcNode: ~p"
459                    "~n      MgNode:  ~p",
460                    [MgcNode, MgNode]),
461                  Nodes = [MgcNode, MgNode],
462                  ok    = ?START_NODES(Nodes),
463                  Nodes
464          end,
465    Case = fun do_req_and_cancel/1,
466    Post = fun(Nodes) ->
467                   d("stop nodes (in the reverse order):"
468                     "~n       ~p", [Nodes]),
469                   ?STOP_NODES(lists:reverse(Nodes))
470           end,
471    try_tc(req_and_cancel, Pre, Case, Post).
472
473do_req_and_cancel([MgcNode, MgNode]) ->
474    %% Start the MGC and MGs
475    i("start the MGC"),
476    ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}],
477    {ok, Mgc} =
478	?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, ?MGC_VERBOSITY),
479
480    i("start the MG"),
481    {ok, Mg} =
482	?MG_START(MgNode, {deviceName, "mg"}, text, tcp, ?MG_VERBOSITY),
483
484    i("connect the MG"),
485    Res1 = ?MG_SERV_CHANGE(Mg),
486    d("service change result: ~p", [Res1]),
487
488
489    sleep(1000),
490
491    i("change request action to pending"),
492    {ok, _} = ?MGC_REQ_DISC(Mgc,5000),
493
494    i("send notify request"),
495    ?MG_NOTIF_REQ(Mg),
496
497    d("wait some to get it going",[]),
498    sleep(1000),
499
500    i("now cancel the notify request"),
501    ok = ?MG_CANCEL(Mg, req_and_cancel),
502
503    i("now await the notify request result"),
504    Res2 = ?MG_NOTIF_AR(Mg),
505    rac_analyze_result(Res2),
506
507
508    %% Tell MGs to stop
509    i("stop the MG"),
510    ?MG_STOP(Mg),
511
512    %% Tell Mgc to stop
513    i("stop the MGC"),
514    ?MGC_STOP(Mgc),
515
516    i("done", []),
517    ok.
518
519
520rac_analyze_result({ok, {_PV,Res}}) ->
521    i("rac_analyze_result -> notify request result:"
522      "~n      ~p", [Res]),
523    rac_analyze_result2(Res);
524rac_analyze_result(Unexpected) ->
525    e("rac_analyze_result -> unexpected result: "
526      "~n      ~p", [Unexpected]),
527    exit({unexpected_result, Unexpected}).
528
529rac_analyze_result2({error,{user_cancel, req_and_cancel}}) ->
530    ok;
531rac_analyze_result2([]) ->
532    ok;
533rac_analyze_result2([{error,{user_cancel, req_and_cancel}}|Res]) ->
534    rac_analyze_result2(Res);
535rac_analyze_result2([Unknown|_Res]) ->
536    e("rac_analyze_result2 -> unexpected result: "
537      "~n      ~p", [Unknown]),
538    exit({unknown_result, Unknown}).
539
540
541%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
542
543make_node_name(Name) ->
544    case string:tokens(atom_to_list(node()), [$@]) of
545	[_,Host] ->
546	    list_to_atom(lists:concat([atom_to_list(Name) ++ "@" ++ Host]));
547	_ ->
548	    exit("Test node must be started with '-sname'")
549     end.
550
551
552%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
553
554sleep(X) ->
555    receive after X -> ok end.
556
557
558%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
559
560try_tc(TCName, Pre, Case, Post) ->
561    try_tc(TCName, "TEST", ?TEST_VERBOSITY, Pre, Case, Post).
562
563try_tc(TCName, Name, Verbosity, Pre, Case, Post) ->
564    ?TRY_TC(TCName, Name, Verbosity, Pre, Case, Post).
565
566
567
568%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
569
570p(F, A) ->
571    io:format("*** [~s] ~p ***"
572	      "~n   " ++ F ++ "~n",
573	      [?FTS(), self() | A]).
574
575%% e(F) ->
576%%     i(F, []).
577
578e(F, A) ->
579    print(info, get(verbosity), "ERROR", get(tc), F, A).
580
581
582i(F) ->
583    i(F, []).
584
585i(F, A) ->
586    print(info, get(verbosity), "INFO", get(tc), F, A).
587
588
589%% d(F) ->
590%%     d(F, []).
591
592d(F, A) ->
593    print(debug, get(verbosity), "DBG", get(tc), F, A).
594
595
596printable(_, debug)   -> true;
597printable(info, info) -> true;
598printable(_,_)        -> false.
599
600print(Severity, Verbosity, P, TC, F, A) ->
601    print(printable(Severity,Verbosity), P, TC, F, A).
602
603print(true, P, TC, F, A) ->
604    io:format("*** [~s] [~s] ~p ~s:~w ***"
605	      "~n   " ++ F ++ "~n",
606	      [?FTS(), P, self(), get(sname), TC | A]);
607print(_, _, _, _, _) ->
608    ok.
609
610