1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2000-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:
24%%----------------------------------------------------------------------
25-module(megaco_tcp_SUITE).
26
27%%----------------------------------------------------------------------
28%% Include files
29%%----------------------------------------------------------------------
30-include_lib("megaco/src/tcp/megaco_tcp.hrl").
31-include("megaco_test_lib.hrl").
32
33
34%%----------------------------------------------------------------------
35%% External exports
36%%----------------------------------------------------------------------
37-export([
38	 suite/0, all/0, groups/0,
39	 init_per_suite/1,    end_per_suite/1,
40         init_per_group/2,    end_per_group/2,
41	 init_per_testcase/2, end_per_testcase/2,
42
43	 start_normal/1,
44	 start_invalid_opt/1,
45	 start_and_stop/1,
46	 sendreceive/1,
47	 block_unblock/1,
48	 socket_failure/1,
49	 accept_process/1,
50	 accept_supervisor/1,
51	 connection_supervisor/1,
52	 tcp_server/1
53
54        ]).
55
56%%----------------------------------------------------------------------
57%% Internal exports
58%%----------------------------------------------------------------------
59
60-export([
61	 receive_message/4,
62	 process_received_message/4
63        ]).
64
65
66%%----------------------------------------------------------------------
67%% Macros
68%%----------------------------------------------------------------------
69
70-define(CH,             megaco_test_command_handler).
71-define(TEST_VERBOSITY, debug).
72
73
74%%----------------------------------------------------------------------
75%% Records
76%%----------------------------------------------------------------------
77
78
79%%======================================================================
80%% Common Test interface functions
81%%======================================================================
82
83suite() ->
84    [{ct_hooks, [ts_install_cth]}].
85
86all() ->
87    [
88     {group, start},
89     {group, sending},
90     {group, error}
91    ].
92
93groups() ->
94    [
95     {start,   [], start_cases()},
96     {sending, [], sending_cases()},
97     {error,   [], error_cases()}
98    ].
99
100start_cases() ->
101    [
102     start_normal,
103     start_invalid_opt,
104     start_and_stop
105    ].
106
107sending_cases() ->
108    [
109     sendreceive,
110     block_unblock
111    ].
112
113error_cases() ->
114    [
115     socket_failure,
116     accept_process,
117     accept_supervisor,
118     connection_supervisor,
119     tcp_server
120    ].
121
122
123%%
124%% -----
125%%
126
127init_per_suite(suite) ->
128    [];
129init_per_suite(doc) ->
130    [];
131init_per_suite(Config0) when is_list(Config0) ->
132
133    ?ANNOUNCE_SUITE_INIT(),
134
135    p("init_per_suite -> entry with"
136      "~n      Config: ~p"
137      "~n      Nodes:  ~p", [Config0, erlang:nodes()]),
138
139    case ?LIB:init_per_suite(Config0) of
140        {skip, _} = SKIP ->
141            SKIP;
142
143        Config1 when is_list(Config1) ->
144
145            %% We need a (local) monitor on this node also
146            megaco_test_sys_monitor:start(),
147
148            p("init_per_suite -> end when"
149              "~n      Config: ~p"
150              "~n      Nodes:  ~p", [Config1, erlang:nodes()]),
151
152            Config1
153    end.
154
155end_per_suite(suite) -> [];
156end_per_suite(doc) -> [];
157end_per_suite(Config0) when is_list(Config0) ->
158
159    p("end_per_suite -> entry with"
160      "~n      Config: ~p"
161      "~n      Nodes:  ~p", [Config0, erlang:nodes()]),
162
163    megaco_test_sys_monitor:stop(),
164    Config1 = ?LIB:end_per_suite(Config0),
165
166    p("end_per_suite -> end when"
167      "~n      Nodes:  ~p", [erlang:nodes()]),
168
169    Config1.
170
171
172%%
173%% -----
174%%
175
176init_per_group(Group, Config) ->
177    ?ANNOUNCE_GROUP_INIT(Group),
178    Config.
179
180end_per_group(_GroupName, Config) ->
181    Config.
182
183
184%%
185%% -----
186%%
187
188init_per_testcase(Case, Config) ->
189
190    p("init_per_testcase -> entry with"
191      "~n   Config: ~p"
192      "~n   Nodes:  ~p", [Config, erlang:nodes()]),
193
194    megaco_test_global_sys_monitor:reset_events(),
195
196    megaco_test_lib:init_per_testcase(Case, Config).
197
198end_per_testcase(Case, Config) ->
199
200    p("end_per_testcase -> entry with"
201      "~n   Config: ~p"
202      "~n   Nodes:  ~p", [Config, erlang:nodes()]),
203
204    p("system events during test: "
205      "~n   ~p", [megaco_test_global_sys_monitor:events()]),
206
207    megaco_test_lib:end_per_testcase(Case, Config).
208
209
210
211
212%% ------------------ start ------------------------
213
214%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
215
216start_normal(suite) ->
217    [];
218start_normal(Config) when is_list(Config) ->
219    put(sname, "start_normal"),
220    p("BEGIN TEST-CASE"),
221    Options = [{port, 20000}, {receive_handle, apa}],
222    {ok, Pid} = start_case(Options, ok),
223    megaco_tcp:stop_transport(Pid),
224    p("done"),
225    ok.
226
227
228%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
229
230start_invalid_opt(suite) ->
231    [];
232start_invalid_opt(Config) when is_list(Config) ->
233    put(sname, "start_invalid_opt"),
234    p("BEGIN TEST-CASE"),
235    Options = [{port, 20000}, {receivehandle, apa}],
236    ok = start_case(Options, error),
237    p("done"),
238    ok.
239
240
241%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
242
243start_and_stop(suite) ->
244    [];
245start_and_stop(doc) ->
246    ["This test case sets up a connection and then cloises it. "
247     "No data is sent. "];
248start_and_stop(Config) when is_list(Config) ->
249    Pre = fun() ->
250		  p("create nodes"),
251		  ServerNode = make_node_name(server),
252		  ClientNode = make_node_name(client),
253		  Nodes = [ServerNode, ClientNode],
254		  ok = ?START_NODES(Nodes),
255		  Nodes
256	  end,
257    Case = fun do_start_and_stop/1,
258    Post = fun(Nodes) ->
259                   p("stop nodes"),
260                   ?STOP_NODES(lists:reverse(Nodes))
261           end,
262    try_tc(start_and_stop, Pre, Case, Post).
263
264do_start_and_stop([ServerNode, ClientNode]) ->
265    %% Create command sequences
266    p("create command sequences"),
267    ServerPort = 2944,
268    ServerCmds = start_and_stop_server_commands(ServerPort),
269    {ok, ServerHost} = inet:gethostname(),
270    ClientCmds = start_and_stop_client_commands(ServerPort, ServerHost),
271
272    %% Start the test procs used in the test-case, one for each node
273    p("start command handlers"),
274    Server = server_start_command_handler(ServerNode, ServerCmds),
275    p("server command handler started: ~p", [Server]),
276    Client = client_start_command_handler(ClientNode, ClientCmds),
277    p("client command handler started: ~p", [Client]),
278
279    await_server_listening(Server, Client),
280
281    ok = await_command_handler_completion([Server, Client], ?SECS(20)),
282    p("done"),
283    ok.
284
285
286start_and_stop_server_commands(Port) ->
287    Opts = [{port, Port}],
288    Self = self(),
289    [
290     #{id   => 1,
291       desc => "Command sequence init",
292       cmd  => fun(State) ->
293		      {ok, State#{parent => Self}}
294	      end},
295
296     #{id   => 2,
297       desc => "Start transport",
298       cmd  => fun(State) ->
299		      server_start_transport(State)
300	      end},
301
302     #{id   => 3,
303       desc => "Listen",
304       cmd  => fun(State) ->
305		      server_listen(State, Opts)
306	      end},
307
308     #{id   => 4,
309       desc => "Notify listening",
310       cmd  => fun(State) ->
311		      server_notify_listening(State)
312	      end},
313
314     #{id   => 5,
315       desc => "Await nothing",
316       cmd  => fun(State) ->
317		      server_await_nothing(State, 6000)
318	      end},
319
320     #{id   => 6,
321       desc => "Stop",
322       cmd  => fun(State) ->
323		      server_stop_transport(State)
324	      end}
325
326    ].
327
328
329start_and_stop_client_commands(ServerPort, ServerHost) ->
330    Opts = [{port, ServerPort}, {host, ServerHost}],
331    Self = self(),
332    [
333     #{id   => 1,
334       desc => "Command sequence init",
335       cmd  => fun(State) ->
336		      {ok, State#{parent => Self}}
337	      end},
338
339     #{id   => 2,
340       desc => "Start transport",
341       cmd  => fun(State) ->
342		      client_start_transport(State)
343	      end},
344
345     #{id   => 3,
346       desc => "Await continue",
347       cmd  => fun(State) ->
348		      client_await_continue_signal(State, 5000)
349	      end},
350
351     #{id   => 4,
352       desc => "Connect",
353       cmd  => fun(State) ->
354		      client_connect(State, Opts)
355	      end},
356
357     #{id   => 5,
358       desc => "Await nothing",
359       cmd  => fun(State) ->
360		      client_await_nothing(State, 5000)
361	      end},
362
363     #{id   => 6,
364       desc => "Disconnect",
365       cmd  => fun(State) ->
366		      client_disconnect(State)
367	      end},
368
369     #{id   => 7,
370       desc => "Stop transport",
371       cmd  => fun(State) ->
372		      client_stop_transport(State)
373	      end}
374    ].
375
376
377%% ------------------ sending ------------------------
378
379%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
380
381sendreceive(suite) ->
382    [];
383sendreceive(Config) when is_list(Config) ->
384    Pre = fun() ->
385		  p("create nodes"),
386		  ServerNode = make_node_name(server),
387		  ClientNode = make_node_name(client),
388		  Nodes = [ServerNode, ClientNode],
389		  ok = ?START_NODES(Nodes),
390		  Nodes
391	  end,
392    Case = fun do_sendreceive/1,
393    Post = fun(Nodes) ->
394                   p("stop nodes"),
395                   ?STOP_NODES(lists:reverse(Nodes))
396           end,
397    try_tc(sendreceive, Pre, Case, Post).
398
399do_sendreceive([ServerNode, ClientNode]) ->
400    %% Create command sequences
401    p("create command sequences"),
402    ServerPort = 2944,
403    ServerCmds = sendreceive_server_commands(ServerPort),
404    {ok, ServerHost} = inet:gethostname(),
405    ClientCmds = sendreceive_client_commands(ServerPort, ServerHost),
406
407    %% Start the test procs used in the test-case, one for each node
408    p("start command handlers"),
409    Server = server_start_command_handler(ServerNode, ServerCmds),
410    p("server command handler started: ~p", [Server]),
411    Client = client_start_command_handler(ClientNode, ClientCmds),
412    p("client command handler started: ~p", [Client]),
413
414    await_server_listening(Server, Client),
415
416    ok = await_command_handler_completion([Server, Client], ?SECS(20)),
417    p("done"),
418    ok.
419
420
421sendreceive_server_commands(Port) ->
422    Opts = [{port, Port}],
423    Self = self(),
424    [
425     #{id   => 1,
426       desc => "Command sequence init",
427       cmd  => fun(State) ->
428		       {ok, State#{parent => Self}}
429	       end},
430
431     #{id   => 2,
432       desc => "Start transport",
433       cmd  => fun(State) ->
434		       server_start_transport(State)
435	       end},
436
437     #{id   => 3,
438       desc => "Listen",
439       cmd  => fun(State) ->
440		       server_listen(State, Opts)
441	       end},
442
443     #{id   => 4,
444       desc => "Notify listening",
445       cmd  => fun(State) ->
446		       server_notify_listening(State)
447	       end},
448
449     #{id   => 5,
450       desc => "Await initial message (ping)",
451       cmd  => fun(State) ->
452		       server_await_initial_message(State, "ping", 5000)
453	       end},
454
455     #{id   => 6,
456       desc => "Send reply (pong) to initial message",
457       cmd  => fun(State) ->
458		       server_send_message(State, "pong")
459	       end},
460
461     #{id   => 7,
462       desc => "Await nothing before sending a message (hejsan)",
463       cmd  => fun(State) ->
464		       server_await_nothing(State, 1000)
465	       end},
466
467     #{id   => 8,
468       desc => "Send message (hejsan)",
469       cmd  => fun(State) ->
470		       server_send_message(State, "hejsan")
471	       end},
472
473     #{id   => 9,
474       desc => "Await reply (hoppsan) to message",
475       cmd  => fun(State) ->
476		       server_await_message(State, "hoppsan", 1000)
477	       end},
478
479     #{id   => 10,
480       desc => "Await nothing before disconnecting",
481       cmd  => fun(State) ->
482		       server_await_nothing(State, 1000)
483	       end},
484
485     #{id   => 11,
486       desc => "Disconnect",
487       cmd  => fun(State) ->
488		       server_disconnect(State)
489	       end},
490
491     #{id   => 12,
492       desc => "Await nothing before stopping transport",
493       cmd  => fun(State) ->
494		       server_await_nothing(State, 1000)
495	       end},
496
497     #{id   => 13,
498       desc => "Stop",
499       cmd  => fun(State) ->
500		       server_stop_transport(State)
501	       end}
502
503    ].
504
505sendreceive_client_commands(ServerPort, ServerHost) ->
506    Opts = [{port, ServerPort}, {host, ServerHost}],
507    Self = self(),
508    [
509     #{id   => 1,
510       desc => "Command sequence init",
511       cmd  => fun(State) ->
512		       {ok, State#{parent => Self}}
513	       end},
514
515     #{id   => 2,
516       desc => "Start transport",
517       cmd  => fun(State) ->
518		       client_start_transport(State)
519	       end},
520
521     #{id   => 3,
522       desc => "Await continue",
523       cmd  => fun(State) ->
524		       client_await_continue_signal(State, 5000)
525	       end},
526
527     #{id   => 4,
528       desc => "Connect",
529       cmd  => fun(State) ->
530		       client_connect(State, Opts)
531	       end},
532
533     #{id   => 5,
534       desc => "Send initial message (ping)",
535       cmd  => fun(State) ->
536		       client_send_message(State, "ping")
537	       end},
538
539     #{id   => 6,
540       desc => "Await reply (pong) to initial message",
541       cmd  => fun(State) ->
542		       client_await_message(State, "pong", 1000)
543	       end},
544
545     #{id   => 7,
546       desc => "Await message (hejsan)",
547       cmd  => fun(State) ->
548		       client_await_message(State, "hejsan", 5000)
549	       end},
550
551     #{id   => 8,
552       desc => "Send reply (hoppsan) to message",
553       cmd  => fun(State) ->
554		       client_send_message(State, "hoppsan")
555	       end},
556
557     #{id   => 9,
558       desc => "Await nothing before disconnecting",
559       cmd  => fun(State) ->
560		       client_await_nothing(State, 1000)
561	       end},
562
563     #{id   => 10,
564       desc => "Disconnect",
565       cmd  => fun(State) ->
566		       client_disconnect(State)
567	       end},
568
569     #{id   => 11,
570       desc => "Await nothing before stopping transport",
571       cmd  => fun(State) ->
572		       client_await_nothing(State, 1000)
573	       end},
574
575     #{id   => 12,
576       desc => "Stop transport",
577       cmd  => fun(State) ->
578		       client_stop_transport(State)
579	       end}
580    ].
581
582
583
584%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
585
586block_unblock(suite) ->
587    [];
588block_unblock(Config) when is_list(Config) ->
589    Pre = fun() ->
590		  p("create nodes"),
591		  ServerNode = make_node_name(server),
592		  ClientNode = make_node_name(client),
593		  Nodes = [ServerNode, ClientNode],
594		  ok = ?START_NODES(Nodes),
595		  Nodes
596	  end,
597    Case = fun do_block_unblock/1,
598    Post = fun(Nodes) ->
599                   p("stop nodes"),
600                   ?STOP_NODES(lists:reverse(Nodes))
601           end,
602    try_tc(block_unblock, Pre, Case, Post).
603
604do_block_unblock([ServerNode, ClientNode]) ->
605    %% Create command sequences
606    p("create command sequences"),
607    ServerPort = 2944,
608    ServerCmds = block_unblock_server_commands(ServerPort),
609    {ok, ServerHost} = inet:gethostname(),
610    ClientCmds = block_unblock_client_commands(ServerPort, ServerHost),
611
612    %% Start the test procs used in the test-case, one for each node
613    p("start command handlers"),
614    Server = server_start_command_handler(ServerNode, ServerCmds),
615    p("server command handler started: ~p", [Server]),
616    Client = client_start_command_handler(ClientNode, ClientCmds),
617    p("client command handler started: ~p", [Client]),
618
619    await_server_listening(Server, Client),
620
621    await_client_blocked(Server, Client),
622
623    ok = await_command_handler_completion([Server, Client], ?SECS(30)),
624    p("done"),
625    ok.
626
627
628block_unblock_server_commands(Port) ->
629    Opts = [{port, Port}],
630    Self = self(),
631    [
632     #{id   => 1,
633       desc => "Command sequence init",
634       cmd  => fun(State) ->
635		       {ok, State#{parent => Self}}
636	       end},
637
638     #{id   => 2,
639       desc => "Start transport",
640       cmd  => fun(State) ->
641		       server_start_transport(State)
642	       end},
643
644     #{id   => 3,
645       desc => "Listen",
646       cmd  => fun(State) ->
647		       server_listen(State, Opts)
648	       end},
649
650     #{id   => 4,
651       desc => "Notify listening",
652       cmd  => fun(State) ->
653		       server_notify_listening(State)
654	       end},
655
656     #{id   => 5,
657       desc => "Await initial message (ping)",
658       cmd  => fun(State) ->
659		       server_await_initial_message(State, "ping", 5000)
660	       end},
661
662     #{id   => 6,
663       desc => "Send reply (pong) to initial message",
664       cmd  => fun(State) ->
665		       server_send_message(State, "pong")
666	       end},
667
668     #{id   => 7,
669       desc => "Await continue",
670       cmd  => fun(State) ->
671		       server_await_continue_signal(State, 5000)
672	       end},
673
674     #{id   => 9,
675       desc => "Await nothing before sending a message (hejsan)",
676       cmd  => fun(State) ->
677		       server_await_nothing(State, 1000)
678	       end},
679
680     #{id   => 10,
681       desc => "Send message (hejsan)",
682       cmd  => fun(State) ->
683		       server_send_message(State, "hejsan")
684	       end},
685
686     #{id   => 11,
687       desc => "Await reply (hoppsan) to message",
688       cmd  => fun(State) ->
689		       server_await_message(State, "hoppsan", 10000)
690	       end},
691
692     #{id   => 12,
693       desc => "Await nothing before disconnecting",
694       cmd  => fun(State) ->
695		       server_await_nothing(State, 1000)
696	       end},
697
698     #{id   => 13,
699       desc => "Disconnect",
700       cmd  => fun(State) ->
701		       server_disconnect(State)
702	       end},
703
704     #{id   => 14,
705       desc => "Await nothing before stopping transport",
706       cmd  => fun(State) ->
707		       server_await_nothing(State, 1000)
708	       end},
709
710     #{id   => 15,
711       desc => "Stop",
712       cmd  => fun(State) ->
713		       server_stop_transport(State)
714	       end}
715
716    ].
717
718block_unblock_client_commands(ServerPort, ServerHost) ->
719    Opts = [{port, ServerPort}, {host, ServerHost}],
720    Self = self(),
721    [
722     #{id   => 1,
723       desc => "Command sequence init",
724       cmd  => fun(State) ->
725		       {ok, State#{parent => Self}}
726	       end},
727
728     #{id   => 2,
729       desc => "Start transport",
730       cmd  => fun(State) ->
731		       client_start_transport(State)
732	       end},
733
734     #{id   => 3,
735       desc => "Await continue",
736       cmd  => fun(State) ->
737		       client_await_continue_signal(State, 5000)
738	       end},
739
740     #{id   => 4,
741       desc => "Connect",
742       cmd  => fun(State) ->
743		       client_connect(State, Opts)
744	       end},
745
746     #{id   => 5,
747       desc => "Send initial message (ping)",
748       cmd  => fun(State) ->
749		       client_send_message(State, "ping")
750	       end},
751
752     #{id   => 6,
753       desc => "Await reply (pong) to initial message",
754       cmd  => fun(State) ->
755		       client_await_message(State, "pong", 1000)
756	       end},
757
758     #{id   => 7,
759       desc => "Await nothing before blocking",
760       cmd  => fun(State) ->
761		       client_await_nothing(State, 1000)
762	       end},
763
764     #{id   => 8,
765       desc => "Block",
766       cmd  => fun(State) ->
767		       client_block(State)
768	       end},
769
770     #{id   => 9,
771       desc => "Notify blocked",
772       cmd  => fun(State) ->
773		       client_notify_blocked(State)
774	       end},
775
776     #{id   => 10,
777       desc => "Await nothing before unblocking",
778       cmd  => fun(State) ->
779		       client_await_nothing(State, 5000)
780	       end},
781
782     #{id   => 11,
783       desc => "Unblock",
784       cmd  => fun(State) ->
785		       client_unblock(State)
786	       end},
787
788     #{id   => 12,
789       desc => "Await message (hejsan)",
790       cmd  => fun(State) ->
791		       client_await_message(State, "hejsan", 100)
792	       end},
793
794     #{id   => 13,
795       desc => "Send reply (hoppsan) to message",
796       cmd  => fun(State) ->
797		       client_send_message(State, "hoppsan")
798	       end},
799
800     #{id   => 14,
801       desc => "Await nothing before disconnecting",
802       cmd  => fun(State) ->
803		       client_await_nothing(State, 1000)
804	       end},
805
806     #{id   => 15,
807       desc => "Disconnect",
808       cmd  => fun(State) ->
809		       client_disconnect(State)
810	       end},
811
812     #{id   => 16,
813       desc => "Await nothing before stopping transport",
814       cmd  => fun(State) ->
815		       client_await_nothing(State, 1000)
816	       end},
817
818     #{id   => 17,
819       desc => "Stop transport",
820       cmd  => fun(State) ->
821		       client_stop_transport(State)
822	       end}
823    ].
824
825
826
827%% ------------------ errors ------------------------
828
829%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
830
831socket_failure(suite) ->
832    [];
833socket_failure(Config) when is_list(Config) ->
834    put(sname, "socket_failure"),
835    p("BEGIN TEST-CASE"),
836
837    %% process_flag(trap_exit, true),
838
839    socket_faulure().
840
841
842%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
843
844accept_process(suite) ->
845    [];
846accept_process(Config) when is_list(Config) ->
847    put(sname, "accept_process"),
848    p("BEGIN TEST-CASE"),
849
850    %% process_flag(trap_exit, true),
851
852    failing_accept_process().
853
854
855%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
856
857accept_supervisor(suite) ->
858    [];
859accept_supervisor(Config) when is_list(Config) ->
860    put(sname, "accept_supervisor"),
861    p("BEGIN TEST-CASE"),
862
863    %% process_flag(trap_exit, true),
864
865    failing_accept_supervisor().
866
867
868%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
869
870connection_supervisor(suite) ->
871    [];
872connection_supervisor(Config) when is_list(Config) ->
873    put(sname, "connection_supervisor"),
874    p("BEGIN TEST-CASE"),
875
876    %% process_flag(trap_exit, true),
877
878    failing_connection_supervisor().
879
880
881%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
882
883tcp_server(suite) ->
884    [];
885tcp_server(Config) when is_list(Config) ->
886    put(sname, "tcp_server"),
887    p("BEGIN TEST-CASE"),
888
889    %% process_flag(trap_exit, true),
890
891    failing_tcp_server().
892
893
894%%======================================================================
895%% Test functions
896%%======================================================================
897
898start_case(Options, Expect) ->
899    p("start transport"),
900    case (catch megaco_tcp:start_transport()) of
901	{ok, Pid} ->
902	    p("create listen socket"),
903	    case (catch megaco_tcp:listen(Pid, Options)) of
904		ok when Expect =:= ok ->
905		    p("extected listen result [ok]"),
906		    {ok, Pid};
907		ok ->
908		    p("unextected listen result [ok] - stop transport"),
909		    megaco_tcp:stop_transport(Pid),
910		    ?ERROR(unexpected_start_sucesss);
911		{error, _Reason} when Expect =:= error ->
912		    p("extected listen result [error] - stop transport"),
913		    megaco_tcp:stop_transport(Pid),
914		    ok;
915		{error, Reason} ->
916		    p("unextected listen result [error] - stop transport"),
917		    megaco_tcp:stop_transport(Pid),
918		    ?ERROR({unexpected_start_failure, Reason});
919		Error ->
920		    p("unextected listen result"),
921		    ?ERROR({unexpected_result, Error})
922	    end;
923	{error, Reason} ->
924	    p("unextected start_transport result"),
925	    ?ERROR({failed_starting_transport, Reason})
926    end.
927
928socket_faulure() ->
929    ?SKIP(not_yet_implemented).
930
931failing_accept_process() ->
932    ?SKIP(not_yet_implemented).
933
934failing_accept_supervisor() ->
935    ?SKIP(not_yet_implemented).
936
937failing_connection_supervisor() ->
938    ?SKIP(not_yet_implemented).
939
940failing_tcp_server() ->
941    ?SKIP(not_yet_implemented).
942
943
944%%----------------------------------------------------------------------
945%% Message Callback functions
946%%----------------------------------------------------------------------
947
948receive_message(ReceiveHandle, ControlPid, SendHandle, BinMsg)
949  when is_pid(ReceiveHandle) andalso is_binary(BinMsg) ->
950    Msg = binary_to_list(BinMsg),
951    ReceiveHandle ! {receive_message, {ControlPid, SendHandle, Msg}},
952    ok.
953
954process_received_message(ReceiveHandle, ControlPid, SendHandle, BinMsg)
955  when is_pid(ReceiveHandle) andalso is_binary(BinMsg) ->
956    Msg = binary_to_list(BinMsg),
957    ReceiveHandle ! {process_received_message, {ControlPid, SendHandle, Msg}},
958    ok.
959
960
961%%======================================================================
962%% Internal functions
963%%======================================================================
964
965await_server_listening(Server, Client) ->
966    receive
967        {listening, Server} ->
968            p("received listening message from server [~p] => "
969              "send continue to client [~p]"
970              "~n", [Server, Client]),
971            Client ! {continue, self()},
972            ok;
973	{'EXIT', Server, SReason} ->
974	    exit({server_crash, SReason});
975	{'EXIT', Client, CReason} ->
976	    exit({client_crash, CReason})
977    after 5000 ->
978            %% There is no normal reason why this should take any time.
979            %% Normally, this takes a few milli seconds. So, if we are not
980            %% up and running after 5 seconds, we give up and skip!!
981            exit(Server, kill),
982            exit(Client, kill),
983            ?SKIP("Server timeout (listen)")
984    end.
985
986
987await_client_blocked(Server, Client) ->
988    receive
989        {blocked, Client} ->
990            p("received blocked message from client [~p] => "
991              "send continue to server [~p]~n", [Client, Server]),
992            Server ! {continue, self()},
993            ok;
994	{'EXIT', Client, CReason} ->
995	    exit({client_crash, CReason});
996	{'EXIT', Server, SReason} ->
997	    exit({server_crash, SReason})
998    after 5000 ->
999            %% There is no normal reason why this should take any time.
1000            %% Normally, this takes a few milli seconds. So, if we are not
1001            %% up and running after 5 seconds, we give up and skip!!
1002            exit(Client, kill),
1003            exit(Server, kill),
1004            ?SKIP("Client timeout (blocked)")
1005    end.
1006
1007
1008
1009%% -------  Server command handler and utility functions ----------
1010
1011server_start_command_handler(Node, Commands) ->
1012    start_command_handler(Node, Commands, #{}, "server").
1013
1014server_start_transport(State) when is_map(State) ->
1015    case (catch megaco_tcp:start_transport()) of
1016	{ok, Ref} ->
1017	    {ok, State#{transport_ref => Ref}};
1018	Error ->
1019	    Error
1020    end.
1021
1022server_listen(#{transport_ref := Ref} = State, Options)
1023  when is_list(Options) ->
1024    Opts = [{receive_handle, self()}, {module, ?MODULE} | Options],
1025    case (catch megaco_tcp:listen(Ref, Opts)) of
1026	ok ->
1027	    {ok, State};
1028	Error ->
1029	    Error
1030    end.
1031
1032server_notify_listening(#{parent := Parent} = State) ->
1033    Parent ! {listening, self()},
1034    {ok, State}.
1035
1036server_await_continue_signal(#{parent := Parent} = State, Timeout) ->
1037    receive
1038	{continue, Parent} ->
1039	    {ok, State}
1040    after Timeout ->
1041	    {error, timeout}
1042    end.
1043
1044server_await_initial_message(State, InitialMessage, Timeout)
1045  when is_map(State) ->
1046    receive
1047	{receive_message, {ControlPid, Handle, InitialMessage}} ->
1048	    NewState = State#{control_pid => ControlPid,
1049			      handle      => Handle},
1050	    {ok, NewState};
1051
1052	Any ->
1053	    p("received unexpected event: ~p", [Any]),
1054	    {error, {unexpected_event, Any}}
1055
1056    after Timeout ->
1057	    {error, timeout}
1058    end.
1059
1060server_send_message(#{handle := Handle} = State, Message) ->
1061    megaco_tcp:send_message(Handle, Message),
1062    {ok, State}.
1063
1064server_await_nothing(State, Timeout)
1065  when is_map(State) ->
1066    receive
1067	Any ->
1068	    p("received unexpected event: ~p", [Any]),
1069	    {error, {unexpected_event, Any}}
1070
1071    after Timeout ->
1072	    {ok, State}
1073    end.
1074
1075server_await_message(State, ExpectMessage, Timeout)
1076  when is_map(State) ->
1077    receive
1078	{receive_message, {_, _, ExpectMessage}} ->
1079	    {ok, State};
1080
1081	Any ->
1082	    p("received unexpected event: ~p", [Any]),
1083	    {error, {unexpected_event, Any}}
1084
1085    after Timeout ->
1086	    {error, timeout}
1087    end.
1088
1089server_disconnect(#{handle := Handle} = State)
1090  when (Handle =/= undefined) ->
1091     megaco_tcp:close(Handle),
1092    {ok, State#{handle => undefined}}.
1093
1094server_stop_transport(#{transport_ref := Ref} = State)
1095  when (Ref =/= undefined) ->
1096    megaco_tcp:stop_transport(Ref),
1097    {ok, State}.
1098
1099
1100%% -------  Client command handler and utility functions ----------
1101
1102client_start_command_handler(Node, Commands) ->
1103    start_command_handler(Node, Commands, #{}, "client").
1104
1105client_start_transport(State) when is_map(State) ->
1106    case (catch megaco_tcp:start_transport()) of
1107	{ok, Ref} ->
1108	    {ok, State#{transport_ref => Ref}};
1109	Error ->
1110	    Error
1111    end.
1112
1113client_connect(#{transport_ref := Ref} = State, Options)
1114  when is_list(Options) ->
1115    Opts = [{receive_handle, self()}, {module, ?MODULE} | Options],
1116    case (catch megaco_tcp:connect(Ref, Opts)) of
1117	{ok, Handle, ControlPid} ->
1118	    {ok, State#{control_pid => ControlPid,
1119			handle      => Handle}};
1120	Error ->
1121	    Error
1122    end.
1123
1124client_await_continue_signal(#{parent := Parent} = State, Timeout) ->
1125    receive
1126	{continue, Parent} ->
1127	    {ok, State}
1128    after Timeout ->
1129	    {error, timeout}
1130    end.
1131
1132client_notify_blocked(#{parent := Parent} = State) ->
1133    Parent ! {blocked, self()},
1134    {ok, State}.
1135
1136client_await_nothing(State, Timeout)
1137  when is_map(State) ->
1138    receive
1139	Any ->
1140	    p("received unexpected event: ~p", [Any]),
1141	    {error, {unexpected_event, Any}}
1142    after Timeout ->
1143	    {ok, State}
1144    end.
1145
1146client_send_message(#{handle := Handle} = State, Message) ->
1147    megaco_tcp:send_message(Handle, Message),
1148    {ok, State}.
1149
1150client_await_message(State, ExpectMessage, Timeout)
1151  when is_map(State) ->
1152    receive
1153	{receive_message, {_, _, ExpectMessage}} ->
1154	    {ok, State};
1155
1156	Any ->
1157	    p("received unexpected event: ~p", [Any]),
1158	    {error, {unexpected_event, Any}}
1159
1160    after Timeout ->
1161	    {error, timeout}
1162    end.
1163
1164client_block(#{handle := Handle} = State)
1165  when (Handle =/= undefined) ->
1166    megaco_tcp:block(Handle),
1167    {ok, State}.
1168
1169client_unblock(#{handle := Handle} = State)
1170  when (Handle =/= undefined) ->
1171    megaco_tcp:unblock(Handle),
1172    {ok, State}.
1173
1174client_disconnect(#{handle := Handle} = State)
1175  when (Handle =/= undefined) ->
1176    megaco_tcp:close(Handle),
1177    {ok, State#{handle => undefined, control_pid => undefined}}.
1178
1179client_stop_transport(#{transport_ref := Ref} = State)
1180  when (Ref =/= undefined) ->
1181    megaco_tcp:stop_transport(Ref),
1182    {ok, State}.
1183
1184
1185%% -------- Command handler ---------
1186
1187start_command_handler(Node, Commands, State, ShortName) ->
1188    ?CH:start(Node, Commands, State, ShortName).
1189
1190await_command_handler_completion(Pids, Timeout) ->
1191    ?CH:await_completion(Pids, Timeout).
1192
1193
1194%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1195
1196try_tc(TCName, Pre, Case, Post) ->
1197    try_tc(TCName, "TEST", ?TEST_VERBOSITY, Pre, Case, Post).
1198
1199try_tc(TCName, Name, Verbosity, Pre, Case, Post) ->
1200    ?TRY_TC(TCName, Name, Verbosity, Pre, Case, Post).
1201
1202
1203%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1204
1205%% ------- Misc functions --------
1206
1207make_node_name(Name) ->
1208    case string:tokens(atom_to_list(node()), [$@]) of
1209        [_,Host] ->
1210            list_to_atom(lists:concat([atom_to_list(Name) ++ "@" ++ Host]));
1211        _ ->
1212            exit("Test node must be started with '-sname'")
1213    end.
1214
1215
1216p(F) ->
1217    p(F, []).
1218
1219p(F, A) ->
1220    p(get(sname), F, A).
1221
1222p(S, F, A) when is_list(S) ->
1223    io:format("*** [~s] ~p ~s ***"
1224	      "~n   " ++ F ++ "~n",
1225	      [?FTS(), self(), S | A]);
1226p(_S, F, A) ->
1227    io:format("*** [~s] ~p *** "
1228	      "~n   " ++ F ++ "~n",
1229	      [?FTS(), self() | A]).
1230
1231
1232