1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2000-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: Test application config
24%%----------------------------------------------------------------------
25
26-module(megaco_config_SUITE).
27
28-export([
29         suite/0, all/0, groups/0,
30	 init_per_suite/1,    end_per_suite/1,
31	 init_per_group/2,    end_per_group/2,
32	 init_per_testcase/2, end_per_testcase/2,
33
34         config/1,
35         transaction_id_counter_mg/1,
36         transaction_id_counter_mgc/1,
37         otp_7216/1,
38         otp_8167/1,
39         otp_8183/1
40        ]).
41
42-include_lib("megaco/include/megaco.hrl").
43-include_lib("megaco/src/app/megaco_internal.hrl").
44-include("megaco_test_lib.hrl").
45
46-record(command, {id, desc, cmd, verify}).
47
48-define(TEST_VERBOSITY, debug).
49-define(NUM_CNT_PROCS,  100).
50
51
52%%======================================================================
53%% Common Test interface functions
54%%======================================================================
55
56suite() ->
57    [{ct_hooks, [ts_install_cth]}].
58
59all() ->
60    [
61     config,
62     {group, transaction_id_counter},
63     {group, tickets}
64    ].
65
66groups() ->
67    [
68     {transaction_id_counter, [], transaction_id_counter_cases()},
69     {tickets,                [], tickets_cases()}
70    ].
71
72
73
74transaction_id_counter_cases() ->
75    [
76     transaction_id_counter_mg,
77     transaction_id_counter_mgc
78    ].
79
80tickets_cases() ->
81    [
82     otp_7216,
83     otp_8167,
84     otp_8183
85    ].
86
87
88
89%%
90%% -----
91%%
92
93init_per_suite(Config0) when is_list(Config0) ->
94
95    p("init_per_suite -> entry with"
96      "~n      Config: ~p"
97      "~n      Nodes:  ~p", [Config0, erlang:nodes()]),
98
99    case ?LIB:init_per_suite(Config0) of
100        {skip, _} = SKIP ->
101            SKIP;
102
103        Config1 when is_list(Config1) ->
104
105            %% We need a (local) monitor on this node also
106            megaco_test_sys_monitor:start(),
107
108            p("init_per_suite -> end when"
109              "~n      Config: ~p"
110              "~n      Nodes:  ~p", [Config1, erlang:nodes()]),
111
112            Config1
113    end.
114
115end_per_suite(Config0) when is_list(Config0) ->
116
117    p("end_per_suite -> entry with"
118      "~n      Config0: ~p"
119      "~n      Nodes:  ~p", [Config0, erlang:nodes()]),
120
121    megaco_test_sys_monitor:stop(),
122    Config1 = ?LIB:end_per_suite(Config0),
123
124    p("end_per_suite -> end when"
125      "~n      Nodes:  ~p", [erlang:nodes()]),
126    Config1.
127
128
129
130%%
131%% -----
132%%
133
134init_per_group(_GroupName, Config) ->
135    Config.
136
137end_per_group(_GroupName, Config) ->
138    Config.
139
140
141%%
142%% -----
143%%
144
145%% Test server callbacks
146init_per_testcase(Case, Config) when (Case =:= otp_7216) orelse
147                                     (Case =:= otp_8167) orelse
148                                     (Case =:= otp_8183) ->
149    i("init_per_testcase -> entry with"
150      "~n   Config: ~p"
151      "~n   Nodes:  ~p", [Config, erlang:nodes()]),
152
153    megaco_test_global_sys_monitor:reset_events(),
154
155    i("try starting megaco_config"),
156    case megaco_config:start_link() of
157        {ok, _} ->
158            C = lists:keydelete(tc_timeout, 1, Config),
159            do_init_per_testcase(Case, [{tc_timeout, min(3)}|C]);
160        {error, Reason} ->
161            i("Failed starting megaco_config: "
162              "~n   ~p", [Reason]),
163            {skip, ?F("Failed starting config: ~p", [Reason])}
164    end;
165init_per_testcase(Case, Config) ->
166    C = lists:keydelete(tc_timeout, 1, Config),
167    do_init_per_testcase(Case, [{tc_timeout, min(3)}|C]).
168
169do_init_per_testcase(Case, Config) ->
170    process_flag(trap_exit, true),
171    megaco_test_lib:init_per_testcase(Case, Config).
172
173min(M) -> timer:minutes(M).
174
175
176end_per_testcase(Case, Config) when (Case =:= otp_7216) orelse
177                                    (Case =:= otp_8167) orelse
178                                    (Case =:= otp_8183) ->
179    p("end_per_testcase -> entry with"
180      "~n   Config: ~p"
181      "~n   Nodes:  ~p", [Config, erlang:nodes()]),
182
183    p("system events during test: "
184      "~n   ~p", [megaco_test_global_sys_monitor:events()]),
185
186    (catch megaco_config:stop()),
187    process_flag(trap_exit, false),
188    megaco_test_lib:end_per_testcase(Case, Config);
189end_per_testcase(Case, Config) ->
190    process_flag(trap_exit, false),
191    megaco_test_lib:end_per_testcase(Case, Config).
192
193
194
195%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
196%% Config test case
197
198config(suite) ->
199    [];
200config(Config) when is_list(Config) ->
201    ?ACQUIRE_NODES(1, Config),
202    Mid = fake_mid,
203
204    %% Nice values
205    Int = 3,
206    IT  = #megaco_incr_timer{max_retries = Int},
207
208    %% Evil values
209    NonInt = non_int,
210    IT2 = #megaco_incr_timer{wait_for = NonInt},
211    IT3 = #megaco_incr_timer{factor = NonInt},
212    IT4 = #megaco_incr_timer{max_retries = NonInt},
213    IT5 = #megaco_incr_timer{max_retries = non_infinity},
214
215    %% Command range values
216    Initial = 100,
217    Verify  = 200,
218    Nice    = 300,
219    Evil    = 400,
220    End     = 500,
221
222    InitialCmd =
223	fun(No, Desc, Cmd, VerifyVal) ->
224		initial_command(Initial + No, Desc, Cmd, VerifyVal)
225	end,
226
227    VerifyCmd =
228	fun(M, No, Key, V) ->
229		verify_user_default_command(M, Verify + No, Key, V)
230	end,
231
232    NiceCmd =
233	fun(M, No, Key, Val) ->
234		nice_user_update_command(M, Nice + No, Key, Val)
235	end,
236
237    EvilCmd =
238	fun(M, No, Key, Val) ->
239		evil_user_update_command(M, Evil + No, Key, Val)
240	end,
241
242    %% End commands
243    ExitCmd =
244	fun(No, Desc, Cmd) ->
245		exit_command(End + No, Desc, Cmd)
246	end,
247    ErrorCmd =
248	fun(No, Desc, Cmd, MainReason, TS) ->
249		error_command(End + No, Desc, Cmd, MainReason, TS)
250	end,
251    PlainCmd =
252	fun(No, Desc, Cmd, V) ->
253		command(End + No, Desc, Cmd, V)
254	end,
255
256    Commands =
257	[
258	 %% Initial commands
259	 InitialCmd(0,
260		    "enable trace",
261		    fun() -> megaco:enable_trace(100, io) end,
262		    ok),
263	 InitialCmd(1,
264		    "start",
265		    fun() -> megaco:start() end,
266		    ok),
267	 InitialCmd(2,
268		    "Verify no active requests",
269		    fun() -> megaco:system_info(n_active_requests) end,
270		    0),
271	 InitialCmd(3,
272		    "Verify no active replies",
273		    fun() -> megaco:system_info(n_active_replies) end,
274		    0),
275	 InitialCmd(4,
276		    "Verify no active connections",
277		    fun() -> megaco:system_info(n_active_connections) end,
278		    0),
279	 InitialCmd(5,
280		    "Verify no connections",
281		    fun() -> megaco:system_info(connections) end,
282		    []),
283	 InitialCmd(6,
284		    "Verify no users",
285		    fun() -> megaco:system_info(users) end,
286		    []),
287	 InitialCmd(7,
288		    "Start user",
289		    fun() -> megaco:start_user(Mid, []) end,
290		    ok),
291
292
293	 %% Verify user defaults
294	 VerifyCmd(Mid,  1, connections, []),
295	 VerifyCmd(Mid,  2, min_trans_id, 1),
296	 VerifyCmd(Mid,  3, max_trans_id, infinity),
297	 VerifyCmd(Mid,  4, request_timer, #megaco_incr_timer{}),
298	 VerifyCmd(Mid,  5, long_request_timer, timer:seconds(60)),
299	 VerifyCmd(Mid,  6, auto_ack, false),
300	 VerifyCmd(Mid,  7, pending_timer, 30000),
301	 VerifyCmd(Mid,  8, reply_timer, 30000),
302	 VerifyCmd(Mid,  9, send_mod, megaco_tcp),
303	 VerifyCmd(Mid, 10, encoding_mod, megaco_pretty_text_encoder),
304	 VerifyCmd(Mid, 11, encoding_config, []),
305	 VerifyCmd(Mid, 12, protocol_version, 1),
306	 VerifyCmd(Mid, 13, reply_data, undefined),
307	 VerifyCmd(Mid, 14, receive_handle,
308		   fun(H) when is_record(H, megaco_receive_handle) ->
309			   {ok, H};
310		      (R)  ->
311			   {error, R}
312		   end),
313
314
315	 %% Nice update
316	 NiceCmd(Mid,  1, min_trans_id, Int),
317	 NiceCmd(Mid,  2, max_trans_id, Int),
318	 NiceCmd(Mid,  3, max_trans_id, infinity),
319	 NiceCmd(Mid,  4, request_timer, Int),
320	 NiceCmd(Mid,  5, request_timer, infinity),
321	 NiceCmd(Mid,  6, request_timer, IT),
322	 NiceCmd(Mid,  7, long_request_timer, Int),
323	 NiceCmd(Mid,  8, long_request_timer, infinity),
324	 NiceCmd(Mid,  9, long_request_timer, IT),
325	 NiceCmd(Mid, 10, auto_ack, true),
326	 NiceCmd(Mid, 11, auto_ack, false),
327	 NiceCmd(Mid, 12, pending_timer, Int),
328	 NiceCmd(Mid, 13, pending_timer, infinity),
329	 NiceCmd(Mid, 14, pending_timer, IT),
330	 NiceCmd(Mid, 15, reply_timer, Int),
331	 NiceCmd(Mid, 16, reply_timer, infinity),
332	 NiceCmd(Mid, 17, reply_timer, IT),
333	 NiceCmd(Mid, 18, send_mod, an_atom),
334	 NiceCmd(Mid, 19, encoding_mod, an_atom),
335	 NiceCmd(Mid, 20, encoding_config, []),
336	 NiceCmd(Mid, 21, protocol_version, Int),
337	 NiceCmd(Mid, 23, reply_data, IT),
338	 NiceCmd(Mid, 23, resend_indication, true),
339	 NiceCmd(Mid, 24, resend_indication, false),
340	 NiceCmd(Mid, 25, resend_indication, flag),
341
342
343	 %% Evil update
344	 EvilCmd(Mid,  1, min_trans_id, NonInt),
345	 EvilCmd(Mid,  2, max_trans_id, NonInt),
346	 EvilCmd(Mid,  3, max_trans_id, non_infinity),
347	 EvilCmd(Mid,  4, request_timer, NonInt),
348	 EvilCmd(Mid,  5, request_timer, non_infinity),
349	 EvilCmd(Mid,  6, request_timer, IT2),
350	 EvilCmd(Mid,  7, request_timer, IT3),
351	 EvilCmd(Mid,  8, request_timer, IT4),
352	 EvilCmd(Mid,  9, request_timer, IT5),
353	 EvilCmd(Mid, 10, long_request_timer, NonInt),
354	 EvilCmd(Mid, 11, long_request_timer, non_infinity),
355	 EvilCmd(Mid, 12, long_request_timer, IT2),
356	 EvilCmd(Mid, 13, long_request_timer, IT3),
357	 EvilCmd(Mid, 14, long_request_timer, IT4),
358	 EvilCmd(Mid, 15, long_request_timer, IT5),
359	 EvilCmd(Mid, 16, auto_ack, non_bool),
360	 EvilCmd(Mid, 17, pending_timer, NonInt),
361	 EvilCmd(Mid, 18, pending_timer, non_infinity),
362	 EvilCmd(Mid, 19, pending_timer, IT2),
363	 EvilCmd(Mid, 20, pending_timer, IT3),
364	 EvilCmd(Mid, 21, pending_timer, IT4),
365	 EvilCmd(Mid, 22, pending_timer, IT5),
366	 EvilCmd(Mid, 23, reply_timer, NonInt),
367	 EvilCmd(Mid, 24, reply_timer, non_infinity),
368	 EvilCmd(Mid, 25, reply_timer, IT2),
369	 EvilCmd(Mid, 26, reply_timer, IT3),
370	 EvilCmd(Mid, 27, reply_timer, IT4),
371	 EvilCmd(Mid, 28, reply_timer, IT5),
372	 EvilCmd(Mid, 29, send_mod, {non_atom}),
373	 EvilCmd(Mid, 30, encoding_mod, {non_atom}),
374	 EvilCmd(Mid, 31, encoding_config, non_list),
375	 EvilCmd(Mid, 32, protocol_version, NonInt),
376	 EvilCmd(Mid, 33, resend_indication, flagg),
377
378
379	 %% End
380	 ExitCmd(1, "Verify non-existing system info",
381		 fun() -> megaco:system_info(non_exist) end),
382	 ExitCmd(2, "Verify non-existing user user info",
383		 fun() -> megaco:user_info(non_exist, trans_id) end),
384	 ExitCmd(3, "Verify non-existing user info",
385		 fun() -> megaco:user_info(Mid, non_exist) end),
386
387	 ErrorCmd(4, "Try updating user info for non-existing user",
388		  fun() ->
389			  megaco:update_user_info(non_exist, trans_id, 1)
390		  end,
391		  no_such_user, 2),
392	 ErrorCmd(11, "Try updating non-existing user info",
393		  fun() ->
394			  megaco:update_user_info(Mid, trans_id, 4711)
395		  end,
396		  bad_user_val, 4),
397	 ErrorCmd(12, "Try start already started user",
398		  fun() -> megaco:start_user(Mid, []) end,
399		  user_already_exists, 2),
400
401	 PlainCmd(13, "Verify started users",
402		  fun() -> megaco:system_info(users) end, [Mid]),
403	 PlainCmd(14, "Stop user", fun() -> megaco:stop_user(Mid) end, ok),
404	 PlainCmd(15, "Verify started users",
405		  fun() -> megaco:system_info(users) end, []),
406	 ErrorCmd(16, "Try stop not started user",
407		  fun() -> megaco:stop_user(Mid) end, no_such_user, 2),
408	 ErrorCmd(17, "Try start megaco (it's already started)",
409		  fun() -> megaco:start() end, already_started, 2),
410	 PlainCmd(18, "Stop megaco", fun() -> megaco:stop() end, ok),
411	 ErrorCmd(19, "Try stop megaco (it's not running)",
412		  fun() -> megaco:stop() end, not_started, 2)
413	],
414
415
416    exec(Commands).
417
418
419
420exec([]) ->
421    ok;
422exec([#command{id     = No,
423	       desc   = Desc,
424	       cmd    = Cmd,
425	       verify = Verify}|Commands]) ->
426    io:format("Executing command ~3w: ~s: ", [No, Desc]),
427    case (catch Verify((catch Cmd()))) of
428	{ok, OK} ->
429	    io:format("ok => ~p~n", [OK]),
430	    exec(Commands);
431	{error, Reason} ->
432	    io:format("error => ~p~n", [Reason]),
433	    {error, {bad_result, No, Reason}};
434	Error ->
435	    io:format("exit => ~p~n", [Error]),
436	    {error, {unexpected_result, No, Error}}
437    end.
438
439initial_command(No, Desc0, Cmd, VerifyVal) when is_function(Cmd) ->
440    Desc = lists:flatten(io_lib:format("Initial - ~s", [Desc0])),
441    command(No, Desc, Cmd, VerifyVal).
442
443verify_user_default_command(Mid, No, Key, Verify) ->
444    Desc = lists:flatten(io_lib:format("Defaults - Verify ~w", [Key])),
445    Cmd = fun() -> megaco:user_info(Mid, Key) end,
446    command(No, Desc, Cmd, Verify).
447
448nice_user_update_command(Mid, No, Key, Val) ->
449    Desc = lists:flatten(io_lib:format("Nice - Update ~w", [Key])),
450    Cmd = fun() -> megaco:update_user_info(Mid, Key, Val) end,
451    Verify = fun(ok) ->
452		     case (catch megaco:user_info(Mid, Key)) of
453			 {'EXIT', R} ->
454			     {error, {value_retreival_failed, R}};
455			 Val ->
456			     {ok, Val};
457			 Invalid ->
458			     {error, {value_update_failed, Val, Invalid}}
459		     end;
460		(R)  ->
461		     {error, R}
462	     end,
463    command(No, Desc, Cmd, Verify).
464
465
466evil_user_update_command(Mid, No, Key, Val) ->
467    Desc = lists:flatten(io_lib:format("Evil - Update ~w", [Key])),
468    Cmd = fun() ->
469		  case (catch megaco:user_info(Mid, Key)) of
470		      {'EXIT', R} ->
471			  {{error, {old_value_retreival_failed, R}},
472			   ignore};
473		      OldVal ->
474			  {OldVal,
475			   (catch megaco:update_user_info(Mid, Key, Val))}
476		  end
477	  end,
478    Verify = fun({{error, _} = Error, ignore}) ->
479		     Error;
480		({OldVal, {error, {bad_user_val, _, _, _}}}) ->
481		     case (catch megaco:user_info(Mid, Key)) of
482			 {'EXIT', R} ->
483			     {error, {value_retreival_failed, R}};
484			 OldVal ->
485			     {ok, OldVal};
486			 Invalid ->
487			     {error, {value_update_failed, OldVal, Invalid}}
488		     end;
489		(R) ->
490		     {error, R}
491	     end,
492    command(No, Desc, Cmd, Verify).
493
494exit_command(No, Desc, Cmd) when is_function(Cmd) ->
495    Verify = fun({'EXIT', _} = E) ->
496		     {ok, E};
497		(R) ->
498		     {error, R}
499	     end,
500    command(No, Desc, Cmd, Verify).
501
502error_command(No, Desc, Cmd, MainReason, TS) when is_function(Cmd) ->
503    Verify = fun({error, Reason}) ->
504		     io:format("verify -> Reason: ~n~p~n", [Reason]),
505		     case Reason of
506			 {MainReason, _} when TS == 2 ->
507			     {ok, MainReason};
508			 {MainReason, _, _, _} when TS == 4 ->
509			     {ok, MainReason};
510			 _ ->
511			     {error, Reason}
512		     end;
513		(R) ->
514		     {error, R}
515	     end,
516    command(No, Desc, Cmd, Verify).
517
518command(No, Desc, Cmd, Verify)
519  when (is_integer(No) andalso
520	is_list(Desc) andalso
521	is_function(Cmd) andalso
522	is_function(Verify)) ->
523    #command{id     = No,
524	     desc   = Desc,
525	     cmd    = Cmd,
526	     verify = Verify};
527command(No, Desc, Cmd, VerifyVal)
528  when (is_integer(No) andalso
529	is_list(Desc) andalso
530	is_function(Cmd)) ->
531    Verify = fun(Val) ->
532		     case Val of
533			 VerifyVal ->
534			     {ok, Val};
535			 _ ->
536			     {error, Val}
537		     end
538	     end,
539    #command{id     = No,
540	     desc   = Desc,
541	     cmd    = Cmd,
542	     verify = Verify}.
543
544
545%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
546
547transaction_id_counter_mg(suite) ->
548    [];
549transaction_id_counter_mg(doc) ->
550    ["This test case is intended to test and verify the "
551     "transaction counter handling of the application "
552     "in with one connection (MG). "];
553transaction_id_counter_mg(Config) when is_list(Config) ->
554    put(verbosity, ?TEST_VERBOSITY),
555    put(sname,     "TEST"),
556    put(tc,        transaction_id_counter_mg),
557
558    process_flag(trap_exit, true),
559
560    i("starting"),
561
562    {ok, _ConfigPid} = megaco_config:start_link(),
563
564    %% Basic user data
565    UserMid = {deviceName, "mg"},
566    UserConfig = [
567		  {min_trans_id, 1}
568		 ],
569
570    %% Basic connection data
571    RemoteMid = {deviceName, "mgc"},
572    RecvHandle = #megaco_receive_handle{local_mid       = UserMid,
573					encoding_mod    = ?MODULE,
574					encoding_config = [],
575					send_mod        = ?MODULE},
576    SendHandle = dummy_send_handle,
577    ControlPid = self(),
578
579    %% Start user
580    i("start user"),
581    ok = megaco_config:start_user(UserMid, UserConfig),
582
583    %% Create connection
584    i("create connection"),
585    {ok, CD} =
586	megaco_config:connect(RecvHandle, RemoteMid, SendHandle, ControlPid),
587
588    %% Set counter limits
589    i("set counter max limit"),
590    CH = CD#conn_data.conn_handle,
591    megaco_config:update_conn_info(CH, max_trans_id, 1000),
592
593    %% Create the counter worker procs
594    i("create counter working procs"),
595    Pids = create_counter_working_procs(CH, ?NUM_CNT_PROCS, []),
596
597    %% Start the counter worker procs
598    i("release the counter working procs"),
599    start_counter_working_procs(Pids),
600
601    %% Await the counter worker procs termination
602    i("await the counter working procs completion"),
603    await_completion_counter_working_procs(Pids),
604
605    %% Verify result
606    i("verify counter result"),
607    TransId = megaco_config:conn_info(CH, trans_id),
608    1 = TransId,
609
610    %% Stop test
611    i("disconnect"),
612    {ok, _, _} = megaco_config:disconnect(CH),
613    i("stop user"),
614    ok = megaco_config:stop_user(UserMid),
615    i("stop megaco_config"),
616    ok = megaco_config:stop(),
617
618    i("done"),
619    ok.
620
621
622
623create_counter_working_procs(_CH, 0, Pids) ->
624    Pids;
625create_counter_working_procs(CH, N, Pids) ->
626    TC = get(tc),
627    Pid = erlang:spawn_link(fun() -> counter_init(CH, TC) end),
628    create_counter_working_procs(CH, N-1, [Pid | Pids]).
629
630counter_init(CH, TC) ->
631    put(verbosity, ?TEST_VERBOSITY),
632    put(sname,     lists:flatten(io_lib:format("CNT-~p", [self()]))),
633    put(tc,        TC),
634    UserMid = CH#megaco_conn_handle.local_mid,
635    Min = megaco_config:user_info(UserMid, min_trans_id),
636    Max = megaco_config:conn_info(CH, max_trans_id),
637    Num = Max - Min + 1,
638    receive
639	start ->
640	    %% i("received start command (~p)", [Num]),
641	    ok
642    end,
643    counter_loop(CH, Num).
644
645counter_loop(_CH, 0) ->
646    %% i("done"),
647    exit(normal);
648counter_loop(CH, Num) when (Num > 0) ->
649    megaco_config:incr_trans_id_counter(CH, 1),
650    counter_loop(CH, Num-1).
651
652start_counter_working_procs([]) ->
653    %% i("released"),
654    ok;
655start_counter_working_procs([Pid | Pids]) ->
656    Pid ! start,
657    start_counter_working_procs(Pids).
658
659await_completion_counter_working_procs([]) ->
660    ok;
661await_completion_counter_working_procs(Pids) ->
662    receive
663	{'EXIT', Pid, normal} ->
664	    Pids2 = lists:delete(Pid, Pids),
665	    await_completion_counter_working_procs(Pids2);
666	_Any ->
667	    await_completion_counter_working_procs(Pids)
668    end.
669
670
671%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
672
673transaction_id_counter_mgc(suite) ->
674    [];
675transaction_id_counter_mgc(doc) ->
676    ["This test case is intended to test and verify the "
677     "transaction counter handling of the application "
678     "in with several connections (MGC). "];
679transaction_id_counter_mgc(Config) when is_list(Config) ->
680    put(verbosity, ?TEST_VERBOSITY),
681    put(sname,     "TEST"),
682    put(tc,        transaction_id_counter_mgc),
683    process_flag(trap_exit, true),
684
685    i("starting"),
686
687    {ok, _ConfigPid} = megaco_config:start_link(),
688
689    %% Basic user data
690    UserMid = {deviceName, "mgc"},
691    UserConfig = [
692		  {min_trans_id, 1}
693		 ],
694
695    %% Basic connection data
696    RemoteMids =
697	[
698	 {deviceName, "mg01"},
699	 {deviceName, "mg02"},
700	 {deviceName, "mg03"},
701	 {deviceName, "mg04"},
702	 {deviceName, "mg05"},
703	 {deviceName, "mg06"},
704	 {deviceName, "mg07"},
705	 {deviceName, "mg08"},
706	 {deviceName, "mg09"},
707	 {deviceName, "mg10"}
708	],
709    RecvHandles =
710	[
711	 #megaco_receive_handle{local_mid     = UserMid,
712	 			encoding_mod    = ?MODULE,
713	 			encoding_config = [],
714	 			send_mod        = ?MODULE},
715	 #megaco_receive_handle{local_mid     = UserMid,
716	 			encoding_mod    = ?MODULE,
717	 			encoding_config = [],
718	 			send_mod        = ?MODULE},
719	 #megaco_receive_handle{local_mid     = UserMid,
720	 			encoding_mod    = ?MODULE,
721	 			encoding_config = [],
722	 			send_mod        = ?MODULE},
723	 #megaco_receive_handle{local_mid     = UserMid,
724	 			encoding_mod    = ?MODULE,
725	 			encoding_config = [],
726	 			send_mod        = ?MODULE},
727	 #megaco_receive_handle{local_mid     = UserMid,
728	 			encoding_mod    = ?MODULE,
729	 			encoding_config = [],
730	 			send_mod        = ?MODULE},
731	 #megaco_receive_handle{local_mid     = UserMid,
732	 			encoding_mod    = ?MODULE,
733	 			encoding_config = [],
734	 			send_mod        = ?MODULE},
735	 #megaco_receive_handle{local_mid     = UserMid,
736	 			encoding_mod    = ?MODULE,
737	 			encoding_config = [],
738	 			send_mod        = ?MODULE},
739	 #megaco_receive_handle{local_mid     = UserMid,
740	 			encoding_mod    = ?MODULE,
741	 			encoding_config = [],
742	 			send_mod        = ?MODULE},
743	 #megaco_receive_handle{local_mid     = UserMid,
744	 			encoding_mod    = ?MODULE,
745	 			encoding_config = [],
746	 			send_mod        = ?MODULE},
747	 #megaco_receive_handle{local_mid     = UserMid,
748				encoding_mod    = ?MODULE,
749				encoding_config = [],
750				send_mod        = ?MODULE}
751	],
752    SendHandle = dummy_send_handle,
753    ControlPid = self(),
754
755    %% Start user
756    i("start user"),
757    ok = megaco_config:start_user(UserMid, UserConfig),
758
759    %% Create connection
760    i("create connection(s)"),
761    CDs = create_connections(RecvHandles, RemoteMids, SendHandle, ControlPid),
762
763    %% Set counter limits
764    i("set counter max limit(s)"),
765    set_counter_max_limits(CDs, 1000),
766
767    %% Create the counter worker procs
768    i("create counter working procs"),
769    Pids = create_counter_working_procs(CDs, ?NUM_CNT_PROCS),
770
771    %% Start the counter worker procs
772    i("release the counter working procs"),
773    start_counter_working_procs(Pids),
774
775    %% Await the counter worker procs termination
776    i("await the counter working procs completion"),
777    await_completion_counter_working_procs(Pids),
778
779    %% Verify result
780    i("verify counter result"),
781    verify_counter_results(CDs),
782
783    %% Stop test
784    i("disconnect"),
785    delete_connections(CDs),
786    i("stop user"),
787    ok = megaco_config:stop_user(UserMid),
788    i("stop megaco_config"),
789    ok = megaco_config:stop(),
790
791    i("done"),
792    ok.
793
794create_connections(RecvHandles, RemoteMids, SendHandle, ControlPid) ->
795    create_connections(RecvHandles, RemoteMids, SendHandle, ControlPid, []).
796
797create_connections([], [], _SendHandle, _ControlPid, Acc) ->
798    lists:reverse(Acc);
799create_connections([RecvHandle | RecvHandles],
800		   [RemoteMid  | RemoteMids],
801		   SendHandle, ControlPid, Acc) ->
802    {ok, CD} =
803	megaco_config:connect(RecvHandle, RemoteMid, SendHandle, ControlPid),
804    create_connections(RecvHandles, RemoteMids,
805		       SendHandle, ControlPid, [CD | Acc]).
806
807
808set_counter_max_limits([], _MaxTransId) ->
809    ok;
810set_counter_max_limits([#conn_data{conn_handle = CH} | CDs], MaxTransId) ->
811    megaco_config:update_conn_info(CH, max_trans_id, MaxTransId),
812    set_counter_max_limits(CDs, MaxTransId).
813
814
815create_counter_working_procs(CDs, NumCntProcs) ->
816    lists:flatten(create_counter_working_procs2(CDs, NumCntProcs)).
817
818create_counter_working_procs2([], _NumCntProcs) ->
819    [];
820create_counter_working_procs2([#conn_data{conn_handle = CH} | CDs],
821			      NumCntProcs) ->
822    [create_counter_working_procs(CH, NumCntProcs, []) |
823     create_counter_working_procs2(CDs, NumCntProcs)].
824
825
826verify_counter_results([]) ->
827    ok;
828verify_counter_results([#conn_data{conn_handle = CH} | CDs]) ->
829    TransId = megaco_config:conn_info(CH, trans_id),
830    if
831	(TransId =:= 1) ->
832	    ok;
833	true ->
834	    ?ERROR({trans_id_verification_failed, CH, TransId})
835    end,
836    verify_counter_results(CDs).
837
838
839delete_connections([]) ->
840    ok;
841delete_connections([#conn_data{conn_handle = CH} | CDs]) ->
842    {ok, _, _} = megaco_config:disconnect(CH),
843    delete_connections(CDs).
844
845
846
847%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
848
849otp_7216(suite) ->
850    [];
851otp_7216(Config) when is_list(Config) ->
852    put(tc, otp_7216),
853    p("start"),
854
855    LocalMid1 = {deviceName, "local-mid-1"},
856    %% LocalMid2 = {deviceName, "local-mid-2"},
857    RemoteMid1 = {deviceName, "remote-mid-1"},
858    %% RemoteMid2 = {deviceName, "remote-mid-2"},
859    RH = #megaco_receive_handle{local_mid       = LocalMid1,
860				encoding_mod    = dummy_codec_module,
861				encoding_config = [],
862				send_mod        = dummy_transport_module},
863    MinTransId = 7216,
864    MaxTransId = MinTransId + 10,
865    User1Config = [{min_trans_id, MinTransId},
866		   {max_trans_id, MaxTransId}],
867
868    VerifySerial =
869	fun(Actual, Expected) ->
870		if
871		    Actual == Expected ->
872			ok;
873		    true ->
874			throw({error, {invalid_counter_value, Actual}})
875		end
876	end,
877
878    p("start local user: ~p", [LocalMid1]),
879    ok = megaco_config:start_user(LocalMid1, User1Config),
880
881    p("connect"),
882    {ok, CD} = megaco_config:connect(RH, RemoteMid1,
883				     dummy_send_handle, self()),
884    p("connect ok: CD = ~n~p", [CD]),
885    CH = CD#conn_data.conn_handle,
886
887
888    p("*** make the first counter increment ***"),
889    {ok, CD01} = megaco_config:incr_trans_id_counter(CH, 1),
890    Serial01   = CD01#conn_data.serial,
891    p("serial: ~p", [Serial01]),
892    VerifySerial(Serial01, MinTransId),
893    p("counter increment 1 ok"),
894
895
896    p("*** make two more counter increments ***"),
897    {ok, _} = megaco_config:incr_trans_id_counter(CH, 1),
898    {ok, CD02} = megaco_config:incr_trans_id_counter(CH, 1),
899    Serial02   = CD02#conn_data.serial,
900    p("serial: ~p", [Serial02]),
901    VerifySerial(Serial02, MinTransId+2),
902    p("counter increment 2 ok"),
903
904
905    p("*** make a big counter increment ***"),
906    {ok, CD03} = megaco_config:incr_trans_id_counter(CH, 8),
907    Serial03   = CD03#conn_data.serial,
908    p("serial: ~p", [Serial03]),
909    VerifySerial(Serial03, MinTransId+2+8),
910    p("counter increment 3 ok"),
911
912
913    p("*** make a wrap-around counter increment ***"),
914    {ok, CD04} = megaco_config:incr_trans_id_counter(CH, 1),
915    Serial04   = CD04#conn_data.serial,
916    p("serial: ~p", [Serial04]),
917    VerifySerial(Serial04, MinTransId),
918    p("counter increment 4 ok"),
919
920
921    p("*** make a big counter increment ***"),
922    {ok, CD05} = megaco_config:incr_trans_id_counter(CH, 10),
923    Serial05   = CD05#conn_data.serial,
924    p("serial: ~p", [Serial05]),
925    VerifySerial(Serial05, MinTransId+10),
926    p("counter increment 5 ok"),
927
928
929    p("*** make a big wrap-around counter increment ***"),
930    {ok, CD06} = megaco_config:incr_trans_id_counter(CH, 3),
931    Serial06   = CD06#conn_data.serial,
932    p("serial: ~p", [Serial06]),
933    VerifySerial(Serial06, MinTransId+(3-1)),
934    p("counter increment 6 ok"),
935
936
937    p("*** make a big counter increment ***"),
938    {ok, CD07} = megaco_config:incr_trans_id_counter(CH, 7),
939    Serial07   = CD07#conn_data.serial,
940    p("serial: ~p", [Serial07]),
941    VerifySerial(Serial07, MinTransId+(3-1)+7),
942    p("counter increment 7 ok"),
943
944
945    p("*** make a big wrap-around counter increment ***"),
946    {ok, CD08} = megaco_config:incr_trans_id_counter(CH, 5),
947    Serial08   = CD08#conn_data.serial,
948    p("serial: ~p", [Serial08]),
949    VerifySerial(Serial08, MinTransId+(5-1-1)),
950    p("counter increment 8 ok"),
951
952
953    p("disconnect"),
954    {ok, CD, RCD} = megaco_config:disconnect(CH),
955    p("disconnect ok: RCD = ~n~p", [RCD]),
956
957    p("stop user"),
958    ok = megaco_config:stop_user(LocalMid1),
959
960    p("stop megaco config process"),
961    megaco_config:stop(),
962
963    p("done"),
964    ok.
965
966
967%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
968
969otp_8167(suite) ->
970    [];
971otp_8167(Config) when is_list(Config) ->
972    put(tc, otp8167),
973    p("start"),
974
975    LocalMid1  = {deviceName, "local-mid-1"},
976    LocalMid2  = {deviceName, "local-mid-2"},
977    RemoteMid1 = {deviceName, "remote-mid-1"},
978    %% RemoteMid2 = {deviceName, "remote-mid-2"},
979    RH1 = #megaco_receive_handle{local_mid       = LocalMid1,
980				 encoding_mod    = dummy_codec_module,
981				 encoding_config = [],
982				 send_mod        = dummy_transport_module},
983%%     RH2 = #megaco_receive_handle{local_mid       = LocalMid2,
984%% 				 encoding_mod    = dummy_codec_module,
985%% 				 encoding_config = [],
986%% 				 send_mod        = dummy_transport_module},
987
988    User1ConfigA = [{call_proxy_gc_timeout, 1}],
989    User1ConfigB = [{call_proxy_gc_timeout, 0}],
990    User2ConfigA = [{call_proxy_gc_timeout, -1}],
991    User2ConfigB = [{call_proxy_gc_timeout, infinity}],
992    User2ConfigC = [{call_proxy_gc_timeout, "1"}],
993    User2ConfigD = [{call_proxy_gc_timeout, 1.0}],
994
995    p("start local user (1A): ~p", [LocalMid1]),
996    ok = megaco_config:start_user(LocalMid1, User1ConfigA),
997    p("stop local user (1A): ~p", [LocalMid1]),
998    ok = megaco_config:stop_user(LocalMid1),
999
1000    p("start local user (1B): ~p", [LocalMid1]),
1001    ok = megaco_config:start_user(LocalMid1, User1ConfigB),
1002    p("try (and fail) change value for item call_proxy_gc_timeout for local user: ~p -> ~p",
1003      [LocalMid1, -1]),
1004    {error, {bad_user_val, LocalMid1, call_proxy_gc_timeout, -1}} =
1005	megaco_config:update_user_info(LocalMid1, call_proxy_gc_timeout, -1),
1006    p("try (and fail) change value for item call_proxy_gc_timeout for local user: ~p -> ~p",
1007      [LocalMid1, infinity]),
1008    {error, {bad_user_val, LocalMid1, call_proxy_gc_timeout, infinity}} =
1009	megaco_config:update_user_info(LocalMid1, call_proxy_gc_timeout, infinity),
1010    p("try (and fail) change value for item call_proxy_gc_timeout for local user: ~p -> ~p",
1011      [LocalMid1, "1"]),
1012    {error, {bad_user_val, LocalMid1, call_proxy_gc_timeout, "1"}} =
1013	megaco_config:update_user_info(LocalMid1, call_proxy_gc_timeout, "1"),
1014    p("try (and fail) change value for item call_proxy_gc_timeout for local user: ~p -> ~p",
1015      [LocalMid1, 1.0]),
1016    {error, {bad_user_val, LocalMid1, call_proxy_gc_timeout, 1.0}} =
1017	megaco_config:update_user_info(LocalMid1, call_proxy_gc_timeout, 1.0),
1018    p("change value for item call_proxy_gc_timeout for local user: ~p", [LocalMid1]),
1019    ok = megaco_config:update_user_info(LocalMid1, call_proxy_gc_timeout, 10101),
1020
1021    p("connect"),
1022    {ok, CD} = megaco_config:connect(RH1, RemoteMid1,
1023				     dummy_send_handle, self()),
1024    p("connect ok: CD = ~n~p", [CD]),
1025    CH = CD#conn_data.conn_handle,
1026
1027    p("get value for item cancel from connection: ~p", [CH]),
1028    false = megaco_config:conn_info(CH, cancel),
1029
1030    p("get value for item cancel from connection data", []),
1031    false = megaco_config:conn_info(CD, cancel),
1032
1033    p("get value for item call_proxy_gc_timeout for connection: ~p", [CH]),
1034    10101 = megaco_config:conn_info(CH, call_proxy_gc_timeout),
1035
1036    p("change value for item call_proxy_gc_timeout for connection: ~p -> ~p",
1037      [CH, 20202]),
1038    ok = megaco_config:update_conn_info(CH, call_proxy_gc_timeout, 20202),
1039
1040    p("try (and fail) change value for item call_proxy_gc_timeout for connection: ~p -> ~p",
1041      [CH, -1]),
1042    {error, {bad_user_val, LocalMid1, call_proxy_gc_timeout, -1}} =
1043	megaco_config:update_conn_info(CH, call_proxy_gc_timeout, -1),
1044
1045    p("try (and fail) change value for item call_proxy_gc_timeout for connection: ~p -> ~p",
1046      [CH, infinity]),
1047    {error, {bad_user_val, LocalMid1, call_proxy_gc_timeout, infinity}} =
1048	megaco_config:update_conn_info(CH, call_proxy_gc_timeout, infinity),
1049
1050    p("try (and fail) change value for item call_proxy_gc_timeout for connection: ~p -> ~p",
1051      [CH, "1"]),
1052    {error, {bad_user_val, LocalMid1, call_proxy_gc_timeout, "1"}} =
1053	megaco_config:update_conn_info(CH, call_proxy_gc_timeout, "1"),
1054
1055    p("try (and fail) change value for item call_proxy_gc_timeout for connection: ~p -> ~p",
1056      [CH, 1.0]),
1057    {error, {bad_user_val, LocalMid1, call_proxy_gc_timeout, 1.0}} =
1058	megaco_config:update_conn_info(CH, call_proxy_gc_timeout, 1.0),
1059
1060    p("disconnect: ~p", [CH]),
1061    {ok, _, _} = megaco_config:disconnect(CH),
1062
1063    p("stop local user (1B): ~p", [LocalMid1]),
1064    ok = megaco_config:stop_user(LocalMid1),
1065
1066    p("try (and fail) start local user (2A): ~p", [LocalMid2]),
1067    {error, {bad_user_val, LocalMid2, call_proxy_gc_timeout, -1}} =
1068	megaco_config:start_user(LocalMid2, User2ConfigA),
1069
1070    p("try (and fail) start local user (2B): ~p", [LocalMid2]),
1071    {error, {bad_user_val, LocalMid2, call_proxy_gc_timeout, infinity}} =
1072	megaco_config:start_user(LocalMid2, User2ConfigB),
1073
1074    p("try (and fail) start local user (2C): ~p", [LocalMid2]),
1075    {error, {bad_user_val, LocalMid2, call_proxy_gc_timeout, "1"}} =
1076	megaco_config:start_user(LocalMid2, User2ConfigC),
1077
1078    p("try (and fail) start local user (2D): ~p", [LocalMid2]),
1079    {error, {bad_user_val, LocalMid2, call_proxy_gc_timeout, 1.0}} =
1080	megaco_config:start_user(LocalMid2, User2ConfigD),
1081
1082    p("done"),
1083    ok.
1084
1085
1086%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1087
1088otp_8183(suite) ->
1089    [];
1090otp_8183(Config) when is_list(Config) ->
1091    put(tc, otp8183),
1092    p("start"),
1093
1094    LocalMid1  = {deviceName, "local-mid-1"},
1095    LocalMid2  = {deviceName, "local-mid-2"},
1096    RemoteMid1 = {deviceName, "remote-mid-1"},
1097%%     RemoteMid2 = {deviceName, "remote-mid-2"},
1098    RH1 = #megaco_receive_handle{local_mid       = LocalMid1,
1099				 encoding_mod    = dummy_codec_module,
1100				 encoding_config = [],
1101				 send_mod        = dummy_transport_module},
1102%%     RH2 = #megaco_receive_handle{local_mid       = LocalMid2,
1103%% 				 encoding_mod    = dummy_codec_module,
1104%% 				 encoding_config = [],
1105%% 				 send_mod        = dummy_transport_module},
1106
1107    OkValA = 100,
1108    OkValB = 0,
1109    OkValC = plain,
1110    OkValD = 10101,
1111    OkValE = 20202,
1112    BadValA = -1,
1113    BadValB = pain,
1114    BadValC = "1",
1115    BadValD = 1.0,
1116    User1ConfigA = [{request_keep_alive_timeout, OkValA}],
1117    User1ConfigB = [{request_keep_alive_timeout, OkValB}],
1118    User1ConfigC = [{request_keep_alive_timeout, OkValC}],
1119    User2ConfigA = [{request_keep_alive_timeout, BadValA}],
1120    User2ConfigB = [{request_keep_alive_timeout, BadValB}],
1121    User2ConfigC = [{request_keep_alive_timeout, BadValC}],
1122    User2ConfigD = [{request_keep_alive_timeout, BadValD}],
1123
1124    p("start local user (1A): ~p", [LocalMid1]),
1125    ok = megaco_config:start_user(LocalMid1, User1ConfigA),
1126    p("stop local user (1A): ~p", [LocalMid1]),
1127    ok = megaco_config:stop_user(LocalMid1),
1128
1129    p("start local user (1B): ~p", [LocalMid1]),
1130    ok = megaco_config:start_user(LocalMid1, User1ConfigB),
1131    p("stop local user (1B): ~p", [LocalMid1]),
1132    ok = megaco_config:stop_user(LocalMid1),
1133
1134    p("start local user (1C): ~p", [LocalMid1]),
1135    ok = megaco_config:start_user(LocalMid1, User1ConfigC),
1136
1137    p("try (and fail) change value for item call_proxy_gc_timeout for local user: ~p -> ~p",
1138      [LocalMid1, BadValA]),
1139    {error, {bad_user_val, LocalMid1, request_keep_alive_timeout, BadValA}} =
1140	megaco_config:update_user_info(LocalMid1, request_keep_alive_timeout, BadValA),
1141
1142    p("try (and fail) change value for item request_keep_alive_timeout for local user: ~p -> ~p",
1143      [LocalMid1, BadValB]),
1144    {error, {bad_user_val, LocalMid1, request_keep_alive_timeout, BadValB}} =
1145	megaco_config:update_user_info(LocalMid1, request_keep_alive_timeout, BadValB),
1146
1147    p("try (and fail) change value for item request_keep_alive_timeout for local user: ~p -> ~p",
1148      [LocalMid1, BadValC]),
1149    {error, {bad_user_val, LocalMid1, request_keep_alive_timeout, BadValC}} =
1150	megaco_config:update_user_info(LocalMid1, request_keep_alive_timeout, BadValC),
1151
1152    p("try (and fail) change value for item request_keep_alive_timeout for local user: ~p -> ~p",
1153      [LocalMid1, BadValD]),
1154    {error, {bad_user_val, LocalMid1, request_keep_alive_timeout, BadValD}} =
1155	megaco_config:update_user_info(LocalMid1, request_keep_alive_timeout, BadValD),
1156
1157    p("change value for item request_keep_alive_timeout for local user: ~p", [LocalMid1]),
1158    ok = megaco_config:update_user_info(LocalMid1, request_keep_alive_timeout, OkValD),
1159
1160    p("connect"),
1161    {ok, CD} = megaco_config:connect(RH1, RemoteMid1,
1162				     dummy_send_handle, self()),
1163    p("connect ok: CD = ~n~p", [CD]),
1164    CH = CD#conn_data.conn_handle,
1165
1166    p("get value for item request_keep_alive_timeout for connection: ~p", [CH]),
1167    OkValD = megaco_config:conn_info(CH, request_keep_alive_timeout),
1168
1169    p("change value for item request_keep_alive_timeout for connection: ~p -> ~p",
1170      [CH, OkValE]),
1171    ok = megaco_config:update_conn_info(CH, request_keep_alive_timeout, OkValE),
1172
1173    p("try (and fail) change value for item request_keep_alive_timeout for connection: ~p -> ~p",
1174      [CH, BadValA]),
1175    {error, {bad_user_val, LocalMid1, request_keep_alive_timeout, BadValA}} =
1176	megaco_config:update_conn_info(CH, request_keep_alive_timeout, BadValA),
1177
1178    p("try (and fail) change value for item request_keep_alive_timeout for connection: ~p -> ~p",
1179      [CH, BadValB]),
1180    {error, {bad_user_val, LocalMid1, request_keep_alive_timeout, BadValB}} =
1181	megaco_config:update_conn_info(CH, request_keep_alive_timeout, BadValB),
1182
1183    p("try (and fail) change value for item request_keep_alive_timeout for connection: ~p -> ~p",
1184      [CH, BadValC]),
1185    {error, {bad_user_val, LocalMid1, request_keep_alive_timeout, BadValC}} =
1186	megaco_config:update_conn_info(CH, request_keep_alive_timeout, BadValC),
1187
1188    p("try (and fail) change value for item request_keep_alive_timeout for connection: ~p -> ~p",
1189      [CH, BadValD]),
1190    {error, {bad_user_val, LocalMid1, request_keep_alive_timeout, BadValD}} =
1191	megaco_config:update_conn_info(CH, request_keep_alive_timeout, BadValD),
1192
1193    p("disconnect: ~p", [CH]),
1194    {ok, _, _} = megaco_config:disconnect(CH),
1195
1196    p("stop local user (1B): ~p", [LocalMid1]),
1197    ok = megaco_config:stop_user(LocalMid1),
1198
1199    p("try (and fail) start local user (2A): ~p", [LocalMid2]),
1200    {error, {bad_user_val, LocalMid2, request_keep_alive_timeout, BadValA}} =
1201	megaco_config:start_user(LocalMid2, User2ConfigA),
1202
1203    p("try (and fail) start local user (2B): ~p", [LocalMid2]),
1204    {error, {bad_user_val, LocalMid2, request_keep_alive_timeout, BadValB}} =
1205	megaco_config:start_user(LocalMid2, User2ConfigB),
1206
1207    p("try (and fail) start local user (2C): ~p", [LocalMid2]),
1208    {error, {bad_user_val, LocalMid2, request_keep_alive_timeout, BadValC}} =
1209	megaco_config:start_user(LocalMid2, User2ConfigC),
1210
1211    p("try (and fail) start local user (2D): ~p", [LocalMid2]),
1212    {error, {bad_user_val, LocalMid2, request_keep_alive_timeout, BadValD}} =
1213	megaco_config:start_user(LocalMid2, User2ConfigD),
1214
1215    p("done"),
1216    ok.
1217
1218
1219%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1220
1221p(F) ->
1222    p(F, []).
1223
1224p(F, A) ->
1225    case get(tc) of
1226        undefined ->
1227            io:format(F ++ "~n", A);
1228        TC ->
1229            io:format("[~w] " ++ F ++ "~n", [TC|A])
1230    end.
1231
1232
1233i(F) ->
1234    i(F, []).
1235
1236i(F, A) ->
1237    print(info, get(verbosity), get(tc), "INF", F, A).
1238
1239printable(_, debug)   -> true;
1240printable(info, info) -> true;
1241printable(_,_)        -> false.
1242
1243print(Severity, Verbosity, Tc, P, F, A) ->
1244    print(printable(Severity,Verbosity), Tc, P, F, A).
1245
1246print(true, Tc, P, F, A) ->
1247    io:format("*** [~s] ~s ~p ~s:~w ***"
1248              "~n   " ++ F ++ "~n",
1249              [?FTS(), P, self(), get(sname), Tc | A]);
1250print(_, _, _, _, _) ->
1251    ok.
1252