1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2004-2019. 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 that it is possible to separately encode
24%%          the action requests list. Do this with all codec's
25%%          that supports partial encode.
26%%----------------------------------------------------------------------
27-module(megaco_actions_SUITE).
28
29-export([
30 	 suite/0, all/0, groups/0,
31         init_per_suite/1, end_per_suite/1,
32         init_per_group/2, end_per_group/2,
33         init_per_testcase/2, end_per_testcase/2,
34
35         pretty_text/1,
36         flex_pretty_text/1,
37         compact_text/1,
38         flex_compact_text/1,
39         erl_dist/1,
40         erl_dist_mc/1
41        ]).
42
43-include_lib("megaco/include/megaco.hrl").
44-include_lib("megaco/include/megaco_message_v1.hrl").
45-include("megaco_test_lib.hrl").
46
47-define(TEST_VERBOSITY, debug).
48-define(MGC_VERBOSITY,  debug).
49-define(MG_VERBOSITY,   debug).
50
51-define(LOAD_COUNTER_START, 10).
52-define(A4444, ["11111111", "00000000", "00000000"]).
53-define(A4445, ["11111111", "00000000", "11111111"]).
54-define(A5555, ["11111111", "11111111", "00000000"]).
55-define(A5556, ["11111111", "11111111", "11111111"]).
56
57-define(MGC_START(Pid, Mid, ET, Verb),
58	megaco_test_mgc:start(Pid, Mid, ET, Verb)).
59-define(MGC_STOP(Pid),          megaco_test_mgc:stop(Pid)).
60-define(MGC_GET_STATS(Pid, No), megaco_test_mgc:get_stats(Pid, No)).
61-define(MGC_RESET_STATS(Pid),   megaco_test_mgc:reset_stats(Pid)).
62-define(MGC_REQ_DISC(Pid,To),   megaco_test_mgc:request_discard(Pid,To)).
63-define(MGC_REQ_PEND(Pid,To),   megaco_test_mgc:request_pending(Pid,To)).
64-define(MGC_REQ_HAND(Pid),      megaco_test_mgc:request_handle(Pid)).
65
66-define(MG_START(Pid, Mid, Codec, EC, Transp, Verb),
67	megaco_test_mg:start(Pid, Mid, {Codec, EC}, Transp, Verb)).
68-define(MG_STOP(Pid),        megaco_test_mg:stop(Pid)).
69-define(MG_GET_STATS(Pid),   megaco_test_mg:get_stats(Pid)).
70-define(MG_RESET_STATS(Pid), megaco_test_mg:reset_stats(Pid)).
71-define(MG_SERV_CHANGE(Pid), megaco_test_mg:service_change(Pid)).
72-define(MG_NOTIF_RAR(Pid),   megaco_test_mg:notify_request_and_reply(Pid)).
73-define(MG_NOTIF_REQ(Pid),   megaco_test_mg:notify_request(Pid)).
74-define(MG_NOTIF_AR(Pid),    megaco_test_mg:await_notify_reply(Pid)).
75-define(MG_CANCEL(Pid,R),    megaco_test_mg:cancel_request(Pid,R)).
76-define(MG_APPLY_LOAD(Pid,CntStart), megaco_test_mg:apply_load(Pid,CntStart)).
77-define(MG_EAR(Pid, Val),    megaco_test_mg:encode_ar_first(Pid, Val)).
78
79
80%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
81
82%%======================================================================
83%% Common Test interface functions
84%%======================================================================
85
86suite() ->
87    [{ct_hooks, [ts_install_cth]}].
88
89all() ->
90    [
91     pretty_text,
92     flex_pretty_text,
93     compact_text,
94     flex_compact_text,
95     erl_dist,
96     erl_dist_mc
97    ].
98
99groups() ->
100    [].
101
102
103
104%%
105%% -----
106%%
107
108init_per_suite(suite) ->
109    [];
110init_per_suite(doc) ->
111    [];
112init_per_suite(Config0) when is_list(Config0) ->
113
114    ?ANNOUNCE_SUITE_INIT(),
115
116    p("init_per_suite -> entry with"
117      "~n      Config: ~p"
118      "~n      Nodes:  ~p", [Config0, erlang:nodes()]),
119
120    case ?LIB:init_per_suite(Config0) of
121        {skip, _} = SKIP ->
122            SKIP;
123
124        Config1 when is_list(Config1) ->
125
126            %% We need a (local) monitor on this node also
127            megaco_test_sys_monitor:start(),
128
129            p("init_per_suite -> end when"
130              "~n      Config: ~p"
131              "~n      Nodes:  ~p", [Config1, erlang:nodes()]),
132
133            Config1
134    end.
135
136end_per_suite(suite) -> [];
137end_per_suite(doc) -> [];
138end_per_suite(Config0) when is_list(Config0) ->
139
140    p("end_per_suite -> entry with"
141      "~n      Config: ~p"
142      "~n      Nodes:  ~p", [Config0, erlang:nodes()]),
143
144    megaco_test_sys_monitor:stop(),
145    Config1 = ?LIB:end_per_suite(Config0),
146
147    p("end_per_suite -> end when"
148      "~n      Nodes:  ~p", [erlang:nodes()]),
149
150    Config1.
151
152
153%%
154%% -----
155%%
156
157init_per_group(_GroupName, Config) ->
158    Config.
159
160end_per_group(_GroupName, Config) ->
161    Config.
162
163
164
165%%
166%% -----
167%%
168
169init_per_testcase(Case, Config) ->
170    process_flag(trap_exit, true),
171
172    p("init_per_suite -> entry with"
173      "~n      Config: ~p"
174      "~n      Nodes:  ~p", [Config, erlang:nodes()]),
175
176    megaco_test_global_sys_monitor:reset_events(),
177    megaco_test_lib:init_per_testcase(Case, Config).
178
179end_per_testcase(Case, Config) ->
180    process_flag(trap_exit, false),
181
182    p("end_per_suite -> entry with"
183      "~n      Config: ~p"
184      "~n      Nodes:  ~p", [Config, erlang:nodes()]),
185
186    p("system events during test: "
187      "~n   ~p", [megaco_test_global_sys_monitor:events()]),
188
189    megaco_test_lib:end_per_testcase(Case, Config).
190
191
192%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
193
194pretty_text(suite) ->
195    [];
196pretty_text(doc) ->
197    [];
198pretty_text(Config) when is_list(Config) ->
199    put(verbosity, ?TEST_VERBOSITY),
200    put(sname,     "TEST"),
201    i("pretty_text -> starting"),
202
203    Codec = pretty_text,
204    Version = 1,
205    EncodingConfig = [],
206    req_and_rep(Config, Codec, Version, EncodingConfig).
207
208
209flex_pretty_text(suite) ->
210    [];
211flex_pretty_text(doc) ->
212    [];
213flex_pretty_text(Config) when is_list(Config) ->
214    ?SKIP(not_implemented_yet).
215
216
217compact_text(suite) ->
218    [];
219compact_text(doc) ->
220    [];
221compact_text(Config) when is_list(Config) ->
222    put(verbosity, ?TEST_VERBOSITY),
223    put(sname,     "TEST"),
224    i("compact_text -> starting"),
225
226    Codec = compact_text,
227    Version = 1,
228    EncodingConfig = [],
229    req_and_rep(Config, Codec, Version, EncodingConfig).
230
231
232flex_compact_text(suite) ->
233    [];
234flex_compact_text(doc) ->
235    [];
236flex_compact_text(Config) when is_list(Config) ->
237    ?SKIP(not_implemented_yet).
238
239
240erl_dist(suite) ->
241    [];
242erl_dist(doc) ->
243    [];
244erl_dist(Config) when is_list(Config) ->
245    put(verbosity, ?TEST_VERBOSITY),
246    put(sname,     "TEST"),
247    i("erl_dist -> starting"),
248
249    Codec = erl_dist,
250    Version = 1,
251    EncodingConfig = [],
252    req_and_rep(Config, Codec, Version, EncodingConfig).
253
254
255erl_dist_mc(suite) ->
256    [];
257erl_dist_mc(doc) ->
258    [];
259erl_dist_mc(Config) when is_list(Config) ->
260    put(verbosity, ?TEST_VERBOSITY),
261    put(sname,     "TEST"),
262    i("erl_dist_mc -> starting"),
263
264    Codec = erl_dist,
265    Version = 1,
266    EncodingConfig = [megaco_compressed],
267    req_and_rep(Config, Codec, Version, EncodingConfig).
268
269
270%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
271
272req_and_rep(Config, Codec, _Version, EC) when is_list(Config) ->
273    put(verbosity, ?TEST_VERBOSITY),
274    put(sname,     "TEST"),
275    i("req_and_rep -> starting"),
276    MgcNode = make_node_name(mgc),
277    Mg1Node = make_node_name(mg1),
278    Mg2Node = make_node_name(mg2),
279    d("req_and_rep -> Nodes: "
280      "~n   MgcNode: ~p"
281      "~n   Mg1Node: ~p"
282      "~n   Mg2Node: ~p",
283      [MgcNode, Mg1Node, Mg2Node]),
284    ok = ?START_NODES([MgcNode, Mg1Node, Mg2Node]),
285
286    %% Start the MGC and MGs
287    i("req_and_rep -> start the MGC"),
288    ET = [{Codec, EC, tcp}, {Codec, EC, udp}],
289    {ok, Mgc} =
290	?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, ?MGC_VERBOSITY),
291
292    i("req_and_rep -> start and connect the MGs"),
293    MgConf0 = [{Mg1Node, "mg1", Codec, EC, tcp, ?MG_VERBOSITY},
294	       {Mg2Node, "mg2", Codec, EC, udp, ?MG_VERBOSITY}],
295    MgConf = connect_mg(MgConf0, []),
296
297    %% Collect the (initial) MGs statistics
298    Stats1 = get_mg_stats(MgConf, []),
299    d("req_and_rep -> stats for the MGs: ~n~p", [Stats1]),
300
301    %% Collect and check the MGC statistics
302    i("req_and_rep -> collect and check the MGC stats"),
303    {ok, MgcStats1} = ?MGC_GET_STATS(Mgc, 1),
304    d("req_and_rep  -> stats (1) for Mgc: ~n~p~n", [MgcStats1]),
305
306
307    sleep(1000),
308
309
310    %% And apply some load
311    i("req_and_rep -> apply traffic load"),
312    ok = apply_load(MgConf),
313
314    %% Await completion of load part and the collect traffic
315    i("req_and_rep -> await load completion"),
316    ok = await_load_complete(MgConf),
317
318
319    sleep(1000),
320
321
322    i("req_and_rep -> collect the MGs statistics"),
323    Stats2 = get_mg_stats(MgConf, []),
324    d("req_and_rep -> stats for MGs: ~n~p", [Stats2]),
325
326    i("req_and_rep -> collect the MGC statistics"),
327    {ok, MgcStats2} = ?MGC_GET_STATS(Mgc, 1),
328    d("req_and_rep  -> stats (1) for Mgc: ~n~p~n", [MgcStats2]),
329
330
331    sleep(1000),
332
333
334    %% Reset counters
335    i("req_and_rep -> reset the MGs statistics"),
336    reset_mg_stats(MgConf),
337    Stats3 = get_mg_stats(MgConf, []),
338    d("req_and_rep -> stats for the MGs: ~n~p", [Stats3]),
339
340    i("req_and_rep -> reset the MGC statistics"),
341    reset_mgc_stats(Mgc),
342    {ok, MgcStats3} = ?MGC_GET_STATS(Mgc, 1),
343    d("req_and_rep  -> stats (1) for Mgc: ~n~p~n", [MgcStats3]),
344
345
346    sleep(1000),
347
348
349    %% Tell MGs to stop
350    i("req_and_rep -> stop the MGs"),
351    stop_mg(MgConf),
352
353
354    sleep(1000),
355
356
357    %% Collect the statistics
358    i("req_and_rep -> collect the MGC statistics"),
359    {ok, MgcStats4} = ?MGC_GET_STATS(Mgc, 1),
360    d("req_and_rep -> stats (1) for Mgc: ~n~p~n", [MgcStats4]),
361    {ok, MgcStats5} = ?MGC_GET_STATS(Mgc, 2),
362    d("req_and_rep -> stats (2) for Mgc: ~n~p~n", [MgcStats5]),
363
364    %% Tell Mgc to stop
365    i("req_and_rep -> stop the MGC"),
366    ?MGC_STOP(Mgc),
367
368    i("req_and_rep -> done", []),
369    ok.
370
371
372connect_mg([], Acc) ->
373    lists:reverse(Acc);
374connect_mg([{Node, Name, Codec, EC, Trans, Verb}|Mg], Acc) ->
375    Pid = connect_mg(Node, Name, Codec, EC, Trans, Verb),
376    connect_mg(Mg, [{Name, Pid}|Acc]).
377
378connect_mg(Node, Name, Codec, EC, Trans, Verb) ->
379    Mid = {deviceName, Name},
380    {ok, Pid} = ?MG_START(Node, Mid, Codec, EC, Trans, Verb),
381
382    {ok, _} = ?MG_EAR(Pid, true),
383
384    %% Ask the MGs to do a service change
385    Res = ?MG_SERV_CHANGE(Pid),
386    d("connect_mg -> (~s) service change result: ~p", [Name,Res]),
387
388    Pid.
389
390
391stop_mg(MGs) ->
392    [?MG_STOP(Pid) || {_Name, Pid} <- MGs].
393
394
395get_mg_stats([], Acc) ->
396    lists:reverse(Acc);
397get_mg_stats([{Name, Pid}|Mgs], Acc) ->
398    {ok, Stats} = ?MG_GET_STATS(Pid),
399    d("get_mg_stats -> stats for ~s: ~n~p~n", [Name, Stats]),
400    get_mg_stats(Mgs, [{Name, Stats}|Acc]).
401
402
403apply_load([]) ->
404    ok;
405apply_load([{_, MG}|MGs]) ->
406    d("apply_load -> apply load to ~p", [MG]),
407    ?MG_APPLY_LOAD(MG,?LOAD_COUNTER_START),
408    apply_load(MGs).
409
410
411reset_mg_stats([]) ->
412    ok;
413reset_mg_stats([{Name, Pid}|MGs]) ->
414    d("reset_mg_stats -> resetting ~s", [Name]),
415    ?MG_RESET_STATS(Pid),
416    reset_mg_stats(MGs).
417
418reset_mgc_stats(Mgc) ->
419    d("reset_mgc_stats -> resetting ~p", [Mgc]),
420    ?MGC_RESET_STATS(Mgc).
421
422
423await_load_complete([]) ->
424    ok;
425await_load_complete(MGs0) ->
426    receive
427	{load_complete, Pid} ->
428	    d("received load_complete from ~p", [Pid]),
429	    MGs1 = lists:keydelete(Pid, 2, MGs0),
430	    await_load_complete(lists:delete(Pid, MGs1));
431	{'EXIT', Pid, Reason} ->
432	    i("exit signal from ~p: ~p", [Pid, Reason]),
433	    case lists:keymember(Pid, 2, MGs0) of
434		true ->
435		    exit({mg_exit, Pid, Reason});
436		false ->
437		    MGs1 = lists:keydelete(Pid, 2, MGs0),
438		    await_load_complete(lists:delete(Pid, MGs1))
439	    end;
440	Other ->
441	    d("received unexpected message: ~n~p", [Other]),
442	    await_load_complete(MGs0)
443    end.
444
445
446%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
447
448make_node_name(Name) ->
449    case string:tokens(atom_to_list(node()), [$@]) of
450	[_,Host] ->
451	    list_to_atom(lists:concat([atom_to_list(Name) ++ "@" ++ Host]));
452	_ ->
453	    exit("Test node must be started with '-sname'")
454     end.
455
456
457%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
458
459sleep(X) ->
460    receive after X -> ok end.
461
462
463%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
464
465i(F) ->
466    i(F, []).
467
468i(F, A) ->
469    print(info, get(verbosity), "", F, A).
470
471
472%% d(F) ->
473%%     d(F, []).
474
475d(F, A) ->
476    print(debug, get(verbosity), "DBG: ", F, A).
477
478
479printable(_, debug)   -> true;
480printable(info, info) -> true;
481printable(_,_)        -> false.
482
483print(Severity, Verbosity, P, F, A) ->
484    print(printable(Severity,Verbosity), P, F, A).
485
486print(true, P, F, A) ->
487    io:format("*** [~s] ~s ~p ~s ***"
488	      "~n   " ++ F ++ "~n",
489	      [?FTS(), P, self(), get(sname) | A]);
490print(_, _, _, _) ->
491    ok.
492
493
494p(F, A) ->
495    io:format("*** [~s] ~p ***"
496	      "~n   " ++ F ++ "~n",
497	      [?FTS(), self() | A]).
498