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