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