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