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