%% %% %CopyrightBegin% %% %% Copyright Ericsson AB 2018-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. %% You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. %% %% %CopyrightEnd% %% %% There are some environment variables that can be used to "manipulate" %% the test suite: %% %% Variable that controls which 'groups' are to run (with default values) %% %% ESOCK_TEST_API: include %% ESOCK_TEST_SOCK_CLOSE: include %% ESOCK_TEST_TRAFFIC: include %% ESOCK_TEST_TTEST: exclude %% %% Variable that controls "verbosity" of the test case(s): %% %% ESOCK_TEST_QUIET: true (default) | false %% %% Defines the runtime of the ttest cases %% (This is the time during which "measurement" is performed. %% the actual time it takes for the test case to complete %% will be longer; setup, completion, ...) %% %% ESOCK_TEST_TTEST_RUNTIME: 10 seconds %% Format of values: [] %% Where unit is: ms | s | m %% ms - milli seconds %% s - seconds (default) %% m - minutes %% %% Run the entire test suite: %% ts:run(emulator, socket_SUITE, [batch]). %% %% Run a specific group: %% ts:run(emulator, socket_SUITE, {group, foo}, [batch]). %% %% Run a specific test case: %% ts:run(emulator, socket_SUITE, foo, [batch]). -module(socket_SUITE). -include_lib("common_test/include/ct.hrl"). -include_lib("common_test/include/ct_event.hrl"). -include("socket_test_evaluator.hrl"). %% Suite exports -export([suite/0, all/0, groups/0]). -export([init_per_suite/1, end_per_suite/1, init_per_group/2, end_per_group/2, init_per_testcase/2, end_per_testcase/2]). %% Test cases -export([ %% *** API Misc *** api_m_debug/1, %% *** API Basic *** api_b_open_and_close_udp4/1, api_b_open_and_close_tcp4/1, api_b_open_and_close_udpL/1, api_b_open_and_close_tcpL/1, api_b_sendto_and_recvfrom_udp4/1, api_b_sendto_and_recvfrom_udpL/1, api_b_sendmsg_and_recvmsg_udp4/1, api_b_sendmsg_and_recvmsg_udpL/1, api_b_send_and_recv_tcp4/1, api_b_send_and_recv_tcpL/1, api_b_sendmsg_and_recvmsg_tcp4/1, api_b_sendmsg_and_recvmsg_tcpL/1, %% *** API async *** api_a_connect_tcp4/1, api_a_connect_tcp6/1, api_a_sendto_and_recvfrom_udp4/1, api_a_sendto_and_recvfrom_udp6/1, api_a_sendmsg_and_recvmsg_udp4/1, api_a_sendmsg_and_recvmsg_udp6/1, api_a_send_and_recv_tcp4/1, api_a_send_and_recv_tcp6/1, api_a_sendmsg_and_recvmsg_tcp4/1, api_a_sendmsg_and_recvmsg_tcp6/1, api_a_recvfrom_cancel_udp4/1, api_a_recvfrom_cancel_udp6/1, api_a_recvmsg_cancel_udp4/1, api_a_recvmsg_cancel_udp6/1, api_a_accept_cancel_tcp4/1, api_a_accept_cancel_tcp6/1, api_a_recv_cancel_tcp4/1, api_a_recv_cancel_tcp6/1, api_a_recvmsg_cancel_tcp4/1, api_a_recvmsg_cancel_tcp6/1, api_a_mrecvfrom_cancel_udp4/1, api_a_mrecvfrom_cancel_udp6/1, api_a_mrecvmsg_cancel_udp4/1, api_a_mrecvmsg_cancel_udp6/1, api_a_maccept_cancel_tcp4/1, api_a_maccept_cancel_tcp6/1, api_a_mrecv_cancel_tcp4/1, api_a_mrecv_cancel_tcp6/1, api_a_mrecvmsg_cancel_tcp4/1, api_a_mrecvmsg_cancel_tcp6/1, %% *** API Options *** api_opt_simple_otp_options/1, api_opt_simple_otp_rcvbuf_option/1, api_opt_simple_otp_controlling_process/1, api_opt_sock_acceptconn_udp/1, api_opt_sock_acceptconn_tcp/1, api_opt_sock_acceptfilter/1, api_opt_sock_bindtodevice/1, api_opt_sock_broadcast/1, api_opt_sock_debug/1, api_opt_sock_domain/1, api_opt_sock_dontroute/1, api_opt_sock_error/1, api_opt_sock_keepalive/1, api_opt_sock_linger/1, api_opt_ip_add_drop_membership/1, %% *** API Operation Timeout *** api_to_connect_tcp4/1, api_to_connect_tcp6/1, api_to_accept_tcp4/1, api_to_accept_tcp6/1, api_to_maccept_tcp4/1, api_to_maccept_tcp6/1, api_to_send_tcp4/1, api_to_send_tcp6/1, api_to_sendto_udp4/1, api_to_sendto_udp6/1, api_to_sendmsg_tcp4/1, api_to_sendmsg_tcp6/1, api_to_recv_udp4/1, api_to_recv_udp6/1, api_to_recv_tcp4/1, api_to_recv_tcp6/1, api_to_recvfrom_udp4/1, api_to_recvfrom_udp6/1, api_to_recvmsg_udp4/1, api_to_recvmsg_udp6/1, api_to_recvmsg_tcp4/1, api_to_recvmsg_tcp6/1, %% *** Socket Closure *** sc_cpe_socket_cleanup_tcp4/1, sc_cpe_socket_cleanup_tcp6/1, sc_cpe_socket_cleanup_tcpL/1, sc_cpe_socket_cleanup_udp4/1, sc_cpe_socket_cleanup_udp6/1, sc_cpe_socket_cleanup_udpL/1, sc_lc_recv_response_tcp4/1, sc_lc_recv_response_tcp6/1, sc_lc_recv_response_tcpL/1, sc_lc_recvfrom_response_udp4/1, sc_lc_recvfrom_response_udp6/1, sc_lc_recvfrom_response_udpL/1, sc_lc_recvmsg_response_tcp4/1, sc_lc_recvmsg_response_tcp6/1, sc_lc_recvmsg_response_tcpL/1, sc_lc_recvmsg_response_udp4/1, sc_lc_recvmsg_response_udp6/1, sc_lc_recvmsg_response_udpL/1, sc_lc_acceptor_response_tcp4/1, sc_lc_acceptor_response_tcp6/1, sc_lc_acceptor_response_tcpL/1, sc_rc_recv_response_tcp4/1, sc_rc_recv_response_tcp6/1, sc_rc_recv_response_tcpL/1, sc_rc_recvmsg_response_tcp4/1, sc_rc_recvmsg_response_tcp6/1, sc_rc_recvmsg_response_tcpL/1, sc_rs_recv_send_shutdown_receive_tcp4/1, sc_rs_recv_send_shutdown_receive_tcp6/1, sc_rs_recv_send_shutdown_receive_tcpL/1, sc_rs_recvmsg_send_shutdown_receive_tcp4/1, sc_rs_recvmsg_send_shutdown_receive_tcp6/1, sc_rs_recvmsg_send_shutdown_receive_tcpL/1, %% *** Traffic *** traffic_send_and_recv_counters_tcp4/1, traffic_send_and_recv_counters_tcp6/1, traffic_send_and_recv_counters_tcpL/1, traffic_sendmsg_and_recvmsg_counters_tcp4/1, traffic_sendmsg_and_recvmsg_counters_tcp6/1, traffic_sendmsg_and_recvmsg_counters_tcpL/1, traffic_sendto_and_recvfrom_counters_udp4/1, traffic_sendto_and_recvfrom_counters_udp6/1, traffic_sendto_and_recvfrom_counters_udpL/1, traffic_sendmsg_and_recvmsg_counters_udp4/1, traffic_sendmsg_and_recvmsg_counters_udp6/1, traffic_sendmsg_and_recvmsg_counters_udpL/1, traffic_send_and_recv_chunks_tcp4/1, traffic_send_and_recv_chunks_tcp6/1, traffic_send_and_recv_chunks_tcpL/1, traffic_ping_pong_small_send_and_recv_tcp4/1, traffic_ping_pong_small_send_and_recv_tcp6/1, traffic_ping_pong_small_send_and_recv_tcpL/1, traffic_ping_pong_medium_send_and_recv_tcp4/1, traffic_ping_pong_medium_send_and_recv_tcp6/1, traffic_ping_pong_medium_send_and_recv_tcpL/1, traffic_ping_pong_large_send_and_recv_tcp4/1, traffic_ping_pong_large_send_and_recv_tcp6/1, traffic_ping_pong_large_send_and_recv_tcpL/1, traffic_ping_pong_small_sendto_and_recvfrom_udp4/1, traffic_ping_pong_small_sendto_and_recvfrom_udp6/1, traffic_ping_pong_small_sendto_and_recvfrom_udpL/1, traffic_ping_pong_medium_sendto_and_recvfrom_udp4/1, traffic_ping_pong_medium_sendto_and_recvfrom_udp6/1, traffic_ping_pong_medium_sendto_and_recvfrom_udpL/1, traffic_ping_pong_small_sendmsg_and_recvmsg_tcp4/1, traffic_ping_pong_small_sendmsg_and_recvmsg_tcp6/1, traffic_ping_pong_small_sendmsg_and_recvmsg_tcpL/1, traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp4/1, traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp6/1, traffic_ping_pong_medium_sendmsg_and_recvmsg_tcpL/1, traffic_ping_pong_large_sendmsg_and_recvmsg_tcp4/1, traffic_ping_pong_large_sendmsg_and_recvmsg_tcp6/1, traffic_ping_pong_large_sendmsg_and_recvmsg_tcpL/1, traffic_ping_pong_small_sendmsg_and_recvmsg_udp4/1, traffic_ping_pong_small_sendmsg_and_recvmsg_udp6/1, traffic_ping_pong_small_sendmsg_and_recvmsg_udpL/1, traffic_ping_pong_medium_sendmsg_and_recvmsg_udp4/1, traffic_ping_pong_medium_sendmsg_and_recvmsg_udp6/1, traffic_ping_pong_medium_sendmsg_and_recvmsg_udpL/1, %% *** Time Test *** %% Server: transport = gen_tcp, active = false %% Client: transport = gen_tcp ttest_sgenf_cgenf_small_tcp4/1, ttest_sgenf_cgenf_small_tcp6/1, ttest_sgenf_cgenf_medium_tcp4/1, ttest_sgenf_cgenf_medium_tcp6/1, ttest_sgenf_cgenf_large_tcp4/1, ttest_sgenf_cgenf_large_tcp6/1, ttest_sgenf_cgeno_small_tcp4/1, ttest_sgenf_cgeno_small_tcp6/1, ttest_sgenf_cgeno_medium_tcp4/1, ttest_sgenf_cgeno_medium_tcp6/1, ttest_sgenf_cgeno_large_tcp4/1, ttest_sgenf_cgeno_large_tcp6/1, ttest_sgenf_cgent_small_tcp4/1, ttest_sgenf_cgent_small_tcp6/1, ttest_sgenf_cgent_medium_tcp4/1, ttest_sgenf_cgent_medium_tcp6/1, ttest_sgenf_cgent_large_tcp4/1, ttest_sgenf_cgent_large_tcp6/1, %% Server: transport = gen_tcp, active = false %% Client: transport = socket(tcp) ttest_sgenf_csockf_small_tcp4/1, ttest_sgenf_csockf_small_tcp6/1, ttest_sgenf_csockf_medium_tcp4/1, ttest_sgenf_csockf_medium_tcp6/1, ttest_sgenf_csockf_large_tcp4/1, ttest_sgenf_csockf_large_tcp6/1, ttest_sgenf_csocko_small_tcp4/1, ttest_sgenf_csocko_small_tcp6/1, ttest_sgenf_csocko_medium_tcp4/1, ttest_sgenf_csocko_medium_tcp6/1, ttest_sgenf_csocko_large_tcp4/1, ttest_sgenf_csocko_large_tcp6/1, ttest_sgenf_csockt_small_tcp4/1, ttest_sgenf_csockt_small_tcp6/1, ttest_sgenf_csockt_medium_tcp4/1, ttest_sgenf_csockt_medium_tcp6/1, ttest_sgenf_csockt_large_tcp4/1, ttest_sgenf_csockt_large_tcp6/1, %% Server: transport = gen_tcp, active = once %% Client: transport = gen_tcp ttest_sgeno_cgenf_small_tcp4/1, ttest_sgeno_cgenf_small_tcp6/1, ttest_sgeno_cgenf_medium_tcp4/1, ttest_sgeno_cgenf_medium_tcp6/1, ttest_sgeno_cgenf_large_tcp4/1, ttest_sgeno_cgenf_large_tcp6/1, ttest_sgeno_cgeno_small_tcp4/1, ttest_sgeno_cgeno_small_tcp6/1, ttest_sgeno_cgeno_medium_tcp4/1, ttest_sgeno_cgeno_medium_tcp6/1, ttest_sgeno_cgeno_large_tcp4/1, ttest_sgeno_cgeno_large_tcp6/1, ttest_sgeno_cgent_small_tcp4/1, ttest_sgeno_cgent_small_tcp6/1, ttest_sgeno_cgent_medium_tcp4/1, ttest_sgeno_cgent_medium_tcp6/1, ttest_sgeno_cgent_large_tcp4/1, ttest_sgeno_cgent_large_tcp6/1, %% Server: transport = gen_tcp, active = once %% Client: transport = socket(tcp) ttest_sgeno_csockf_small_tcp4/1, ttest_sgeno_csockf_small_tcp6/1, ttest_sgeno_csockf_medium_tcp4/1, ttest_sgeno_csockf_medium_tcp6/1, ttest_sgeno_csockf_large_tcp4/1, ttest_sgeno_csockf_large_tcp6/1, ttest_sgeno_csocko_small_tcp4/1, ttest_sgeno_csocko_small_tcp6/1, ttest_sgeno_csocko_medium_tcp4/1, ttest_sgeno_csocko_medium_tcp6/1, ttest_sgeno_csocko_large_tcp4/1, ttest_sgeno_csocko_large_tcp6/1, ttest_sgeno_csockt_small_tcp4/1, ttest_sgeno_csockt_small_tcp6/1, ttest_sgeno_csockt_medium_tcp4/1, ttest_sgeno_csockt_medium_tcp6/1, ttest_sgeno_csockt_large_tcp4/1, ttest_sgeno_csockt_large_tcp6/1, %% Server: transport = gen_tcp, active = true %% Client: transport = gen_tcp ttest_sgent_cgenf_small_tcp4/1, ttest_sgent_cgenf_small_tcp6/1, ttest_sgent_cgenf_medium_tcp4/1, ttest_sgent_cgenf_medium_tcp6/1, ttest_sgent_cgenf_large_tcp4/1, ttest_sgent_cgenf_large_tcp6/1, ttest_sgent_cgeno_small_tcp4/1, ttest_sgent_cgeno_small_tcp6/1, ttest_sgent_cgeno_medium_tcp4/1, ttest_sgent_cgeno_medium_tcp6/1, ttest_sgent_cgeno_large_tcp4/1, ttest_sgent_cgeno_large_tcp6/1, ttest_sgent_cgent_small_tcp4/1, ttest_sgent_cgent_small_tcp6/1, ttest_sgent_cgent_medium_tcp4/1, ttest_sgent_cgent_medium_tcp6/1, ttest_sgent_cgent_large_tcp4/1, ttest_sgent_cgent_large_tcp6/1, %% Server: transport = gen_tcp, active = true %% Client: transport = socket(tcp) ttest_sgent_csockf_small_tcp4/1, ttest_sgent_csockf_small_tcp6/1, ttest_sgent_csockf_medium_tcp4/1, ttest_sgent_csockf_medium_tcp6/1, ttest_sgent_csockf_large_tcp4/1, ttest_sgent_csockf_large_tcp6/1, ttest_sgent_csocko_small_tcp4/1, ttest_sgent_csocko_small_tcp6/1, ttest_sgent_csocko_medium_tcp4/1, ttest_sgent_csocko_medium_tcp6/1, ttest_sgent_csocko_large_tcp4/1, ttest_sgent_csocko_large_tcp6/1, ttest_sgent_csockt_small_tcp4/1, ttest_sgent_csockt_small_tcp6/1, ttest_sgent_csockt_medium_tcp4/1, ttest_sgent_csockt_medium_tcp6/1, ttest_sgent_csockt_large_tcp4/1, ttest_sgent_csockt_large_tcp6/1, %% Server: transport = socket(tcp), active = false %% Client: transport = gen_tcp ttest_ssockf_cgenf_small_tcp4/1, ttest_ssockf_cgenf_small_tcp6/1, ttest_ssockf_cgenf_medium_tcp4/1, ttest_ssockf_cgenf_medium_tcp6/1, ttest_ssockf_cgenf_large_tcp4/1, ttest_ssockf_cgenf_large_tcp6/1, ttest_ssockf_cgeno_small_tcp4/1, ttest_ssockf_cgeno_small_tcp6/1, ttest_ssockf_cgeno_medium_tcp4/1, ttest_ssockf_cgeno_medium_tcp6/1, ttest_ssockf_cgeno_large_tcp4/1, ttest_ssockf_cgeno_large_tcp6/1, ttest_ssockf_cgent_small_tcp4/1, ttest_ssockf_cgent_small_tcp6/1, ttest_ssockf_cgent_medium_tcp4/1, ttest_ssockf_cgent_medium_tcp6/1, ttest_ssockf_cgent_large_tcp4/1, ttest_ssockf_cgent_large_tcp6/1, %% Server: transport = socket(tcp), active = false %% Client: transport = socket(tcp) ttest_ssockf_csockf_small_tcp4/1, ttest_ssockf_csockf_small_tcp6/1, ttest_ssockf_csockf_small_tcpL/1, ttest_ssockf_csockf_medium_tcp4/1, ttest_ssockf_csockf_medium_tcp6/1, ttest_ssockf_csockf_medium_tcpL/1, ttest_ssockf_csockf_large_tcp4/1, ttest_ssockf_csockf_large_tcp6/1, ttest_ssockf_csockf_large_tcpL/1, ttest_ssockf_csocko_small_tcp4/1, ttest_ssockf_csocko_small_tcp6/1, ttest_ssockf_csocko_small_tcpL/1, ttest_ssockf_csocko_medium_tcp4/1, ttest_ssockf_csocko_medium_tcp6/1, ttest_ssockf_csocko_medium_tcpL/1, ttest_ssockf_csocko_large_tcp4/1, ttest_ssockf_csocko_large_tcp6/1, ttest_ssockf_csocko_large_tcpL/1, ttest_ssockf_csockt_small_tcp4/1, ttest_ssockf_csockt_small_tcp6/1, ttest_ssockf_csockt_small_tcpL/1, ttest_ssockf_csockt_medium_tcp4/1, ttest_ssockf_csockt_medium_tcp6/1, ttest_ssockf_csockt_medium_tcpL/1, ttest_ssockf_csockt_large_tcp4/1, ttest_ssockf_csockt_large_tcp6/1, ttest_ssockf_csockt_large_tcpL/1, %% Server: transport = socket(tcp), active = once %% Client: transport = gen_tcp ttest_ssocko_cgenf_small_tcp4/1, ttest_ssocko_cgenf_small_tcp6/1, ttest_ssocko_cgenf_medium_tcp4/1, ttest_ssocko_cgenf_medium_tcp6/1, ttest_ssocko_cgenf_large_tcp4/1, ttest_ssocko_cgenf_large_tcp6/1, ttest_ssocko_cgeno_small_tcp4/1, ttest_ssocko_cgeno_small_tcp6/1, ttest_ssocko_cgeno_medium_tcp4/1, ttest_ssocko_cgeno_medium_tcp6/1, ttest_ssocko_cgeno_large_tcp4/1, ttest_ssocko_cgeno_large_tcp6/1, ttest_ssocko_cgent_small_tcp4/1, ttest_ssocko_cgent_small_tcp6/1, ttest_ssocko_cgent_medium_tcp4/1, ttest_ssocko_cgent_medium_tcp6/1, ttest_ssocko_cgent_large_tcp4/1, ttest_ssocko_cgent_large_tcp6/1, %% Server: transport = socket(tcp), active = once %% Client: transport = socket(tcp) ttest_ssocko_csockf_small_tcp4/1, ttest_ssocko_csockf_small_tcp6/1, ttest_ssocko_csockf_small_tcpL/1, ttest_ssocko_csockf_medium_tcp4/1, ttest_ssocko_csockf_medium_tcpL/1, ttest_ssocko_csockf_medium_tcp6/1, ttest_ssocko_csockf_large_tcp4/1, ttest_ssocko_csockf_large_tcp6/1, ttest_ssocko_csockf_large_tcpL/1, ttest_ssocko_csocko_small_tcp4/1, ttest_ssocko_csocko_small_tcp6/1, ttest_ssocko_csocko_small_tcpL/1, ttest_ssocko_csocko_medium_tcp4/1, ttest_ssocko_csocko_medium_tcp6/1, ttest_ssocko_csocko_medium_tcpL/1, ttest_ssocko_csocko_large_tcp4/1, ttest_ssocko_csocko_large_tcp6/1, ttest_ssocko_csocko_large_tcpL/1, ttest_ssocko_csockt_small_tcp4/1, ttest_ssocko_csockt_small_tcp6/1, ttest_ssocko_csockt_small_tcpL/1, ttest_ssocko_csockt_medium_tcp4/1, ttest_ssocko_csockt_medium_tcp6/1, ttest_ssocko_csockt_medium_tcpL/1, ttest_ssocko_csockt_large_tcp4/1, ttest_ssocko_csockt_large_tcp6/1, ttest_ssocko_csockt_large_tcpL/1, %% Server: transport = socket(tcp), active = true %% Client: transport = gen_tcp ttest_ssockt_cgenf_small_tcp4/1, ttest_ssockt_cgenf_small_tcp6/1, ttest_ssockt_cgenf_medium_tcp4/1, ttest_ssockt_cgenf_medium_tcp6/1, ttest_ssockt_cgenf_large_tcp4/1, ttest_ssockt_cgenf_large_tcp6/1, ttest_ssockt_cgeno_small_tcp4/1, ttest_ssockt_cgeno_small_tcp6/1, ttest_ssockt_cgeno_medium_tcp4/1, ttest_ssockt_cgeno_medium_tcp6/1, ttest_ssockt_cgeno_large_tcp4/1, ttest_ssockt_cgeno_large_tcp6/1, ttest_ssockt_cgent_small_tcp4/1, ttest_ssockt_cgent_small_tcp6/1, ttest_ssockt_cgent_medium_tcp4/1, ttest_ssockt_cgent_medium_tcp6/1, ttest_ssockt_cgent_large_tcp4/1, ttest_ssockt_cgent_large_tcp6/1, %% Server: transport = socket(tcp), active = true %% Client: transport = socket(tcp) ttest_ssockt_csockf_small_tcp4/1, ttest_ssockt_csockf_small_tcp6/1, ttest_ssockt_csockf_small_tcpL/1, ttest_ssockt_csockf_medium_tcp4/1, ttest_ssockt_csockf_medium_tcp6/1, ttest_ssockt_csockf_medium_tcpL/1, ttest_ssockt_csockf_large_tcp4/1, ttest_ssockt_csockf_large_tcp6/1, ttest_ssockt_csockf_large_tcpL/1, ttest_ssockt_csocko_small_tcp4/1, ttest_ssockt_csocko_small_tcp6/1, ttest_ssockt_csocko_small_tcpL/1, ttest_ssockt_csocko_medium_tcp4/1, ttest_ssockt_csocko_medium_tcp6/1, ttest_ssockt_csocko_medium_tcpL/1, ttest_ssockt_csocko_large_tcp4/1, ttest_ssockt_csocko_large_tcp6/1, ttest_ssockt_csocko_large_tcpL/1, ttest_ssockt_csockt_small_tcp4/1, ttest_ssockt_csockt_small_tcp6/1, ttest_ssockt_csockt_small_tcpL/1, ttest_ssockt_csockt_medium_tcp4/1, ttest_ssockt_csockt_medium_tcp6/1, ttest_ssockt_csockt_medium_tcpL/1, ttest_ssockt_csockt_large_tcp4/1, ttest_ssockt_csockt_large_tcp6/1, ttest_ssockt_csockt_large_tcpL/1 %% Tickets ]). %% Internal exports %% -export([]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -define(LIB, socket_test_lib). -define(TTEST_LIB, socket_test_ttest_lib). -define(LOGGER, socket_test_logger). -define(BASIC_REQ, <<"hejsan">>). -define(BASIC_REP, <<"hoppsan">>). -define(DATA, <<"HOPPSAN">>). % Temporary -define(FAIL(R), exit(R)). -define(SLEEP(T), receive after T -> ok end). -define(MINS(M), timer:minutes(M)). -define(SECS(S), timer:seconds(S)). -define(TT(T), ct:timetrap(T)). -define(F(F, A), ?LIB:f(F, A)). -define(TPP_SMALL, lists:seq(1, 8)). -define(TPP_MEDIUM, lists:flatten(lists:duplicate(1024, ?TPP_SMALL))). -define(TPP_LARGE, lists:flatten(lists:duplicate(1024, ?TPP_MEDIUM))). -define(TPP_SMALL_NUM, 10000). -define(TPP_MEDIUM_NUM, 1000). -define(TPP_LARGE_NUM, 100). -define(TTEST_RUNTIME, ?SECS(10)). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% suite() -> [{ct_hooks,[ts_install_cth]}, {timetrap,{minutes,1}}]. all() -> Groups = [{api, "ESOCK_TEST_API", include}, {socket_close, "ESOCK_TEST_SOCK_CLOSE", include}, {traffic, "ESOCK_TEST_TRAFFIC", include}, {ttest, "ESOCK_TEST_TTEST", exclude}], [use_group(Group, Env, Default) || {Group, Env, Default} <- Groups]. use_group(Group, Env, Default) -> case os:getenv(Env) of false when (Default =:= include) -> [{group, Group}]; false -> []; Val -> case list_to_atom(string:to_lower(Val)) of Use when (Use =:= include) orelse (Use =:= enable) orelse (Use =:= true) -> [{group, Group}]; _ -> [] end end. groups() -> [{api, [], api_cases()}, {api_misc, [], api_misc_cases()}, {api_basic, [], api_basic_cases()}, {api_async, [], api_async_cases()}, {api_options, [], api_options_cases()}, {api_options_otp, [], api_options_otp_cases()}, {api_options_socket, [], api_options_socket_cases()}, {api_option_sock_acceptconn, [], api_option_sock_acceptconn_cases()}, {api_options_ip, [], api_options_ip_cases()}, %% {api_options_ipv6, [], api_options_ipv6_cases()}, %% {api_options_tcp, [], api_options_tcp_cases()}, %% {api_options_udp, [], api_options_udp_cases()}, %% {api_options_sctp, [], api_options_sctp_cases()}, {api_op_with_timeout, [], api_op_with_timeout_cases()}, {socket_close, [], socket_close_cases()}, {sc_ctrl_proc_exit, [], sc_cp_exit_cases()}, {sc_local_close, [], sc_lc_cases()}, {sc_remote_close, [], sc_rc_cases()}, {sc_remote_shutdown, [], sc_rs_cases()}, {traffic, [], traffic_cases()}, {traffic_counters, [], traffic_counters_cases()}, {traffic_chunks, [], traffic_chunks_cases()}, {traffic_pp_send_recv, [], traffic_pp_send_recv_cases()}, {traffic_pp_sendto_recvfrom, [], traffic_pp_sendto_recvfrom_cases()}, {traffic_pp_sendmsg_recvmsg, [], traffic_pp_sendmsg_recvmsg_cases()}, {ttest, [], ttest_cases()}, {ttest_sgenf, [], ttest_sgenf_cases()}, {ttest_sgenf_cgen, [], ttest_sgenf_cgen_cases()}, {ttest_sgenf_cgenf, [], ttest_sgenf_cgenf_cases()}, {ttest_sgenf_cgeno, [], ttest_sgenf_cgeno_cases()}, {ttest_sgenf_cgent, [], ttest_sgenf_cgent_cases()}, {ttest_sgenf_csock, [], ttest_sgenf_csock_cases()}, {ttest_sgenf_csockf, [], ttest_sgenf_csockf_cases()}, {ttest_sgenf_csocko, [], ttest_sgenf_csocko_cases()}, {ttest_sgenf_csockt, [], ttest_sgenf_csockt_cases()}, {ttest_sgeno, [], ttest_sgeno_cases()}, {ttest_sgeno_cgen, [], ttest_sgeno_cgen_cases()}, {ttest_sgeno_cgenf, [], ttest_sgeno_cgenf_cases()}, {ttest_sgeno_cgeno, [], ttest_sgeno_cgeno_cases()}, {ttest_sgeno_cgent, [], ttest_sgeno_cgent_cases()}, {ttest_sgeno_csock, [], ttest_sgeno_csock_cases()}, {ttest_sgeno_csockf, [], ttest_sgeno_csockf_cases()}, {ttest_sgeno_csocko, [], ttest_sgeno_csocko_cases()}, {ttest_sgeno_csockt, [], ttest_sgeno_csockt_cases()}, {ttest_sgent, [], ttest_sgent_cases()}, {ttest_sgent_cgen, [], ttest_sgent_cgen_cases()}, {ttest_sgent_cgenf, [], ttest_sgent_cgenf_cases()}, {ttest_sgent_cgeno, [], ttest_sgent_cgeno_cases()}, {ttest_sgent_cgent, [], ttest_sgent_cgent_cases()}, {ttest_sgent_csock, [], ttest_sgent_csock_cases()}, {ttest_sgent_csockf, [], ttest_sgent_csockf_cases()}, {ttest_sgent_csocko, [], ttest_sgent_csocko_cases()}, {ttest_sgent_csockt, [], ttest_sgent_csockt_cases()}, {ttest_ssockf, [], ttest_ssockf_cases()}, {ttest_ssockf_cgen, [], ttest_ssockf_cgen_cases()}, {ttest_ssockf_cgenf, [], ttest_ssockf_cgenf_cases()}, {ttest_ssockf_cgeno, [], ttest_ssockf_cgeno_cases()}, {ttest_ssockf_cgent, [], ttest_ssockf_cgent_cases()}, {ttest_ssockf_csock, [], ttest_ssockf_csock_cases()}, {ttest_ssockf_csockf, [], ttest_ssockf_csockf_cases()}, {ttest_ssockf_csocko, [], ttest_ssockf_csocko_cases()}, {ttest_ssockf_csockt, [], ttest_ssockf_csockt_cases()}, {ttest_ssocko, [], ttest_ssocko_cases()}, {ttest_ssocko_cgen, [], ttest_ssocko_cgen_cases()}, {ttest_ssocko_cgenf, [], ttest_ssocko_cgenf_cases()}, {ttest_ssocko_cgeno, [], ttest_ssocko_cgeno_cases()}, {ttest_ssocko_cgent, [], ttest_ssocko_cgent_cases()}, {ttest_ssocko_csock, [], ttest_ssocko_csock_cases()}, {ttest_ssocko_csockf, [], ttest_ssocko_csockf_cases()}, {ttest_ssocko_csocko, [], ttest_ssocko_csocko_cases()}, {ttest_ssocko_csockt, [], ttest_ssocko_csockt_cases()}, {ttest_ssockt, [], ttest_ssockt_cases()}, {ttest_ssockt_cgen, [], ttest_ssockt_cgen_cases()}, {ttest_ssockt_cgenf, [], ttest_ssockt_cgenf_cases()}, {ttest_ssockt_cgeno, [], ttest_ssockt_cgeno_cases()}, {ttest_ssockt_cgent, [], ttest_ssockt_cgent_cases()}, {ttest_ssockt_csock, [], ttest_ssockt_csock_cases()}, {ttest_ssockt_csockf, [], ttest_ssockt_csockf_cases()}, {ttest_ssockt_csocko, [], ttest_ssockt_csocko_cases()}, {ttest_ssockt_csockt, [], ttest_ssockt_csockt_cases()} %% {tickets, [], ticket_cases()} ]. api_cases() -> [ {group, api_misc}, {group, api_basic}, {group, api_async}, {group, api_options}, {group, api_op_with_timeout} ]. api_misc_cases() -> [ api_m_debug ]. api_basic_cases() -> [ api_b_open_and_close_udp4, api_b_open_and_close_tcp4, api_b_open_and_close_udpL, api_b_open_and_close_tcpL, api_b_sendto_and_recvfrom_udp4, api_b_sendto_and_recvfrom_udpL, api_b_sendmsg_and_recvmsg_udp4, api_b_sendmsg_and_recvmsg_udpL, api_b_send_and_recv_tcp4, api_b_send_and_recv_tcpL, api_b_sendmsg_and_recvmsg_tcp4, api_b_sendmsg_and_recvmsg_tcpL ]. api_async_cases() -> [ api_a_connect_tcp4, api_a_connect_tcp6, api_a_sendto_and_recvfrom_udp4, api_a_sendto_and_recvfrom_udp6, api_a_sendmsg_and_recvmsg_udp4, api_a_sendmsg_and_recvmsg_udp6, api_a_send_and_recv_tcp4, api_a_send_and_recv_tcp6, api_a_sendmsg_and_recvmsg_tcp4, api_a_sendmsg_and_recvmsg_tcp6, api_a_recvfrom_cancel_udp4, api_a_recvfrom_cancel_udp6, api_a_recvmsg_cancel_udp4, api_a_recvmsg_cancel_udp6, api_a_accept_cancel_tcp4, api_a_accept_cancel_tcp6, api_a_recv_cancel_tcp4, api_a_recv_cancel_tcp6, api_a_recvmsg_cancel_tcp4, api_a_recvmsg_cancel_tcp6, api_a_mrecvfrom_cancel_udp4, api_a_mrecvfrom_cancel_udp6, api_a_mrecvmsg_cancel_udp4, api_a_mrecvmsg_cancel_udp6, api_a_maccept_cancel_tcp4, api_a_maccept_cancel_tcp6, api_a_mrecv_cancel_tcp4, api_a_mrecv_cancel_tcp6, api_a_mrecvmsg_cancel_tcp4, api_a_mrecvmsg_cancel_tcp6 ]. api_options_cases() -> [ {group, api_options_otp}, {group, api_options_socket}, {group, api_options_ip}% , %% {group, api_options_ipv6}, %% {group, api_options_tcp}, %% {group, api_options_udp}, %% {group, api_options_sctp} ]. api_options_otp_cases() -> [ api_opt_simple_otp_options, api_opt_simple_otp_rcvbuf_option, api_opt_simple_otp_controlling_process ]. api_options_socket_cases() -> [ {group, api_option_sock_acceptconn}, api_opt_sock_acceptfilter, api_opt_sock_bindtodevice, api_opt_sock_broadcast, api_opt_sock_debug, api_opt_sock_domain, api_opt_sock_dontroute, api_opt_sock_error, api_opt_sock_keepalive, api_opt_sock_linger ]. api_option_sock_acceptconn_cases() -> [ api_opt_sock_acceptconn_udp, api_opt_sock_acceptconn_tcp ]. api_options_ip_cases() -> [ api_opt_ip_add_drop_membership ]. %% api_options_ipv6_cases() -> %% [ %% ]. api_op_with_timeout_cases() -> [ api_to_connect_tcp4, api_to_connect_tcp6, api_to_accept_tcp4, api_to_accept_tcp6, api_to_maccept_tcp4, api_to_maccept_tcp6, api_to_send_tcp4, api_to_send_tcp6, api_to_sendto_udp4, api_to_sendto_udp6, api_to_sendmsg_tcp4, api_to_sendmsg_tcp6, api_to_recv_udp4, api_to_recv_udp6, api_to_recv_tcp4, api_to_recv_tcp6, api_to_recvfrom_udp4, api_to_recvfrom_udp6, api_to_recvmsg_udp4, api_to_recvmsg_udp6, api_to_recvmsg_tcp4, api_to_recvmsg_tcp6 ]. %% These cases tests what happens when the socket is closed/shutdown, %% locally or remotely. socket_close_cases() -> [ {group, sc_ctrl_proc_exit}, {group, sc_local_close}, {group, sc_remote_close}, {group, sc_remote_shutdown} ]. %% These cases are all about socket cleanup after the controlling process %% exits *without* explicitly calling socket:close/1. sc_cp_exit_cases() -> [ sc_cpe_socket_cleanup_tcp4, sc_cpe_socket_cleanup_tcp6, sc_cpe_socket_cleanup_tcpL, sc_cpe_socket_cleanup_udp4, sc_cpe_socket_cleanup_udp6, sc_cpe_socket_cleanup_udpL ]. %% These cases tests what happens when the socket is closed locally. sc_lc_cases() -> [ sc_lc_recv_response_tcp4, sc_lc_recv_response_tcp6, sc_lc_recv_response_tcpL, sc_lc_recvfrom_response_udp4, sc_lc_recvfrom_response_udp6, sc_lc_recvfrom_response_udpL, sc_lc_recvmsg_response_tcp4, sc_lc_recvmsg_response_tcp6, sc_lc_recvmsg_response_tcpL, sc_lc_recvmsg_response_udp4, sc_lc_recvmsg_response_udp6, sc_lc_recvmsg_response_udpL, sc_lc_acceptor_response_tcp4, sc_lc_acceptor_response_tcp6, sc_lc_acceptor_response_tcpL ]. %% These cases tests what happens when the socket is closed remotely. sc_rc_cases() -> [ sc_rc_recv_response_tcp4, sc_rc_recv_response_tcp6, sc_rc_recv_response_tcpL, sc_rc_recvmsg_response_tcp4, sc_rc_recvmsg_response_tcp6, sc_rc_recvmsg_response_tcpL ]. %% These cases tests what happens when the socket is shutdown/closed remotely %% after writing and reading is ongoing. sc_rs_cases() -> [ sc_rs_recv_send_shutdown_receive_tcp4, sc_rs_recv_send_shutdown_receive_tcp6, sc_rs_recv_send_shutdown_receive_tcpL, sc_rs_recvmsg_send_shutdown_receive_tcp4, sc_rs_recvmsg_send_shutdown_receive_tcp6, sc_rs_recvmsg_send_shutdown_receive_tcpL ]. traffic_cases() -> [ {group, traffic_counters}, {group, traffic_chunks}, {group, traffic_pp_send_recv}, {group, traffic_pp_sendto_recvfrom}, {group, traffic_pp_sendmsg_recvmsg} ]. traffic_counters_cases() -> [ traffic_send_and_recv_counters_tcp4, traffic_send_and_recv_counters_tcp6, traffic_send_and_recv_counters_tcpL, traffic_sendmsg_and_recvmsg_counters_tcp4, traffic_sendmsg_and_recvmsg_counters_tcp6, traffic_sendmsg_and_recvmsg_counters_tcpL, traffic_sendto_and_recvfrom_counters_udp4, traffic_sendto_and_recvfrom_counters_udp6, traffic_sendto_and_recvfrom_counters_udpL, traffic_sendmsg_and_recvmsg_counters_udp4, traffic_sendmsg_and_recvmsg_counters_udp6, traffic_sendmsg_and_recvmsg_counters_udpL ]. traffic_chunks_cases() -> [ traffic_send_and_recv_chunks_tcp4, traffic_send_and_recv_chunks_tcp6, traffic_send_and_recv_chunks_tcpL ]. traffic_pp_send_recv_cases() -> [ traffic_ping_pong_small_send_and_recv_tcp4, traffic_ping_pong_small_send_and_recv_tcp6, traffic_ping_pong_small_send_and_recv_tcpL, traffic_ping_pong_medium_send_and_recv_tcp4, traffic_ping_pong_medium_send_and_recv_tcp6, traffic_ping_pong_medium_send_and_recv_tcpL, traffic_ping_pong_large_send_and_recv_tcp4, traffic_ping_pong_large_send_and_recv_tcp6, traffic_ping_pong_large_send_and_recv_tcpL ]. traffic_pp_sendto_recvfrom_cases() -> [ traffic_ping_pong_small_sendto_and_recvfrom_udp4, traffic_ping_pong_small_sendto_and_recvfrom_udp6, traffic_ping_pong_small_sendto_and_recvfrom_udpL, traffic_ping_pong_medium_sendto_and_recvfrom_udp4, traffic_ping_pong_medium_sendto_and_recvfrom_udp6, traffic_ping_pong_medium_sendto_and_recvfrom_udpL ]. traffic_pp_sendmsg_recvmsg_cases() -> [ traffic_ping_pong_small_sendmsg_and_recvmsg_tcp4, traffic_ping_pong_small_sendmsg_and_recvmsg_tcp6, traffic_ping_pong_small_sendmsg_and_recvmsg_tcpL, traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp4, traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp6, traffic_ping_pong_medium_sendmsg_and_recvmsg_tcpL, traffic_ping_pong_large_sendmsg_and_recvmsg_tcp4, traffic_ping_pong_large_sendmsg_and_recvmsg_tcp6, traffic_ping_pong_large_sendmsg_and_recvmsg_tcpL, traffic_ping_pong_small_sendmsg_and_recvmsg_udp4, traffic_ping_pong_small_sendmsg_and_recvmsg_udp6, traffic_ping_pong_small_sendmsg_and_recvmsg_udpL, traffic_ping_pong_medium_sendmsg_and_recvmsg_udp4, traffic_ping_pong_medium_sendmsg_and_recvmsg_udp6, traffic_ping_pong_medium_sendmsg_and_recvmsg_udpL ]. ttest_cases() -> [ %% Server: transport = gen_tcp, active = false {group, ttest_sgenf}, %% Server: transport = gen_tcp, active = once {group, ttest_sgeno}, %% Server: transport = gen_tcp, active = true {group, ttest_sgent}, %% Server: transport = socket(tcp), active = false {group, ttest_ssockf}, %% Server: transport = socket(tcp), active = once {group, ttest_ssocko}, %% Server: transport = socket(tcp), active = true {group, ttest_ssockt} ]. %% Server: transport = gen_tcp, active = false ttest_sgenf_cases() -> [ {group, ttest_sgenf_cgen}, {group, ttest_sgenf_csock} ]. %% Server: transport = gen_tcp, active = false %% Client: transport = gen_tcp ttest_sgenf_cgen_cases() -> [ {group, ttest_sgenf_cgenf}, {group, ttest_sgenf_cgeno}, {group, ttest_sgenf_cgent} ]. %% Server: transport = gen_tcp, active = false %% Client: transport = gen_tcp, active = false ttest_sgenf_cgenf_cases() -> [ ttest_sgenf_cgenf_small_tcp4, ttest_sgenf_cgenf_small_tcp6, ttest_sgenf_cgenf_medium_tcp4, ttest_sgenf_cgenf_medium_tcp6, ttest_sgenf_cgenf_large_tcp4, ttest_sgenf_cgenf_large_tcp6 ]. %% Server: transport = gen_tcp, active = false %% Client: transport = gen_tcp, active = once ttest_sgenf_cgeno_cases() -> [ ttest_sgenf_cgeno_small_tcp4, ttest_sgenf_cgeno_small_tcp6, ttest_sgenf_cgeno_medium_tcp4, ttest_sgenf_cgeno_medium_tcp6, ttest_sgenf_cgeno_large_tcp4, ttest_sgenf_cgeno_large_tcp6 ]. %% Server: transport = gen_tcp, active = false %% Client: transport = gen_tcp, active = true ttest_sgenf_cgent_cases() -> [ ttest_sgenf_cgent_small_tcp4, ttest_sgenf_cgent_small_tcp6, ttest_sgenf_cgent_medium_tcp4, ttest_sgenf_cgent_medium_tcp6, ttest_sgenf_cgent_large_tcp4, ttest_sgenf_cgent_large_tcp6 ]. %% Server: transport = gen_tcp, active = false %% Client: transport = socket(tcp) ttest_sgenf_csock_cases() -> [ {group, ttest_sgenf_csockf}, {group, ttest_sgenf_csocko}, {group, ttest_sgenf_csockt} ]. ttest_sgenf_csockf_cases() -> [ ttest_sgenf_csockf_small_tcp4, ttest_sgenf_csockf_small_tcp6, ttest_sgenf_csockf_medium_tcp4, ttest_sgenf_csockf_medium_tcp6, ttest_sgenf_csockf_large_tcp4, ttest_sgenf_csockf_large_tcp6 ]. ttest_sgenf_csocko_cases() -> [ ttest_sgenf_csocko_small_tcp4, ttest_sgenf_csocko_small_tcp6, ttest_sgenf_csocko_medium_tcp4, ttest_sgenf_csocko_medium_tcp6, ttest_sgenf_csocko_large_tcp4, ttest_sgenf_csocko_large_tcp6 ]. ttest_sgenf_csockt_cases() -> [ ttest_sgenf_csockt_small_tcp4, ttest_sgenf_csockt_small_tcp6, ttest_sgenf_csockt_medium_tcp4, ttest_sgenf_csockt_medium_tcp6, ttest_sgenf_csockt_large_tcp4, ttest_sgenf_csockt_large_tcp6 ]. %% Server: transport = gen_tcp, active = once ttest_sgeno_cases() -> [ {group, ttest_sgeno_cgen}, {group, ttest_sgeno_csock} ]. %% Server: transport = gen_tcp, active = once %% Client: transport = gen_tcp ttest_sgeno_cgen_cases() -> [ {group, ttest_sgeno_cgenf}, {group, ttest_sgeno_cgeno}, {group, ttest_sgeno_cgent} ]. %% Server: transport = gen_tcp, active = once %% Client: transport = gen_tcp, active = false ttest_sgeno_cgenf_cases() -> [ ttest_sgeno_cgenf_small_tcp4, ttest_sgeno_cgenf_small_tcp6, ttest_sgeno_cgenf_medium_tcp4, ttest_sgeno_cgenf_medium_tcp6, ttest_sgeno_cgenf_large_tcp4, ttest_sgeno_cgenf_large_tcp6 ]. %% Server: transport = gen_tcp, active = once %% Client: transport = gen_tcp, active = once ttest_sgeno_cgeno_cases() -> [ ttest_sgeno_cgeno_small_tcp4, ttest_sgeno_cgeno_small_tcp6, ttest_sgeno_cgeno_medium_tcp4, ttest_sgeno_cgeno_medium_tcp6, ttest_sgeno_cgeno_large_tcp4, ttest_sgeno_cgeno_large_tcp6 ]. %% Server: transport = gen_tcp, active = once %% Client: transport = gen_tcp, active = true ttest_sgeno_cgent_cases() -> [ ttest_sgeno_cgent_small_tcp4, ttest_sgeno_cgent_small_tcp6, ttest_sgeno_cgent_medium_tcp4, ttest_sgeno_cgent_medium_tcp6, ttest_sgeno_cgent_large_tcp4, ttest_sgeno_cgent_large_tcp6 ]. %% Server: transport = gen_tcp, active = once %% Client: transport = socket(tcp) ttest_sgeno_csock_cases() -> [ {group, ttest_sgeno_csockf}, {group, ttest_sgeno_csocko}, {group, ttest_sgeno_csockt} ]. ttest_sgeno_csockf_cases() -> [ ttest_sgeno_csockf_small_tcp4, ttest_sgeno_csockf_small_tcp6, ttest_sgeno_csockf_medium_tcp4, ttest_sgeno_csockf_medium_tcp6, ttest_sgeno_csockf_large_tcp4, ttest_sgeno_csockf_large_tcp6 ]. ttest_sgeno_csocko_cases() -> [ ttest_sgeno_csocko_small_tcp4, ttest_sgeno_csocko_small_tcp6, ttest_sgeno_csocko_medium_tcp4, ttest_sgeno_csocko_medium_tcp6, ttest_sgeno_csocko_large_tcp4, ttest_sgeno_csocko_large_tcp6 ]. ttest_sgeno_csockt_cases() -> [ ttest_sgeno_csockt_small_tcp4, ttest_sgeno_csockt_small_tcp6, ttest_sgeno_csockt_medium_tcp4, ttest_sgeno_csockt_medium_tcp6, ttest_sgeno_csockt_large_tcp4, ttest_sgeno_csockt_large_tcp6 ]. %% Server: transport = gen_tcp, active = true ttest_sgent_cases() -> [ {group, ttest_sgent_cgen}, {group, ttest_sgent_csock} ]. %% Server: transport = gen_tcp, active = true %% Client: transport = gen_tcp ttest_sgent_cgen_cases() -> [ {group, ttest_sgent_cgenf}, {group, ttest_sgent_cgeno}, {group, ttest_sgent_cgent} ]. %% Server: transport = gen_tcp, active = true %% Client: transport = gen_tcp, active = false ttest_sgent_cgenf_cases() -> [ ttest_sgent_cgenf_small_tcp4, ttest_sgent_cgenf_small_tcp6, ttest_sgent_cgenf_medium_tcp4, ttest_sgent_cgenf_medium_tcp6, ttest_sgent_cgenf_large_tcp4, ttest_sgent_cgenf_large_tcp6 ]. %% Server: transport = gen_tcp, active = true %% Client: transport = gen_tcp, active = once ttest_sgent_cgeno_cases() -> [ ttest_sgent_cgeno_small_tcp4, ttest_sgent_cgeno_small_tcp6, ttest_sgent_cgeno_medium_tcp4, ttest_sgent_cgeno_medium_tcp6, ttest_sgent_cgeno_large_tcp4, ttest_sgent_cgeno_large_tcp6 ]. %% Server: transport = gen_tcp, active = true %% Client: transport = gen_tcp, active = true ttest_sgent_cgent_cases() -> [ ttest_sgent_cgent_small_tcp4, ttest_sgent_cgent_small_tcp6, ttest_sgent_cgent_medium_tcp4, ttest_sgent_cgent_medium_tcp6, ttest_sgent_cgent_large_tcp4, ttest_sgent_cgent_large_tcp6 ]. %% Server: transport = gen_tcp, active = true %% Client: transport = socket(tcp) ttest_sgent_csock_cases() -> [ {group, ttest_sgent_csockf}, {group, ttest_sgent_csocko}, {group, ttest_sgent_csockt} ]. ttest_sgent_csockf_cases() -> [ ttest_sgent_csockf_small_tcp4, ttest_sgent_csockf_small_tcp6, ttest_sgent_csockf_medium_tcp4, ttest_sgent_csockf_medium_tcp6, ttest_sgent_csockf_large_tcp4, ttest_sgent_csockf_large_tcp6 ]. ttest_sgent_csocko_cases() -> [ ttest_sgent_csocko_small_tcp4, ttest_sgent_csocko_small_tcp6, ttest_sgent_csocko_medium_tcp4, ttest_sgent_csocko_medium_tcp6, ttest_sgent_csocko_large_tcp4, ttest_sgent_csocko_large_tcp6 ]. ttest_sgent_csockt_cases() -> [ ttest_sgent_csockt_small_tcp4, ttest_sgent_csockt_small_tcp6, ttest_sgent_csockt_medium_tcp4, ttest_sgent_csockt_medium_tcp6, ttest_sgent_csockt_large_tcp4, ttest_sgent_csockt_large_tcp6 ]. %% Server: transport = socket(tcp), active = false ttest_ssockf_cases() -> [ {group, ttest_ssockf_cgen}, {group, ttest_ssockf_csock} ]. %% Server: transport = socket(tcp), active = false %% Client: transport = gen_tcp ttest_ssockf_cgen_cases() -> [ {group, ttest_ssockf_cgenf}, {group, ttest_ssockf_cgeno}, {group, ttest_ssockf_cgent} ]. %% Server: transport = socket(tcp), active = false %% Client: transport = gen_tcp, active = false ttest_ssockf_cgenf_cases() -> [ ttest_ssockf_cgenf_small_tcp4, ttest_ssockf_cgenf_small_tcp6, ttest_ssockf_cgenf_medium_tcp4, ttest_ssockf_cgenf_medium_tcp6, ttest_ssockf_cgenf_large_tcp4, ttest_ssockf_cgenf_large_tcp6 ]. %% Server: transport = socket(tcp), active = false %% Client: transport = gen_tcp, active = once ttest_ssockf_cgeno_cases() -> [ ttest_ssockf_cgeno_small_tcp4, ttest_ssockf_cgeno_small_tcp6, ttest_ssockf_cgeno_medium_tcp4, ttest_ssockf_cgeno_medium_tcp6, ttest_ssockf_cgeno_large_tcp4, ttest_ssockf_cgeno_large_tcp6 ]. %% Server: transport = socket(tcp), active = false %% Client: transport = gen_tcp, active = true ttest_ssockf_cgent_cases() -> [ ttest_ssockf_cgent_small_tcp4, ttest_ssockf_cgent_small_tcp6, ttest_ssockf_cgent_medium_tcp4, ttest_ssockf_cgent_medium_tcp6, ttest_ssockf_cgent_large_tcp4, ttest_ssockf_cgent_large_tcp6 ]. %% Server: transport = socket(tcp), active = false %% Client: transport = socket(tcp) ttest_ssockf_csock_cases() -> [ {group, ttest_ssockf_csockf}, {group, ttest_ssockf_csocko}, {group, ttest_ssockf_csockt} ]. %% Server: transport = socket(tcp), active = false %% Client: transport = socket(tcp), active = false ttest_ssockf_csockf_cases() -> [ ttest_ssockf_csockf_small_tcp4, ttest_ssockf_csockf_small_tcp6, ttest_ssockf_csockf_small_tcpL, ttest_ssockf_csockf_medium_tcp4, ttest_ssockf_csockf_medium_tcp6, ttest_ssockf_csockf_medium_tcpL, ttest_ssockf_csockf_large_tcp4, ttest_ssockf_csockf_large_tcp6, ttest_ssockf_csockf_large_tcpL ]. %% Server: transport = socket(tcp), active = false %% Client: transport = socket(tcp), active = once ttest_ssockf_csocko_cases() -> [ ttest_ssockf_csocko_small_tcp4, ttest_ssockf_csocko_small_tcp6, ttest_ssockf_csocko_small_tcpL, ttest_ssockf_csocko_medium_tcp4, ttest_ssockf_csocko_medium_tcp6, ttest_ssockf_csocko_medium_tcpL, ttest_ssockf_csocko_large_tcp4, ttest_ssockf_csocko_large_tcp6, ttest_ssockf_csocko_large_tcpL ]. %% Server: transport = socket(tcp), active = false %% Client: transport = socket(tcp), active = true ttest_ssockf_csockt_cases() -> [ ttest_ssockf_csockt_small_tcp4, ttest_ssockf_csockt_small_tcp6, ttest_ssockf_csockt_small_tcpL, ttest_ssockf_csockt_medium_tcp4, ttest_ssockf_csockt_medium_tcp6, ttest_ssockf_csockt_medium_tcpL, ttest_ssockf_csockt_large_tcp4, ttest_ssockf_csockt_large_tcp6, ttest_ssockf_csockt_large_tcpL ]. %% Server: transport = socket(tcp), active = once ttest_ssocko_cases() -> [ {group, ttest_ssocko_cgen}, {group, ttest_ssocko_csock} ]. %% Server: transport = socket(tcp), active = once %% Client: transport = gen_tcp ttest_ssocko_cgen_cases() -> [ {group, ttest_ssocko_cgenf}, {group, ttest_ssocko_cgeno}, {group, ttest_ssocko_cgent} ]. %% Server: transport = socket(tcp), active = once %% Client: transport = gen_tcp, active = false ttest_ssocko_cgenf_cases() -> [ ttest_ssocko_cgenf_small_tcp4, ttest_ssocko_cgenf_small_tcp6, ttest_ssocko_cgenf_medium_tcp4, ttest_ssocko_cgenf_medium_tcp6, ttest_ssocko_cgenf_large_tcp4, ttest_ssocko_cgenf_large_tcp6 ]. %% Server: transport = socket(tcp), active = once %% Client: transport = gen_tcp, active = once ttest_ssocko_cgeno_cases() -> [ ttest_ssocko_cgeno_small_tcp4, ttest_ssocko_cgeno_small_tcp6, ttest_ssocko_cgeno_medium_tcp4, ttest_ssocko_cgeno_medium_tcp6, ttest_ssocko_cgeno_large_tcp4, ttest_ssocko_cgeno_large_tcp6 ]. %% Server: transport = socket(tcp), active = once %% Client: transport = gen_tcp, active = true ttest_ssocko_cgent_cases() -> [ ttest_ssocko_cgent_small_tcp4, ttest_ssocko_cgent_small_tcp6, ttest_ssocko_cgent_medium_tcp4, ttest_ssocko_cgent_medium_tcp6, ttest_ssocko_cgent_large_tcp4, ttest_ssocko_cgent_large_tcp6 ]. %% Server: transport = socket(tcp), active = once %% Client: transport = socket(tcp) ttest_ssocko_csock_cases() -> [ {group, ttest_ssocko_csockf}, {group, ttest_ssocko_csocko}, {group, ttest_ssocko_csockt} ]. %% Server: transport = socket(tcp), active = once %% Client: transport = socket(tcp), active = false ttest_ssocko_csockf_cases() -> [ ttest_ssocko_csockf_small_tcp4, ttest_ssocko_csockf_small_tcp6, ttest_ssocko_csockf_small_tcpL, ttest_ssocko_csockf_medium_tcp4, ttest_ssocko_csockf_medium_tcp6, ttest_ssocko_csockf_medium_tcpL, ttest_ssocko_csockf_large_tcp4, ttest_ssocko_csockf_large_tcp6, ttest_ssocko_csockf_large_tcpL ]. %% Server: transport = socket(tcp), active = once %% Client: transport = socket(tcp), active = once ttest_ssocko_csocko_cases() -> [ ttest_ssocko_csocko_small_tcp4, ttest_ssocko_csocko_small_tcp6, ttest_ssocko_csocko_small_tcpL, ttest_ssocko_csocko_medium_tcp4, ttest_ssocko_csocko_medium_tcp6, ttest_ssocko_csocko_medium_tcpL, ttest_ssocko_csocko_large_tcp4, ttest_ssocko_csocko_large_tcp6, ttest_ssocko_csocko_large_tcpL ]. %% Server: transport = socket(tcp), active = once %% Client: transport = socket(tcp), active = true ttest_ssocko_csockt_cases() -> [ ttest_ssocko_csockt_small_tcp4, ttest_ssocko_csockt_small_tcp6, ttest_ssocko_csockt_small_tcpL, ttest_ssocko_csockt_medium_tcp4, ttest_ssocko_csockt_medium_tcp6, ttest_ssocko_csockt_medium_tcpL, ttest_ssocko_csockt_large_tcp4, ttest_ssocko_csockt_large_tcp6, ttest_ssocko_csockt_large_tcpL ]. %% Server: transport = socket(tcp), active = true ttest_ssockt_cases() -> [ {group, ttest_ssockt_cgen}, {group, ttest_ssockt_csock} ]. %% Server: transport = socket(tcp), active = true %% Client: transport = gen_tcp ttest_ssockt_cgen_cases() -> [ {group, ttest_ssockt_cgenf}, {group, ttest_ssockt_cgeno}, {group, ttest_ssockt_cgent} ]. %% Server: transport = socket(tcp), active = true %% Client: transport = gen_tcp, active = false ttest_ssockt_cgenf_cases() -> [ ttest_ssockt_cgenf_small_tcp4, ttest_ssockt_cgenf_small_tcp6, ttest_ssockt_cgenf_medium_tcp4, ttest_ssockt_cgenf_medium_tcp6, ttest_ssockt_cgenf_large_tcp4, ttest_ssockt_cgenf_large_tcp6 ]. %% Server: transport = socket(tcp), active = true %% Client: transport = gen_tcp, active = once ttest_ssockt_cgeno_cases() -> [ ttest_ssockt_cgeno_small_tcp4, ttest_ssockt_cgeno_small_tcp6, ttest_ssockt_cgeno_medium_tcp4, ttest_ssockt_cgeno_medium_tcp6, ttest_ssockt_cgeno_large_tcp4, ttest_ssockt_cgeno_large_tcp6 ]. %% Server: transport = socket(tcp), active = true %% Client: transport = gen_tcp, active = true ttest_ssockt_cgent_cases() -> [ ttest_ssockt_cgent_small_tcp4, ttest_ssockt_cgent_small_tcp6, ttest_ssockt_cgent_medium_tcp4, ttest_ssockt_cgent_medium_tcp6, ttest_ssockt_cgent_large_tcp4, ttest_ssockt_cgent_large_tcp6 ]. %% Server: transport = socket(tcp), active = true %% Client: transport = socket(tcp) ttest_ssockt_csock_cases() -> [ {group, ttest_ssockt_csockf}, {group, ttest_ssockt_csocko}, {group, ttest_ssockt_csockt} ]. %% Server: transport = socket(tcp), active = true %% Client: transport = socket(tcp), active = false ttest_ssockt_csockf_cases() -> [ ttest_ssockt_csockf_small_tcp4, ttest_ssockt_csockf_small_tcp6, ttest_ssockt_csockf_small_tcpL, ttest_ssockt_csockf_medium_tcp4, ttest_ssockt_csockf_medium_tcp6, ttest_ssockt_csockf_medium_tcpL, ttest_ssockt_csockf_large_tcp4, ttest_ssockt_csockf_large_tcp6, ttest_ssockt_csockf_large_tcpL ]. %% Server: transport = socket(tcp), active = true %% Client: transport = socket(tcp), active = once ttest_ssockt_csocko_cases() -> [ ttest_ssockt_csocko_small_tcp4, ttest_ssockt_csocko_small_tcp6, ttest_ssockt_csocko_small_tcpL, ttest_ssockt_csocko_medium_tcp4, ttest_ssockt_csocko_medium_tcp6, ttest_ssockt_csocko_medium_tcpL, ttest_ssockt_csocko_large_tcp4, ttest_ssockt_csocko_large_tcp6, ttest_ssockt_csocko_large_tcpL ]. %% Server: transport = socket(tcp), active = true %% Client: transport = socket(tcp), active = true ttest_ssockt_csockt_cases() -> [ ttest_ssockt_csockt_small_tcp4, ttest_ssockt_csockt_small_tcp6, ttest_ssockt_csockt_small_tcpL, ttest_ssockt_csockt_medium_tcp4, ttest_ssockt_csockt_medium_tcp6, ttest_ssockt_csockt_medium_tcpL, ttest_ssockt_csockt_large_tcp4, ttest_ssockt_csockt_large_tcp6, ttest_ssockt_csockt_large_tcpL ]. %% ticket_cases() -> %% []. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% init_per_suite(Config) -> case lists:member(socket, erlang:loaded()) of true -> case os:type() of {win32, _} -> (catch not_yet_implemented()); _ -> case quiet_mode(Config) of default -> ?LOGGER:start(), Config; Quiet -> ?LOGGER:start(Quiet), [{esock_test_quiet, Quiet}|Config] end end; false -> {skip, "esock disabled"} end. end_per_suite(_) -> (catch ?LOGGER:stop()), ok. init_per_group(ttest = _GroupName, Config) -> io:format("init_per_group(~w) -> entry with" "~n Config: ~p" "~n", [_GroupName, Config]), ttest_manager_start(), case lists:keysearch(esock_test_ttest_runtime, 1, Config) of {value, _} -> Config; false -> [{esock_test_ttest_runtime, which_ttest_runtime_env()} | Config] end; init_per_group(_GroupName, Config) -> Config. end_per_group(ttest = _GroupName, Config) -> io:format("init_per_group(~w) -> entry with" "~n Config: ~p" "~n", [_GroupName, Config]), ttest_manager_stop(), lists:keydelete(esock_test_ttest_runtime, 1, Config); end_per_group(_GroupName, Config) -> Config. init_per_testcase(_TC, Config) -> io:format("init_per_testcase(~w) -> entry with" "~n Config: ~p" "~n", [_TC, Config]), %% case quiet_mode(Config) of %% default -> %% ?LOGGER:start(); %% Quiet -> %% ?LOGGER:start(Quiet) %% end, Config. end_per_testcase(_TC, Config) -> %% ?LOGGER:stop(), Config. quiet_mode(Config) -> case lists:keysearch(esock_test_quiet, 1, Config) of {value, {esock_test_quiet, Quiet}} -> Quiet; false -> case os:getenv("ESOCK_TEST_QUIET") of "true" -> true; "false" -> false; _ -> default end end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %% %% API MISC %% %% %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% A simple test case that tests that the global debug can be changed. %% At the same time, it will test the info function (since it uses it %% for verification). api_m_debug(suite) -> []; api_m_debug(doc) -> []; api_m_debug(_Config) when is_list(_Config) -> ?TT(?SECS(5)), tc_try(api_m_debug, fun() -> has_bugfree_gcc() end, fun() -> ok = api_m_debug() end). %% For some reason this test case triggers a gcc bug, which causes %% a segfault, on an ancient Fedora 16 VM. So, check the version of gcc... %% Not pretty, but the simplest way to skip (without actually testing %% for the host). has_bugfree_gcc() -> has_bugfree_gcc(os:type()). %% Make sure we are on linux has_bugfree_gcc({unix, linux}) -> has_bugfree_gcc2(string:trim(os:cmd("cat /etc/issue"))); has_bugfree_gcc(_) -> ok. %% Make sure we are on Fedora 16 has_bugfree_gcc2("Fedora release 16 " ++ _) -> has_bugfree_gcc3(os:cmd("gcc --version")); has_bugfree_gcc2("Welcome to SUSE Linux " ++ _) -> has_bugfree_gcc4(os:cmd("gcc --version")); has_bugfree_gcc2(_) -> ok. has_bugfree_gcc3("gcc (GCC) 4.6.3 20120306 (Red Hat 4.6.3-2" ++ _) -> skip("Buggy GCC"); has_bugfree_gcc3(_) -> ok. has_bugfree_gcc4("gcc (SUSE Linux) 4.3.2" ++ _) -> skip("Buggy GCC"); has_bugfree_gcc4(_) -> ok. api_m_debug() -> i("get initial info"), #{debug := D0} = socket:info(), D1 = not D0, i("set new debug (~w => ~w)", [D0, D1]), ok = socket:debug(D1), i("get updated info (~w)", [D1]), #{debug := D1} = socket:info(), D2 = not D1, i("set new debug (~w => ~w)", [D1, D2]), ok = socket:debug(D2), i("get updated info (~w)", [D2]), #{debug := D2} = socket:info(), i("ok"), ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %% %% API BASIC %% %% %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically open (create) and close an IPv4 UDP (dgram) socket. %% With some extra checks... api_b_open_and_close_udp4(suite) -> []; api_b_open_and_close_udp4(doc) -> []; api_b_open_and_close_udp4(_Config) when is_list(_Config) -> ?TT(?SECS(5)), tc_try(api_b_open_and_close_udp4, fun() -> InitState = #{domain => inet, type => dgram, protocol => udp}, ok = api_b_open_and_close(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically open (create) and close an IPv4 TCP (stream) socket. %% With some extra checks... api_b_open_and_close_tcp4(suite) -> []; api_b_open_and_close_tcp4(doc) -> []; api_b_open_and_close_tcp4(_Config) when is_list(_Config) -> ?TT(?SECS(5)), tc_try(api_b_open_and_close_tcp4, fun() -> InitState = #{domain => inet, type => stream, protocol => tcp}, ok = api_b_open_and_close(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically open (create) and close an Unix Domain dgram (UDP) socket. %% With some extra checks... api_b_open_and_close_udpL(suite) -> []; api_b_open_and_close_udpL(doc) -> []; api_b_open_and_close_udpL(_Config) when is_list(_Config) -> ?TT(?SECS(5)), tc_try(api_b_open_and_close_udpL, fun() -> has_support_unix_domain_socket() end, fun() -> InitState = #{domain => local, type => dgram, protocol => default}, ok = api_b_open_and_close(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically open (create) and close an Unix Domain stream (TCP) socket. %% With some extra checks... api_b_open_and_close_tcpL(suite) -> []; api_b_open_and_close_tcpL(doc) -> []; api_b_open_and_close_tcpL(_Config) when is_list(_Config) -> ?TT(?SECS(5)), tc_try(api_b_open_and_close_tcpL, fun() -> has_support_unix_domain_socket() end, fun() -> InitState = #{domain => local, type => stream, protocol => default}, ok = api_b_open_and_close(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% api_b_open_and_close(InitState) -> Seq = [ #{desc => "open", cmd => fun(#{domain := Domain, type := Type, protocol := Protocol} = S) -> Res = socket:open(Domain, Type, Protocol), {ok, {S, Res}} end}, #{desc => "validate open", cmd => fun({S, {ok, Sock}}) -> NewS = S#{socket => Sock}, {ok, NewS}; ({_, {error, _} = ERROR}) -> ERROR end}, #{desc => "get domain (maybe)", cmd => fun(#{socket := Sock} = S) -> Res = socket:getopt(Sock, socket, domain), {ok, {S, Res}} end}, #{desc => "validate domain (maybe)", cmd => fun({#{domain := Domain} = S, {ok, Domain}}) -> {ok, S}; ({#{domain := ExpDomain}, {ok, Domain}}) -> {error, {unexpected_domain, ExpDomain, Domain}}; %% Some platforms do not support this option ({S, {error, einval}}) -> {ok, S}; ({_, {error, _} = ERROR}) -> ERROR end}, #{desc => "get type", cmd => fun(#{socket := Sock} = State) -> Res = socket:getopt(Sock, socket, type), {ok, {State, Res}} end}, #{desc => "validate type", cmd => fun({#{type := Type} = State, {ok, Type}}) -> {ok, State}; ({#{type := ExpType}, {ok, Type}}) -> {error, {unexpected_type, ExpType, Type}}; ({_, {error, _} = ERROR}) -> ERROR end}, #{desc => "get protocol", cmd => fun(#{socket := Sock} = State) -> case socket:supports(options, socket, protocol) of true -> Res = socket:getopt(Sock, socket, protocol), {ok, {State, Res}}; false -> {ok, {State, not_supported}} end end}, #{desc => "validate protocol", cmd => fun({State, not_supported}) -> ?SEV_IPRINT("socket option 'protocol' " "not supported"), {ok, State}; ({#{protocol := Protocol} = State, {ok, Protocol}}) -> {ok, State}; ({#{protocol := ExpProtocol}, {ok, Protocol}}) -> {error, {unexpected_type, ExpProtocol, Protocol}}; ({_, {error, _} = ERROR}) -> ERROR end}, #{desc => "get controlling-process", cmd => fun(#{socket := Sock} = State) -> Res = socket:getopt(Sock, otp, controlling_process), {ok, {State, Res}} end}, #{desc => "validate controlling-process", cmd => fun({State, {ok, Pid}}) -> case self() of Pid -> {ok, State}; _ -> {error, {unexpected_owner, Pid}} end; ({_, {error, _} = ERROR}) -> ERROR end}, #{desc => "close socket", cmd => fun(#{socket := Sock} = State) -> Res = socket:close(Sock), {ok, {State, Res}} end}, #{desc => "validate socket close", cmd => fun({_, ok}) -> ok; ({_, {error, _} = ERROR}) -> ERROR end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], Evaluator = ?SEV_START("tester", Seq, InitState), ok = ?SEV_AWAIT_FINISH([Evaluator]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically send and receive on an IPv4 UDP (dgram) socket using %% sendto and recvfrom.. api_b_sendto_and_recvfrom_udp4(suite) -> []; api_b_sendto_and_recvfrom_udp4(doc) -> []; api_b_sendto_and_recvfrom_udp4(_Config) when is_list(_Config) -> ?TT(?SECS(5)), tc_try(api_b_sendto_and_recvfrom_udp4, fun() -> Send = fun(Sock, Data, Dest) -> socket:sendto(Sock, Data, Dest) end, Recv = fun(Sock) -> socket:recvfrom(Sock) end, InitState = #{domain => inet, proto => udp, send => Send, recv => Recv}, ok = api_b_send_and_recv_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically send and receive on an IPv4 UDP (dgram) socket using %% sendto and recvfrom. api_b_sendto_and_recvfrom_udpL(suite) -> []; api_b_sendto_and_recvfrom_udpL(doc) -> []; api_b_sendto_and_recvfrom_udpL(_Config) when is_list(_Config) -> ?TT(?SECS(5)), tc_try(api_b_sendto_and_recvfrom_udpL, fun() -> has_support_unix_domain_socket(), unix_domain_socket_host_cond() end, fun() -> Send = fun(Sock, Data, Dest) -> socket:sendto(Sock, Data, Dest) end, Recv = fun(Sock) -> socket:recvfrom(Sock) end, InitState = #{domain => local, proto => default, send => Send, recv => Recv}, ok = api_b_send_and_recv_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically send and receive on an IPv4 UDP (dgram) socket %% using sendmsg and recvmsg. api_b_sendmsg_and_recvmsg_udp4(suite) -> []; api_b_sendmsg_and_recvmsg_udp4(doc) -> []; api_b_sendmsg_and_recvmsg_udp4(_Config) when is_list(_Config) -> ?TT(?SECS(5)), tc_try(api_b_sendmsg_and_recvmsg_udp4, fun() -> Send = fun(Sock, Data, Dest) -> %% We need tests for this, %% but this is not the place it. %% CMsgHdr = #{level => ip, %% type => tos, %% data => reliability}, %% CMsgHdrs = [CMsgHdr], MsgHdr = #{addr => Dest, %% ctrl => CMsgHdrs, iov => [Data]}, socket:sendmsg(Sock, MsgHdr) end, Recv = fun(Sock) -> %% We have some issues on old darwing... %% socket:setopt(Sock, otp, debug, true), case socket:recvmsg(Sock) of {ok, #{addr := Source, iov := [Data]}} -> %% socket:setopt(Sock, otp, debug, false), {ok, {Source, Data}}; {error, _} = ERROR -> ERROR end end, InitState = #{domain => inet, proto => udp, send => Send, recv => Recv}, ok = api_b_send_and_recv_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically send and receive on an IPv4 UDP (dgram) socket %% using sendmsg and recvmsg. api_b_sendmsg_and_recvmsg_udpL(suite) -> []; api_b_sendmsg_and_recvmsg_udpL(doc) -> []; api_b_sendmsg_and_recvmsg_udpL(_Config) when is_list(_Config) -> ?TT(?SECS(5)), tc_try(api_b_sendmsg_and_recvmsg_udpL, fun() -> has_support_unix_domain_socket(), unix_domain_socket_host_cond() end, fun() -> Send = fun(Sock, Data, Dest) -> %% We need tests for this, %% but this is not the place it. %% CMsgHdr = #{level => ip, %% type => tos, %% data => reliability}, %% CMsgHdrs = [CMsgHdr], MsgHdr = #{addr => Dest, %% ctrl => CMsgHdrs, iov => [Data]}, socket:sendmsg(Sock, MsgHdr) end, Recv = fun(Sock) -> %% We have some issues on old darwing... %% socket:setopt(Sock, otp, debug, true), case socket:recvmsg(Sock) of {ok, #{addr := Source, iov := [Data]}} -> %% socket:setopt(Sock, otp, debug, false), {ok, {Source, Data}}; {error, _} = ERROR -> ERROR end end, InitState = #{domain => local, proto => default, send => Send, recv => Recv}, ok = api_b_send_and_recv_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% api_b_send_and_recv_udp(InitState) -> Seq = [ #{desc => "local address", cmd => fun(#{domain := local = Domain} = State) -> LSASrc = which_local_socket_addr(Domain), LSADst = which_local_socket_addr(Domain), {ok, State#{lsa_src => LSASrc, lsa_dst => LSADst}}; (#{domain := Domain} = State) -> LSA = which_local_socket_addr(Domain), {ok, State#{lsa_src => LSA, lsa_dst => LSA}} end}, #{desc => "open src socket", cmd => fun(#{domain := Domain, proto := Proto} = State) -> Sock = sock_open(Domain, dgram, Proto), {ok, State#{sock_src => Sock}} end}, #{desc => "bind src", cmd => fun(#{sock_src := Sock, lsa_src := LSA}) -> case socket:bind(Sock, LSA) of {ok, _Port} -> ?SEV_IPRINT("src bound"), ok; {error, Reason} = ERROR -> ?SEV_EPRINT("src bind failed: ~p", [Reason]), ERROR end end}, #{desc => "sockname src socket", cmd => fun(#{sock_src := Sock} = State) -> SASrc = sock_sockname(Sock), ?SEV_IPRINT("src sockaddr: " "~n ~p", [SASrc]), {ok, State#{sa_src => SASrc}} end}, #{desc => "open dst socket", cmd => fun(#{domain := Domain, proto := Proto} = State) -> Sock = sock_open(Domain, dgram, Proto), {ok, State#{sock_dst => Sock}} end}, #{desc => "bind dst", cmd => fun(#{sock_dst := Sock, lsa_dst := LSA}) -> case socket:bind(Sock, LSA) of {ok, _Port} -> ?SEV_IPRINT("src bound"), ok; {error, Reason} = ERROR -> ?SEV_EPRINT("src bind failed: ~p", [Reason]), ERROR end end}, #{desc => "sockname dst socket", cmd => fun(#{sock_dst := Sock} = State) -> SADst = sock_sockname(Sock), ?SEV_IPRINT("dst sockaddr: " "~n ~p", [SADst]), {ok, State#{sa_dst => SADst}} end}, #{desc => "send req (to dst)", cmd => fun(#{sock_src := Sock, sa_dst := Dst, send := Send}) -> Send(Sock, ?BASIC_REQ, Dst) end}, #{desc => "recv req (from src)", cmd => fun(#{sock_dst := Sock, sa_src := Src, recv := Recv}) -> case Recv(Sock) of {ok, {Src, ?BASIC_REQ}} -> ok; {ok, UnexpData} -> {error, {unexpected_data, UnexpData}}; {error, _} = ERROR -> %% At the moment there is no way to get %% status or state for the socket... ERROR end end}, #{desc => "send rep (to src)", cmd => fun(#{sock_dst := Sock, sa_src := Src, send := Send}) -> Send(Sock, ?BASIC_REP, Src) end}, #{desc => "recv rep (from dst)", cmd => fun(#{sock_src := Sock, sa_dst := Dst, recv := Recv}) -> case Recv(Sock) of {ok, {Dst, ?BASIC_REP}} -> ok; {ok, UnexpData} -> {error, {unexpected_data, UnexpData}}; {error, _} = ERROR -> %% At the moment there is no way to get %% status or state for the socket... ERROR end end}, #{desc => "close src socket", cmd => fun(#{domain := local, sock_src := Sock, lsa_src := #{path := Path}} = State) -> ok = socket:close(Sock), State1 = unlink_path(Path, fun() -> maps:remove(lsa_src, State) end, fun() -> State end), {ok, maps:remove(sock_src, State1)}; (#{sock_src := Sock} = State) -> ok = socket:close(Sock), {ok, maps:remove(sock_src, State)} end}, #{desc => "close dst socket", cmd => fun(#{domain := local, sock_dst := Sock, lsa_dst := #{path := Path}} = State) -> ok = socket:close(Sock), State1 = unlink_path(Path, fun() -> maps:remove(lsa_dst, State) end, fun() -> State end), {ok, maps:remove(sock_dst, State1)}; (#{sock_dst := Sock} = State) -> ok = socket:close(Sock), {ok, maps:remove(sock_dst, State)} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], Evaluator = ?SEV_START("tester", Seq, InitState), ok = ?SEV_AWAIT_FINISH([Evaluator]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically send and receive using the "common" functions (send and recv) %% on an IPv4 TCP (stream) socket. api_b_send_and_recv_tcp4(suite) -> []; api_b_send_and_recv_tcp4(doc) -> []; api_b_send_and_recv_tcp4(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_b_send_and_recv_tcp4, fun() -> Send = fun(Sock, Data) -> socket:send(Sock, Data) end, Recv = fun(Sock) -> socket:recv(Sock) end, InitState = #{domain => inet, proto => tcp, send => Send, recv => Recv}, ok = api_b_send_and_recv_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically send and receive using the "common" functions (send and recv) %% on an Unix Domain (stream) socket (TCP). api_b_send_and_recv_tcpL(suite) -> []; api_b_send_and_recv_tcpL(doc) -> []; api_b_send_and_recv_tcpL(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_b_send_and_recv_tcpL, fun() -> has_support_unix_domain_socket() end, fun() -> Send = fun(Sock, Data) -> socket:send(Sock, Data) end, Recv = fun(Sock) -> socket:recv(Sock) end, InitState = #{domain => local, proto => default, send => Send, recv => Recv}, ok = api_b_send_and_recv_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically send and receive using the msg functions (sendmsg and recvmsg) %% on an IPv4 TCP (stream) socket. api_b_sendmsg_and_recvmsg_tcp4(suite) -> []; api_b_sendmsg_and_recvmsg_tcp4(doc) -> []; api_b_sendmsg_and_recvmsg_tcp4(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_b_sendmsg_and_recvmsg_tcp4, fun() -> Send = fun(Sock, Data) -> MsgHdr = #{iov => [Data]}, socket:sendmsg(Sock, MsgHdr) end, Recv = fun(Sock) -> case socket:recvmsg(Sock) of {ok, #{addr := undefined, iov := [Data]}} -> {ok, Data}; {error, _} = ERROR -> ERROR end end, InitState = #{domain => inet, proto => tcp, send => Send, recv => Recv}, ok = api_b_send_and_recv_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically send and receive using the msg functions (sendmsg and recvmsg) %% on an Unix Domain (stream) socket (TCP). api_b_sendmsg_and_recvmsg_tcpL(suite) -> []; api_b_sendmsg_and_recvmsg_tcpL(doc) -> []; api_b_sendmsg_and_recvmsg_tcpL(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_b_sendmsg_and_recvmsg_tcpL, fun() -> has_support_unix_domain_socket() end, fun() -> Send = fun(Sock, Data) -> MsgHdr = #{iov => [Data]}, socket:sendmsg(Sock, MsgHdr) end, Recv = fun(Sock) -> case socket:recvmsg(Sock) of %% On some platforms, the address %% is *not* provided (e.g. FreeBSD) {ok, #{addr := undefined, iov := [Data]}} -> {ok, Data}; %% On some platforms, the address %% *is* provided (e.g. linux) {ok, #{addr := #{family := local}, iov := [Data]}} -> socket:setopt(Sock, otp, debug, false), {ok, Data}; {error, _} = ERROR -> socket:setopt(Sock, otp, debug, false), ERROR end end, InitState = #{domain => local, proto => default, send => Send, recv => Recv}, ok = api_b_send_and_recv_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% api_b_send_and_recv_tcp(InitState) -> process_flag(trap_exit, true), ServerSeq = [ %% *** Wait for start order *** #{desc => "await start (from tester)", cmd => fun(State) -> Tester = ?SEV_AWAIT_START(), {ok, State#{tester => Tester}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester}) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> LSA = which_local_socket_addr(Domain), {ok, State#{lsa => LSA}} end}, #{desc => "create listen socket", cmd => fun(#{domain := Domain, proto := Proto} = State) -> case socket:open(Domain, stream, Proto) of {ok, Sock} -> {ok, State#{lsock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind to local address", cmd => fun(#{domain := local, lsock := LSock, lsa := LSA} = _State) -> case socket:bind(LSock, LSA) of {ok, _Port} -> ok; % We do not care about the port for local {error, _} = ERROR -> ERROR end; (#{lsock := LSock, lsa := LSA} = State) -> case socket:bind(LSock, LSA) of {ok, Port} -> ?SEV_IPRINT("bound to port: ~w", [Port]), {ok, State#{lport => Port}}; {error, _} = ERROR -> ERROR end end}, #{desc => "make listen socket", cmd => fun(#{lsock := LSock}) -> socket:listen(LSock) end}, #{desc => "announce ready (init)", cmd => fun(#{domain := local, tester := Tester, lsa := #{path := Path}}) -> ?SEV_ANNOUNCE_READY(Tester, init, Path), ok; (#{tester := Tester, lport := Port}) -> %% This is actually not used for unix domain socket ?SEV_ANNOUNCE_READY(Tester, init, Port), ok end}, %% The actual test #{desc => "await continue (accept)", cmd => fun(#{tester := Tester}) -> ?SEV_AWAIT_CONTINUE(Tester, tester, accept) end}, #{desc => "await connection", cmd => fun(#{lsock := LSock} = State) -> case socket:accept(LSock) of {ok, Sock} -> ?SEV_IPRINT("accepted: ~n ~p", [Sock]), {ok, State#{csock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (accept)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, accept), ok end}, #{desc => "await (recv) request", cmd => fun(#{csock := Sock, recv := Recv}) -> case Recv(Sock) of {ok, ?BASIC_REQ} -> ok; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (recv request)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv_req), ok end}, #{desc => "await continue (with send reply)", cmd => fun(#{tester := Tester}) -> ?SEV_AWAIT_CONTINUE(Tester, tester, send_reply) end}, #{desc => "send reply", cmd => fun(#{csock := Sock, send := Send}) -> Send(Sock, ?BASIC_REP) end}, #{desc => "announce ready (send reply)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, send_reply), ok end}, %% *** Termination *** #{desc => "await terminate", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "close connection socket", cmd => fun(#{csock := Sock} = State) -> ok = socket:close(Sock), {ok, maps:remove(csock, State)} end}, #{desc => "close listen socket", cmd => fun(#{domain := local, lsock := Sock, local_sa := #{path := Path}} = State) -> ok = socket:close(Sock), State1 = unlink_path(Path, fun() -> maps:remove(local_sa, State) end, fun() -> State end), {ok, maps:remove(lsock, State1)}; (#{lsock := LSock} = State) -> case socket:close(LSock) of ok -> {ok, maps:remove(lsock, State)}; {error, _} = ERROR -> ERROR end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], ClientSeq = [ %% *** Wait for start order *** #{desc => "await start (from tester)", cmd => fun(#{domain := local} = State) -> {Tester, Path} = ?SEV_AWAIT_START(), {ok, State#{tester => Tester, server_path => Path}}; (State) -> {Tester, Port} = ?SEV_AWAIT_START(), {ok, State#{tester => Tester, server_port => Port}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester}) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** The init part *** #{desc => "which server (local) address", cmd => fun(#{domain := local = Domain, server_path := Path} = State) -> LSA = which_local_socket_addr(Domain), SSA = #{family => Domain, path => Path}, {ok, State#{local_sa => LSA, server_sa => SSA}}; (#{domain := Domain, server_port := Port} = State) -> LSA = which_local_socket_addr(Domain), SSA = LSA#{port => Port}, {ok, State#{local_sa => LSA, server_sa => SSA}} end}, #{desc => "create socket", cmd => fun(#{domain := Domain, proto := Proto} = State) -> case socket:open(Domain, stream, Proto) of {ok, Sock} -> {ok, State#{sock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind to local address", cmd => fun(#{sock := Sock, local_sa := LSA} = _State) -> case socket:bind(Sock, LSA) of {ok, _Port} -> ok; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, init), ok end}, %% *** The actual test *** #{desc => "await continue (connect)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, connect) end}, #{desc => "connect to server", cmd => fun(#{sock := Sock, server_sa := SSA}) -> socket:connect(Sock, SSA) end}, #{desc => "announce ready (connect)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, connect), ok end}, #{desc => "await continue (send request)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, send_req) end}, #{desc => "send request (to server)", cmd => fun(#{sock := Sock, send := Send}) -> Send(Sock, ?BASIC_REQ) end}, #{desc => "announce ready (send request)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, send_req), ok end}, #{desc => "await recv reply (from server)", cmd => fun(#{sock := Sock, recv := Recv}) -> {ok, ?BASIC_REP} = Recv(Sock), ok end}, #{desc => "announce ready (recv reply)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv_reply), ok end}, %% *** Termination *** #{desc => "await terminate", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "close socket", cmd => fun(#{domain := local, sock := Sock, local_sa := #{path := Path}} = State) -> ok = socket:close(Sock), State1 = unlink_path(Path, fun() -> maps:remove(local_sa, State) end, fun() -> State end), {ok, maps:remove(sock, State1)}; (#{sock := Sock} = State) -> ok = socket:close(Sock), {ok, maps:remove(sock, State)} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], TesterSeq = [ %% *** Init part *** #{desc => "monitor server", cmd => fun(#{server := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "monitor client", cmd => fun(#{client := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, %% Start the server #{desc => "order server start", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_START(Pid), ok end}, #{desc => "await server ready (init)", cmd => fun(#{server := Pid} = State) -> {ok, Port} = ?SEV_AWAIT_READY(Pid, server, init), {ok, State#{server_port => Port}} end}, %% Start the client #{desc => "order client start", cmd => fun(#{client := Pid, server_port := Port} = _State) -> ?SEV_ANNOUNCE_START(Pid, Port), ok end}, #{desc => "await client ready (init)", cmd => fun(#{client := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, client, init) end}, %% *** The actual test *** #{desc => "order server to continue (with accept)", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Server, accept), ok end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order client to continue (with connect)", cmd => fun(#{client := Client} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Client, connect), ok end}, #{desc => "await client ready (connect)", cmd => fun(#{client := Client} = _State) -> ?SEV_AWAIT_READY(Client, client, connect) end}, #{desc => "await server ready (accept)", cmd => fun(#{server := Server} = _State) -> ?SEV_AWAIT_READY(Server, server, accept) end}, #{desc => "order client to continue (with send request)", cmd => fun(#{client := Client} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Client, send_req), ok end}, #{desc => "await client ready (with send request)", cmd => fun(#{client := Client} = _State) -> ?SEV_AWAIT_READY(Client, client, send_req) end}, #{desc => "await server ready (request recv)", cmd => fun(#{server := Server} = _State) -> ?SEV_AWAIT_READY(Server, server, recv_req) end}, #{desc => "order server to continue (with send reply)", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Server, send_reply), ok end}, #{desc => "await server ready (with reply sent)", cmd => fun(#{server := Server} = _State) -> ?SEV_AWAIT_READY(Server, server, send_reply) end}, #{desc => "await client ready (reply recv)", cmd => fun(#{client := Client} = _State) -> ?SEV_AWAIT_READY(Client, client, recv_reply) end}, %% *** Termination *** #{desc => "order client to terminate", cmd => fun(#{client := Client} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Client), ok end}, #{desc => "await client termination", cmd => fun(#{client := Client} = State) -> ?SEV_AWAIT_TERMINATION(Client), State1 = maps:remove(client, State), {ok, State1} end}, #{desc => "order server to terminate", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Server), ok end}, #{desc => "await server termination", cmd => fun(#{server := Server} = State) -> ?SEV_AWAIT_TERMINATION(Server), State1 = maps:remove(server, State), {ok, State1} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], i("start server evaluator"), Server = ?SEV_START("server", ServerSeq, InitState), i("start client evaluator"), Client = ?SEV_START("client", ClientSeq, InitState), i("await evaluator(s)"), i("start tester evaluator"), TesterInitState = #{server => Server#ev.pid, client => Client#ev.pid}, Tester = ?SEV_START("tester", TesterSeq, TesterInitState), ok = ?SEV_AWAIT_FINISH([Server, Client, Tester]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically establish a TCP connection via an async connect. IPv4. api_a_connect_tcp4(suite) -> []; api_a_connect_tcp4(doc) -> []; api_a_connect_tcp4(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_a_connect_tcp4, fun() -> ok = api_a_connect_tcpD(inet) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically establish a TCP connection via an async connect. IPv6. api_a_connect_tcp6(suite) -> []; api_a_connect_tcp6(doc) -> []; api_a_connect_tcp6(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_a_connect_tcp6, fun() -> has_support_ipv6() end, fun() -> ok = api_a_connect_tcpD(inet6) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% api_a_connect_tcpD(Domain) -> Connect = fun(Sock, SockAddr) -> socket:connect(Sock, SockAddr, nowait) end, Send = fun(Sock, Data) -> socket:send(Sock, Data) end, Recv = fun(Sock) -> socket:recv(Sock) end, InitState = #{domain => Domain, connect => Connect, send => Send, recv => Recv}, api_a_connect_tcp(InitState). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% api_a_connect_tcp(InitState) -> process_flag(trap_exit, true), ServerSeq = [ %% *** Wait for start order *** #{desc => "await start (from tester)", cmd => fun(State) -> Tester = ?SEV_AWAIT_START(), {ok, State#{tester => Tester}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester}) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> LSA = which_local_socket_addr(Domain), {ok, State#{lsa => LSA}} end}, #{desc => "create listen socket", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, stream, tcp) of {ok, Sock} -> {ok, State#{lsock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind to local address", cmd => fun(#{lsock := LSock, lsa := LSA} = State) -> case socket:bind(LSock, LSA) of {ok, Port} -> {ok, State#{lport => Port}}; {error, _} = ERROR -> ERROR end end}, #{desc => "make listen socket", cmd => fun(#{lsock := LSock}) -> socket:listen(LSock) end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester, lport := Port}) -> ?SEV_ANNOUNCE_READY(Tester, init, Port), ok end}, %% The actual test #{desc => "await continue (accept)", cmd => fun(#{tester := Tester}) -> ?SEV_AWAIT_CONTINUE(Tester, tester, accept) end}, #{desc => "await connection", cmd => fun(#{lsock := LSock} = State) -> case socket:accept(LSock) of {ok, Sock} -> ?SEV_IPRINT("accepted: ~n ~p", [Sock]), {ok, State#{csock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (accept)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, accept), ok end}, #{desc => "await continue (recv_req)", cmd => fun(#{tester := Tester}) -> ?SEV_AWAIT_CONTINUE(Tester, tester, recv_req) end}, #{desc => "recv req", cmd => fun(#{csock := Sock, recv := Recv}) -> case Recv(Sock) of {ok, ?BASIC_REQ} -> ok; {ok, UnexpData} -> {error, {unexpected_data, UnexpData}}; {error, _} = ERROR -> %% At the moment there is no way to get %% status or state for the socket... ERROR end end}, #{desc => "announce ready (recv_req)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv_req), ok end}, #{desc => "await continue (send_rep)", cmd => fun(#{tester := Tester}) -> ?SEV_AWAIT_CONTINUE(Tester, tester, send_rep) end}, #{desc => "send rep", cmd => fun(#{csock := Sock, send := Send}) -> Send(Sock, ?BASIC_REP) end}, #{desc => "announce ready (send_rep)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, send_rep), ok end}, %% *** Termination *** #{desc => "await terminate", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "close connection socket", cmd => fun(#{csock := Sock} = State) -> ok = socket:close(Sock), {ok, maps:remove(csock, State)} end}, #{desc => "close listen socket", cmd => fun(#{lsock := Sock} = State) -> ok = socket:close(Sock), {ok, maps:remove(lsock, State)} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], ClientSeq = [ %% *** Wait for start order *** #{desc => "await start (from tester)", cmd => fun(State) -> {Tester, Port} = ?SEV_AWAIT_START(), {ok, State#{tester => Tester, server_port => Port}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester}) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** The init part *** #{desc => "which server (local) address", cmd => fun(#{domain := Domain, server_port := Port} = State) -> LSA = which_local_socket_addr(Domain), SSA = LSA#{port => Port}, {ok, State#{local_sa => LSA, server_sa => SSA}} end}, #{desc => "create socket", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, stream, tcp) of {ok, Sock} -> {ok, State#{sock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind to local address", cmd => fun(#{sock := Sock, local_sa := LSA} = _State) -> case socket:bind(Sock, LSA) of {ok, _Port} -> ok; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, init), ok end}, %% *** The actual test *** #{desc => "await continue (async connect)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, async_connect) end}, #{desc => "connect (async) to server", cmd => fun(#{sock := Sock, server_sa := SSA, connect := Connect} = State) -> case Connect(Sock, SSA) of ok -> ?SEV_IPRINT("ok -> " "unexpected success => SKIP", []), {skip, unexpected_success}; {select, {select_info, ST, SR}} -> ?SEV_IPRINT("select ->" "~n tag: ~p" "~n ref: ~p", [ST, SR]), {ok, State#{connect_stag => ST, connect_sref => SR}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (connect select)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, connect_select), ok end}, #{desc => "await select message", cmd => fun(#{sock := Sock, connect_sref := Ref}) -> receive {'$socket', Sock, select, Ref} -> ?SEV_IPRINT("select message ->" "~n ref: ~p", [Ref]), ok after 5000 -> ?SEV_EPRINT("timeout: " "~n message queue: ~p", [mq()]), {error, timeout} end end}, #{desc => "announce ready (select)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, select), ok end}, #{desc => "connect (async) to server", cmd => fun(#{sock := Sock, server_sa := SSA, connect := Connect}) -> case Connect(Sock, SSA) of ok -> ok; {select, SelectInfo} -> {error, {unexpected_select, SelectInfo}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (connect)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, connect), ok end}, #{desc => "get peername", cmd => fun(#{sock := Sock} = _State) -> case socket:peername(Sock) of {ok, SockAddr} -> ?SEV_IPRINT("Peer Name: ~p", [SockAddr]), ok; {error, _} = ERROR -> ERROR end end}, #{desc => "await continue (send_req)", cmd => fun(#{tester := Tester}) -> ?SEV_AWAIT_CONTINUE(Tester, tester, send_req) end}, #{desc => "send req", cmd => fun(#{sock := Sock, send := Send}) -> Send(Sock, ?BASIC_REQ) end}, #{desc => "announce ready (send_req)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, send_req), ok end}, #{desc => "await continue (recv_rep)", cmd => fun(#{tester := Tester}) -> ?SEV_AWAIT_CONTINUE(Tester, tester, recv_rep) end}, #{desc => "recv rep", cmd => fun(#{sock := Sock, recv := Recv}) -> case Recv(Sock) of {ok, ?BASIC_REP} -> ok; {ok, UnexpData} -> {error, {unexpected_data, UnexpData}}; {error, _} = ERROR -> %% At the moment there is no way to get %% status or state for the socket... ERROR end end}, #{desc => "announce ready (recv_rep)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv_rep), ok end}, %% *** Termination *** #{desc => "await terminate", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "close socket", cmd => fun(#{sock := Sock} = State) -> ok = socket:close(Sock), State2 = maps:remove(sock, State), State3 = maps:remove(connect_stag, State2), State4 = maps:remove(connect_sref, State3), {ok, State4} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], TesterSeq = [ %% *** Init part *** #{desc => "monitor server", cmd => fun(#{server := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "monitor client", cmd => fun(#{client := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, %% Start the server #{desc => "order server start", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_START(Pid), ok end}, #{desc => "await server ready (init)", cmd => fun(#{server := Pid} = State) -> {ok, Port} = ?SEV_AWAIT_READY(Pid, server, init), {ok, State#{server_port => Port}} end}, %% Start the client #{desc => "order client start", cmd => fun(#{client := Pid, server_port := Port} = _State) -> ?SEV_ANNOUNCE_START(Pid, Port), ok end}, #{desc => "await client ready (init)", cmd => fun(#{client := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, client, init) end}, %% *** The actual test *** #{desc => "order client to continue (async connect)", cmd => fun(#{client := Client} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Client, async_connect), ok end}, #{desc => "await client ready (connect select)", cmd => fun(#{client := Client} = _State) -> ?SEV_AWAIT_READY(Client, client, connect_select) end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order server to continue (with accept)", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Server, accept), ok end}, #{desc => "await client ready (select)", cmd => fun(#{client := Client} = _State) -> ?SEV_AWAIT_READY(Client, client, select) end}, #{desc => "await client ready (connect)", cmd => fun(#{client := Client} = _State) -> ?SEV_AWAIT_READY(Client, client, connect) end}, #{desc => "await server ready (accept)", cmd => fun(#{server := Server} = _State) -> ?SEV_AWAIT_READY(Server, server, accept) end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order server to recv test req (recv req)", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Server, recv_req), ok end}, #{desc => "order client to send test req (send req)", cmd => fun(#{client := Client} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Client, send_req), ok end}, #{desc => "await client ready (send_req)", cmd => fun(#{client := Client} = _State) -> ?SEV_AWAIT_READY(Client, client, send_req) end}, #{desc => "await server ready (recv_req)", cmd => fun(#{server := Server} = _State) -> ?SEV_AWAIT_READY(Server, server, recv_req) end}, #{desc => "order client to recv test rep (send rep)", cmd => fun(#{client := Client} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Client, recv_rep), ok end}, #{desc => "order server to send test rep (send rep)", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Server, send_rep), ok end}, #{desc => "await server ready (send_rep)", cmd => fun(#{server := Server} = _State) -> ?SEV_AWAIT_READY(Server, server, send_rep) end}, #{desc => "await client ready (recv_rep)", cmd => fun(#{client := Client} = _State) -> ?SEV_AWAIT_READY(Client, client, recv_rep) end}, %% *** Termination *** #{desc => "order client to terminate", cmd => fun(#{client := Client} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Client), ok end}, #{desc => "await client termination", cmd => fun(#{client := Client} = State) -> ?SEV_AWAIT_TERMINATION(Client), State1 = maps:remove(client, State), {ok, State1} end}, #{desc => "order server to terminate", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Server), ok end}, #{desc => "await server termination", cmd => fun(#{server := Server} = State) -> ?SEV_AWAIT_TERMINATION(Server), State1 = maps:remove(server, State), {ok, State1} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], i("start server evaluator"), Server = ?SEV_START("server", ServerSeq, InitState), i("start client evaluator"), Client = ?SEV_START("client", ClientSeq, InitState), i("await evaluator(s)"), i("start tester evaluator"), TesterInitState = #{server => Server#ev.pid, client => Client#ev.pid}, Tester = ?SEV_START("tester", TesterSeq, TesterInitState), ok = ?SEV_AWAIT_FINISH([Server, Client, Tester]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically send and receive on an IPv4 UDP (dgram) socket using %% sendto and recvfrom. But we try to be async. That is, we use %% the 'nowait' value for the Timeout argument (and await the eventual %% select message). Note that we only do this for the recvfrom, %% since its much more difficult to "arrange" for sendto. %% api_a_sendto_and_recvfrom_udp4(suite) -> []; api_a_sendto_and_recvfrom_udp4(doc) -> []; api_a_sendto_and_recvfrom_udp4(_Config) when is_list(_Config) -> ?TT(?SECS(5)), tc_try(api_a_sendto_and_recvfrom_udp4, fun() -> Send = fun(Sock, Data, Dest) -> socket:sendto(Sock, Data, Dest) end, Recv = fun(Sock) -> socket:recvfrom(Sock, 0, nowait) end, InitState = #{domain => inet, send => Send, recv => Recv}, ok = api_a_send_and_recv_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically send and receive on an IPv6 UDP (dgram) socket using %% sendto and recvfrom. But we try to be async. That is, we use %% the 'nowait' value for the Timeout argument (and await the eventual %% select message). Note that we only do this for the recvfrom, %% since its much more difficult to "arrange" for sendto. %% api_a_sendto_and_recvfrom_udp6(suite) -> []; api_a_sendto_and_recvfrom_udp6(doc) -> []; api_a_sendto_and_recvfrom_udp6(_Config) when is_list(_Config) -> ?TT(?SECS(5)), tc_try(api_a_sendto_and_recvfrom_udp6, fun() -> has_support_ipv6() end, fun() -> Send = fun(Sock, Data, Dest) -> socket:sendto(Sock, Data, Dest) end, Recv = fun(Sock) -> socket:recvfrom(Sock, 0, nowait) end, InitState = #{domain => inet6, send => Send, recv => Recv}, ok = api_a_send_and_recv_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically send and receive on an IPv4 UDP (dgram) socket using %% sendto and recvfrom. But we try to be async. That is, we use %% the 'nowait' value for the Timeout argument (and await the eventual %% select message). Note that we only do this for the recvmsg, %% since its much more difficult to "arrange" for sendmsg. %% api_a_sendmsg_and_recvmsg_udp4(suite) -> []; api_a_sendmsg_and_recvmsg_udp4(doc) -> []; api_a_sendmsg_and_recvmsg_udp4(_Config) when is_list(_Config) -> ?TT(?SECS(5)), tc_try(api_a_sendmsg_and_recvmsg_udp4, fun() -> Send = fun(Sock, Data, Dest) -> MsgHdr = #{addr => Dest, %% ctrl => CMsgHdrs, iov => [Data]}, socket:sendmsg(Sock, MsgHdr) end, Recv = fun(Sock) -> case socket:recvmsg(Sock, nowait) of {ok, #{addr := Source, iov := [Data]}} -> {ok, {Source, Data}}; {ok, _} = OK -> OK; {select, _} = SELECT -> SELECT; {error, _} = ERROR -> ERROR end end, InitState = #{domain => inet, send => Send, recv => Recv}, ok = api_a_send_and_recv_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically send and receive on an IPv6 UDP (dgram) socket using %% sendto and recvfrom. But we try to be async. That is, we use %% the 'nowait' value for the Timeout argument (and await the eventual %% select message). Note that we only do this for the recvmsg, %% since its much more difficult to "arrange" for sendmsg. %% api_a_sendmsg_and_recvmsg_udp6(suite) -> []; api_a_sendmsg_and_recvmsg_udp6(doc) -> []; api_a_sendmsg_and_recvmsg_udp6(_Config) when is_list(_Config) -> ?TT(?SECS(5)), tc_try(api_a_sendmsg_and_recvmsg_udp6, fun() -> has_support_ipv6() end, fun() -> Send = fun(Sock, Data, Dest) -> MsgHdr = #{addr => Dest, %% ctrl => CMsgHdrs, iov => [Data]}, socket:sendmsg(Sock, MsgHdr) end, Recv = fun(Sock) -> case socket:recvmsg(Sock, nowait) of {ok, #{addr := Source, iov := [Data]}} -> {ok, {Source, Data}}; {ok, _} = OK -> OK; {select, _} = SELECT -> SELECT; {error, _} = ERROR -> ERROR end end, InitState = #{domain => inet6, send => Send, recv => Recv}, ok = api_a_send_and_recv_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% api_a_send_and_recv_udp(InitState) -> ServerSeq = [ %% *** Wait for start order part *** #{desc => "await start", cmd => fun(State) -> Tester = ?SEV_AWAIT_START(), {ok, State#{tester => Tester}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, #{desc => "create socket", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, dgram, udp) of {ok, Sock} -> {ok, State#{sock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind socket (to local address)", cmd => fun(#{sock := Sock, local_sa := LSA} = State) -> case socket:bind(Sock, LSA) of {ok, Port} -> {ok, State#{port => Port}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester, local_sa := LSA, port := Port}) -> ServerSA = LSA#{port => Port}, ?SEV_ANNOUNCE_READY(Tester, init, ServerSA), ok end}, %% The actual test #{desc => "await continue (recv)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, recv) end}, #{desc => "try recv request (with nowait, expect select)", cmd => fun(#{sock := Sock, recv := Recv} = State) -> case Recv(Sock) of {select, {select_info, Tag, RecvRef}} -> ?SEV_IPRINT("expected select: " "~n Tag: ~p" "~n Ref: ~p", [Tag, RecvRef]), {ok, State#{recv_stag => Tag, recv_sref => RecvRef}}; {ok, X} -> {error, {unexpected_succes, X}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (recv_select)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv_select), ok end}, #{desc => "await select message", cmd => fun(#{sock := Sock, recv_sref := RecvRef}) -> receive {'$socket', Sock, select, RecvRef} -> ok after 5000 -> ?SEV_EPRINT("message queue: ~p", [mq()]), {error, timeout} end end}, #{desc => "announce ready (select)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, select), ok end}, #{desc => "now read the data (request)", cmd => fun(#{sock := Sock, recv := Recv} = State) -> case Recv(Sock) of {ok, {Src, ?BASIC_REQ}} -> {ok, State#{req_src => Src}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (recv request)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv_req), ok end}, #{desc => "await continue (send reply)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, send_reply) end}, #{desc => "send reply", cmd => fun(#{sock := Sock, req_src := Src, send := Send}) -> Send(Sock, ?BASIC_REP, Src) end}, #{desc => "announce ready (send)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, send), ok end}, %% Termination #{desc => "await terminate (from tester)", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> State2 = maps:remove(tester, State), State3 = maps:remove(recv_stag, State2), State4 = maps:remove(recv_sref, State3), State5 = maps:remove(req_src, State4), {ok, State5}; {error, _} = ERROR -> ERROR end end}, #{desc => "close socket", cmd => fun(#{sock := Sock} = State) -> ok = socket:close(Sock), {ok, maps:remove(sock, State)} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], ClientSeq = [ %% *** Wait for start order part *** #{desc => "await start", cmd => fun(State) -> {Tester, ServerSA} = ?SEV_AWAIT_START(), {ok, State#{tester => Tester, server_sa => ServerSA}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "local address", cmd => fun(#{domain := Domain} = State) -> LSA = which_local_socket_addr(Domain), {ok, State#{lsa => LSA}} end}, #{desc => "open socket", cmd => fun(#{domain := Domain} = State) -> Sock = sock_open(Domain, dgram, udp), SA = sock_sockname(Sock), {ok, State#{sock => Sock, sa => SA}} end}, #{desc => "bind socket (to local address)", cmd => fun(#{sock := Sock, lsa := LSA}) -> case socket:bind(Sock, LSA) of {ok, _Port} -> ok; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, init), ok end}, %% The actual test #{desc => "await continue (send request)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, send_req) end}, #{desc => "send request", cmd => fun(#{sock := Sock, server_sa := Server, send := Send}) -> Send(Sock, ?BASIC_REQ, Server) end}, #{desc => "announce ready (send request)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, send_req), ok end}, #{desc => "await continue (recv)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, recv) end}, #{desc => "try recv reply (with nowait)", cmd => fun(#{sock := Sock, recv := Recv} = State) -> case Recv(Sock) of {select, {select_info, Tag, RecvRef}} -> {ok, State#{recv_stag => Tag, recv_sref => RecvRef}}; {ok, X} -> {error, {unexpected_select_info, X}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (recv_select)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv_select), ok end}, #{desc => "await select message", cmd => fun(#{sock := Sock, recv_sref := RecvRef}) -> receive {'$socket', Sock, select, RecvRef} -> ok end end}, #{desc => "announce ready (select)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, select), ok end}, #{desc => "now read the data (reply)", cmd => fun(#{sock := Sock, recv := Recv}) -> case Recv(Sock) of {ok, {_Src, ?BASIC_REP}} -> ok; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (recv reply)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv_rep), ok end}, %% Termination #{desc => "await terminate (from tester)", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> State2 = maps:remove(tester, State), State3 = maps:remove(recv_stag, State2), State4 = maps:remove(recv_sref, State3), {ok, State4}; {error, _} = ERROR -> ERROR end end}, #{desc => "close socket", cmd => fun(#{sock := Sock} = State) -> ok = socket:close(Sock), {ok, maps:remove(sock, State)} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], TesterSeq = [ %% *** Init part *** #{desc => "monitor server", cmd => fun(#{server := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "monitor client", cmd => fun(#{client := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, %% Start the server #{desc => "order server start", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_START(Pid), ok end}, #{desc => "await server ready (init)", cmd => fun(#{server := Pid} = State) -> {ok, ServerSA} = ?SEV_AWAIT_READY(Pid, server, init), {ok, State#{server_sa => ServerSA}} end}, %% Start the client #{desc => "order client start", cmd => fun(#{client := Pid, server_sa := ServerSA} = _State) -> ?SEV_ANNOUNCE_START(Pid, ServerSA), ok end}, #{desc => "await client ready (init)", cmd => fun(#{client := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, client, init) end}, %% The actual test #{desc => "order server continue (recv)", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, recv), ok end}, #{desc => "await server ready (recv_select)", cmd => fun(#{server := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, server, recv_select) end}, #{desc => "order client continue (send request)", cmd => fun(#{client := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, send_req), ok end}, #{desc => "await client ready (send request)", cmd => fun(#{client := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, client, send_req) end}, #{desc => "await server ready (select)", cmd => fun(#{server := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, server, select) end}, #{desc => "await server ready (recv request)", cmd => fun(#{server := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, server, recv_req) end}, #{desc => "order client continue (recv)", cmd => fun(#{client := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, recv), ok end}, #{desc => "await client ready (recv_select)", cmd => fun(#{client := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, client, recv_select) end}, #{desc => "order server continue (send reply)", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, send_reply), ok end}, #{desc => "await server ready (send)", cmd => fun(#{server := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, server, send) end}, #{desc => "await client ready (select)", cmd => fun(#{client := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, client, select) end}, #{desc => "await client ready (recv reply)", cmd => fun(#{client := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, client, recv_rep) end}, %% Terminations #{desc => "order client to terminate", cmd => fun(#{client := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await client termination", cmd => fun(#{client := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> State1 = maps:remove(client, State), {ok, State1}; {error, _} = ERROR -> ERROR end end}, #{desc => "order server to terminate", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await server termination", cmd => fun(#{server := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> State1 = maps:remove(server, State), {ok, State1}; {error, _} = ERROR -> ERROR end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], i("start server evaluator"), ServerInitState = InitState, Server = ?SEV_START("server", ServerSeq, ServerInitState), i("start client evaluator(s)"), ClientInitState = InitState, Client = ?SEV_START("client", ClientSeq, ClientInitState), i("start 'tester' evaluator"), TesterInitState = #{server => Server#ev.pid, client => Client#ev.pid}, Tester = ?SEV_START("tester", TesterSeq, TesterInitState), i("await evaluator"), ok = ?SEV_AWAIT_FINISH([Server, Client, Tester]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically send and receive using the "common" functions (send and recv) %% on an IPv4 TCP (stream) socket. But we try to be async. That is, we use %% the 'nowait' value for the Timeout argument (and await the eventual %% select message). Note that we only do this for the recv, %% since its much more difficult to "arrange" for send. %% We *also* test async for accept. api_a_send_and_recv_tcp4(suite) -> []; api_a_send_and_recv_tcp4(doc) -> []; api_a_send_and_recv_tcp4(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_a_send_and_recv_tcp4, fun() -> Send = fun(Sock, Data) -> socket:send(Sock, Data) end, Recv = fun(Sock) -> socket:recv(Sock, 0, nowait) end, InitState = #{domain => inet, send => Send, recv => Recv}, ok = api_a_send_and_recv_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically send and receive using the "common" functions (send and recv) %% on an IPv6 TCP (stream) socket. But we try to be async. That is, we use %% the 'nowait' value for the Timeout argument (and await the eventual %% select message). Note that we only do this for the recv, %% since its much more difficult to "arrange" for send. %% We *also* test async for accept. api_a_send_and_recv_tcp6(suite) -> []; api_a_send_and_recv_tcp6(doc) -> []; api_a_send_and_recv_tcp6(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_a_send_and_recv_tcp6, fun() -> has_support_ipv6() end, fun() -> Send = fun(Sock, Data) -> socket:send(Sock, Data) end, Recv = fun(Sock) -> socket:recv(Sock, 0, nowait) end, InitState = #{domain => inet6, send => Send, recv => Recv}, ok = api_a_send_and_recv_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically send and receive using the msg functions (sendmsg and recvmsg) %% on an IPv4 TCP (stream) socket. But we try to be async. That is, we use %% the 'nowait' value for the Timeout argument (and await the eventual %% select message). Note that we only do this for the recvmsg, %% since its much more difficult to "arrange" for sendmsg. %% We *also* test async for accept. api_a_sendmsg_and_recvmsg_tcp4(suite) -> []; api_a_sendmsg_and_recvmsg_tcp4(doc) -> []; api_a_sendmsg_and_recvmsg_tcp4(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_a_sendmsg_and_recvmsg_tcp4, fun() -> Send = fun(Sock, Data) -> MsgHdr = #{iov => [Data]}, socket:sendmsg(Sock, MsgHdr) end, Recv = fun(Sock) -> case socket:recvmsg(Sock, nowait) of {ok, #{addr := undefined, iov := [Data]}} -> {ok, Data}; {ok, _} = OK -> OK; {select, _} = SELECT -> SELECT; {error, _} = ERROR -> ERROR end end, InitState = #{domain => inet, send => Send, recv => Recv}, ok = api_a_send_and_recv_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically send and receive using the msg functions (sendmsg and recvmsg) %% on an IPv6 TCP (stream) socket. But we try to be async. That is, we use %% the 'nowait' value for the Timeout argument (and await the eventual %% select message). Note that we only do this for the recvmsg, %% since its much more difficult to "arrange" for sendmsg. %% We *also* test async for accept. api_a_sendmsg_and_recvmsg_tcp6(suite) -> []; api_a_sendmsg_and_recvmsg_tcp6(doc) -> []; api_a_sendmsg_and_recvmsg_tcp6(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_a_sendmsg_and_recvmsg_tcp6, fun() -> has_support_ipv6() end, fun() -> Send = fun(Sock, Data) -> MsgHdr = #{iov => [Data]}, socket:sendmsg(Sock, MsgHdr) end, Recv = fun(Sock) -> case socket:recvmsg(Sock, nowait) of {ok, #{addr := undefined, iov := [Data]}} -> {ok, Data}; {ok, _} = OK -> OK; {select, _} = SELECT -> SELECT; {error, _} = ERROR -> ERROR end end, InitState = #{domain => inet6, send => Send, recv => Recv}, ok = api_a_send_and_recv_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% api_a_send_and_recv_tcp(InitState) -> process_flag(trap_exit, true), ServerSeq = [ %% *** Wait for start order *** #{desc => "await start (from tester)", cmd => fun(State) -> Tester = ?SEV_AWAIT_START(), {ok, State#{tester => Tester}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester}) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> LSA = which_local_socket_addr(Domain), {ok, State#{lsa => LSA}} end}, #{desc => "create listen socket", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, stream, tcp) of {ok, Sock} -> {ok, State#{lsock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind to local address", cmd => fun(#{lsock := LSock, lsa := LSA} = State) -> case socket:bind(LSock, LSA) of {ok, Port} -> {ok, State#{lport => Port}}; {error, _} = ERROR -> ERROR end end}, #{desc => "make listen socket", cmd => fun(#{lsock := LSock}) -> socket:listen(LSock) end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester, lport := Port}) -> ?SEV_ANNOUNCE_READY(Tester, init, Port), ok end}, %% The actual test #{desc => "await continue (accept)", cmd => fun(#{tester := Tester}) -> ?SEV_AWAIT_CONTINUE(Tester, tester, accept) end}, #{desc => "await connection (nowait)", cmd => fun(#{lsock := LSock} = State) -> case socket:accept(LSock, nowait) of {select, {select_info, Tag, Ref}} -> ?SEV_IPRINT("accept select: " "~n Tag: ~p" "~n Ref: ~p", [Tag, Ref]), {ok, State#{accept_stag => Tag, accept_sref => Ref}}; {ok, X} -> {error, {unexpected_select_info, X}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (accept_select)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, accept_select), ok end}, #{desc => "await select message", cmd => fun(#{lsock := Sock, accept_sref := Ref}) -> receive {'$socket', Sock, select, Ref} -> ok end end}, #{desc => "announce ready (select)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, select), ok end}, #{desc => "await connection (again)", cmd => fun(#{lsock := LSock} = State) -> case socket:accept(LSock, nowait) of {ok, Sock} -> ?SEV_IPRINT("accepted: " "~n Sock: ~p", [Sock]), {ok, State#{csock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (accept)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, accept), ok end}, #{desc => "await continue (recv request)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, recv_req) end}, #{desc => "try recv request (with nowait, expect select)", cmd => fun(#{csock := Sock, recv := Recv} = State) -> case Recv(Sock) of {select, {select_info, Tag, Ref}} -> ?SEV_IPRINT("recv select: " "~n Tag: ~p" "~n Ref: ~p", [Tag, Ref]), {ok, State#{recv_stag => Tag, recv_sref => Ref}}; {ok, X} -> {error, {unexpected_select_info, X}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (recv_select)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv_select), ok end}, #{desc => "await select message", cmd => fun(#{csock := Sock, recv_sref := RecvRef}) -> receive {'$socket', Sock, select, RecvRef} -> ok end end}, #{desc => "announce ready (select)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, select), ok end}, #{desc => "now read the data (request)", cmd => fun(#{csock := Sock, recv := Recv} = _State) -> case Recv(Sock) of {ok, ?BASIC_REQ} -> ok; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (recv request)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv_req), ok end}, #{desc => "await continue (send reply)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, send_rep) end}, #{desc => "send reply", cmd => fun(#{csock := Sock, send := Send}) -> Send(Sock, ?BASIC_REP) end}, #{desc => "announce ready (send reply)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, send_rep), ok end}, %% *** Termination *** #{desc => "await terminate", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "close connection socket", cmd => fun(#{csock := Sock}) -> socket:close(Sock) end}, #{desc => "close listen socket", cmd => fun(#{lsock := Sock}) -> socket:close(Sock) end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], ClientSeq = [ %% *** Wait for start order *** #{desc => "await start (from tester)", cmd => fun(State) -> {Tester, Port} = ?SEV_AWAIT_START(), {ok, State#{tester => Tester, server_port => Port}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester}) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** The init part *** #{desc => "which server (local) address", cmd => fun(#{domain := Domain, server_port := Port} = State) -> LSA = which_local_socket_addr(Domain), SSA = LSA#{port => Port}, {ok, State#{local_sa => LSA, server_sa => SSA}} end}, #{desc => "create socket", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, stream, tcp) of {ok, Sock} -> {ok, State#{sock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind to local address", cmd => fun(#{sock := Sock, local_sa := LSA} = _State) -> case socket:bind(Sock, LSA) of {ok, _Port} -> ok; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, init), ok end}, %% *** The actual test *** #{desc => "await continue (connect)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, connect) end}, #{desc => "connect to server", cmd => fun(#{sock := Sock, server_sa := SSA}) -> socket:connect(Sock, SSA) end}, #{desc => "announce ready (connect)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, connect), ok end}, #{desc => "await continue (send request)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, send_req) end}, #{desc => "send request (to server)", cmd => fun(#{sock := Sock, send := Send}) -> ok = Send(Sock, ?BASIC_REQ) end}, #{desc => "announce ready (send request)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, send_req), ok end}, #{desc => "try recv reply (with nowait, expect select)", cmd => fun(#{sock := Sock, recv := Recv} = State) -> case Recv(Sock) of {select, {select_info, Tag, Ref}} -> ?SEV_IPRINT("recv select: " "~n Tag: ~p" "~n Ref: ~p", [Tag, Ref]), {ok, State#{recv_stag => Tag, recv_sref => Ref}}; {ok, X} -> {error, {unexpected_select_info, X}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (recv_select)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv_select), ok end}, #{desc => "await select message", cmd => fun(#{sock := Sock, recv_sref := RecvRef}) -> receive {'$socket', Sock, select, RecvRef} -> ok end end}, #{desc => "announce ready (select)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, select), ok end}, #{desc => "now read the data (reply)", cmd => fun(#{sock := Sock, recv := Recv}) -> {ok, ?BASIC_REP} = Recv(Sock), ok end}, #{desc => "announce ready (recv reply)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv_rep), ok end}, %% *** Termination *** #{desc => "await terminate", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "close socket", cmd => fun(#{sock := Sock}) -> socket:close(Sock) end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], TesterSeq = [ %% *** Init part *** #{desc => "monitor server", cmd => fun(#{server := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "monitor client", cmd => fun(#{client := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, %% Start the server #{desc => "order server start", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_START(Pid), ok end}, #{desc => "await server ready (init)", cmd => fun(#{server := Pid} = State) -> {ok, Port} = ?SEV_AWAIT_READY(Pid, server, init), {ok, State#{server_port => Port}} end}, %% Start the client #{desc => "order client start", cmd => fun(#{client := Pid, server_port := Port} = _State) -> ?SEV_ANNOUNCE_START(Pid, Port), ok end}, #{desc => "await client ready (init)", cmd => fun(#{client := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, client, init) end}, %% *** The actual test *** #{desc => "order server to continue (with accept)", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Server, accept), ok end}, #{desc => "await server ready (accept select)", cmd => fun(#{server := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, server, accept_select) end}, #{desc => "order client to continue (with connect)", cmd => fun(#{client := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, connect), ok end}, #{desc => "await server ready (select)", cmd => fun(#{server := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, server, select) end}, #{desc => "await server ready (accept)", cmd => fun(#{server := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, server, accept) end}, #{desc => "await client ready (connect)", cmd => fun(#{client := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, client, connect) end}, #{desc => "order server to continue (recv request)", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, recv_req), ok end}, #{desc => "await server ready (recv select)", cmd => fun(#{server := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, server, recv_select) end}, #{desc => "order client to continue (send request)", cmd => fun(#{client := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, send_req), ok end}, #{desc => "await client ready (send request)", cmd => fun(#{client := Client} = _State) -> ?SEV_AWAIT_READY(Client, client, send_req) end}, #{desc => "await server ready (select)", cmd => fun(#{server := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, server, select) end}, #{desc => "await server ready (recv request)", cmd => fun(#{server := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, server, recv_req) end}, #{desc => "order client to continue (recv reply)", cmd => fun(#{client := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, recv_rep), ok end}, #{desc => "await client ready (recv select)", cmd => fun(#{client := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, client, recv_select) end}, #{desc => "order server to continue (send reply)", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, send_rep), ok end}, #{desc => "await server ready (send reply)", cmd => fun(#{server := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, server, send_rep) end}, #{desc => "await client ready (select)", cmd => fun(#{client := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, client, select) end}, #{desc => "await client ready (reply recv)", cmd => fun(#{client := Client} = _State) -> ?SEV_AWAIT_READY(Client, client, recv_rep) end}, %% *** Termination *** #{desc => "order client to terminate", cmd => fun(#{client := Client} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Client), ok end}, #{desc => "await client termination", cmd => fun(#{client := Client} = State) -> ?SEV_AWAIT_TERMINATION(Client), State1 = maps:remove(client, State), {ok, State1} end}, #{desc => "order server to terminate", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Server), ok end}, #{desc => "await server termination", cmd => fun(#{server := Server} = State) -> ?SEV_AWAIT_TERMINATION(Server), State1 = maps:remove(server, State), {ok, State1} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], i("start server evaluator"), Server = ?SEV_START("server", ServerSeq, InitState), i("start client evaluator"), Client = ?SEV_START("client", ClientSeq, InitState), i("start tester evaluator"), TesterInitState = #{server => Server#ev.pid, client => Client#ev.pid}, Tester = ?SEV_START("tester", TesterSeq, TesterInitState), i("await evaluator(s)"), ok = ?SEV_AWAIT_FINISH([Server, Client, Tester]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically we make an async (Timeout = nowait) call to recvfrom, %% wait some time and then cancel. IPv4 %% api_a_recvfrom_cancel_udp4(suite) -> []; api_a_recvfrom_cancel_udp4(doc) -> []; api_a_recvfrom_cancel_udp4(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_a_recvfrom_cancel_udp4, fun() -> Recv = fun(Sock) -> case socket:recvfrom(Sock, 0, nowait) of {ok, _} = OK -> OK; {select, _} = SELECT -> SELECT; {error, _} = ERROR -> ERROR end end, InitState = #{domain => inet, recv => Recv}, ok = api_a_recv_cancel_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically we make an async (Timeout = nowait) call to recvfrom, %% wait some time and then cancel. IPv6 %% api_a_recvfrom_cancel_udp6(suite) -> []; api_a_recvfrom_cancel_udp6(doc) -> []; api_a_recvfrom_cancel_udp6(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_a_recvfrom_cancel_udp6, fun() -> has_support_ipv6() end, fun() -> Recv = fun(Sock) -> case socket:recvfrom(Sock, 0, nowait) of {ok, _} = OK -> OK; {select, _} = SELECT -> SELECT; {error, _} = ERROR -> ERROR end end, InitState = #{domain => inet6, recv => Recv}, ok = api_a_recv_cancel_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically we make an async (Timeout = nowait) call to recvmsg, %% wait some time and then cancel. IPv4 %% api_a_recvmsg_cancel_udp4(suite) -> []; api_a_recvmsg_cancel_udp4(doc) -> []; api_a_recvmsg_cancel_udp4(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_a_recvmsg_cancel_udp4, fun() -> Recv = fun(Sock) -> case socket:recvmsg(Sock, nowait) of {ok, _} = OK -> OK; {select, _} = SELECT -> SELECT; {error, _} = ERROR -> ERROR end end, InitState = #{domain => inet, recv => Recv}, ok = api_a_recv_cancel_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically we make an async (Timeout = nowait) call to recvmsg, %% wait some time and then cancel. IPv6 %% api_a_recvmsg_cancel_udp6(suite) -> []; api_a_recvmsg_cancel_udp6(doc) -> []; api_a_recvmsg_cancel_udp6(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_a_recvmsg_cancel_udp6, fun() -> has_support_ipv6() end, fun() -> Recv = fun(Sock) -> case socket:recvmsg(Sock, nowait) of {ok, _} = OK -> OK; {select, _} = SELECT -> SELECT; {error, _} = ERROR -> ERROR end end, InitState = #{domain => inet6, recv => Recv}, ok = api_a_recv_cancel_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% api_a_recv_cancel_udp(InitState) -> ServerSeq = [ %% *** Wait for start order part *** #{desc => "await start", cmd => fun(State) -> Tester = ?SEV_AWAIT_START(), {ok, State#{tester => Tester}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, #{desc => "create socket", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, dgram, udp) of {ok, Sock} -> {ok, State#{sock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind socket (to local address)", cmd => fun(#{sock := Sock, local_sa := LSA} = State) -> case socket:bind(Sock, LSA) of {ok, Port} -> {ok, State#{port => Port}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester, local_sa := LSA, port := Port}) -> ServerSA = LSA#{port => Port}, ?SEV_ANNOUNCE_READY(Tester, init, ServerSA), ok end}, %% The actual test #{desc => "await continue (recv)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, recv) end}, #{desc => "try recv request (with nowait, expect select)", cmd => fun(#{sock := Sock, recv := Recv} = State) -> case Recv(Sock) of {select, SelectInfo} -> {ok, State#{recv_select_info => SelectInfo}}; {ok, X} -> {error, {unexpected_select_info, X}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (recv_select)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv_select), ok end}, #{desc => "await select message (without success)", cmd => fun(#{sock := Sock}) -> receive {'$socket', Sock, select, Ref} -> {error, {unexpected_select, Ref}} after 5000 -> ok end end}, #{desc => "announce ready (no select)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, no_select), ok end}, #{desc => "await continue (cancel)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, cancel) end}, #{desc => "cancel", cmd => fun(#{sock := Sock, recv_select_info := SelectInfo}) -> ok = socket:cancel(Sock, SelectInfo) end}, #{desc => "announce ready (cancel)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, cancel), ok end}, %% Termination #{desc => "await terminate (from tester)", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> State2 = maps:remove(tester, State), State3 = maps:remove(recv_stag, State2), State4 = maps:remove(recv_sref, State3), State5 = maps:remove(req_src, State4), {ok, State5}; {error, _} = ERROR -> ERROR end end}, #{desc => "close socket", cmd => fun(#{sock := Sock} = State) -> ok = socket:close(Sock), {ok, maps:remove(sock, State)} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], TesterSeq = [ %% *** Init part *** #{desc => "monitor server", cmd => fun(#{server := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, %% Start the server #{desc => "order server start", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_START(Pid), ok end}, #{desc => "await server ready (init)", cmd => fun(#{server := Pid} = State) -> {ok, ServerSA} = ?SEV_AWAIT_READY(Pid, server, init), {ok, State#{server_sa => ServerSA}} end}, %% The actual test #{desc => "order server continue (recv)", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, recv), ok end}, #{desc => "await server ready (recv select)", cmd => fun(#{server := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, server, recv_select) end}, #{desc => "await server ready (no select)", cmd => fun(#{server := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, server, no_select) end}, #{desc => "order server continue (cancel)", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, cancel), ok end}, #{desc => "await server ready (cancel)", cmd => fun(#{server := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, server, cancel) end}, %% Terminations #{desc => "order server to terminate", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await server termination", cmd => fun(#{server := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> State1 = maps:remove(server, State), {ok, State1}; {error, _} = ERROR -> ERROR end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], i("start server evaluator"), ServerInitState = InitState, Server = ?SEV_START("server", ServerSeq, ServerInitState), i("start 'tester' evaluator"), TesterInitState = #{server => Server#ev.pid}, Tester = ?SEV_START("tester", TesterSeq, TesterInitState), i("await evaluator"), ok = ?SEV_AWAIT_FINISH([Server, Tester]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically we make an async (Timeout = nowait) call to accept, %% wait some time and then cancel. IPv4 %% api_a_accept_cancel_tcp4(suite) -> []; api_a_accept_cancel_tcp4(doc) -> []; api_a_accept_cancel_tcp4(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_a_accept_cancel_tcp4, fun() -> Accept = fun(Sock) -> case socket:accept(Sock, nowait) of {ok, _} = OK -> OK; {select, _} = SELECT -> SELECT; {error, _} = ERROR -> ERROR end end, InitState = #{domain => inet, accept => Accept}, ok = api_a_accept_cancel_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically we make an async (Timeout = nowait) call to accept, %% wait some time and then cancel. IPv6 %% api_a_accept_cancel_tcp6(suite) -> []; api_a_accept_cancel_tcp6(doc) -> []; api_a_accept_cancel_tcp6(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_a_accept_cancel_tcp6, fun() -> has_support_ipv6() end, fun() -> Accept = fun(Sock) -> case socket:accept(Sock, nowait) of {ok, _} = OK -> OK; {select, _} = SELECT -> SELECT; {error, _} = ERROR -> ERROR end end, InitState = #{domain => inet6, accept => Accept}, ok = api_a_accept_cancel_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% api_a_accept_cancel_tcp(InitState) -> process_flag(trap_exit, true), ServerSeq = [ %% *** Wait for start order *** #{desc => "await start (from tester)", cmd => fun(State) -> Tester = ?SEV_AWAIT_START(), {ok, State#{tester => Tester}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester}) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> LSA = which_local_socket_addr(Domain), {ok, State#{lsa => LSA}} end}, #{desc => "create listen socket", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, stream, tcp) of {ok, Sock} -> {ok, State#{lsock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind to local address", cmd => fun(#{lsock := LSock, lsa := LSA} = State) -> case socket:bind(LSock, LSA) of {ok, Port} -> {ok, State#{lport => Port}}; {error, _} = ERROR -> ERROR end end}, #{desc => "make listen socket", cmd => fun(#{lsock := LSock}) -> socket:listen(LSock) end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester, lport := Port}) -> ?SEV_ANNOUNCE_READY(Tester, init, Port), ok end}, %% The actual test #{desc => "await continue (accept)", cmd => fun(#{tester := Tester}) -> ?SEV_AWAIT_CONTINUE(Tester, tester, accept) end}, #{desc => "await connection (nowait)", cmd => fun(#{lsock := LSock, accept := Accept} = State) -> case Accept(LSock) of {select, {select_info, T, R} = SelectInfo} -> ?SEV_IPRINT("accept select: " "~n T: ~p" "~n R: ~p", [T, R]), {ok, State#{accept_select_info => SelectInfo}}; {ok, X} -> {error, {unexpected_select_info, X}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (accept_select)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, accept_select), ok end}, #{desc => "await select message (without success)", cmd => fun(#{lsock := Sock}) -> receive {'$socket', Sock, select, Ref} -> {error, {unexpected_select, Ref}} after 5000 -> ok end end}, #{desc => "announce ready (no select)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, no_select), ok end}, #{desc => "await continue (cancel)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, cancel) end}, #{desc => "cancel", cmd => fun(#{lsock := Sock, accept_select_info := SelectInfo}) -> ok = socket:cancel(Sock, SelectInfo) end}, #{desc => "announce ready (cancel)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, cancel), ok end}, %% *** Termination *** #{desc => "await terminate", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "close listen socket", cmd => fun(#{lsock := Sock}) -> socket:close(Sock) end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], TesterSeq = [ %% *** Init part *** #{desc => "monitor server", cmd => fun(#{server := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, %% Start the server #{desc => "order server start", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_START(Pid), ok end}, #{desc => "await server ready (init)", cmd => fun(#{server := Pid} = State) -> {ok, Port} = ?SEV_AWAIT_READY(Pid, server, init), {ok, State#{server_port => Port}} end}, %% *** The actual test *** #{desc => "order server to continue (with accept)", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Server, accept), ok end}, #{desc => "await server ready (accept select)", cmd => fun(#{server := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, server, accept_select) end}, #{desc => "await server ready (no select)", cmd => fun(#{server := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, server, no_select) end}, #{desc => "order server to continue (cancel)", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, cancel), ok end}, #{desc => "await server ready (cancel)", cmd => fun(#{server := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, server, cancel) end}, %% *** Termination *** #{desc => "order server to terminate", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Server), ok end}, #{desc => "await server termination", cmd => fun(#{server := Server} = State) -> ?SEV_AWAIT_TERMINATION(Server), State1 = maps:remove(server, State), {ok, State1} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], i("start server evaluator"), Server = ?SEV_START("server", ServerSeq, InitState), i("start tester evaluator"), TesterInitState = #{server => Server#ev.pid}, Tester = ?SEV_START("tester", TesterSeq, TesterInitState), i("await evaluator(s)"), ok = ?SEV_AWAIT_FINISH([Server, Tester]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically we make an async (Timeout = nowait) call to recv, %% wait some time and then cancel. IPv4 %% api_a_recv_cancel_tcp4(suite) -> []; api_a_recv_cancel_tcp4(doc) -> []; api_a_recv_cancel_tcp4(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_a_recv_cancel_tcp4, fun() -> Recv = fun(Sock) -> socket:recv(Sock, 0, nowait) end, InitState = #{domain => inet, recv => Recv}, ok = api_a_recv_cancel_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically we make an async (Timeout = nowait) call to recv, %% wait some time and then cancel. IPv6 %% api_a_recv_cancel_tcp6(suite) -> []; api_a_recv_cancel_tcp6(doc) -> []; api_a_recv_cancel_tcp6(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_a_recv_cancel_tcp6, fun() -> has_support_ipv6() end, fun() -> Recv = fun(Sock) -> socket:recv(Sock, 0, nowait) end, InitState = #{domain => inet6, recv => Recv}, ok = api_a_recv_cancel_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically we make an async (Timeout = nowait) call to recvmsg, %% wait some time and then cancel. IPv4 %% api_a_recvmsg_cancel_tcp4(suite) -> []; api_a_recvmsg_cancel_tcp4(doc) -> []; api_a_recvmsg_cancel_tcp4(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_a_recvmsg_cancel_tcp4, fun() -> Recv = fun(Sock) -> socket:recvmsg(Sock, nowait) end, InitState = #{domain => inet, recv => Recv}, ok = api_a_recv_cancel_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically we make an async (Timeout = nowait) call to recvmsg, %% wait some time and then cancel. IPv6 %% api_a_recvmsg_cancel_tcp6(suite) -> []; api_a_recvmsg_cancel_tcp6(doc) -> []; api_a_recvmsg_cancel_tcp6(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_a_recvmsg_cancel_tcp6, fun() -> has_support_ipv6() end, fun() -> Recv = fun(Sock) -> socket:recvmsg(Sock, nowait) end, InitState = #{domain => inet6, recv => Recv}, ok = api_a_recv_cancel_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% api_a_recv_cancel_tcp(InitState) -> process_flag(trap_exit, true), ServerSeq = [ %% *** Wait for start order *** #{desc => "await start (from tester)", cmd => fun(State) -> Tester = ?SEV_AWAIT_START(), {ok, State#{tester => Tester}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester}) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> LSA = which_local_socket_addr(Domain), {ok, State#{lsa => LSA}} end}, #{desc => "create listen socket", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, stream, tcp) of {ok, Sock} -> {ok, State#{lsock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind to local address", cmd => fun(#{lsock := LSock, lsa := LSA} = State) -> case socket:bind(LSock, LSA) of {ok, Port} -> {ok, State#{lport => Port}}; {error, _} = ERROR -> ERROR end end}, #{desc => "make listen socket", cmd => fun(#{lsock := LSock}) -> socket:listen(LSock) end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester, lport := Port}) -> ?SEV_ANNOUNCE_READY(Tester, init, Port), ok end}, %% The actual test #{desc => "await continue (accept)", cmd => fun(#{tester := Tester}) -> ?SEV_AWAIT_CONTINUE(Tester, tester, accept) end}, #{desc => "await connection (nowait)", cmd => fun(#{lsock := LSock} = State) -> case socket:accept(LSock) of {ok, CSock} -> {ok, State#{csock => CSock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (accept)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, accept), ok end}, #{desc => "await continue (nowait recv)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, recv) end}, #{desc => "try recv request (with nowait, expect select)", cmd => fun(#{csock := Sock, recv := Recv} = State) -> case Recv(Sock) of {select, {select_info, T, R} = SelectInfo} -> ?SEV_IPRINT("recv select: " "~n Tag: ~p" "~n Ref: ~p", [T, R]), {ok, State#{recv_select_info => SelectInfo}}; {ok, X} -> {error, {unexpected_select_info, X}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (recv_select)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv_select), ok end}, #{desc => "await select message", cmd => fun(#{csock := Sock}) -> receive {'$socket', Sock, select, Ref} -> {error, {unexpected_select, Ref}} after 5000 -> ok end end}, #{desc => "announce ready (no select)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, no_select), ok end}, #{desc => "await continue (cancel)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, cancel) end}, #{desc => "cancel", cmd => fun(#{csock := Sock, recv_select_info := SelectInfo}) -> ok = socket:cancel(Sock, SelectInfo) end}, #{desc => "announce ready (cancel)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, cancel), ok end}, %% *** Termination *** #{desc => "await terminate", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "close connection socket", cmd => fun(#{csock := Sock}) -> socket:close(Sock) end}, #{desc => "close listen socket", cmd => fun(#{lsock := Sock}) -> socket:close(Sock) end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], ClientSeq = [ %% *** Wait for start order *** #{desc => "await start (from tester)", cmd => fun(State) -> {Tester, Port} = ?SEV_AWAIT_START(), {ok, State#{tester => Tester, server_port => Port}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester}) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** The init part *** #{desc => "which server (local) address", cmd => fun(#{domain := Domain, server_port := Port} = State) -> LSA = which_local_socket_addr(Domain), SSA = LSA#{port => Port}, {ok, State#{local_sa => LSA, server_sa => SSA}} end}, #{desc => "create socket", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, stream, tcp) of {ok, Sock} -> {ok, State#{sock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind to local address", cmd => fun(#{sock := Sock, local_sa := LSA} = _State) -> case socket:bind(Sock, LSA) of {ok, _Port} -> ok; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, init), ok end}, %% *** The actual test *** #{desc => "await continue (connect)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, connect) end}, #{desc => "connect to server", cmd => fun(#{sock := Sock, server_sa := SSA}) -> socket:connect(Sock, SSA) end}, #{desc => "announce ready (connect)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, connect), ok end}, %% *** Termination *** #{desc => "await terminate", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "close socket", cmd => fun(#{sock := Sock}) -> socket:close(Sock) end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], TesterSeq = [ %% *** Init part *** #{desc => "monitor server", cmd => fun(#{server := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "monitor client", cmd => fun(#{client := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, %% Start the server #{desc => "order server start", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_START(Pid), ok end}, #{desc => "await server ready (init)", cmd => fun(#{server := Pid} = State) -> {ok, Port} = ?SEV_AWAIT_READY(Pid, server, init), {ok, State#{server_port => Port}} end}, %% Start the client #{desc => "order client start", cmd => fun(#{client := Pid, server_port := Port} = _State) -> ?SEV_ANNOUNCE_START(Pid, Port), ok end}, #{desc => "await client ready (init)", cmd => fun(#{client := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, client, init) end}, %% *** The actual test *** #{desc => "order server to continue (with accept)", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Server, accept), ok end}, #{desc => "order client to continue (connect)", cmd => fun(#{client := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, connect), ok end}, #{desc => "await client ready (connect)", cmd => fun(#{client := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, client, connect) end}, #{desc => "await server ready (accept)", cmd => fun(#{server := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, server, accept) end}, #{desc => "order server to continue (recv)", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, recv), ok end}, #{desc => "await server ready (recv select)", cmd => fun(#{server := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, server, recv_select) end}, #{desc => "await server ready (no select)", cmd => fun(#{server := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, server, no_select) end}, #{desc => "order server to continue (send request)", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, cancel), ok end}, #{desc => "await server ready (cancel)", cmd => fun(#{server := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, server, cancel) end}, %% *** Termination *** #{desc => "order client to terminate", cmd => fun(#{client := Client} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Client), ok end}, #{desc => "await client termination", cmd => fun(#{client := Client} = State) -> ?SEV_AWAIT_TERMINATION(Client), State1 = maps:remove(client, State), {ok, State1} end}, #{desc => "order server to terminate", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Server), ok end}, #{desc => "await server termination", cmd => fun(#{server := Server} = State) -> ?SEV_AWAIT_TERMINATION(Server), State1 = maps:remove(server, State), {ok, State1} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], i("start server evaluator"), Server = ?SEV_START("server", ServerSeq, InitState), i("start client evaluator"), Client = ?SEV_START("client", ClientSeq, InitState), i("start tester evaluator"), TesterInitState = #{server => Server#ev.pid, client => Client#ev.pid}, Tester = ?SEV_START("tester", TesterSeq, TesterInitState), i("await evaluator(s)"), ok = ?SEV_AWAIT_FINISH([Server, Client, Tester]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically we make multiple async (Timeout = nowait) call(s) to recvfrom %% (from *several* processes), wait some time and then cancel. %% This should result in abort messages to the 'other' processes. IPv4 %% api_a_mrecvfrom_cancel_udp4(suite) -> []; api_a_mrecvfrom_cancel_udp4(doc) -> []; api_a_mrecvfrom_cancel_udp4(_Config) when is_list(_Config) -> ?TT(?SECS(20)), tc_try(api_a_mrecvfrom_cancel_udp4, fun() -> Recv = fun(Sock) -> case socket:recvfrom(Sock, 0, nowait) of {ok, _} = OK -> OK; {select, _} = SELECT -> SELECT; {error, _} = ERROR -> ERROR end end, InitState = #{domain => inet, recv => Recv}, ok = api_a_mrecv_cancel_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically we make multiple async (Timeout = nowait) call(s) to recvfrom %% (from *several* processes), wait some time and then cancel. %% This should result in abort messages to the 'other' processes. IPv6 %% api_a_mrecvfrom_cancel_udp6(suite) -> []; api_a_mrecvfrom_cancel_udp6(doc) -> []; api_a_mrecvfrom_cancel_udp6(_Config) when is_list(_Config) -> ?TT(?SECS(20)), tc_try(api_a_mrecvfrom_cancel_udp6, fun() -> has_support_ipv6() end, fun() -> Recv = fun(Sock) -> case socket:recvfrom(Sock, 0, nowait) of {ok, _} = OK -> OK; {select, _} = SELECT -> SELECT; {error, _} = ERROR -> ERROR end end, InitState = #{domain => inet6, recv => Recv}, ok = api_a_mrecv_cancel_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically we make multiple async (Timeout = nowait) call(s) to recvmsg %% (from *several* processes), wait some time and then cancel. %% This should result in abort messages to the 'other' processes. IPv4 %% api_a_mrecvmsg_cancel_udp4(suite) -> []; api_a_mrecvmsg_cancel_udp4(doc) -> []; api_a_mrecvmsg_cancel_udp4(_Config) when is_list(_Config) -> ?TT(?SECS(20)), tc_try(api_a_mrecvmsg_cancel_udp4, fun() -> Recv = fun(Sock) -> case socket:recvmsg(Sock, nowait) of {ok, _} = OK -> OK; {select, _} = SELECT -> SELECT; {error, _} = ERROR -> ERROR end end, InitState = #{domain => inet, recv => Recv}, ok = api_a_mrecv_cancel_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically we make multiple async (Timeout = nowait) call(s) to recvmsg %% (from *several* processes), wait some time and then cancel. %% This should result in abort messages to the 'other' processes. IPv6 %% api_a_mrecvmsg_cancel_udp6(suite) -> []; api_a_mrecvmsg_cancel_udp6(doc) -> []; api_a_mrecvmsg_cancel_udp6(_Config) when is_list(_Config) -> ?TT(?SECS(20)), tc_try(api_a_mrecvmsg_cancel_udp6, fun() -> has_support_ipv6() end, fun() -> Recv = fun(Sock) -> case socket:recvmsg(Sock, nowait) of {ok, _} = OK -> OK; {select, _} = SELECT -> SELECT; {error, _} = ERROR -> ERROR end end, InitState = #{domain => inet6, recv => Recv}, ok = api_a_mrecv_cancel_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% api_a_mrecv_cancel_udp(InitState) -> ServerSeq = [ %% *** Wait for start order part *** #{desc => "await start", cmd => fun(State) -> Tester = ?SEV_AWAIT_START(), {ok, State#{tester => Tester}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, #{desc => "create socket", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, dgram, udp) of {ok, Sock} -> {ok, State#{sock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind socket (to local address)", cmd => fun(#{sock := Sock, local_sa := LSA} = State) -> case socket:bind(Sock, LSA) of {ok, Port} -> {ok, State#{port => Port}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester, sock := Sock}) -> ?SEV_ANNOUNCE_READY(Tester, init, Sock), ok end}, %% The actual test #{desc => "await continue (recv)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, recv) end}, #{desc => "try recv request (with nowait, expect select)", cmd => fun(#{sock := Sock, recv := Recv} = State) -> case Recv(Sock) of {select, SelectInfo} -> {ok, State#{recv_select_info => SelectInfo}}; {ok, X} -> {error, {unexpected_select_info, X}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (recv_select)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv_select), ok end}, #{desc => "await abort message", cmd => fun(#{sock := Sock, recv_select_info := {select_info, _, Ref}} = State) -> receive {'$socket', Sock, select, Ref} -> {error, {unexpected_select, Ref}}; {'$socket', Sock, abort, {Ref, closed}} -> {ok, maps:remove(sock, State)} after 5000 -> ?SEV_EPRINT("message queue: ~p", [mq()]), {error, timeout} end end}, #{desc => "announce ready (abort)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, abort), ok end}, %% Termination #{desc => "await terminate (from tester)", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> State2 = maps:remove(tester, State), State3 = maps:remove(recv_stag, State2), State4 = maps:remove(recv_sref, State3), State5 = maps:remove(req_src, State4), {ok, State5}; {error, _} = ERROR -> ERROR end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], AltServerSeq = [ %% *** Wait for start order part *** #{desc => "await start", cmd => fun(State) -> {Tester, Sock} = ?SEV_AWAIT_START(), {ok, State#{tester => Tester, sock => Sock}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, init), ok end}, %% The actual test #{desc => "await continue (recv)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, recv) end}, #{desc => "try recv request (with nowait, expect select)", cmd => fun(#{sock := Sock, recv := Recv} = State) -> case Recv(Sock) of {select, SelectInfo} -> {ok, State#{recv_select_info => SelectInfo}}; {ok, X} -> {error, {unexpected_select_info, X}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (recv_select)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv_select), ok end}, #{desc => "await abort message", cmd => fun(#{sock := Sock, recv_select_info := {select_info, _, Ref}} = State) -> receive {'$socket', Sock, select, Ref} -> {error, {unexpected_select, Ref}}; {'$socket', Sock, abort, {Ref, closed}} -> {ok, maps:remove(sock, State)} after 5000 -> ?SEV_EPRINT("message queue: ~p", [mq()]), {error, timeout} end end}, #{desc => "announce ready (abort)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, abort), ok end}, %% Termination #{desc => "await terminate (from tester)", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> ?SEV_IPRINT("terminating"), State1 = maps:remove(recv_select_info, State), State2 = maps:remove(tester, State1), State3 = maps:remove(sock, State2), {ok, State3}; {error, _} = ERROR -> ERROR end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], TesterSeq = [ %% *** Init part *** #{desc => "monitor server", cmd => fun(#{server := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "monitor alt-server 1", cmd => fun(#{alt_server1 := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "monitor alt-server 2", cmd => fun(#{alt_server2 := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, %% Start the server #{desc => "order server start", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_START(Pid), ok end}, #{desc => "await server ready (init)", cmd => fun(#{server := Pid} = State) -> {ok, Sock} = ?SEV_AWAIT_READY(Pid, server, init), {ok, State#{sock => Sock}} end}, %% Start the alt-server 1 #{desc => "order alt-server 1 start", cmd => fun(#{alt_server1 := Pid, sock := Sock} = _State) -> ?SEV_ANNOUNCE_START(Pid, Sock), ok end}, #{desc => "await alt-server 1 ready (init)", cmd => fun(#{alt_server1 := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, alt_server1, init) end}, %% Start the alt-server 2 #{desc => "order alt-server 2 start", cmd => fun(#{alt_server2 := Pid, sock := Sock} = _State) -> ?SEV_ANNOUNCE_START(Pid, Sock), ok end}, #{desc => "await alt-server 2 ready (init)", cmd => fun(#{alt_server2 := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, alt_server2, init) end}, %% The actual test #{desc => "order server continue (recv)", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, recv), ok end}, #{desc => "await server ready (recv select)", cmd => fun(#{server := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, server, recv_select) end}, #{desc => "order alt-server 1 continue (recv)", cmd => fun(#{alt_server1 := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, recv), ok end}, #{desc => "await alt-server 1 ready (recv select)", cmd => fun(#{alt_server1 := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, alt_server1, recv_select) end}, #{desc => "order alt-server 2 continue (recv)", cmd => fun(#{alt_server2 := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, recv), ok end}, #{desc => "await alt-server 2 ready (recv select)", cmd => fun(#{alt_server2 := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, alt_server2, recv_select) end}, ?SEV_SLEEP(?SECS(1)), #{desc => "close the socket", cmd => fun(#{sock := Sock} = _State) -> socket:close(Sock) end}, #{desc => "await server ready (abort)", cmd => fun(#{server := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, server, abort) end}, #{desc => "await alt-server 1 ready (abort)", cmd => fun(#{alt_server1 := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, alt_server1, abort) end}, #{desc => "await alt-server 2 ready (abort)", cmd => fun(#{alt_server2 := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, alt_server2, abort) end}, %% Terminations #{desc => "order alt-server 2 to terminate", cmd => fun(#{alt_server2 := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await alt-server 2 termination", cmd => fun(#{alt_server2 := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> State1 = maps:remove(alt_server2, State), {ok, State1}; {error, _} = ERROR -> ERROR end end}, #{desc => "order alt-server 1 to terminate", cmd => fun(#{alt_server1 := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await alt-server 1 termination", cmd => fun(#{alt_server1 := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> State1 = maps:remove(alt_server1, State), {ok, State1}; {error, _} = ERROR -> ERROR end end}, #{desc => "order server to terminate", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await server termination", cmd => fun(#{server := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> State1 = maps:remove(server, State), {ok, State1}; {error, _} = ERROR -> ERROR end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], i("start server evaluator"), Server = ?SEV_START("server", ServerSeq, InitState), i("start alt-server 1 evaluator"), AltServer1 = ?SEV_START("alt_server1", AltServerSeq, InitState), i("start alt-server 2 evaluator"), AltServer2 = ?SEV_START("alt_server2", AltServerSeq, InitState), i("start 'tester' evaluator"), TesterInitState = #{server => Server#ev.pid, alt_server1 => AltServer1#ev.pid, alt_server2 => AltServer2#ev.pid}, Tester = ?SEV_START("tester", TesterSeq, TesterInitState), i("await evaluator(s)"), ok = ?SEV_AWAIT_FINISH([Server, AltServer1, AltServer2, Tester]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically we make multiple async (Timeout = nowait) call(s) to accept %% (from *several* processes), wait some time and then cancel, %% This should result in abort messages to the 'other' processes. IPv4 %% api_a_maccept_cancel_tcp4(suite) -> []; api_a_maccept_cancel_tcp4(doc) -> []; api_a_maccept_cancel_tcp4(_Config) when is_list(_Config) -> ?TT(?SECS(20)), tc_try(api_a_maccept_cancel_tcp4, fun() -> Accept = fun(Sock) -> case socket:accept(Sock, nowait) of {ok, _} = OK -> OK; {select, _} = SELECT -> SELECT; {error, _} = ERROR -> ERROR end end, InitState = #{domain => inet, accept => Accept}, ok = api_a_maccept_cancel_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically we make multiple async (Timeout = nowait) call(s) to accept %% (from *several* processes), wait some time and then cancel, %% This should result in abort messages to the 'other' processes. IPv6 %% api_a_maccept_cancel_tcp6(suite) -> []; api_a_maccept_cancel_tcp6(doc) -> []; api_a_maccept_cancel_tcp6(_Config) when is_list(_Config) -> ?TT(?SECS(20)), tc_try(api_a_maccept_cancel_tcp6, fun() -> has_support_ipv6() end, fun() -> Accept = fun(Sock) -> case socket:accept(Sock, nowait) of {ok, _} = OK -> OK; {select, _} = SELECT -> SELECT; {error, _} = ERROR -> ERROR end end, InitState = #{domain => inet6, accept => Accept}, ok = api_a_maccept_cancel_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% api_a_maccept_cancel_tcp(InitState) -> process_flag(trap_exit, true), ServerSeq = [ %% *** Wait for start order *** #{desc => "await start (from tester)", cmd => fun(State) -> Tester = ?SEV_AWAIT_START(), {ok, State#{tester => Tester}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester}) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> LSA = which_local_socket_addr(Domain), {ok, State#{lsa => LSA}} end}, #{desc => "create listen socket", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, stream, tcp) of {ok, Sock} -> {ok, State#{lsock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind to local address", cmd => fun(#{lsock := LSock, lsa := LSA} = State) -> case socket:bind(LSock, LSA) of {ok, Port} -> {ok, State#{lport => Port}}; {error, _} = ERROR -> ERROR end end}, #{desc => "make listen socket", cmd => fun(#{lsock := LSock}) -> socket:listen(LSock) end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester, lsock := Sock}) -> ?SEV_ANNOUNCE_READY(Tester, init, Sock), ok end}, %% The actual test #{desc => "await continue (accept)", cmd => fun(#{tester := Tester}) -> ?SEV_AWAIT_CONTINUE(Tester, tester, accept) end}, #{desc => "await connection (nowait)", cmd => fun(#{lsock := LSock, accept := Accept} = State) -> case Accept(LSock) of {select, {select_info, T, R} = SelectInfo} -> ?SEV_IPRINT("accept select: " "~n T: ~p" "~n R: ~p", [T, R]), {ok, State#{accept_select_info => SelectInfo}}; {ok, X} -> {error, {unexpected_select_info, X}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (accept_select)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, accept_select), ok end}, #{desc => "await select message (without success)", cmd => fun(#{lsock := Sock, accept_select_info := {select_info, _, Ref}} = State) -> receive {'$socket', Sock, select, Ref} -> {error, {unexpected_select, Ref}}; {'$socket', Sock, abort, {Ref, closed}} -> {ok, maps:remove(lsock, State)} after 5000 -> ?SEV_EPRINT("message queue: ~p", [mq()]), {error, timeout} end end}, #{desc => "announce ready (abort)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, abort), ok end}, %% *** Termination *** #{desc => "await terminate", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], AltServerSeq = [ %% *** Wait for start order part *** #{desc => "await start", cmd => fun(State) -> {Tester, Sock} = ?SEV_AWAIT_START(), {ok, State#{tester => Tester, lsock => Sock}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, init), ok end}, %% The actual test #{desc => "await continue (accept)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, accept) end}, #{desc => "try accept request (with nowait, expect select)", cmd => fun(#{lsock := Sock, accept := Accept} = State) -> case Accept(Sock) of {select, SelectInfo} -> {ok, State#{accept_select_info => SelectInfo}}; {ok, X} -> {error, {unexpected_select_info, X}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (accept_select)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, accept_select), ok end}, #{desc => "await abort message", cmd => fun(#{lsock := Sock, accept_select_info := {select_info, _, Ref}} = State) -> receive {'$socket', Sock, select, Ref} -> {error, {unexpected_select, Ref}}; {'$socket', Sock, abort, {Ref, closed}} -> {ok, maps:remove(sock, State)} after 5000 -> ?SEV_EPRINT("message queue: ~p", [mq()]), {error, timeout} end end}, #{desc => "announce ready (abort)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, abort), ok end}, %% Termination #{desc => "await terminate (from tester)", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> ?SEV_IPRINT("terminating"), State1 = maps:remove(tester, State), State2 = maps:remove(accept_select_info, State1), State3 = maps:remove(lsock, State2), {ok, State3}; {error, _} = ERROR -> ERROR end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], TesterSeq = [ %% *** Init part *** #{desc => "monitor server", cmd => fun(#{server := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "monitor alt-server 1", cmd => fun(#{alt_server1 := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "monitor alt-server 2", cmd => fun(#{alt_server2 := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, %% Start the server #{desc => "order server start", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_START(Pid), ok end}, #{desc => "await server ready (init)", cmd => fun(#{server := Pid} = State) -> {ok, Sock} = ?SEV_AWAIT_READY(Pid, server, init), {ok, State#{sock => Sock}} end}, %% Start the alt-server 1 #{desc => "order alt-server 1 start", cmd => fun(#{alt_server1 := Pid, sock := Sock} = _State) -> ?SEV_ANNOUNCE_START(Pid, Sock), ok end}, #{desc => "await alt-server 1 ready (init)", cmd => fun(#{alt_server1 := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, alt_server1, init) end}, %% Start the alt-server 2 #{desc => "order alt-server 2 start", cmd => fun(#{alt_server2 := Pid, sock := Sock} = _State) -> ?SEV_ANNOUNCE_START(Pid, Sock), ok end}, #{desc => "await alt-server 2 ready (init)", cmd => fun(#{alt_server2 := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, alt_server2, init) end}, %% *** The actual test *** #{desc => "order server continue (accept)", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, accept), ok end}, #{desc => "await server ready (accept select)", cmd => fun(#{server := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, server, accept_select) end}, #{desc => "order alt-server 1 continue (accept)", cmd => fun(#{alt_server1 := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, accept), ok end}, #{desc => "await alt-server 1 ready (accept select)", cmd => fun(#{alt_server1 := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, alt_server1, accept_select) end}, #{desc => "order alt-server 2 continue (accept)", cmd => fun(#{alt_server2 := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, accept), ok end}, #{desc => "await alt-server 2 ready (accept select)", cmd => fun(#{alt_server2 := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, alt_server2, accept_select) end}, ?SEV_SLEEP(?SECS(1)), #{desc => "close the socket", cmd => fun(#{sock := Sock} = _State) -> socket:close(Sock) end}, #{desc => "await server ready (abort)", cmd => fun(#{server := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, server, abort) end}, #{desc => "await alt-server 1 ready (abort)", cmd => fun(#{alt_server1 := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, alt_server1, abort) end}, #{desc => "await alt-server 2 ready (abort)", cmd => fun(#{alt_server2 := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, alt_server2, abort) end}, %% *** Termination *** #{desc => "order alt-server 2 to terminate", cmd => fun(#{alt_server2 := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await alt-server 2 termination", cmd => fun(#{alt_server2 := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> State1 = maps:remove(alt_server2, State), {ok, State1}; {error, _} = ERROR -> ERROR end end}, #{desc => "order alt-server 1 to terminate", cmd => fun(#{alt_server1 := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await alt-server 1 termination", cmd => fun(#{alt_server1 := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> State1 = maps:remove(alt_server1, State), {ok, State1}; {error, _} = ERROR -> ERROR end end}, #{desc => "order server to terminate", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Server), ok end}, #{desc => "await server termination", cmd => fun(#{server := Server} = State) -> ?SEV_AWAIT_TERMINATION(Server), State1 = maps:remove(server, State), {ok, State1} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], i("start server evaluator"), Server = ?SEV_START("server", ServerSeq, InitState), i("start alt-server 1 evaluator"), AltServer1 = ?SEV_START("alt_server1", AltServerSeq, InitState), i("start alt-server 2 evaluator"), AltServer2 = ?SEV_START("alt_server2", AltServerSeq, InitState), i("start tester evaluator"), TesterInitState = #{server => Server#ev.pid, alt_server1 => AltServer1#ev.pid, alt_server2 => AltServer2#ev.pid}, Tester = ?SEV_START("tester", TesterSeq, TesterInitState), i("await evaluator(s)"), ok = ?SEV_AWAIT_FINISH([Server, AltServer1, AltServer2, Tester]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically we make multiple async (Timeout = nowait) call(s) to recv %% (from *several* processes), wait some time and then cancel, %% This should result in abort messages to the 'other' processes. IPv4 %% api_a_mrecv_cancel_tcp4(suite) -> []; api_a_mrecv_cancel_tcp4(doc) -> []; api_a_mrecv_cancel_tcp4(_Config) when is_list(_Config) -> ?TT(?SECS(20)), tc_try(api_a_mrecv_cancel_tcp4, fun() -> Recv = fun(Sock) -> socket:recv(Sock, 0, nowait) end, InitState = #{domain => inet, recv => Recv}, ok = api_a_mrecv_cancel_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically we make multiple async (Timeout = nowait) call(s) to recv %% (from *several* processes), wait some time and then cancel, %% This should result in abort messages to the 'other' processes. IPv6 %% api_a_mrecv_cancel_tcp6(suite) -> []; api_a_mrecv_cancel_tcp6(doc) -> []; api_a_mrecv_cancel_tcp6(_Config) when is_list(_Config) -> ?TT(?SECS(20)), tc_try(api_a_mrecv_cancel_tcp6, fun() -> has_support_ipv6() end, fun() -> Recv = fun(Sock) -> socket:recv(Sock, 0, nowait) end, InitState = #{domain => inet6, recv => Recv}, ok = api_a_mrecv_cancel_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically we make multiple async (Timeout = nowait) call(s) to recvmsg %% (from *several* processes), wait some time and then cancel, %% This should result in abort messages to the 'other' processes. IPv4 %% api_a_mrecvmsg_cancel_tcp4(suite) -> []; api_a_mrecvmsg_cancel_tcp4(doc) -> []; api_a_mrecvmsg_cancel_tcp4(_Config) when is_list(_Config) -> ?TT(?SECS(20)), tc_try(api_a_mrecvmsg_cancel_tcp4, fun() -> Recv = fun(Sock) -> socket:recvmsg(Sock, nowait) end, InitState = #{domain => inet, recv => Recv}, ok = api_a_mrecv_cancel_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically we make multiple async (Timeout = nowait) call(s) to recvmsg %% (from *several* processes), wait some time and then cancel, %% This should result in abort messages to the 'other' processes. IPv6 %% api_a_mrecvmsg_cancel_tcp6(suite) -> []; api_a_mrecvmsg_cancel_tcp6(doc) -> []; api_a_mrecvmsg_cancel_tcp6(_Config) when is_list(_Config) -> ?TT(?SECS(20)), tc_try(api_a_mrecvmsg_cancel_tcp6, fun() -> has_support_ipv6() end, fun() -> Recv = fun(Sock) -> socket:recvmsg(Sock, nowait) end, InitState = #{domain => inet6, recv => Recv}, ok = api_a_mrecv_cancel_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% api_a_mrecv_cancel_tcp(InitState) -> process_flag(trap_exit, true), ServerSeq = [ %% *** Wait for start order *** #{desc => "await start (from tester)", cmd => fun(State) -> Tester = ?SEV_AWAIT_START(), {ok, State#{tester => Tester}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester}) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> LSA = which_local_socket_addr(Domain), {ok, State#{lsa => LSA}} end}, #{desc => "create listen socket", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, stream, tcp) of {ok, Sock} -> {ok, State#{lsock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind to local address", cmd => fun(#{lsock := LSock, lsa := LSA} = State) -> case socket:bind(LSock, LSA) of {ok, Port} -> {ok, State#{lport => Port}}; {error, _} = ERROR -> ERROR end end}, #{desc => "make listen socket", cmd => fun(#{lsock := LSock}) -> socket:listen(LSock) end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester, lport := Port}) -> ?SEV_ANNOUNCE_READY(Tester, init, Port), ok end}, %% The actual test #{desc => "await continue (accept)", cmd => fun(#{tester := Tester}) -> ?SEV_AWAIT_CONTINUE(Tester, tester, accept) end}, #{desc => "await connection (nowait)", cmd => fun(#{lsock := LSock} = State) -> case socket:accept(LSock) of {ok, CSock} -> {ok, State#{csock => CSock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (accept)", cmd => fun(#{tester := Tester, csock := Sock}) -> ?SEV_ANNOUNCE_READY(Tester, accept, Sock), ok end}, #{desc => "await continue (nowait recv)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, recv) end}, #{desc => "try recv request (with nowait, expect select)", cmd => fun(#{csock := Sock, recv := Recv} = State) -> case Recv(Sock) of {select, {select_info, T, R} = SelectInfo} -> ?SEV_IPRINT("recv select: " "~n Tag: ~p" "~n Ref: ~p", [T, R]), {ok, State#{recv_select_info => SelectInfo}}; {ok, X} -> {error, {unexpected_select_info, X}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (recv_select)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv_select), ok end}, #{desc => "await select message", cmd => fun(#{csock := Sock, recv_select_info := {select_info, _, Ref}} = State) -> receive {'$socket', Sock, select, Ref} -> {error, {unexpected_select, Ref}}; {'$socket', Sock, abort, {Ref, closed}} -> {ok, maps:remove(sock, State)} after 5000 -> ok end end}, #{desc => "announce ready (abort)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, abort), ok end}, %% *** Termination *** #{desc => "await terminate", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "close listen socket", cmd => fun(#{lsock := Sock}) -> socket:close(Sock) end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], AltServerSeq = [ %% *** Wait for start order part *** #{desc => "await start", cmd => fun(State) -> {Tester, Sock} = ?SEV_AWAIT_START(), {ok, State#{tester => Tester, sock => Sock}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, init), ok end}, %% The actual test #{desc => "await continue (recv)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, recv) end}, #{desc => "try recv request (with nowait, expect select)", cmd => fun(#{sock := Sock, recv := Recv} = State) -> case Recv(Sock) of {select, SelectInfo} -> {ok, State#{recv_select_info => SelectInfo}}; {ok, X} -> {error, {unexpected_select_info, X}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (recv_select)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv_select), ok end}, #{desc => "await abort message", cmd => fun(#{sock := Sock, recv_select_info := {select_info, _, Ref}} = State) -> receive {'$socket', Sock, select, Ref} -> {error, {unexpected_select, Ref}}; {'$socket', Sock, abort, {Ref, closed}} -> {ok, maps:remove(sock, State)} after 5000 -> ?SEV_EPRINT("message queue: ~p", [mq()]), {error, timeout} end end}, #{desc => "announce ready (abort)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, abort), ok end}, %% Termination #{desc => "await terminate (from tester)", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> ?SEV_IPRINT("terminating"), State1 = maps:remove(recv_select_info, State), State2 = maps:remove(tester, State1), State3 = maps:remove(sock, State2), {ok, State3}; {error, _} = ERROR -> ERROR end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], ClientSeq = [ %% *** Wait for start order *** #{desc => "await start (from tester)", cmd => fun(State) -> {Tester, Port} = ?SEV_AWAIT_START(), {ok, State#{tester => Tester, server_port => Port}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester}) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** The init part *** #{desc => "which server (local) address", cmd => fun(#{domain := Domain, server_port := Port} = State) -> LSA = which_local_socket_addr(Domain), SSA = LSA#{port => Port}, {ok, State#{local_sa => LSA, server_sa => SSA}} end}, #{desc => "create socket", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, stream, tcp) of {ok, Sock} -> {ok, State#{sock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind to local address", cmd => fun(#{sock := Sock, local_sa := LSA} = _State) -> case socket:bind(Sock, LSA) of {ok, _Port} -> ok; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, init), ok end}, %% *** The actual test *** #{desc => "await continue (connect)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, connect) end}, #{desc => "connect to server", cmd => fun(#{sock := Sock, server_sa := SSA}) -> socket:connect(Sock, SSA) end}, #{desc => "announce ready (connect)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, connect), ok end}, %% *** Termination *** #{desc => "await terminate", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "close socket", cmd => fun(#{sock := Sock}) -> socket:close(Sock) end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], TesterSeq = [ %% *** Init part *** #{desc => "monitor server", cmd => fun(#{server := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "monitor alt-server 1", cmd => fun(#{alt_server1 := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "monitor alt-server 2", cmd => fun(#{alt_server2 := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "monitor client", cmd => fun(#{client := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, %% Start the server #{desc => "order server start", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_START(Pid), ok end}, #{desc => "await server ready (init)", cmd => fun(#{server := Pid} = State) -> {ok, Port} = ?SEV_AWAIT_READY(Pid, server, init), {ok, State#{server_port => Port}} end}, %% Start the client #{desc => "order client start", cmd => fun(#{client := Pid, server_port := Port} = _State) -> ?SEV_ANNOUNCE_START(Pid, Port), ok end}, #{desc => "await client ready (init)", cmd => fun(#{client := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, client, init) end}, #{desc => "order server to continue (with accept)", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Server, accept), ok end}, #{desc => "order client to continue (connect)", cmd => fun(#{client := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, connect), ok end}, #{desc => "await client ready (connect)", cmd => fun(#{client := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, client, connect) end}, #{desc => "await server ready (accept)", cmd => fun(#{server := Pid} = State) -> {ok, Sock} = ?SEV_AWAIT_READY(Pid, server, accept), {ok, State#{sock => Sock}} end}, %% Start the alt server 1 #{desc => "order alt-server 1 start", cmd => fun(#{alt_server1 := Pid, sock := Sock} = _State) -> ?SEV_ANNOUNCE_START(Pid, Sock), ok end}, #{desc => "await alt-server 1 ready (init)", cmd => fun(#{alt_server1 := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, alt_server1, init) end}, %% Start the alt server 2 #{desc => "order alt-server 2 start", cmd => fun(#{alt_server2 := Pid, sock := Sock} = _State) -> ?SEV_ANNOUNCE_START(Pid, Sock), ok end}, #{desc => "await alt-server 2 ready (init)", cmd => fun(#{alt_server2 := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, alt_server2, init) end}, %% *** The actual test *** #{desc => "order server continue (recv)", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, recv), ok end}, #{desc => "await server ready (recv select)", cmd => fun(#{server := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, server, recv_select) end}, #{desc => "order alt-server 1 continue (recv)", cmd => fun(#{alt_server1 := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, recv), ok end}, #{desc => "await alt-server 1 ready (recv select)", cmd => fun(#{alt_server1 := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, alt_server1, recv_select) end}, #{desc => "order alt-server 2 continue (recv)", cmd => fun(#{alt_server2 := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, recv), ok end}, #{desc => "await alt-server 2 ready (recv select)", cmd => fun(#{alt_server2 := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, alt_server2, recv_select) end}, ?SEV_SLEEP(?SECS(1)), #{desc => "close the socket", cmd => fun(#{sock := Sock} = _State) -> socket:close(Sock) end}, #{desc => "await server ready (abort)", cmd => fun(#{server := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, server, abort) end}, #{desc => "await alt-server 1 ready (abort)", cmd => fun(#{alt_server1 := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, alt_server1, abort) end}, #{desc => "await alt-server 2 ready (abort)", cmd => fun(#{alt_server2 := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, alt_server2, abort) end}, %% Terminations #{desc => "order client to terminate", cmd => fun(#{client := Client} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Client), ok end}, #{desc => "await client termination", cmd => fun(#{client := Client} = State) -> ?SEV_AWAIT_TERMINATION(Client), State1 = maps:remove(client, State), {ok, State1} end}, #{desc => "order alt-server 2 to terminate", cmd => fun(#{alt_server2 := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await alt-server 2 termination", cmd => fun(#{alt_server2 := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> State1 = maps:remove(alt_server2, State), {ok, State1}; {error, _} = ERROR -> ERROR end end}, #{desc => "order alt-server 1 to terminate", cmd => fun(#{alt_server1 := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await alt-server 1 termination", cmd => fun(#{alt_server1 := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> State1 = maps:remove(alt_server1, State), {ok, State1}; {error, _} = ERROR -> ERROR end end}, #{desc => "order server to terminate", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await server termination", cmd => fun(#{server := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> State1 = maps:remove(server, State), {ok, State1}; {error, _} = ERROR -> ERROR end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], i("start server evaluator"), Server = ?SEV_START("server", ServerSeq, InitState), i("start alt-server 1 evaluator"), AltServer1 = ?SEV_START("alt_server1", AltServerSeq, InitState), i("start alt-server 2 evaluator"), AltServer2 = ?SEV_START("alt_server2", AltServerSeq, InitState), i("start client evaluator"), Client = ?SEV_START("client", ClientSeq, InitState), i("start tester evaluator"), TesterInitState = #{server => Server#ev.pid, alt_server1 => AltServer1#ev.pid, alt_server2 => AltServer2#ev.pid, client => Client#ev.pid}, Tester = ?SEV_START("tester", TesterSeq, TesterInitState), i("await evaluator(s)"), ok = ?SEV_AWAIT_FINISH([Server, AltServer1, AltServer2, Client, Tester]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %% %% API OPTIONS %% %% %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Perform some simple getopt and setopt with the level = otp options api_opt_simple_otp_options(suite) -> []; api_opt_simple_otp_options(doc) -> []; api_opt_simple_otp_options(_Config) when is_list(_Config) -> ?TT(?SECS(5)), tc_try(api_opt_simple_otp_options, fun() -> api_opt_simple_otp_options() end). api_opt_simple_otp_options() -> Get = fun(S, Key) -> socket:getopt(S, otp, Key) end, Set = fun(S, Key, Val) -> socket:setopt(S, otp, Key, Val) end, Seq = [ %% *** Init part *** #{desc => "create socket", cmd => fun(#{domain := Domain, type := Type, protocol := Protocol} = State) -> Sock = sock_open(Domain, Type, Protocol), {ok, State#{sock => Sock}} end}, #{desc => "create dummy process", cmd => fun(State) -> Pid = spawn_link(fun() -> put(sname, "dummy"), receive die -> exit(normal) end end), {ok, State#{dummy => Pid}} end}, %% *** Check iow part *** #{desc => "get iow", cmd => fun(#{sock := Sock} = State) -> case Get(Sock, iow) of {ok, IOW} when is_boolean(IOW) -> {ok, State#{iow => IOW}}; {ok, InvalidIOW} -> {error, {invalid, InvalidIOW}}; {error, _} = ERROR -> ERROR end end}, %% #{desc => "enable debug", %% cmd => fun(#{sock := Sock}) -> %% ok = socket:setopt(Sock, otp, debug, true) %% end}, #{desc => "set (new) iow", cmd => fun(#{sock := Sock, iow := OldIOW} = State) -> NewIOW = not OldIOW, case Set(Sock, iow, NewIOW) of ok -> {ok, State#{iow => NewIOW}}; {error, _} = ERROR -> ERROR end end}, #{desc => "get (new) iow", cmd => fun(#{sock := Sock, iow := IOW}) -> case Get(Sock, iow) of {ok, IOW} -> ok; {ok, InvalidIOW} -> {error, {invalid, InvalidIOW}}; {error, _} = ERROR -> ERROR end end}, %% *** Check rcvbuf part *** #{desc => "get rcvbuf", cmd => fun(#{sock := Sock} = State) -> case Get(Sock, rcvbuf) of {ok, RcvBuf} when is_integer(RcvBuf) -> {ok, State#{rcvbuf => RcvBuf}}; {ok, {N, RcvBuf} = V} when is_integer(N) andalso is_integer(RcvBuf) -> {ok, State#{rcvbuf => V}}; {ok, InvalidRcvBuf} -> {error, {invalid, InvalidRcvBuf}}; {error, _} = ERROR -> ERROR end end}, #{desc => "set (new) rcvbuf", cmd => fun(#{sock := Sock, rcvbuf := {OldN, OldRcvBuf}} = State) -> NewRcvBuf = {OldN+2, OldRcvBuf + 1024}, case Set(Sock, rcvbuf, NewRcvBuf) of ok -> {ok, State#{rcvbuf => NewRcvBuf}}; {error, _} = ERROR -> ERROR end; (#{sock := Sock, rcvbuf := OldRcvBuf} = State) when is_integer(OldRcvBuf) -> NewRcvBuf = 2 * OldRcvBuf, case Set(Sock, rcvbuf, NewRcvBuf) of ok -> {ok, State#{rcvbuf => NewRcvBuf}}; {error, _} = ERROR -> ERROR end; (#{sock := Sock, rcvbuf := OldRcvBuf, type := stream, protocol := tcp} = State) when is_integer(OldRcvBuf) -> NewRcvBuf = {2, OldRcvBuf}, case Set(Sock, rcvbuf, NewRcvBuf) of ok -> {ok, State#{rcvbuf => NewRcvBuf}}; {error, _} = ERROR -> ERROR end end}, #{desc => "get (new) rcvbuf", cmd => fun(#{sock := Sock, rcvbuf := RcvBuf}) -> case Get(Sock, rcvbuf) of {ok, RcvBuf} -> ok; {ok, InvalidRcvBuf} -> {error, {invalid, InvalidRcvBuf}}; {error, _} = ERROR -> ERROR end end}, %% *** Check rcvctrlbuf part *** #{desc => "get rcvctrlbuf", cmd => fun(#{sock := Sock} = State) -> case Get(Sock, rcvctrlbuf) of {ok, RcvCtrlBuf} when is_integer(RcvCtrlBuf) -> {ok, State#{rcvctrlbuf => RcvCtrlBuf}}; {ok, InvalidRcvCtrlBuf} -> {error, {invalid, InvalidRcvCtrlBuf}}; {error, _} = ERROR -> ERROR end end}, #{desc => "set (new) rcvctrlbuf", cmd => fun(#{sock := Sock, rcvctrlbuf := OldRcvCtrlBuf} = State) -> NewRcvCtrlBuf = 2 * OldRcvCtrlBuf, case Set(Sock, rcvctrlbuf, NewRcvCtrlBuf) of ok -> {ok, State#{rcvctrlbuf => NewRcvCtrlBuf}}; {error, _} = ERROR -> ERROR end end}, #{desc => "get (new) rcvctrlbuf", cmd => fun(#{sock := Sock, rcvctrlbuf := RcvCtrlBuf}) -> case Get(Sock, rcvctrlbuf) of {ok, RcvCtrlBuf} -> ok; {ok, InvalidRcvCtrlBuf} -> {error, {invalid, InvalidRcvCtrlBuf}}; {error, _} = ERROR -> ERROR end end}, %% *** Check rcvctrlbuf part *** #{desc => "get rcvctrlbuf", cmd => fun(#{sock := Sock} = State) -> case Get(Sock, rcvctrlbuf) of {ok, RcvCtrlBuf} when is_integer(RcvCtrlBuf) -> {ok, State#{rcvctrlbuf => RcvCtrlBuf}}; {ok, InvalidRcvCtrlBuf} -> {error, {invalid, InvalidRcvCtrlBuf}}; {error, _} = ERROR -> ERROR end end}, #{desc => "set (new) rcvctrlbuf", cmd => fun(#{sock := Sock, rcvctrlbuf := OldRcvCtrlBuf} = State) -> NewRcvCtrlBuf = 2 * OldRcvCtrlBuf, case Set(Sock, rcvctrlbuf, NewRcvCtrlBuf) of ok -> {ok, State#{rcvctrlbuf => NewRcvCtrlBuf}}; {error, _} = ERROR -> ERROR end end}, #{desc => "get (new) rcvctrlbuf", cmd => fun(#{sock := Sock, rcvctrlbuf := RcvCtrlBuf}) -> case Get(Sock, rcvctrlbuf) of {ok, RcvCtrlBuf} -> ok; {ok, InvalidRcvCtrlBuf} -> {error, {invalid, InvalidRcvCtrlBuf}}; {error, _} = ERROR -> ERROR end end}, %% *** Check sndctrlbuf part *** #{desc => "get sndctrlbuf", cmd => fun(#{sock := Sock} = State) -> case Get(Sock, sndctrlbuf) of {ok, SndCtrlBuf} when is_integer(SndCtrlBuf) -> {ok, State#{sndctrlbuf => SndCtrlBuf}}; {ok, InvalidSndCtrlBuf} -> {error, {invalid, InvalidSndCtrlBuf}}; {error, _} = ERROR -> ERROR end end}, #{desc => "set (new) sndctrlbuf", cmd => fun(#{sock := Sock, sndctrlbuf := OldSndCtrlBuf} = State) -> NewSndCtrlBuf = 2 * OldSndCtrlBuf, case Set(Sock, sndctrlbuf, NewSndCtrlBuf) of ok -> {ok, State#{sndctrlbuf => NewSndCtrlBuf}}; {error, _} = ERROR -> ERROR end end}, #{desc => "get (new) sndctrlbuf", cmd => fun(#{sock := Sock, sndctrlbuf := SndCtrlBuf}) -> case Get(Sock, sndctrlbuf) of {ok, SndCtrlBuf} -> ok; {ok, InvalidSndCtrlBuf} -> {error, {invalid, InvalidSndCtrlBuf}}; {error, _} = ERROR -> ERROR end end}, %% *** Check controlling-process part *** #{desc => "verify self as controlling-process", cmd => fun(#{sock := Sock}) -> Self = self(), case Get(Sock, controlling_process) of {ok, Self} -> ok; {ok, InvalidPid} -> {error, {invalid, InvalidPid}}; {error, _} = ERROR -> ERROR end end}, #{desc => "set dummy as controlling-process", cmd => fun(#{sock := Sock, dummy := Dummy}) -> Set(Sock, controlling_process, Dummy) end}, #{desc => "verify dummy as controlling-process", cmd => fun(#{sock := Sock, dummy := Dummy}) -> case Get(Sock, controlling_process) of {ok, Dummy} -> ok; {ok, InvalidPid} -> {error, {invalid, InvalidPid}}; {error, _} = ERROR -> ERROR end end}, %% *** We are done *** #{desc => "finish", cmd => fun(_) -> {ok, normal} end} ], i("start tcp (stream) evaluator"), InitState1 = #{domain => inet, type => stream, protocol => tcp}, Tester1 = ?SEV_START("tcp-tester", Seq, InitState1), i("await tcp evaluator"), ok = ?SEV_AWAIT_FINISH([Tester1]), i("start udp (dgram) socket"), InitState2 = #{domain => inet, type => dgram, protocol => udp}, Tester2 = ?SEV_START("udp-tester", Seq, InitState2), i("await udp evaluator"), ok = ?SEV_AWAIT_FINISH([Tester2]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Perform some simple operations with the rcvbuf otp option %% The operations we test here are only for type = stream and %% protocol = tcp. api_opt_simple_otp_rcvbuf_option(suite) -> []; api_opt_simple_otp_rcvbuf_option(doc) -> []; api_opt_simple_otp_rcvbuf_option(_Config) when is_list(_Config) -> ?TT(?SECS(15)), tc_try(api_opt_simple_otp_rcvbuf_option, fun() -> api_opt_simple_otp_rcvbuf_option() end). api_opt_simple_otp_rcvbuf_option() -> Get = fun(S) -> socket:getopt(S, otp, rcvbuf) end, Set = fun(S, Val) -> socket:setopt(S, otp, rcvbuf, Val) end, ServerSeq = [ %% *** Wait for start order part *** #{desc => "await start (from tester)", cmd => fun(State) -> Tester = ?SEV_AWAIT_START(), {ok, State#{tester => Tester}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, #{desc => "create listen socket", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, stream, tcp) of {ok, Sock} -> {ok, State#{lsock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind to local address", cmd => fun(#{lsock := LSock, local_sa := LSA} = State) -> case socket:bind(LSock, LSA) of {ok, Port} -> {ok, State#{lport => Port}}; {error, _} = ERROR -> ERROR end end}, #{desc => "make listen socket", cmd => fun(#{lsock := LSock}) -> socket:listen(LSock) end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester, local_sa := LocalSA, lport := Port}) -> ServerSA = LocalSA#{port => Port}, ?SEV_ANNOUNCE_READY(Tester, init, ServerSA), ok end}, %% *** The actual test part *** #{desc => "await continue (accept)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, accept) end}, #{desc => "attempt to accept", cmd => fun(#{lsock := LSock} = State) -> case socket:accept(LSock) of {ok, Sock} -> {ok, State#{sock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (accept)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, accept), ok end}, %% Recv with default size for (otp) rcvbuf #{desc => "await continue (recv initial)", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_CONTINUE(Tester, tester, recv) of {ok, MsgSz} -> ?SEV_IPRINT("MsgSz: ~p", [MsgSz]), {ok, State#{msg_sz => MsgSz}}; {error, _} = ERROR -> ERROR end end}, #{desc => "attempt to recv", cmd => fun(#{sock := Sock, msg_sz := MsgSz} = _State) -> ?SEV_IPRINT("try recv ~w bytes when rcvbuf is ~s", [MsgSz, case Get(Sock) of {ok, RcvBuf} -> f("~w", [RcvBuf]); {error, _} -> "-" end]), case socket:recv(Sock) of {ok, Data} when (size(Data) =:= MsgSz) -> ok; {ok, Data} -> {error, {invalid_msg_sz, MsgSz, size(Data)}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (recv initial)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv), ok end}, %% Recv with new size (1) for (otp) rcvbuf #{desc => "await continue (recv 1)", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_CONTINUE(Tester, tester, recv) of {ok, NewRcvBuf} -> ?SEV_IPRINT("set new rcvbuf: ~p", [NewRcvBuf]), {ok, State#{rcvbuf => NewRcvBuf}}; {error, _} = ERROR -> ERROR end end}, #{desc => "attempt to setopt rcvbuf", cmd => fun(#{sock := Sock, rcvbuf := NewRcvBuf} = _State) -> case Set(Sock, NewRcvBuf) of ok -> ok; {error, _} = ERROR -> ERROR end end}, #{desc => "attempt to recv", cmd => fun(#{sock := Sock, msg_sz := MsgSz} = _State) -> case socket:recv(Sock) of {ok, Data} when (size(Data) =:= MsgSz) -> ok; {ok, Data} -> {error, {invalid_msg_sz, MsgSz, size(Data)}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (recv 1)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv), ok end}, %% Recv with new size (2) for (otp) rcvbuf #{desc => "await continue (recv 2)", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_CONTINUE(Tester, tester, recv) of {ok, NewRcvBuf} -> ?SEV_IPRINT("set new rcvbuf: ~p", [NewRcvBuf]), {ok, State#{rcvbuf => NewRcvBuf}}; {error, _} = ERROR -> ERROR end end}, #{desc => "attempt to setopt rcvbuf", cmd => fun(#{sock := Sock, rcvbuf := NewRcvBuf} = _State) -> case Set(Sock, NewRcvBuf) of ok -> ok; {error, _} = ERROR -> ERROR end end}, #{desc => "attempt to recv", cmd => fun(#{sock := Sock, msg_sz := MsgSz} = _State) -> case socket:recv(Sock) of {ok, Data} when (size(Data) =:= MsgSz) -> ok; {ok, Data} -> {error, {invalid_msg_sz, MsgSz, size(Data)}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (recv 2)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv), ok end}, %% Recv with new size (3) for (otp) rcvbuf #{desc => "await continue (recv 3, truncated)", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_CONTINUE(Tester, tester, recv) of {ok, {ExpSz, NewRcvBuf}} -> {ok, State#{msg_sz => ExpSz, rcvbuf => NewRcvBuf}}; {error, _} = ERROR -> ERROR end end}, #{desc => "attempt to setopt rcvbuf", cmd => fun(#{sock := Sock, rcvbuf := NewRcvBuf} = _State) -> case Set(Sock, NewRcvBuf) of ok -> ?SEV_IPRINT("set new rcvbuf: ~p", [NewRcvBuf]), ok; {error, _} = ERROR -> ERROR end end}, #{desc => "attempt to recv", cmd => fun(#{sock := Sock, msg_sz := MsgSz} = _State) -> ?SEV_IPRINT("try recv ~w bytes of data", [MsgSz]), case socket:recv(Sock) of {ok, Data} when (size(Data) =:= MsgSz) -> ok; {ok, Data} -> {error, {invalid_msg_sz, MsgSz, size(Data)}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (recv)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv), ok end}, %% Termination #{desc => "await terminate", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "close socket(s)", cmd => fun(#{lsock := LSock, sock := Sock} = State) -> sock_close(Sock), sock_close(LSock), State1 = maps:remove(sock, State), State2 = maps:remove(lport, State1), State3 = maps:remove(lsock, State2), {ok, State3} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], ClientSeq = [ %% *** Wait for start order part *** #{desc => "await start", cmd => fun(State) -> {Tester, ServerSA} = ?SEV_AWAIT_START(), {ok, State#{tester => Tester, server_sa => ServerSA}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, #{desc => "create socket", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, stream, tcp) of {ok, Sock} -> {ok, State#{sock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind to local address", cmd => fun(#{sock := Sock, local_sa := LSA} = _State) -> case socket:bind(Sock, LSA) of {ok, _Port} -> ok; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, init), ok end}, %% The actual test #{desc => "await continue (connect)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, connect) end}, #{desc => "connect to server", cmd => fun(#{sock := Sock, server_sa := SSA}) -> socket:connect(Sock, SSA) end}, #{desc => "announce ready (connect)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, connect), ok end}, #{desc => "await continue (send initial)", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_CONTINUE(Tester, tester, send) of {ok, Data} -> {ok, State#{data => Data}}; {error, _} = ERROR -> ERROR end end}, #{desc => "send (initial) data to server", cmd => fun(#{sock := Sock, data := Data} = _State) -> ?SEV_IPRINT("try send ~w bytes", [size(Data)]), socket:send(Sock, Data) end}, #{desc => "announce ready (send initial)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, send), ok end}, #{desc => "await continue (send 1)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, send) end}, #{desc => "send (1) data to server", cmd => fun(#{sock := Sock, data := Data}) -> ?SEV_IPRINT("try send ~w bytes", [size(Data)]), socket:send(Sock, Data) end}, #{desc => "announce ready (send 1)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, send), ok end}, #{desc => "await continue (send 2)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, send) end}, #{desc => "send (2) data to server", cmd => fun(#{sock := Sock, data := Data}) -> ?SEV_IPRINT("try send ~w bytes", [size(Data)]), socket:send(Sock, Data) end}, #{desc => "announce ready (send 2)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, send), ok end}, #{desc => "await continue (send 3)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, send) end}, #{desc => "send (3) data to server", cmd => fun(#{sock := Sock, data := Data}) -> ?SEV_IPRINT("try send ~w bytes", [size(Data)]), socket:send(Sock, Data) end}, #{desc => "announce ready (send 3)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, send), ok end}, %% Termination #{desc => "await terminate", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "close socket", cmd => fun(#{sock := Sock}) -> socket:close(Sock) end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], TesterSeq = [ %% *** Init part *** #{desc => "monitor server", cmd => fun(#{server := Server} = _State) -> _MRef = erlang:monitor(process, Server), ok end}, #{desc => "monitor client", cmd => fun(#{client := Client} = _State) -> _MRef = erlang:monitor(process, Client), ok end}, #{desc => "order server start", cmd => fun(#{server := Server}) -> ?SEV_ANNOUNCE_START(Server) end}, #{desc => "await server ready (init)", cmd => fun(#{server := Server} = State) -> {ok, ServerSA} = ?SEV_AWAIT_READY(Server, server, init), {ok, State#{server_sa => ServerSA}} end}, #{desc => "order client start", cmd => fun(#{client := Client, server_sa := ServerSA}) -> ?SEV_ANNOUNCE_START(Client, ServerSA), ok end}, #{desc => "await client ready (init)", cmd => fun(#{client := Client} = _State) -> ?SEV_AWAIT_READY(Client, client, init) end}, %% The actual test (connecting) #{desc => "order server accept (accept)", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Server, accept), ok end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order client continue (connect)", cmd => fun(#{client := Client} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Client, connect), ok end}, #{desc => "await client ready (connect)", cmd => fun(#{client := Client} = _State) -> ?SEV_AWAIT_READY(Client, client, connect) end}, #{desc => "await server ready (accept)", cmd => fun(#{server := Server} = _State) -> ?SEV_AWAIT_READY(Server, server, accept) end}, %% The actual test (initial part) #{desc => "order client continue (send initial)", cmd => fun(#{client := Client, data := Data} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Client, send, Data), ok end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order server continue (recv initial)", cmd => fun(#{server := Server, data := Data} = _State) -> ExpMsgSz = size(Data), ?SEV_ANNOUNCE_CONTINUE(Server, recv, ExpMsgSz), ok end}, #{desc => "await client ready (send initial)", cmd => fun(#{server := Server, client := Client} = _State) -> case ?SEV_AWAIT_READY(Client, client, send, [{server, Server}]) of ok -> ok; {error, _} = ERROR -> ERROR end end}, #{desc => "await server ready (recv initial)", cmd => fun(#{server := Server, client := Client} = _State) -> case ?SEV_AWAIT_READY(Server, client, recv, [{client, Client}]) of ok -> ok; {error, _} = ERROR -> ERROR end end}, %% The actual test (part 1) #{desc => "order client continue (send 1)", cmd => fun(#{client := Client} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Client, send), ok end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order server continue (recv 1)", cmd => fun(#{server := Server, data := Data} = _State) -> MsgSz = size(Data), NewRcvBuf = {2 + (MsgSz div 1024), 1024}, ?SEV_ANNOUNCE_CONTINUE(Server, recv, NewRcvBuf), ok end}, #{desc => "await client ready (send 1)", cmd => fun(#{server := Server, client := Client} = _State) -> case ?SEV_AWAIT_READY(Client, client, send, [{server, Server}]) of ok -> ok; {error, _} = ERROR -> ERROR end end}, #{desc => "await server ready (recv 1)", cmd => fun(#{server := Server, client := Client} = _State) -> case ?SEV_AWAIT_READY(Server, client, recv, [{client, Client}]) of ok -> ok; {error, _} = ERROR -> ERROR end end}, %% The actual test (part 2) #{desc => "order client continue (send 2)", cmd => fun(#{client := Client} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Client, send), ok end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order server continue (recv 2)", cmd => fun(#{server := Server, data := Data} = _State) -> MsgSz = size(Data), NewRcvBuf = {2 + (MsgSz div 2048), 2048}, ?SEV_ANNOUNCE_CONTINUE(Server, recv, NewRcvBuf), ok end}, #{desc => "await client ready (send 2)", cmd => fun(#{server := Server, client := Client} = _State) -> case ?SEV_AWAIT_READY(Client, client, send, [{server, Server}]) of ok -> ok; {error, _} = ERROR -> ERROR end end}, #{desc => "await server ready (recv 2)", cmd => fun(#{server := Server, client := Client} = _State) -> case ?SEV_AWAIT_READY(Server, client, recv, [{client, Client}]) of ok -> ok; {error, _} = ERROR -> ERROR end end}, %% The actual test (part 3) #{desc => "order client continue (send 3)", cmd => fun(#{client := Client} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Client, send), ok end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order server continue (recv 3)", cmd => fun(#{server := Server, data := Data} = _State) -> MsgSz = size(Data), BufSz = 2048, N = MsgSz div BufSz - 1, NewRcvBuf = {N, BufSz}, ?SEV_ANNOUNCE_CONTINUE(Server, recv, {N*BufSz, NewRcvBuf}) end}, #{desc => "await client ready (send 3)", cmd => fun(#{server := Server, client := Client} = _State) -> case ?SEV_AWAIT_READY(Client, client, send, [{server, Server}]) of ok -> ok; {error, _} = ERROR -> ERROR end end}, #{desc => "await server ready (recv 3)", cmd => fun(#{server := Server, client := Client} = _State) -> case ?SEV_AWAIT_READY(Server, client, recv, [{client, Client}]) of ok -> ok; {error, _} = ERROR -> ERROR end end}, ?SEV_SLEEP(?SECS(1)), %% *** Terminate server *** #{desc => "order client terminate", cmd => fun(#{client := Client} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Client), ok end}, #{desc => "await client down", cmd => fun(#{client := Client} = State) -> ?SEV_AWAIT_TERMINATION(Client), State1 = maps:remove(client, State), {ok, State1} end}, #{desc => "order server terminate", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Server), ok end}, #{desc => "await server down", cmd => fun(#{server := Server} = State) -> ?SEV_AWAIT_TERMINATION(Server), State1 = maps:remove(server, State), State2 = maps:remove(server_sa, State1), {ok, State2} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], %% Create a data binary of 6*1024 bytes Data = list_to_binary(lists:duplicate(6*4, lists:seq(0, 255))), InitState = #{domain => inet, data => Data}, i("create server evaluator"), ServerInitState = #{domain => maps:get(domain, InitState)}, Server = ?SEV_START("server", ServerSeq, ServerInitState), i("create client evaluator"), ClientInitState = #{host => local_host(), domain => maps:get(domain, InitState)}, Client = ?SEV_START("client", ClientSeq, ClientInitState), i("create tester evaluator"), TesterInitState = InitState#{server => Server#ev.pid, client => Client#ev.pid}, Tester = ?SEV_START("tester", TesterSeq, TesterInitState), i("await evaluator(s)"), ok = ?SEV_AWAIT_FINISH([Server, Client, Tester]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Perform some simple getopt and setopt with the level = otp options api_opt_simple_otp_controlling_process(suite) -> []; api_opt_simple_otp_controlling_process(doc) -> []; api_opt_simple_otp_controlling_process(_Config) when is_list(_Config) -> ?TT(?SECS(30)), tc_try(api_opt_simple_otp_controlling_process, fun() -> api_opt_simple_otp_controlling_process() end). api_opt_simple_otp_controlling_process() -> Get = fun(S, Key) -> socket:getopt(S, otp, Key) end, Set = fun(S, Key, Val) -> socket:setopt(S, otp, Key, Val) end, ClientSeq = [ %% *** Init part *** #{desc => "await start", cmd => fun(State) -> {Tester, Sock} = ?SEV_AWAIT_START(), {ok, State#{tester => Tester, sock => Sock}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester}) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** The actual test *** #{desc => "verify tester as controlling-process", cmd => fun(#{tester := Tester, sock := Sock} = _State) -> case Get(Sock, controlling_process) of {ok, Tester} -> ok; {ok, InvalidPid} -> {error, {invalid, InvalidPid}}; {error, _} = ERROR -> ERROR end end}, #{desc => "attempt invalid controlling-process transfer (to self)", cmd => fun(#{sock := Sock} = _State) -> case Set(Sock, controlling_process, self()) of {error, not_owner} -> ok; ok -> {error, unexpected_success}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (not owner)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_ANNOUNCE_READY(Tester, not_owner), ok end}, #{desc => "await continue (owner)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, owner) end}, #{desc => "verify self as controlling-process", cmd => fun(#{sock := Sock} = _State) -> Self = self(), case Get(Sock, controlling_process) of {ok, Self} -> ok; {ok, InvalidPid} -> {error, {invalid, InvalidPid}}; {error, _} = ERROR -> ERROR end end}, #{desc => "attempt controlling-process transfer to tester", cmd => fun(#{tester := Tester, sock := Sock} = _State) -> Set(Sock, controlling_process, Tester) end}, #{desc => "attempt invalid controlling-process transfer (to self)", cmd => fun(#{sock := Sock} = _State) -> case Set(Sock, controlling_process, self()) of {error, not_owner} -> ok; ok -> {error, unexpected_success}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (owner)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_ANNOUNCE_READY(Tester, owner), ok end}, %% *** Termination *** #{desc => "await termination", cmd => fun(#{tester := Tester} = State) -> ?SEV_AWAIT_TERMINATE(Tester, tester), State1 = maps:remove(tester, State), State2 = maps:remove(sock, State1), {ok, State2} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], TesterSeq = [ %% *** Init part *** #{desc => "create socket", cmd => fun(#{domain := Domain, type := Type, protocol := Protocol} = State) -> Sock = sock_open(Domain, Type, Protocol), {ok, State#{sock => Sock}} end}, #{desc => "monitor client", cmd => fun(#{client := Client} = _State) -> _MRef = erlang:monitor(process, Client), ok end}, %% *** The actual test *** #{desc => "verify self as controlling-process", cmd => fun(#{sock := Sock} = _State) -> Self = self(), case Get(Sock, controlling_process) of {ok, Self} -> ok; {ok, InvalidPid} -> {error, {invalid, InvalidPid}}; {error, _} = ERROR -> ERROR end end}, #{desc => "order (client) start", cmd => fun(#{client := Client, sock := Sock} = _State) -> ?SEV_ANNOUNCE_START(Client, Sock), ok end}, #{desc => "await (client) ready (not owner)", cmd => fun(#{client := Client} = _State) -> ?SEV_AWAIT_READY(Client, client, not_owner) end}, #{desc => "attempt controlling-process transfer to client", cmd => fun(#{client := Client, sock := Sock} = _State) -> Set(Sock, controlling_process, Client) end}, #{desc => "verify client as controlling-process", cmd => fun(#{client := Client, sock := Sock} = _State) -> case Get(Sock, controlling_process) of {ok, Client} -> ok; {ok, InvalidPid} -> {error, {invalid, InvalidPid}}; {error, _} = ERROR -> ERROR end end}, #{desc => "attempt invalid controlling-process transfer (to self)", cmd => fun(#{sock := Sock} = _State) -> case Set(Sock, controlling_process, self()) of {error, not_owner} -> ok; ok -> {error, unexpected_success}; {error, _} = ERROR -> ERROR end end}, #{desc => "order (client) continue (owner)", cmd => fun(#{client := Client} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Client, owner), ok end}, #{desc => "await (client) ready (2)", cmd => fun(#{client := Client} = _State) -> ?SEV_AWAIT_READY(Client, client, owner), ok end}, #{desc => "verify self as controlling-process", cmd => fun(#{sock := Sock} = _State) -> Self = self(), case Get(Sock, controlling_process) of {ok, Self} -> ok; {ok, InvalidPid} -> {error, {invalid, InvalidPid}}; {error, _} = ERROR -> ERROR end end}, %% *** Termination *** #{desc => "order (client) terminate", cmd => fun(#{client := Client} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Client), ok end}, #{desc => "await client termination", cmd => fun(#{client := Client} = State) -> ?SEV_AWAIT_TERMINATION(Client), {ok, maps:remove(client, State)} end}, #{desc => "close socket", cmd => fun(#{sock := Sock} = State) -> sock_close(Sock), {ok, maps:remove(sock, State)} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], i("start tcp (stream) client evaluator"), ClientInitState1 = #{}, Client1 = ?SEV_START("tcp-client", ClientSeq, ClientInitState1), i("start tcp (stream) tester evaluator"), TesterInitState1 = #{domain => inet, type => stream, protocol => tcp, client => Client1#ev.pid}, Tester1 = ?SEV_START("tcp-tester", TesterSeq, TesterInitState1), i("await tcp evaluator(s)"), ok = ?SEV_AWAIT_FINISH([Tester1, Client1]), i("start udp (dgram) client evaluator"), ClientInitState2 = #{}, Client2 = ?SEV_START("udp-client", ClientSeq, ClientInitState2), i("start udp (dgram) tester evaluator"), TesterInitState2 = #{domain => inet, type => dgram, protocol => udp, client => Client2#ev.pid}, Tester2 = ?SEV_START("udp-tester", TesterSeq, TesterInitState2), i("await udp evaluator(s)"), ok = ?SEV_AWAIT_FINISH([Tester2, Client2]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Tests the socket option acceptconn for UDP. %% This should be possible to get but not set. api_opt_sock_acceptconn_udp(suite) -> []; api_opt_sock_acceptconn_udp(doc) -> []; api_opt_sock_acceptconn_udp(_Config) when is_list(_Config) -> ?TT(?SECS(30)), tc_try(api_opt_sock_acceptconn_udp, fun() -> has_support_sock_acceptconn() end, fun() -> api_opt_sock_acceptconn_udp() end). api_opt_sock_acceptconn_udp() -> Opt = acceptconn, Set = fun(S, Val) -> socket:setopt(S, socket, Opt, Val) end, Get = fun(S) -> socket:getopt(S, socket, Opt) end, TesterSeq = [ #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, #{desc => "create socket", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, dgram, udp) of {ok, Sock} -> {ok, State#{sock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "[get] verify socket (before bind)", cmd => fun(#{sock := Sock} = _State) -> case Get(Sock) of {ok, false} -> ?SEV_IPRINT("Expected Success: " "Not accepting connections"), ok; {ok, true} -> ?SEV_EPRINT("Unexpected Success: " "Accepting connections"), {error, {unexpected_success, {Opt, true}}}; {error, enoprotoopt = Reason} -> %% On some platforms this is not accepted %% for UDP, so skip this part (UDP). ?SEV_EPRINT("Expected Failure: " "~p => SKIP", [Reason]), (catch socket:close(Sock)), {skip, Reason}; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, #{desc => "[set] verify socket (before bind)", cmd => fun(#{sock := Sock} = _State) -> case Set(Sock, true) of {error, Reason} -> ?SEV_IPRINT("Expected Failure: ~p", [Reason]), ok; ok -> ?SEV_EPRINT("Unexpected Success: " "Set acceptconn (=true)"), {error, unexpected_success} end end}, #{desc => "bind socket to local address", cmd => fun(#{sock := Sock, local_sa := LSA} = _State) -> case socket:bind(Sock, LSA) of {ok, _} -> ok; {error, _} = ERROR -> ERROR end end}, ?SEV_SLEEP(?SECS(1)), #{desc => "[get] verify socket (after bind)", cmd => fun(#{sock := Sock} = _State) -> case Get(Sock) of {ok, false} -> ?SEV_IPRINT("Expected Success: " "Not accepting connections"), ok; {ok, true} -> ?SEV_EPRINT("Unexpected Success: " "Accepting connections"), {error, {unexpected_success, {Opt, true}}}; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, #{desc => "[set] verify socket (after bind)", cmd => fun(#{sock := Sock} = _State) -> case Set(Sock, true) of {error, Reason} -> ?SEV_IPRINT("Expected Failure: ~p", [Reason]), ok; ok -> ?SEV_EPRINT("Unexpected Success: " "Set acceptconn (=true)"), {error, unexpected_success} end end}, %% *** Termination *** #{desc => "close socket", cmd => fun(#{sock := Sock} = State) -> socket:close(Sock), {ok, maps:remove(sock, State)} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], Domain = inet, i("start tester evaluator"), InitState = #{domain => Domain}, Tester = ?SEV_START("tester", TesterSeq, InitState), i("await evaluator(s)"), ok = ?SEV_AWAIT_FINISH([Tester]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Tests the socket option acceptconn for TCP. %% This should be possible to get but not set. api_opt_sock_acceptconn_tcp(suite) -> []; api_opt_sock_acceptconn_tcp(doc) -> []; api_opt_sock_acceptconn_tcp(_Config) when is_list(_Config) -> ?TT(?SECS(30)), tc_try(api_opt_sock_acceptconn_tcp, fun() -> has_support_sock_acceptconn() end, fun() -> api_opt_sock_acceptconn_tcp() end). api_opt_sock_acceptconn_tcp() -> Opt = acceptconn, Set = fun(S, Val) -> socket:setopt(S, socket, Opt, Val) end, Get = fun(S) -> socket:getopt(S, socket, Opt) end, TesterSeq = [ #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, #{desc => "create listen socket", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, stream, tcp) of {ok, Sock} -> {ok, State#{lsock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "[get] verify listen socket (before bind)", cmd => fun(#{lsock := Sock} = _State) -> case Get(Sock) of {ok, false} -> ?SEV_IPRINT("Expected Success: " "Not accepting connections"), ok; {ok, true} -> ?SEV_EPRINT("Unexpected Success: " "Accepting connections"), {error, {unexpected_success, {Opt, true}}}; {error, enoprotoopt = Reason} -> ?SEV_EPRINT("Expected Failure: " "~p => SKIP", [Reason]), (catch socket:close(Sock)), {skip, Reason}; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, #{desc => "[set] verify listen socket (before bind)", cmd => fun(#{lsock := Sock} = _State) -> case Set(Sock, true) of {error, Reason} -> ?SEV_IPRINT("Expected Failure: ~p", [Reason]), ok; ok -> ?SEV_EPRINT("Unexpected Success: " "Set acceptconn (=true)"), {error, unexpected_success} end end}, ?SEV_SLEEP(?SECS(1)), #{desc => "bind listen socket to local address", cmd => fun(#{lsock := Sock, local_sa := LSA} = State) -> case socket:bind(Sock, LSA) of {ok, Port} -> {ok, State#{server_sa => LSA#{port => Port}}}; {error, _} = ERROR -> ERROR end end}, #{desc => "[get] verify listen socket (after bind)", cmd => fun(#{lsock := Sock} = _State) -> case Get(Sock) of {ok, false} -> ?SEV_IPRINT("Expected Success: " "Not accepting connections"), ok; {ok, true} -> ?SEV_EPRINT("Unexpected Success: " "Accepting connections"), {error, {unexpected_success, {Opt, true}}}; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, #{desc => "[set] verify listen socket (after bind)", cmd => fun(#{lsock := Sock} = _State) -> case Set(Sock, true) of {error, Reason} -> ?SEV_IPRINT("Expected Failure: ~p", [Reason]), ok; ok -> ?SEV_EPRINT("Unexpected Success: " "Set acceptconn (=true)"), {error, unexpected_success} end end}, ?SEV_SLEEP(?SECS(1)), #{desc => "make listen socket accept connections", cmd => fun(#{lsock := Sock} = _State) -> case socket:listen(Sock) of ok -> ok; {error, _} = ERROR -> ERROR end end}, #{desc => "[get] verify listen socket (after listen)", cmd => fun(#{lsock := Sock} = _State) -> case Get(Sock) of {ok, true} -> ?SEV_IPRINT("Expected Success: " "Accepting connections"), ok; {ok, false} -> ?SEV_EPRINT("Unexpected Success: " "Not accepting connections"), {error, {unexpected_success, {Opt, false}}}; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, #{desc => "[set] verify listen socket (after listen)", cmd => fun(#{lsock := Sock} = _State) -> case Set(Sock, false) of {error, Reason} -> ?SEV_IPRINT("Expected Failure: ~p", [Reason]), ok; ok -> ?SEV_EPRINT("Unexpected Success: " "Set acceptconn (=false)"), {error, unexpected_success} end end}, ?SEV_SLEEP(?SECS(1)), #{desc => "create (connecting) socket", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, stream, tcp) of {ok, Sock} -> {ok, State#{csockc => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind connecting socket to local address", cmd => fun(#{csockc := Sock, local_sa := LSA} = _State) -> case socket:bind(Sock, LSA) of {ok, _Port} -> ok; {error, _} = ERROR -> ERROR end end}, ?SEV_SLEEP(?SECS(1)), #{desc => "[get] verify connecting socket (before connect)", cmd => fun(#{csockc := Sock} = _State) -> case Get(Sock) of {ok, false} -> ?SEV_IPRINT("Expected Success: " "Not accepting connections"), ok; {ok, true} -> ?SEV_EPRINT("Unexpected Success: " "Accepting connections"), {error, {unexpected_success, {Opt, true}}}; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, #{desc => "[set] verify connecting socket (before connect)", cmd => fun(#{csockc := Sock} = _State) -> case Set(Sock, true) of {error, Reason} -> ?SEV_IPRINT("Expected Failure: ~p", [Reason]), ok; ok -> ?SEV_EPRINT("Unexpected Success: " "Set acceptconn (=true)"), {error, unexpected_success} end end}, ?SEV_SLEEP(?SECS(1)), #{desc => "connect to server", cmd => fun(#{csockc := Sock, server_sa := SSA} = _State) -> case socket:connect(Sock, SSA) of ok -> ok; {error, _} = ERROR -> ERROR end end}, #{desc => "accept connection", cmd => fun(#{lsock := Sock} = State) -> case socket:accept(Sock) of {ok, CSock} -> {ok, State#{csocks => CSock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "[get] verify connecting socket (after connect)", cmd => fun(#{csockc := Sock} = _State) -> case Get(Sock) of {ok, false} -> ?SEV_IPRINT("Expected Success: " "Not accepting connections"), ok; {ok, true} -> ?SEV_EPRINT("Unexpected Success: " "Accepting connections"), {error, {unexpected_success, {Opt, true}}}; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, #{desc => "[set] verify connecting socket (after connect)", cmd => fun(#{csockc := Sock} = _State) -> case Set(Sock, true) of {error, Reason} -> ?SEV_IPRINT("Expected Failure: ~p", [Reason]), ok; ok -> ?SEV_EPRINT("Unexpected Success: " "Set acceptconn (=true)"), {error, unexpected_success} end end}, #{desc => "[get] verify connected socket", cmd => fun(#{csocks := Sock} = _State) -> case Get(Sock) of {ok, false} -> ?SEV_IPRINT("Expected Success: " "Not accepting connections"), ok; {ok, true} -> ?SEV_EPRINT("Unexpected Success: " "Accepting connections"), {error, {unexpected_success, {Opt, true}}}; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, #{desc => "[set] verify connected socket", cmd => fun(#{csocks := Sock} = _State) -> case Set(Sock, true) of {error, Reason} -> ?SEV_IPRINT("Expected Failure: ~p", [Reason]), ok; ok -> ?SEV_EPRINT("Unexpected Success: " "Set acceptconn (=true)"), {error, unexpected_success} end end}, #{desc => "[get] verify listen socket (after connect)", cmd => fun(#{lsock := Sock} = _State) -> case Get(Sock) of {ok, true} -> ?SEV_IPRINT("Expected Success: " "Accepting connections"), ok; {ok, false} -> ?SEV_EPRINT("Unexpected Success: " "Not accepting connections"), {error, {unexpected_success, {Opt, false}}}; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, #{desc => "[set] verify listen socket (after connect)", cmd => fun(#{lsock := Sock} = _State) -> case Set(Sock, false) of {error, Reason} -> ?SEV_IPRINT("Expected Failure: ~p", [Reason]), ok; ok -> ?SEV_EPRINT("Unexpected Success: " "Set acceptconn (=false)"), {error, unexpected_success} end end}, %% *** Termination *** #{desc => "close connecting socket(s)", cmd => fun(#{csockc := Sock} = State0) -> socket:close(Sock), State1 = maps:remove(csockc, State0), State2 = maps:remove(csocks, State1), %% Auto-close {ok, maps:remove(csockc, State2)} end}, #{desc => "close listen socket", cmd => fun(#{lsock := Sock} = State) -> socket:close(Sock), {ok, maps:remove(lsock, State)} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], Domain = inet, i("start tester evaluator"), InitState = #{domain => Domain}, Tester = ?SEV_START("tester", TesterSeq, InitState), i("await evaluator(s)"), ok = ?SEV_AWAIT_FINISH([Tester]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Tests the socket option acceptfilter. PLACEHOLDER! api_opt_sock_acceptfilter(suite) -> []; api_opt_sock_acceptfilter(doc) -> []; api_opt_sock_acceptfilter(_Config) when is_list(_Config) -> ?TT(?SECS(30)), tc_try(api_opt_sock_acceptfilter, fun() -> not_yet_implemented() end, fun() -> ok end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Tests the socket option bindtodevice. %% It has not always been possible to 'get' this option %% (atleast on linux). api_opt_sock_bindtodevice(suite) -> []; api_opt_sock_bindtodevice(doc) -> []; api_opt_sock_bindtodevice(_Config) when is_list(_Config) -> ?TT(?SECS(30)), tc_try(api_opt_sock_bindtodevice, fun() -> has_support_sock_bindtodevice() end, fun() -> api_opt_sock_bindtodevice() end). api_opt_sock_bindtodevice() -> Opt = bindtodevice, Set = fun(S, Val) -> socket:setopt(S, socket, Opt, Val) end, Get = fun(S) -> socket:getopt(S, socket, Opt) end, TesterSeq = [ #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> case ?LIB:which_local_host_info(Domain) of {ok, #{name := Name, addr := Addr}} -> ?SEV_IPRINT("local host info (~p): " "~n Name: ~p" "~n Addr: ~p", [Domain, Name, Addr]), LSA = #{family => Domain, addr => Addr}, {ok, State#{dev => Name, local_sa => LSA}}; {error, _} = ERROR -> ERROR end end}, #{desc => "create UDP socket 1", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, dgram, udp) of {ok, Sock} -> {ok, State#{usock1 => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "create UDP socket 2", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, dgram, udp) of {ok, Sock} -> {ok, State#{usock2 => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "create TCP socket 1", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, stream, tcp) of {ok, Sock} -> {ok, State#{tsock1 => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "create TCP socket 2", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, stream, tcp) of {ok, Sock} -> {ok, State#{tsock2 => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "[get] verify UDP socket 1 (before bindtodevice)", cmd => fun(#{usock1 := Sock} = _State) -> case Get(Sock) of {ok, Dev} -> ?SEV_IPRINT("Expected Success: ~p", [Dev]), ok; {error, enoprotoopt = Reason} -> ?SEV_EPRINT("Unexpected Failure: ~p => SKIP", [Reason]), {skip, Reason}; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, #{desc => "[get] verify UDP socket 2 (before bind)", cmd => fun(#{usock2 := Sock} = _State) -> case Get(Sock) of {ok, Dev} -> ?SEV_IPRINT("Expected Success: ~p", [Dev]), ok; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, #{desc => "[get] verify TCP socket 1 (before bindtodevice)", cmd => fun(#{tsock1 := Sock} = _State) -> case Get(Sock) of {ok, Dev} -> ?SEV_IPRINT("Expected Success: ~p", [Dev]), ok; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, #{desc => "[get] verify TCP socket 2 (before bind)", cmd => fun(#{tsock2 := Sock} = _State) -> case Get(Sock) of {ok, Dev} -> ?SEV_IPRINT("Expected Success: ~p", [Dev]), ok; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, ?SEV_SLEEP(?SECS(1)), #{desc => "Bind UDP socket 1 to device", cmd => fun(#{usock1 := Sock, dev := Dev} = State) -> case Set(Sock, Dev) of ok -> ?SEV_IPRINT("Expected Success"), ok; {error, eperm = Reason} -> ?SEV_IPRINT("Expected Failure: ~p", [Reason]), (catch socket:close(Sock)), {ok, State#{usock1 => skip}}; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, #{desc => "Bind UDP socket 2 to local address", cmd => fun(#{usock2 := Sock, local_sa := LSA} = _State) -> case socket:bind(Sock, LSA) of {ok, _Port} -> ?SEV_IPRINT("Expected Success"), ok; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, #{desc => "Bind TCP socket 1 to device", cmd => fun(#{usock1 := USock1, tsock1 := Sock, dev := Dev} = State) -> case Set(Sock, Dev) of ok -> ?SEV_IPRINT("Expected Success"), ok; {error, eperm = Reason} when (USock1 =:= skip) -> ?SEV_IPRINT("Expected Failure: ~p", [Reason]), {skip, Reason}; {error, eperm = Reason} -> ?SEV_IPRINT("Expected Failure: ~p", [Reason]), (catch socket:close(Sock)), {ok, State#{tsock1 => skip}}; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, #{desc => "Bind TCP socket 2 to local address", cmd => fun(#{tsock2 := Sock, local_sa := LSA} = _State) -> case socket:bind(Sock, LSA) of {ok, _Port} -> ?SEV_IPRINT("Expected Success"), ok; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, ?SEV_SLEEP(?SECS(1)), #{desc => "[get] verify UDP socket 1 (after bindtodevice)", cmd => fun(#{usock1 := skip} = _State) -> ?SEV_IPRINT("SKIP'ed (previous eperm)"), ok; (#{usock1 := Sock} = _State) -> case Get(Sock) of {ok, Dev} -> ?SEV_IPRINT("Expected Success: ~p", [Dev]), ok; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, #{desc => "[get] verify UDP socket 2 (after bind)", cmd => fun(#{usock2 := Sock} = _State) -> case Get(Sock) of {ok, Dev} -> ?SEV_IPRINT("Expected Success: ~p", [Dev]), ok; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, #{desc => "[get] verify TCP socket 1 (after bindtodevice)", cmd => fun(#{tsock1 := skip} = _State) -> ?SEV_IPRINT("SKIP'ed (previous eperm)"), ok; (#{tsock1 := Sock} = _State) -> case Get(Sock) of {ok, Dev} -> ?SEV_IPRINT("Expected Success: ~p", [Dev]), ok; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, #{desc => "[get] verify TCP socket 2 (after bind)", cmd => fun(#{tsock2 := Sock} = _State) -> case Get(Sock) of {ok, Dev} -> ?SEV_IPRINT("Expected Success: ~p", [Dev]), ok; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, ?SEV_SLEEP(?SECS(1)), %% *** Termination *** #{desc => "close UDP socket 1", cmd => fun(#{usock1 := skip} = State) -> ?SEV_IPRINT("SKIP'ed (already closed)"), {ok, maps:remove(usock1, State)}; (#{usock1 := Sock} = State) -> socket:close(Sock), {ok, maps:remove(usock1, State)} end}, #{desc => "close UDP socket 2", cmd => fun(#{usock2 := Sock} = State) -> socket:close(Sock), {ok, maps:remove(usock2, State)} end}, #{desc => "close TCP socket 1", cmd => fun(#{tsock1 := skip} = State) -> ?SEV_IPRINT("SKIP'ed (already closed)"), {ok, maps:remove(tsock1, State)}; (#{tsock1 := Sock} = State) -> socket:close(Sock), {ok, maps:remove(tsock1, State)} end}, #{desc => "close TCP socket 2", cmd => fun(#{tsock2 := Sock} = State) -> socket:close(Sock), {ok, maps:remove(tsock2, State)} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], Domain = inet, i("start tester evaluator"), InitState = #{domain => Domain}, Tester = ?SEV_START("tester", TesterSeq, InitState), i("await evaluator(s)"), ok = ?SEV_AWAIT_FINISH([Tester]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Tests the socket option broadcast. %% Make it possible for datagram sockets to send packets to a broadcast %% address (IPv4 only). api_opt_sock_broadcast(suite) -> []; api_opt_sock_broadcast(doc) -> []; api_opt_sock_broadcast(_Config) when is_list(_Config) -> ?TT(?SECS(30)), tc_try(api_opt_sock_broadcast, fun() -> has_support_sock_broadcast() end, fun() -> api_opt_sock_broadcast() end). api_opt_sock_broadcast() -> Opt = broadcast, Set = fun(S, Val) when is_boolean(Val) -> socket:setopt(S, socket, Opt, Val) end, Get = fun(S) -> socket:getopt(S, socket, Opt) end, TesterSeq = [ #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> case ?LIB:which_local_host_info(Domain) of {ok, #{name := Name, addr := Addr, broadaddr := BAddr}} -> ?SEV_IPRINT("local host info: " "~n Name: ~p" "~n Addr: ~p" "~n Broadcast Addr: ~p", [Name, Addr, BAddr]), LSA = #{family => Domain, addr => Addr}, BSA = #{family => Domain, addr => BAddr}, {ok, State#{lsa => LSA, bsa => BSA}}; {error, _} = ERROR -> ERROR end end}, #{desc => "[socket 1] create UDP socket (listening 1)", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, dgram, udp) of {ok, Sock} -> {ok, State#{sock1 => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "[socket 1] Bind UDP socket (to limited broadcast address)", cmd => fun(#{sock1 := Sock} = State) -> BSA = #{family => inet, addr => broadcast}, ?SEV_IPRINT("Try bind (socket 1) to: " "~n ~p", [BSA]), case socket:bind(Sock, BSA) of {ok, Port} -> ?SEV_IPRINT("Expected Success (bound): ~p", [Port]), {ok, State#{sa1 => BSA#{port => Port}}}; {error, eaddrnotavail = Reason} -> ?SEV_IPRINT("~p => " "SKIP limited broadcast test", [Reason]), {ok, State#{sa1 => skip}}; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, #{desc => "[socket 1] UDP socket sockname", cmd => fun(#{sa1 := skip} = _State) -> ?SEV_IPRINT("SKIP limited broadcast test"), ok; (#{sock1 := Sock} = _State) -> case socket:sockname(Sock) of {ok, SA} -> ?SEV_IPRINT("SA: ~p", [SA]), ok; {error, _} = ERROR -> ERROR end end}, ?SEV_SLEEP(?SECS(1)), #{desc => "[socket 2] create UDP socket (listening 2)", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, dgram, udp) of {ok, Sock} -> {ok, State#{sock2 => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "[socket 2] Bind UDP socket (to subnet-directed broadcast address)", cmd => fun(#{sock2 := Sock, bsa := BSA} = State) -> ?SEV_IPRINT("Try bind (socket 1) to: " "~n ~p", [BSA]), case socket:bind(Sock, BSA) of {ok, Port} -> ?SEV_IPRINT("Expected Success (bound): ~p", [Port]), {ok, State#{sa2 => BSA#{port => Port}}}; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, #{desc => "[socket 2] UDP socket sockname", cmd => fun(#{sock2 := Sock} = _State) -> case socket:sockname(Sock) of {ok, SA} -> ?SEV_IPRINT("SA: ~p", [SA]), ok; {error, _} = ERROR -> ERROR end end}, ?SEV_SLEEP(?SECS(1)), #{desc => "[socket 3] create UDP socket (sender)", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, dgram, udp) of {ok, Sock} -> {ok, State#{sock3 => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "[socket 3][get] verify UDP socket (before bind and set)", cmd => fun(#{sock3 := Sock} = _State) -> case Get(Sock) of {ok, false} -> ?SEV_IPRINT("Expected Success: " "broadcast not allowed"), ok; {ok, true} -> ?SEV_IPRINT("Unexpected Success result: " "broadcast already allowed"), ok; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, #{desc => "[socket 3] Try make broadcast allowed", cmd => fun(#{sock3 := Sock} = _State) -> case Set(Sock, true) of ok -> ?SEV_IPRINT("Expected Success: " "broadcast now allowed"), ok; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, #{desc => "[socket 3] verify UDP socket broadcast allowed", cmd => fun(#{sock3 := Sock} = _State) -> case Get(Sock) of {ok, true} -> ?SEV_IPRINT("Expected Success: " "broadcast allowed"), ok; {ok, false} -> ?SEV_IPRINT("Unexpected Success result: " "broadcast *not* allowed"), ok; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, #{desc => "[socket 3] Bind UDP socket (to local address)", cmd => fun(#{sock3 := Sock, lsa := LSA} = State) -> ?SEV_IPRINT("Try bind (socket 2) to: " "~n ~p", [LSA]), case socket:bind(Sock, LSA) of {ok, Port} -> ?SEV_IPRINT("Expected Success (bound): ~p", [Port]), {ok, State#{sa3 => LSA#{port => Port}}}; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, #{desc => "[socket 3] verify UDP socket (after set)", cmd => fun(#{sock3 := Sock} = _State) -> case Get(Sock) of {ok, true} -> ?SEV_IPRINT("Expected Success: " "broadcast allowed"), ok; {ok, false} -> ?SEV_IPRINT("Unexpected Success result: " "broadcast not allowed"), {error, not_allowed}; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, ?SEV_SLEEP(?SECS(1)), #{desc => "[socket 3] try send to limited broadcast address", cmd => fun(#{sa1 := skip} = _State) -> ?SEV_IPRINT("SKIP limited broadcast test"), ok; (#{sock3 := Sock, sa1 := Dest} = _State) -> Data = list_to_binary("hejsan"), ?SEV_IPRINT("try send to bradcast address: " "~n ~p", [Dest]), case socket:sendto(Sock, Data, Dest) of ok -> ?SEV_IPRINT("Expected Success: " "broadcast message sent"), ok; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, #{desc => "[socket 1] try recv", cmd => fun(#{sa1 := skip} = _State) -> ?SEV_IPRINT("SKIP limited broadcast test"), ok; (#{sock1 := Sock} = State) -> case socket:recvfrom(Sock, 0, 5000) of {ok, _} -> ?SEV_IPRINT("Expected Success: " "received message"), ok; {error, timeout = Reason} -> %% Some platforms seem to balk at this. %% It spossible to bind to this, and %% send to it, but no data is received. %% At some point we should investigate... %% For now, we just skip this part of %% the test... ?SEV_IPRINT("Unexpected Failure: ~p", [Reason]), {ok, State#{sa1 => skip}}; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, ?SEV_SLEEP(?SECS(1)), #{desc => "[socket 3] try send to subnet-directed broadcast address", cmd => fun(#{sock3 := Sock, sa2 := Dest} = _State) -> Data = list_to_binary("hejsan"), ?SEV_IPRINT("try send to bradcast address: " "~n ~p", [Dest]), case socket:sendto(Sock, Data, Dest) of ok -> ?SEV_IPRINT("Expected Success: " "broadcast message sent"), ok; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, #{desc => "[socket 2] try recv", cmd => fun(#{sock2 := Sock, sa1 := SA1} = _State) -> case socket:recvfrom(Sock, 0, 5000) of {ok, _} -> ?SEV_IPRINT("Expected Success: " "received message"), ok; {error, timeout = Reason} when (SA1 =:= skip) -> ?SEV_IPRINT("Unexpected Failure: ~p", [Reason]), {skip, "receive timeout"}; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, %% *** Termination *** #{desc => "[socket 3] close UDP socket (sender)", cmd => fun(#{sock3 := Sock} = State0) -> socket:close(Sock), State1 = maps:remove(sock3, State0), State2 = maps:remove(sa3, State1), {ok, State2} end}, #{desc => "[socket 2] close UDP socket (listener 2)", cmd => fun(#{sock2 := Sock} = State0) -> socket:close(Sock), State1 = maps:remove(sock2, State0), State2 = maps:remove(sa2, State1), {ok, State2} end}, #{desc => "[socket 1] close UDP socket (listener 1)", cmd => fun(#{sock1 := Sock} = State0) -> socket:close(Sock), State1 = maps:remove(sock1, State0), State2 = maps:remove(sa1, State1), {ok, State2} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], Domain = inet, i("start tester evaluator"), InitState = #{domain => Domain}, Tester = ?SEV_START("tester", TesterSeq, InitState), i("await evaluator(s)"), ok = ?SEV_AWAIT_FINISH([Tester]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Tests the socket option debug. %% On linux, this test requires that the user running the test to have %% CAP_NET_ADMIN capabilities or be root (effective user ID of 0), %% therefor we explicitly test for the result eacces when attempting to %% set, and skip if we get it. api_opt_sock_debug(suite) -> []; api_opt_sock_debug(doc) -> []; api_opt_sock_debug(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_opt_sock_debug, fun() -> has_support_sock_debug() end, fun() -> api_opt_sock_debug() end). api_opt_sock_debug() -> Opt = debug, Set = fun(S, Val) when is_integer(Val) -> socket:setopt(S, socket, Opt, Val) end, Get = fun(S) -> socket:getopt(S, socket, Opt) end, TesterSeq = [ #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> case ?LIB:which_local_host_info(Domain) of {ok, #{name := Name, addr := Addr, broadaddr := BAddr}} -> ?SEV_IPRINT("local host info: " "~n Name: ~p" "~n Addr: ~p" "~n Broadcast Addr: ~p", [Name, Addr, BAddr]), LSA = #{family => Domain, addr => Addr}, BSA = #{family => Domain, addr => BAddr}, {ok, State#{lsa => LSA, bsa => BSA}}; {error, _} = ERROR -> ERROR end end}, #{desc => "create UDP socket", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, dgram, udp) of {ok, Sock} -> {ok, State#{sock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "Get current debug value", cmd => fun(#{sock := Sock} = State) -> case Get(Sock) of {ok, Debug} when is_integer(Debug) -> ?SEV_IPRINT("Success: ~p", [Debug]), {ok, State#{debug => Debug}}; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected failure: ~p", [Reason]), ERROR end end}, #{desc => "Try enable socket debug", cmd => fun(#{sock := Sock, debug := Debug} = State) -> NewDebug = Debug + 1, case Set(Sock, NewDebug) of ok -> ?SEV_IPRINT("Expected Success"), {ok, State#{debug => NewDebug}}; {error, eacces = Reason} -> ?SEV_EPRINT("NO ACCESS => SKIP"), {skip, Reason}; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, #{desc => "Get current (new) debug value", cmd => fun(#{sock := Sock, debug := Debug} = _State) -> case Get(Sock) of {ok, Debug} when is_integer(Debug) -> ?SEV_IPRINT("Success: ~p", [Debug]), ok; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected failure: ~p", [Reason]), ERROR end end}, %% *** Termination *** #{desc => "close UDP socket", cmd => fun(#{sock := Sock} = State0) -> socket:close(Sock), State1 = maps:remove(sock, State0), {ok, State1} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], Domain = inet, i("start tester evaluator"), InitState = #{domain => Domain}, Tester = ?SEV_START("tester", TesterSeq, InitState), i("await evaluator(s)"), ok = ?SEV_AWAIT_FINISH([Tester]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Tests the socket option domain. %% This is a read only option. Also not available on all platforms. api_opt_sock_domain(suite) -> []; api_opt_sock_domain(doc) -> []; api_opt_sock_domain(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_opt_sock_domain, fun() -> has_support_sock_domain() end, fun() -> api_opt_sock_domain() end). api_opt_sock_domain() -> Opt = domain, Get = fun(S) -> socket:getopt(S, socket, Opt) end, TesterSeq = [ #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> case ?LIB:which_local_host_info(Domain) of {ok, #{name := Name, addr := Addr, broadaddr := BAddr}} -> ?SEV_IPRINT("local host info: " "~n Name: ~p" "~n Addr: ~p" "~n Broadcast Addr: ~p", [Name, Addr, BAddr]), LSA = #{family => Domain, addr => Addr}, BSA = #{family => Domain, addr => BAddr}, {ok, State#{lsa => LSA, bsa => BSA}}; {error, _} = ERROR -> ERROR end end}, #{desc => "create IPv4 UDP socket", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, dgram, udp) of {ok, Sock} -> {ok, State#{usock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "Get domain for the UDP socket", cmd => fun(#{domain := Domain, usock := Sock} = _State) -> case Get(Sock) of {ok, Domain} -> ?SEV_IPRINT("Success: ~p", [Domain]), ok; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected failure: ~p", [Reason]), ERROR end end}, #{desc => "create TCP socket", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, stream, tcp) of {ok, Sock} -> {ok, State#{tsock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "Get domain for the TCP socket", cmd => fun(#{domain := Domain, tsock := Sock} = _State) -> case Get(Sock) of {ok, Domain} -> ?SEV_IPRINT("Success: ~p", [Domain]), ok; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected failure: ~p", [Reason]), ERROR end end}, %% *** Termination *** #{desc => "close UDP socket", cmd => fun(#{usock := Sock} = State0) -> socket:close(Sock), State1 = maps:remove(usock, State0), {ok, State1} end}, #{desc => "close TCP socket", cmd => fun(#{tsock := Sock} = State0) -> socket:close(Sock), State1 = maps:remove(tsock, State0), {ok, State1} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], Domain = inet, i("start tester evaluator"), InitState = #{domain => Domain}, Tester = ?SEV_START("tester", TesterSeq, InitState), i("await evaluator(s)"), ok = ?SEV_AWAIT_FINISH([Tester]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Tests the socket option dontroute. %% The man page has the following to say: %% "Don't send via a gateway, send only to directly connected hosts. %% The same effect can be achieved by setting the MSG_DONTROUTE %% flag on a socket send(2) operation." %% Since its "kind of" difficult to check if it actually takes an %% effect (you would need a gateway for that and a machine "on the %% other side"), we only test if we can set and get the value. %% Better then nothing. api_opt_sock_dontroute(suite) -> []; api_opt_sock_dontroute(doc) -> []; api_opt_sock_dontroute(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_opt_sock_dontroute, fun() -> has_support_sock_dontroute() end, fun() -> api_opt_sock_dontroute() end). api_opt_sock_dontroute() -> Opt = dontroute, Set = fun(S, Val) when is_boolean(Val) -> socket:setopt(S, socket, Opt, Val) end, Get = fun(S) -> socket:getopt(S, socket, Opt) end, TesterSeq = [ #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> case ?LIB:which_local_host_info(Domain) of {ok, #{name := Name, addr := Addr, broadaddr := BAddr}} -> ?SEV_IPRINT("local host info: " "~n Name: ~p" "~n Addr: ~p" "~n Broadcast Addr: ~p", [Name, Addr, BAddr]), LSA = #{family => Domain, addr => Addr}, BSA = #{family => Domain, addr => BAddr}, {ok, State#{lsa => LSA, bsa => BSA}}; {error, _} = ERROR -> ERROR end end}, #{desc => "create UDP socket", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, dgram, udp) of {ok, Sock} -> {ok, State#{sock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "Get current value", cmd => fun(#{sock := Sock} = State) -> case Get(Sock) of {ok, Val} when is_boolean(Val) -> ?SEV_IPRINT("Success: ~p", [Val]), {ok, State#{dontroute => Val}}; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected failure: ~p", [Reason]), ERROR end end}, #{desc => "Try change value", cmd => fun(#{sock := Sock, dontroute := Current} = State) -> New = not Current, ?SEV_IPRINT("Change from ~p to ~p", [Current, New]), case Set(Sock, New) of ok -> ?SEV_IPRINT("Expected Success"), {ok, State#{dontroute => New}}; {error, eopnotsupp = Reason} -> ?SEV_EPRINT("Expected Failure: ~p", [Reason]), {skip, Reason}; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, #{desc => "Verify changed value", cmd => fun(#{sock := Sock, dontroute := Val} = _State) -> case Get(Sock) of {ok, Val} -> ?SEV_IPRINT("Expected Success"), ok; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected failure: ~p", [Reason]), ERROR end end}, %% *** Termination *** #{desc => "close UDP socket", cmd => fun(#{sock := Sock} = State0) -> socket:close(Sock), State1 = maps:remove(sock, State0), {ok, State1} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], Domain = inet, i("start tester evaluator"), InitState = #{domain => Domain}, Tester = ?SEV_START("tester", TesterSeq, InitState), i("await evaluator(s)"), ok = ?SEV_AWAIT_FINISH([Tester]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Tests the socket option error. PLACEHOLDER! api_opt_sock_error(suite) -> []; api_opt_sock_error(doc) -> []; api_opt_sock_error(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_opt_sock_error, fun() -> not_yet_implemented() end, fun() -> ok end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Tests the socket option keepalive. %% This is bit tricky to test, partly because we have no control over %% the underlying TCP timeouts. So, for now, we just test that we can %% change the value. api_opt_sock_keepalive(suite) -> []; api_opt_sock_keepalive(doc) -> []; api_opt_sock_keepalive(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_opt_sock_keepalive, fun() -> has_support_sock_keepalive() end, fun() -> api_opt_sock_keepalive() end). api_opt_sock_keepalive() -> Opt = keepalive, Set = fun(S, Val) when is_boolean(Val) -> socket:setopt(S, socket, Opt, Val) end, Get = fun(S) -> socket:getopt(S, socket, Opt) end, TesterSeq = [ #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> case ?LIB:which_local_host_info(Domain) of {ok, #{name := Name, addr := Addr, broadaddr := BAddr}} -> ?SEV_IPRINT("local host info: " "~n Name: ~p" "~n Addr: ~p" "~n Broadcast Addr: ~p", [Name, Addr, BAddr]), LSA = #{family => Domain, addr => Addr}, BSA = #{family => Domain, addr => BAddr}, {ok, State#{lsa => LSA, bsa => BSA}}; {error, _} = ERROR -> ERROR end end}, #{desc => "create TCP socket", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, stream, tcp) of {ok, Sock} -> {ok, State#{sock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "Get current value", cmd => fun(#{sock := Sock} = State) -> case Get(Sock) of {ok, Val} when is_boolean(Val) -> ?SEV_IPRINT("Success: ~p", [Val]), {ok, State#{keepalive => Val}}; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected failure: ~p", [Reason]), ERROR end end}, #{desc => "Try change the value", cmd => fun(#{sock := Sock, keepalive := Current} = State) -> New = not Current, ?SEV_IPRINT("Try change value from ~p to ~p", [Current, New]), case Set(Sock, New) of ok -> ?SEV_IPRINT("Expected Success"), {ok, State#{keepalive => New}}; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, #{desc => "Verify (new) current value", cmd => fun(#{sock := Sock, keepalive := Val} = _State) -> case Get(Sock) of {ok, Val} -> ?SEV_IPRINT("Expected Success (~p)", [Val]), ok; {ok, OtherVal} -> ?SEV_IPRINT("Unexpected Success: ~p", [OtherVal]), {error, {unexpected_success_value, Val, OtherVal}}; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected failure: ~p", [Reason]), ERROR end end}, %% *** Termination *** #{desc => "close UDP socket", cmd => fun(#{sock := Sock} = State0) -> socket:close(Sock), State1 = maps:remove(sock, State0), {ok, State1} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], Domain = inet, i("start tester evaluator"), InitState = #{domain => Domain}, Tester = ?SEV_START("tester", TesterSeq, InitState), i("await evaluator(s)"), ok = ?SEV_AWAIT_FINISH([Tester]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Tests the socket option linger. PLACEHOLDER! api_opt_sock_linger(suite) -> []; api_opt_sock_linger(doc) -> []; api_opt_sock_linger(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_opt_sock_linger, fun() -> not_yet_implemented() end, fun() -> ok end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Tests that the add_mambership and drop_membership ip options work. %% We create one server and two clients. The server only send messages, %% the clients only receives messages. %% An UDP datagram is forbidden (RFC 1122) from having a source address %% that is a multicast address (or a broadcast address). %% So, the server create a socket "for sending" and the clients sockets %% "for receiving". %% Sending socket: Bound to the local address (and any port). %% When sending, the dest will be the multicast address %% and port of the receiving socket. %% Receiving socket: Bound to the multicast address and port. api_opt_ip_add_drop_membership(suite) -> []; api_opt_ip_add_drop_membership(doc) -> ["OTP-15908 (ERL-980)"]; api_opt_ip_add_drop_membership(_Config) when is_list(_Config) -> ?TT(?SECS(30)), tc_try(api_opt_ip_add_drop_membership, fun() -> has_support_ip_add_membership(), has_support_ip_drop_membership(), has_support_ip_multicast() end, fun() -> api_opt_ip_add_drop_membership() end). api_opt_ip_add_drop_membership() -> Set = fun(S, Key, Val) -> socket:setopt(S, ip, Key, Val) end, AddMembership = fun(S, Val) -> Set(S, add_membership, Val) end, DropMembership = fun(S, Val) -> Set(S, drop_membership, Val) end, ServerSeq = [ %% *** Wait for start order part *** #{desc => "await start", cmd => fun(State) -> {Tester, MSA} = ?SEV_AWAIT_START(), {ok, State#{tester => Tester, msa => MSA}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, #{desc => "create socket", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, dgram, udp) of {ok, Sock} -> {ok, State#{sock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "make recv socket reuse addr", cmd => fun(#{sock := Sock} = _State) -> case socket:setopt(Sock, socket, reuseaddr, true) of ok -> ok; {error, Reason} = ERROR -> ?SEV_EPRINT("Failed set reuseaddr: " "~n ~p", [Reason]), ERROR end end}, #{desc => "bind recv socket to multicast address", cmd => fun(#{sock := Sock, msa := MSA} = State) -> case socket:bind(Sock, MSA) of {ok, Port} -> ?SEV_IPRINT("bound to:" "~n ~p", [Port]), {ok, State#{msa => MSA#{port => Port}}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, init), ok end}, %% The actual test #{desc => "await continue (add_membership)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, add_membership) end}, #{desc => "add membership", cmd => fun(#{sock := Sock, msa := #{addr := MAddr}, local_sa := #{addr := Addr}} = State) -> MReq = #{multiaddr => MAddr, interface => Addr}, ?SEV_IPRINT("try add membership to:" "~n ~p", [MReq]), case AddMembership(Sock, MReq) of ok -> ?SEV_IPRINT("membership added"), {ok, State#{mreq => MReq}}; {error, Reason} = ERROR -> ?SEV_EPRINT("Failed adding membership to: " "~n ~p" "~n Reason: ~p", [MReq, Reason]), ERROR end end}, #{desc => "announce ready (add-membership)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, add_membership), ok end}, #{desc => "await continue (drop_membership)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, drop_membership) end}, #{desc => "drop membership", cmd => fun(#{sock := Sock, mreq := MReq} = State) -> ?SEV_IPRINT("try drop membership from:" "~n ~p", [MReq]), case DropMembership(Sock, MReq) of ok -> ?SEV_IPRINT("membership dropped"), {ok, maps:remove(mreq, State)}; {error, Reason} = ERROR -> ?SEV_EPRINT("Failed drop membership from: " "~n ~p" "~n Reason: ~p", [MReq, Reason]), ERROR end end}, #{desc => "announce ready (drop-membership)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, drop_membership), ok end}, %% Termination #{desc => "await terminate (from tester)", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "close socket", cmd => fun(#{sock := Sock} = State) -> socket:close(Sock), {ok, maps:remove(sock, State)} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], TesterSeq = [ %% *** Init part *** #{desc => "monitor server", cmd => fun(#{server := Server} = _State) -> _MRef = erlang:monitor(process, Server), ok end}, %% Start the server #{desc => "order server start", cmd => fun(#{server := Pid, msa := MSA} = _State) -> ?SEV_ANNOUNCE_START(Pid, MSA), ok end}, #{desc => "await server ready (init)", cmd => fun(#{server := Pid} = _State) -> case ?SEV_AWAIT_READY(Pid, server, init) of ok -> ok; {error, Reason} = ERROR -> ?SEV_EPRINT("Start of server failed: " "~n ~p", [Reason]), ERROR end end}, %% *** The actual test *** #{desc => "order server to continue (add-membership)", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Server, add_membership), ok end}, #{desc => "await server ready (add-membership)", cmd => fun(#{server := Server} = _State) -> ?SEV_AWAIT_READY(Server, server, add_membership) end}, #{desc => "order server to continue (drop-membership)", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Server, drop_membership), ok end}, #{desc => "await server ready (drop-membership)", cmd => fun(#{server := Server} = _State) -> ?SEV_AWAIT_READY(Server, server, drop_membership) end}, ?SEV_SLEEP(?SECS(1)), %% *** Termination *** #{desc => "order server terminate", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Server), ok end}, #{desc => "await server termination", cmd => fun(#{server := Server} = State) -> ?SEV_AWAIT_TERMINATION(Server), {ok, maps:remove(server, State)} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], Domain = inet, i("get multicast address"), MAddr = which_ip_multicast_address(), MSA = #{family => Domain, addr => MAddr}, i("start server evaluator"), ServerInitState = #{domain => Domain}, Server = ?SEV_START("server", ServerSeq, ServerInitState), i("start tester evaluator"), TesterInitState = #{domain => Domain, msa => MSA, server => Server#ev.pid}, Tester = ?SEV_START("tester", TesterSeq, TesterInitState), i("await evaluator(s)"), ok = ?SEV_AWAIT_FINISH([Tester, Server]). which_ip_multicast_address() -> which_multicast_address(inet). which_multicast_address(Domain) -> case os:type() of {unix, linux} -> WhichMAddr = fun([_, _, MAddr]) -> MAddr end, which_multicast_address2(Domain, WhichMAddr); {unix, sunos} -> WhichMAddr = fun([_, MAddr, _]) -> MAddr end, which_multicast_address2(Domain, WhichMAddr); Type -> %% Actually, what is "not supported". is netstat! not_supported({multicast, Type}) end. %% Note that the 'netstat -g' table looks different on linux and SunOS %% Linux: IfName - RefCnt - Group %% SunOS: IfName - Group - RefCnt which_multicast_address2(Domain, WhichMAddr) -> IfName = which_local_host_ifname(Domain), %% On some platforms the netstat barfs out some crap on stderr %% before the actual info... case os:cmd("netstat -g 2>/dev/null | grep " ++ IfName) of [] -> %% Can't figure out if we support multicast or not... not_supported(no_netstat); NetstatGroupsStr -> try begin NetstatGroups0 = string:tokens(NetstatGroupsStr, [$\n]), NetstatGroups = [string:tokens(G, [$ ]) || G <- NetstatGroups0], MAddrs = [WhichMAddr(NetstatGroup) || NetstatGroup <- NetstatGroups], which_multicast_address3(Domain, MAddrs) end catch throw:E:_ -> throw(E); C:E:S -> not_supported({multicast, {C,E,S}}) end end. which_multicast_address3(_Domain, []) -> not_supported({multicast, no_valid_addrs}); which_multicast_address3(Domain, [MAddrStr|MAddrs]) -> %% Even on linux some of these are not actually addresses, but %% "host names", such as all-systems.mcast.net. But both %% address strings, such as "224.0.0.251" and host name strings %% gets translated into an address by the inet:inet:getaddr/2. case inet:getaddr(MAddrStr, Domain) of {ok, MAddr} -> MAddr; {error, _} -> which_multicast_address3(Domain, MAddrs) end. which_local_host_ifname(Domain) -> case ?LIB:which_local_host_info(Domain) of {ok, #{name := Name}} -> Name; {error, Reason} -> not_supported({multicast, Reason}) end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %% %% API OPERATIONS WITH TIMEOUT %% %% %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test the connect timeout option %% on an IPv4 TCP (stream) socket. api_to_connect_tcp4(suite) -> []; api_to_connect_tcp4(doc) -> []; api_to_connect_tcp4(_Config) when is_list(_Config) -> ?TT(?SECS(10)), Cond = fun() -> api_to_connect_cond() end, tc_try(api_to_connect_tcp4, Cond, fun() -> InitState = #{domain => inet, backlog => 1, timeout => 5000, connect_limit => 3}, ok = api_to_connect_tcp(InitState) end). api_to_connect_cond() -> api_to_connect_cond(os:type(), os:version()). %% I don't know exactly at which version this starts to work. %% I know it does not work for 4.4.*, but is does for 4.15. %% So, just to simplify, we require atleast 4.15 api_to_connect_cond({unix, linux}, {Maj, Min, _Rev}) -> if (Maj > 4) -> ok; ((Maj =:= 4) andalso (Min >= 15)) -> ok; true -> skip("TC does not work") end; %% Only test on one machine, which has version 6.3, and there it does %% not work, so disable for all. api_to_connect_cond({unix, openbsd}, _) -> skip("TC does not work"); api_to_connect_cond({unix, freebsd}, {Maj, Min, _Rev}) -> if ((Maj >= 10) andalso (Min >= 4)) -> ok; true -> skip("TC may not work") end; api_to_connect_cond({unix, sunos}, {Maj, Min, _Rev}) -> if ((Maj >= 5) andalso (Min >= 10)) -> ok; true -> skip("TC may not work") end; api_to_connect_cond(_, _) -> skip("TC may not work"). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test the connect timeout option %% on an IPv6 TCP (stream) socket. api_to_connect_tcp6(suite) -> []; api_to_connect_tcp6(doc) -> []; api_to_connect_tcp6(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_to_connect_tcp6, fun() -> has_support_ipv6(), api_to_connect_cond() end, fun() -> InitState = #{domain => inet6, backlog => 1, timeout => 5000, connect_limit => 3}, ok = api_to_connect_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% We use the backlog (listen) argument to test this. %% Note that the behaviour of the TCP "server side" can vary when %% a client connect to a "busy" server (full backlog). %% For instance, on FreeBSD (11.2) the reponse when the backlog is full %% is a econreset. api_to_connect_tcp(InitState) -> process_flag(trap_exit, true), ServerSeq = [ %% *** Wait for start order part *** #{desc => "await start (from tester)", cmd => fun(State) -> {Tester, Backlog} = ?SEV_AWAIT_START(), {ok, State#{tester => Tester, backlog => Backlog}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, #{desc => "create listen socket", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, stream, tcp) of {ok, Sock} -> {ok, State#{lsock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind to local address", cmd => fun(#{lsock := LSock, local_sa := LSA} = State) -> case socket:bind(LSock, LSA) of {ok, Port} -> {ok, State#{lport => Port}}; {error, _} = ERROR -> ERROR end end}, #{desc => "make listen socket (with backlog = 1)", cmd => fun(#{lsock := LSock, backlog := Backlog}) -> socket:listen(LSock, Backlog) end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester, lport := Port}) -> ?SEV_ANNOUNCE_READY(Tester, init, Port), ok end}, %% Termination #{desc => "await terminate", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "close socket", cmd => fun(#{lsock := Sock} = State) -> sock_close(Sock), State1 = maps:remove(lport, State), State2 = maps:remove(sock, State1), {ok, State2} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], ClientSeq = [ %% *** Wait for start order part *** #{desc => "await start", cmd => fun(State) -> {Tester, ServerSA} = ?SEV_AWAIT_START(), {ok, State#{tester => Tester, server_sa => ServerSA}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, #{desc => "create node", cmd => fun(#{host := Host} = State) -> ?SEV_IPRINT("try create node on ~p", [Host]), case start_node(Host, client) of {ok, Node} -> ?SEV_IPRINT("client node ~p started", [Node]), {ok, State#{node => Node}}; {error, Reason} -> {skip, Reason} end end}, #{desc => "monitor client node", cmd => fun(#{node := Node} = _State) -> true = erlang:monitor_node(Node, true), ok end}, #{desc => "start remote client on client node", cmd => fun(#{node := Node} = State) -> Pid = api_toc_tcp_client_start(Node), ?SEV_IPRINT("remote client ~p started", [Pid]), {ok, State#{rclient => Pid}} end}, #{desc => "monitor remote client", cmd => fun(#{rclient := Pid}) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "order remote client to start", cmd => fun(#{rclient := Client, server_sa := ServerSA}) -> ?SEV_ANNOUNCE_START(Client, ServerSA), ok end}, #{desc => "await remote client ready", cmd => fun(#{tester := Tester, rclient := Client} = _State) -> ?SEV_AWAIT_READY(Client, rclient, init, [{tester, Tester}]) end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, init), ok end}, %% The actual test #{desc => "await continue (connect)", cmd => fun(#{tester := Tester, rclient := Client} = State) -> case ?SEV_AWAIT_CONTINUE(Tester, tester, connect, [{rclient, Client}]) of {ok, {ConTimeout, ConLimit}} -> {ok, State#{connect_timeout => ConTimeout, connect_limit => ConLimit}}; {error, _} = ERROR -> ERROR end end}, #{desc => "order remote client to continue (connect)", cmd => fun(#{rclient := RClient, connect_timeout := ConTimeout, connect_limit := ConLimit}) -> ?SEV_ANNOUNCE_CONTINUE(RClient, connect, {ConTimeout, ConLimit}), ok end}, #{desc => "await remote client ready (connect)", cmd => fun(#{tester := Tester, rclient := RClient} = State) -> case ?SEV_AWAIT_READY(RClient, rclient, connect, [{tester, Tester}]) of {ok, ok = _Result} -> {ok, maps:remove(connect_limit, State)}; {ok, {error, {connect_limit_reached,R,L}}} -> {skip, ?LIB:f("Connect limit reached ~w: ~w", [L, R])}; {ok, Result} -> Result; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (connect)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, connect), ok end}, %% Termination #{desc => "await terminate (from tester)", cmd => fun(#{tester := Tester, rclient := RClient} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester, [{rclient, RClient}]) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "kill remote client", cmd => fun(#{rclient := Client}) -> ?SEV_ANNOUNCE_TERMINATE(Client), ok end}, #{desc => "await remote client termination", cmd => fun(#{rclient := Client} = State) -> ?SEV_AWAIT_TERMINATION(Client), State1 = maps:remove(rclient, State), {ok, State1} end}, #{desc => "stop client node", cmd => fun(#{node := Node} = _State) -> stop_node(Node) end}, #{desc => "await client node termination", cmd => fun(#{node := Node} = State) -> receive {nodedown, Node} -> State1 = maps:remove(node_id, State), State2 = maps:remove(node, State1), {ok, State2} end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], TesterSeq = [ %% *** Init part *** #{desc => "monitor server", cmd => fun(#{server := Server} = _State) -> _MRef = erlang:monitor(process, Server), ok end}, #{desc => "monitor client", cmd => fun(#{client := Client} = _State) -> _MRef = erlang:monitor(process, Client), ok end}, #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, #{desc => "order server start", cmd => fun(#{server := Server, backlog := Backlog}) -> ?SEV_ANNOUNCE_START(Server, Backlog), ok end}, #{desc => "await server ready (init)", cmd => fun(#{server := Server, local_sa := LSA} = State) -> {ok, Port} = ?SEV_AWAIT_READY(Server, server, init), ServerSA = LSA#{port => Port}, {ok, State#{server_sa => ServerSA}} end}, #{desc => "order client start", cmd => fun(#{client := Client, server_sa := ServerSA}) -> ?SEV_ANNOUNCE_START(Client, ServerSA), ok end}, #{desc => "await client ready (init)", cmd => fun(#{client := Client} = _State) -> ?SEV_AWAIT_READY(Client, client, init), ok end}, %% The actual test %% The server does nothing (this is the point), no accept, %% the client tries to connect. #{desc => "order client continue (connect)", cmd => fun(#{client := Client, timeout := Timeout, connect_limit := ConLimit} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Client, connect, {Timeout, ConLimit}), ok end}, #{desc => "await client ready (connect)", cmd => fun(#{server := Server, client := Client} = _State) -> case ?SEV_AWAIT_READY(Client, client, connect, [{server, Server}]) of ok -> ok; {error, _} = ERROR -> ERROR end end}, %% *** Terminate server *** #{desc => "order client terminate", cmd => fun(#{client := Client} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Client), ok end}, #{desc => "await client down", cmd => fun(#{client := Client} = State) -> ?SEV_AWAIT_TERMINATION(Client), State1 = maps:remove(client, State), {ok, State1} end}, #{desc => "order server terminate", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Server), ok end}, #{desc => "await server down", cmd => fun(#{server := Server} = State) -> ?SEV_AWAIT_TERMINATION(Server), State1 = maps:remove(server, State), State2 = maps:remove(server_sa, State1), {ok, State2} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], i("create server evaluator"), ServerInitState = #{domain => maps:get(domain, InitState)}, Server = ?SEV_START("server", ServerSeq, ServerInitState), i("create client evaluator"), ClientInitState = #{host => local_host(), domain => maps:get(domain, InitState)}, Client = ?SEV_START("client", ClientSeq, ClientInitState), i("create tester evaluator"), TesterInitState = InitState#{server => Server#ev.pid, client => Client#ev.pid}, Tester = ?SEV_START("tester", TesterSeq, TesterInitState), i("await evaluator(s)"), ok = ?SEV_AWAIT_FINISH([Server, Client, Tester]). api_toc_tcp_client_start(Node) -> Self = self(), Fun = fun() -> api_toc_tcp_client(Self) end, erlang:spawn(Node, Fun). api_toc_tcp_client(Parent) -> api_toc_tcp_client_init(Parent), ServerSA = api_toc_tcp_client_await_start(Parent), Domain = maps:get(family, ServerSA), api_toc_tcp_client_announce_ready(Parent, init), {To, ConLimit} = api_toc_tcp_client_await_continue(Parent, connect), Result = api_to_connect_tcp_await_timeout(To, ServerSA, Domain, ConLimit), ?SEV_IPRINT("result: ~p", [Result]), api_toc_tcp_client_announce_ready(Parent, connect, Result), Reason = api_toc_tcp_client_await_terminate(Parent), exit(Reason). api_toc_tcp_client_init(Parent) -> put(sname, "rclient"), %% i("api_toc_tcp_client_init -> entry"), _MRef = erlang:monitor(process, Parent), ok. api_toc_tcp_client_await_start(Parent) -> %% i("api_toc_tcp_client_await_start -> entry"), ?SEV_AWAIT_START(Parent). api_toc_tcp_client_announce_ready(Parent, Slogan) -> ?SEV_ANNOUNCE_READY(Parent, Slogan). api_toc_tcp_client_announce_ready(Parent, Slogan, Result) -> ?SEV_ANNOUNCE_READY(Parent, Slogan, Result). api_toc_tcp_client_await_continue(Parent, Slogan) -> %% i("api_toc_tcp_client_await_continue -> entry"), case ?SEV_AWAIT_CONTINUE(Parent, parent, Slogan) of ok -> ok; {ok, Extra} -> Extra; {error, Reason} -> exit({await_continue, Slogan, Reason}) end. api_toc_tcp_client_await_terminate(Parent) -> %% i("api_toc_tcp_client_await_terminate -> entry"), case ?SEV_AWAIT_TERMINATE(Parent, parent) of ok -> ok; {error, Reason} -> Reason end. api_to_connect_tcp_await_timeout(To, ServerSA, Domain, ConLimit) -> LSA = which_local_socket_addr(Domain), NewSock = fun() -> S = case socket:open(Domain, stream, tcp) of {ok, Sock} -> Sock; {error, OReason} -> ?FAIL({open, OReason}) end, case socket:bind(S, LSA) of {ok, _} -> S; {error, BReason} -> ?FAIL({bind, BReason}) end end, api_to_connect_tcp_await_timeout(1, ConLimit, To, ServerSA, NewSock, []). api_to_connect_tcp_await_timeout(ID, ConLimit, _To, _ServerSA, _NewSock, Acc) when (ID > ConLimit) -> api_to_connect_tcp_await_timeout3(Acc), {error, {connect_limit_reached, ID, ConLimit}}; api_to_connect_tcp_await_timeout(ID, ConLimit, To, ServerSA, NewSock, Acc) -> case api_to_connect_tcp_await_timeout2(ID, To, ServerSA, NewSock) of ok -> %% ?SEV_IPRINT("success when number of socks: ~w", [length(Acc)]), api_to_connect_tcp_await_timeout3(Acc), ok; {ok, Sock} -> %% ?SEV_IPRINT("~w: unexpected success (connect)", [ID]), api_to_connect_tcp_await_timeout(ID+1, ConLimit, To, ServerSA, NewSock, [Sock|Acc]); {error, _} = ERROR -> ERROR end. api_to_connect_tcp_await_timeout2(_ID, To, ServerSA, NewSock) -> Sock = NewSock(), %% ?SEV_IPRINT("~w: try connect", [ID]), Start = t(), case socket:connect(Sock, ServerSA, To) of {error, timeout} -> Stop = t(), TDiff = Stop - Start, if (TDiff >= To) -> (catch socket:close(Sock)), ok; true -> (catch socket:close(Sock)), ?FAIL({unexpected_timeout, TDiff, To}) end; {error, econnreset = _Reason} -> (catch socket:close(Sock)), ok; {error, Reason} -> (catch socket:close(Sock)), ?FAIL({connect, Reason}); ok -> {ok, Sock} end. api_to_connect_tcp_await_timeout3([]) -> ok; api_to_connect_tcp_await_timeout3([Sock|Socka]) -> (catch socket:close(Sock)), api_to_connect_tcp_await_timeout3(Socka). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test the accept timeout option %% on an IPv4 TCP (stream) socket. api_to_accept_tcp4(suite) -> []; api_to_accept_tcp4(doc) -> []; api_to_accept_tcp4(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_to_accept_tcp4, fun() -> InitState = #{domain => inet, timeout => 5000}, ok = api_to_accept_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test the accept timeout option %% on an IPv6 TCP (stream) socket. api_to_accept_tcp6(suite) -> []; api_to_accept_tcp6(doc) -> []; api_to_accept_tcp6(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_to_accept_tcp4, fun() -> has_support_ipv6() end, fun() -> InitState = #{domain => inet6, timeout => 5000}, ok = api_to_accept_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% api_to_accept_tcp(InitState) -> TesterSeq = [ %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> LSA = which_local_socket_addr(Domain), {ok, State#{lsa => LSA}} end}, #{desc => "create (listen) socket", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, stream, tcp) of {ok, Sock} -> {ok, State#{lsock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind to local address", cmd => fun(#{lsock := LSock, lsa := LSA} = _State) -> case socket:bind(LSock, LSA) of {ok, _} -> ok; {error, _} = ERROR -> ERROR end end}, #{desc => "make listen socket", cmd => fun(#{lsock := LSock}) -> socket:listen(LSock) end}, %% *** The actual test part *** #{desc => "attempt to accept (without success)", cmd => fun(#{lsock := LSock, timeout := To} = State) -> Start = t(), case socket:accept(LSock, To) of {error, timeout} -> {ok, State#{start => Start, stop => t()}}; {ok, Sock} -> (catch socket:close(Sock)), {error, unexpected_success}; {error, _} = ERROR -> ERROR end end}, #{desc => "validate timeout time", cmd => fun(#{start := Start, stop := Stop, timeout := To} = _State) -> TDiff = Stop - Start, if (TDiff >= To) -> ok; true -> {error, {unexpected_timeout, TDiff, To}} end end}, %% *** Close (listen) socket *** #{desc => "close (listen) socket", cmd => fun(#{lsock := LSock} = State) -> sock_close(LSock), {ok, maps:remove(sock3, State)} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], i("create tester evaluator"), Tester = ?SEV_START("tester", TesterSeq, InitState), i("await evaluator"), ok = ?SEV_AWAIT_FINISH([Tester]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test the multi accept timeout option %% on an IPv4 TCP (stream) socket with multiple acceptor processes %% (three in this case). api_to_maccept_tcp4(suite) -> []; api_to_maccept_tcp4(doc) -> []; api_to_maccept_tcp4(_Config) when is_list(_Config) -> ?TT(?SECS(20)), tc_try(api_to_maccept_tcp4, fun() -> InitState = #{domain => inet, timeout => 5000}, ok = api_to_maccept_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test the accept timeout option %% on an IPv6 TCP (stream) socket. api_to_maccept_tcp6(suite) -> []; api_to_maccept_tcp6(doc) -> []; api_to_maccept_tcp6(_Config) when is_list(_Config) -> ?TT(?SECS(20)), tc_try(api_to_maccept_tcp4, fun() -> has_support_ipv6() end, fun() -> InitState = #{domain => inet6, timeout => 5000}, ok = api_to_maccept_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% api_to_maccept_tcp(InitState) -> PrimAcceptorSeq = [ %% *** Init part *** #{desc => "await start", cmd => fun(State) -> Tester = ?SEV_AWAIT_START(), {ok, State#{tester => Tester}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> LSA = which_local_socket_addr(Domain), {ok, State#{lsa => LSA}} end}, #{desc => "create (listen) socket", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, stream, tcp) of {ok, Sock} -> {ok, State#{lsock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind to local address", cmd => fun(#{lsock := LSock, lsa := LSA} = _State) -> case socket:bind(LSock, LSA) of {ok, _} -> ok; {error, _} = ERROR -> ERROR end end}, #{desc => "make listen socket", cmd => fun(#{lsock := LSock}) -> socket:listen(LSock) end}, #{desc => "announce ready (init)", cmd => fun(#{lsock := LSock, tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, init, LSock), ok end}, %% *** The actual test *** #{desc => "await continue (accept)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, accept) end}, #{desc => "attempt to accept (without success)", cmd => fun(#{lsock := LSock, timeout := To} = State) -> Start = t(), case socket:accept(LSock, To) of {error, timeout} -> {ok, State#{start => Start, stop => t()}}; {ok, Sock} -> ?SEV_EPRINT("Unexpected accept success: " "~n ~p", [Sock]), (catch socket:close(Sock)), {error, unexpected_success}; {error, _} = ERROR -> ERROR end end}, #{desc => "validate timeout time", cmd => fun(#{start := Start, stop := Stop, timeout := To} = _State) -> TDiff = Stop - Start, if (TDiff >= To) -> ok; true -> {error, {unexpected_timeout, TDiff, To}} end end}, #{desc => "announce ready (accept)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, accept), ok end}, %% *** Terminate *** #{desc => "await terminate", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_TERMINATE(Tester, tester), ok end}, %% *** Close (listen) socket *** #{desc => "close (listen) socket", cmd => fun(#{lsock := LSock} = State) -> sock_close(LSock), {ok, maps:remove(lsock, State)} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], SecAcceptorSeq = [ %% *** Init part *** #{desc => "await start", cmd => fun(State) -> {Tester, LSock} = ?SEV_AWAIT_START(), {ok, State#{tester => Tester, lsock => LSock}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_ANNOUNCE_READY(Tester, init), ok end}, %% *** The actual test part *** #{desc => "await continue (accept)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, accept) end}, #{desc => "attempt to accept (without success)", cmd => fun(#{lsock := LSock, timeout := To} = State) -> Start = t(), case socket:accept(LSock, To) of {error, timeout} -> {ok, State#{start => Start, stop => t()}}; {ok, Sock} -> (catch socket:close(Sock)), {error, unexpected_success}; {error, _} = ERROR -> ERROR end end}, #{desc => "validate timeout time", cmd => fun(#{start := Start, stop := Stop, timeout := To} = State) -> TDiff = Stop - Start, if (TDiff >= To) -> State1 = maps:remove(start, State), State2 = maps:remove(stop, State1), {ok, State2}; true -> {error, {unexpected_timeout, TDiff, To}} end end}, #{desc => "announce ready (accept)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_ANNOUNCE_READY(Tester, accept), ok end}, %% *** Terminate *** #{desc => "await terminate", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], TesterSeq = [ %% Init part #{desc => "monitor prim-acceptor", cmd => fun(#{prim_acceptor := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "monitor sec-acceptor 1", cmd => fun(#{sec_acceptor1 := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "monitor sec-acceptor 2", cmd => fun(#{sec_acceptor2 := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, %% Start the prim-acceptor #{desc => "start prim-acceptor", cmd => fun(#{prim_acceptor := Pid} = _State) -> ?SEV_ANNOUNCE_START(Pid), ok end}, #{desc => "await prim-acceptor ready (init)", cmd => fun(#{prim_acceptor := Pid} = State) -> {ok, Sock} = ?SEV_AWAIT_READY(Pid, prim_acceptor, init), {ok, State#{lsock => Sock}} end}, %% Start sec-acceptor-1 #{desc => "start sec-acceptor 1", cmd => fun(#{sec_acceptor1 := Pid, lsock := LSock} = _State) -> ?SEV_ANNOUNCE_START(Pid, LSock), ok end}, #{desc => "await sec-acceptor 1 ready (init)", cmd => fun(#{sec_acceptor1 := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, sec_acceptor1, init) end}, %% Start sec-acceptor-2 #{desc => "start sec-acceptor 2", cmd => fun(#{sec_acceptor2 := Pid, lsock := LSock} = _State) -> ?SEV_ANNOUNCE_START(Pid, LSock), ok end}, #{desc => "await sec-acceptor 2 ready (init)", cmd => fun(#{sec_acceptor2 := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, sec_acceptor2, init) end}, %% Activate the acceptor(s) #{desc => "active prim-acceptor", cmd => fun(#{prim_acceptor := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, accept), ok end}, #{desc => "active sec-acceptor 1", cmd => fun(#{sec_acceptor1 := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, accept), ok end}, #{desc => "active sec-acceptor 2", cmd => fun(#{sec_acceptor2 := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, accept), ok end}, %% Await acceptor(s) completions #{desc => "await prim-acceptor ready (accept)", cmd => fun(#{prim_acceptor := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, prim_acceptor, accept) end}, #{desc => "await sec-acceptor 1 ready (accept)", cmd => fun(#{sec_acceptor1 := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, sec_acceptor1, accept) end}, #{desc => "await sec-acceptor 2 ready (accept)", cmd => fun(#{sec_acceptor2 := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, sec_acceptor2, accept) end}, %% Terminate #{desc => "order prim-acceptor to terminate", cmd => fun(#{prim_acceptor := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await prim-acceptor termination", cmd => fun(#{prim_acceptor := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> State1 = maps:remove(prim_acceptor, State), {ok, State1}; {error, _} = ERROR -> ERROR end end}, #{desc => "order sec-acceptor 1 to terminate", cmd => fun(#{sec_acceptor1 := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await sec-acceptor 1 termination", cmd => fun(#{sec_acceptor1 := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> State1 = maps:remove(sec_acceptor1, State), {ok, State1}; {error, _} = ERROR -> ERROR end end}, #{desc => "order sec-acceptor 2 to terminate", cmd => fun(#{sec_acceptor2 := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await sec-acceptor 2 termination", cmd => fun(#{sec_acceptor2 := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> State1 = maps:remove(sec_acceptor2, State), {ok, State1}; {error, _} = ERROR -> ERROR end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], i("create prim-acceptor evaluator"), PrimAInitState = InitState, PrimAcceptor = ?SEV_START("prim-acceptor", PrimAcceptorSeq, PrimAInitState), i("create sec-acceptor 1 evaluator"), SecAInitState1 = maps:remove(domain, InitState), SecAcceptor1 = ?SEV_START("sec-acceptor-1", SecAcceptorSeq, SecAInitState1), i("create sec-acceptor 2 evaluator"), SecAInitState2 = SecAInitState1, SecAcceptor2 = ?SEV_START("sec-acceptor-2", SecAcceptorSeq, SecAInitState2), i("create tester evaluator"), TesterInitState = #{prim_acceptor => PrimAcceptor#ev.pid, sec_acceptor1 => SecAcceptor1#ev.pid, sec_acceptor2 => SecAcceptor2#ev.pid}, Tester = ?SEV_START("tester", TesterSeq, TesterInitState), i("await evaluator(s)"), ok = ?SEV_AWAIT_FINISH([PrimAcceptor, SecAcceptor1, SecAcceptor2, Tester]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test the send timeout option %% on an IPv4 TCP (stream) socket. api_to_send_tcp4(suite) -> []; api_to_send_tcp4(doc) -> []; api_to_send_tcp4(_Config) when is_list(_Config) -> tc_try(api_to_send_tcp4, fun() -> not_yet_implemented()%% , %% ok = api_to_send_tcp(inet) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test the send timeout option %% on an IPv6 TCP (stream) socket. api_to_send_tcp6(suite) -> []; api_to_send_tcp6(doc) -> []; api_to_send_tcp6(_Config) when is_list(_Config) -> tc_try(api_to_send_tcp6, fun() -> has_support_ipv6() end, fun() -> not_yet_implemented()%% , %% ok = api_to_send_tcp(inet6) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test the sendto timeout option %% on an IPv4 UDP (dgram) socket. api_to_sendto_udp4(suite) -> []; api_to_sendto_udp4(doc) -> []; api_to_sendto_udp4(_Config) when is_list(_Config) -> tc_try(api_to_sendto_udp4, fun() -> not_yet_implemented()%% , %% ok = api_to_sendto_to_udp(inet) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test the sendto timeout option %% on an IPv6 UDP (dgram) socket. api_to_sendto_udp6(suite) -> []; api_to_sendto_udp6(doc) -> []; api_to_sendto_udp6(_Config) when is_list(_Config) -> tc_try(api_to_sendto_udp6, fun() -> has_support_ipv6() end, fun() -> not_yet_implemented()%% , %% ok = api_to_sendto_to_udp(inet6) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test the sendmsg timeout option %% on an IPv4 TCP (stream) socket. api_to_sendmsg_tcp4(suite) -> []; api_to_sendmsg_tcp4(doc) -> []; api_to_sendmsg_tcp4(_Config) when is_list(_Config) -> tc_try(api_to_sendmsg_tcp4, fun() -> not_yet_implemented()%% , %% ok = api_to_sendmsg_tcp(inet) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test the sendmsg timeout option %% on an IPv6 TCP (stream) socket. api_to_sendmsg_tcp6(suite) -> []; api_to_sendmsg_tcp6(doc) -> []; api_to_sendmsg_tcp6(_Config) when is_list(_Config) -> tc_try(api_to_sendmsg_tcp6, fun() -> has_support_ipv6() end, fun() -> not_yet_implemented()%% , %% ok = api_to_sendmsg_tcp(inet6) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test the recv timeout option %% on an IPv4 UDP (dgram) socket. To test this we must connect %% the socket. api_to_recv_udp4(suite) -> []; api_to_recv_udp4(doc) -> []; api_to_recv_udp4(_Config) when is_list(_Config) -> tc_try(api_to_recv_udp4, fun() -> not_yet_implemented()%%, %%ok = api_to_recv_udp(inet) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test the recv timeout option %% on an IPv6 UDP (dgram) socket. To test this we must connect %% the socket. api_to_recv_udp6(suite) -> []; api_to_recv_udp6(doc) -> []; api_to_recv_udp6(_Config) when is_list(_Config) -> tc_try(api_to_recv_udp6, fun() -> has_support_ipv6() end, fun() -> not_yet_implemented()%% , %% ok = api_to_recv_udp(inet6) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test the recv timeout option %% on an IPv4 TCP (stream) socket. api_to_recv_tcp4(suite) -> []; api_to_recv_tcp4(doc) -> []; api_to_recv_tcp4(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_to_recv_tcp4, fun() -> Recv = fun(Sock, To) -> socket:recv(Sock, 0, To) end, InitState = #{domain => inet, recv => Recv, timeout => 2000}, ok = api_to_receive_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test the recv timeout option %% on an IPv6 TCP (stream) socket. api_to_recv_tcp6(suite) -> []; api_to_recv_tcp6(doc) -> []; api_to_recv_tcp6(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_to_recv_tcp6, fun() -> has_support_ipv6() end, fun() -> case socket:supports(ipv6) of true -> Recv = fun(Sock, To) -> socket:recv(Sock, 0, To) end, InitState = #{domain => inet6, recv => Recv, timeout => 2000}, ok = api_to_receive_tcp(InitState); false -> skip("ipv6 not supported") end end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% api_to_receive_tcp(InitState) -> process_flag(trap_exit, true), ServerSeq = [ %% *** Wait for start order *** #{desc => "await start (from tester)", cmd => fun(State) -> Tester = ?SEV_AWAIT_START(), {ok, State#{tester => Tester}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester}) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, #{desc => "create listen socket", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, stream, tcp) of {ok, Sock} -> {ok, State#{lsock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind to local address", cmd => fun(#{lsock := LSock, local_sa := LSA} = State) -> case socket:bind(LSock, LSA) of {ok, Port} -> {ok, State#{lport => Port}}; {error, _} = ERROR -> ERROR end end}, #{desc => "make listen socket (with backlog = 1)", cmd => fun(#{lsock := LSock}) -> socket:listen(LSock, 1) end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester, lport := Port}) -> ?SEV_ANNOUNCE_READY(Tester, init, Port), ok end}, %% *** The actual test *** #{desc => "await continue (accept and recv)", cmd => fun(#{tester := Tester}) -> ?SEV_AWAIT_CONTINUE(Tester, tester, accept_recv) end}, #{desc => "attempt accept", cmd => fun(#{lsock := LSock} = State) -> case socket:accept(LSock) of {ok, Sock} -> {ok, State#{sock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "attempt to recv (without success)", cmd => fun(#{sock := Sock, recv := Recv, timeout := To} = State) -> Start = t(), case Recv(Sock, To) of {error, timeout} -> {ok, State#{start => Start, stop => t()}}; {ok, _Data} -> {error, unexpected_success}; {error, _} = ERROR -> ERROR end end}, #{desc => "validate timeout time", cmd => fun(#{start := Start, stop := Stop, timeout := To} = State) -> TDiff = Stop - Start, if (TDiff >= To) -> State1 = maps:remove(start, State), State2 = maps:remove(stop, State1), {ok, State2}; true -> {error, {unexpected_timeout, TDiff, To}} end end}, #{desc => "announce ready (recv timeout success)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_ANNOUNCE_READY(Tester, accept_recv), ok end}, %% *** Termination *** #{desc => "await terminate", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "close (traffic) socket", cmd => fun(#{sock := Sock} = State) -> sock_close(Sock), {ok, maps:remove(sock, State)} end}, #{desc => "close (listen) socket", cmd => fun(#{lsock := LSock} = State) -> sock_close(LSock), {ok, maps:remove(lsock, State)} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], ClientSeq = [ %% *** Wait for start order part *** #{desc => "await start (from tester)", cmd => fun(State) -> {Tester, Port} = ?SEV_AWAIT_START(), {ok, State#{tester => Tester, server_port => Port}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain, server_port := Port} = State) -> LSA = which_local_socket_addr(Domain), SSA = LSA#{port => Port}, {ok, State#{local_sa => LSA, server_sa => SSA}} end}, #{desc => "create socket", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, stream, tcp) of {ok, Sock} -> {ok, State#{sock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind to local address", cmd => fun(#{sock := Sock, local_sa := LSA} = _State) -> case socket:bind(Sock, LSA) of {ok, _} -> ok; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_ANNOUNCE_READY(Tester, init), ok end}, %% *** The actual test *** #{desc => "await continue (with connect)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, connect) end}, #{desc => "connect", cmd => fun(#{sock := Sock, server_sa := SSA}) -> sock_connect(Sock, SSA), ok end}, %% *** Termination *** #{desc => "await terminate", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "close socket", cmd => fun(#{sock := Sock} = State) -> sock_close(Sock), {ok, maps:remove(sock, State)} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], TesterSeq = [ %% *** Init part *** #{desc => "monitor server", cmd => fun(#{server := Server} = _State) -> _MRef = erlang:monitor(process, Server), ok end}, #{desc => "monitor client", cmd => fun(#{client := Client} = _State) -> _MRef = erlang:monitor(process, Client), ok end}, %% *** Activate server *** #{desc => "start server", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_START(Server), ok end}, #{desc => "await server ready (init)", cmd => fun(#{server := Server} = State) -> {ok, Port} = ?SEV_AWAIT_READY(Server, server, init), {ok, State#{server_port => Port}} end}, #{desc => "order server to continue (with accept)", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Server, accept_recv), ok end}, %% *** Activate client *** #{desc => "start client", cmd => fun(#{client := Client, server_port := Port} = _State) -> ?SEV_ANNOUNCE_START(Client, Port), ok end}, #{desc => "await client ready (init)", cmd => fun(#{client := Client} = _State) -> ?SEV_AWAIT_READY(Client, client, init) end}, %% *** The actual test *** #{desc => "order client to continue (with connect)", cmd => fun(#{client := Client} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Client, connect), ok end}, #{desc => "await server ready (accept/recv)", cmd => fun(#{server := Server} = _State) -> ?SEV_AWAIT_READY(Server, server, accept_recv) end}, %% *** Termination *** #{desc => "order client to terminate", cmd => fun(#{client := Client} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Client), ok end}, #{desc => "await client termination", cmd => fun(#{client := Client} = State) -> case ?SEV_AWAIT_TERMINATION(Client) of ok -> State1 = maps:remove(client, State), {ok, State1}; {error, _} = ERROR -> ERROR end end}, #{desc => "order server to terminate", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Server), ok end}, #{desc => "await server termination", cmd => fun(#{server := Server} = State) -> case ?SEV_AWAIT_TERMINATION(Server) of ok -> State1 = maps:remove(server, State), State2 = maps:remove(server_port, State1), {ok, State2}; {error, _} = ERROR -> ERROR end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], i("start server evaluator"), ServerInitState = InitState, Server = ?SEV_START("server", ServerSeq, ServerInitState), i("start client evaluator"), ClientInitState = InitState, Client = ?SEV_START("client", ClientSeq, ClientInitState), i("start tester evaluator"), TesterInitState = #{server => Server#ev.pid, client => Client#ev.pid}, Tester = ?SEV_START("tester", TesterSeq, TesterInitState), i("await evaluator(s)"), ok = ?SEV_AWAIT_FINISH([Server, Client, Tester]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test the recvfrom timeout option %% on an IPv4 UDP (dgram) socket. api_to_recvfrom_udp4(suite) -> []; api_to_recvfrom_udp4(doc) -> []; api_to_recvfrom_udp4(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_to_recvfrom_udp4, fun() -> Recv = fun(Sock, To) -> socket:recvfrom(Sock, 0, To) end, InitState = #{domain => inet, recv => Recv, timeout => 2000}, ok = api_to_receive_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test the recvfrom timeout option %% on an IPv6 UDP (dgram) socket. api_to_recvfrom_udp6(suite) -> []; api_to_recvfrom_udp6(doc) -> []; api_to_recvfrom_udp6(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_to_recvfrom_udp6, fun() -> has_support_ipv6() end, fun() -> Recv = fun(Sock, To) -> socket:recvfrom(Sock, 0, To) end, InitState = #{domain => inet6, recv => Recv, timeout => 2000}, ok = api_to_receive_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% api_to_receive_udp(InitState) -> TesterSeq = [ %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> LSA = which_local_socket_addr(Domain), {ok, State#{lsa => LSA}} end}, #{desc => "create socket", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, dgram, udp) of {ok, Sock} -> {ok, State#{sock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind to local address", cmd => fun(#{sock := Sock, lsa := LSA} = _State) -> case socket:bind(Sock, LSA) of {ok, _Port} -> ok; {error, _} = ERROR -> ERROR end end}, %% *** The actual test *** #{desc => "attempt to read (without success)", cmd => fun(#{sock := Sock, recv := Recv, timeout := To} = State) -> Start = t(), case Recv(Sock, To) of {error, timeout} -> {ok, State#{start => Start, stop => t()}}; {ok, _} -> {error, unexpected_sucsess}; {error, _} = ERROR -> ERROR end end}, #{desc => "validate timeout time", cmd => fun(#{start := Start, stop := Stop, timeout := To} = _State) -> TDiff = Stop - Start, if (TDiff >= To) -> ok; true -> {error, {unexpected_timeout, TDiff, To}} end end}, %% *** Termination *** #{desc => "close socket", cmd => fun(#{sock := Sock} = _State) -> %% socket:setopt(Sock, otp, debug, true), sock_close(Sock), ok end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], i("start tester evaluator"), Tester = ?SEV_START("tester", TesterSeq, InitState), i("await evaluator"), ok = ?SEV_AWAIT_FINISH([Tester]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test the recvmsg timeout option %% on an IPv4 UDP (dgram) socket. api_to_recvmsg_udp4(suite) -> []; api_to_recvmsg_udp4(doc) -> []; api_to_recvmsg_udp4(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_to_recvmsg_udp4, fun() -> Recv = fun(Sock, To) -> socket:recvmsg(Sock, To) end, InitState = #{domain => inet, recv => Recv, timeout => 2000}, ok = api_to_receive_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test the recvmsg timeout option %% on an IPv6 UDP (dgram) socket. api_to_recvmsg_udp6(suite) -> []; api_to_recvmsg_udp6(doc) -> []; api_to_recvmsg_udp6(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_to_recvmsg_udp6, fun() -> has_support_ipv6() end, fun() -> Recv = fun(Sock, To) -> socket:recvmsg(Sock, To) end, InitState = #{domain => inet6, recv => Recv, timeout => 2000}, ok = api_to_receive_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test the recvmsg timeout option %% on an IPv4 TCP (stream) socket. api_to_recvmsg_tcp4(suite) -> []; api_to_recvmsg_tcp4(doc) -> []; api_to_recvmsg_tcp4(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_to_recvmsg_tcp4, fun() -> Recv = fun(Sock, To) -> socket:recvmsg(Sock, To) end, InitState = #{domain => inet, recv => Recv, timeout => 2000}, ok = api_to_receive_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test the recvmsg timeout option %% on an IPv6 TCP (stream) socket. api_to_recvmsg_tcp6(suite) -> []; api_to_recvmsg_tcp6(doc) -> []; api_to_recvmsg_tcp6(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_to_recvmsg_tcp6, fun() -> has_support_ipv6() end, fun() -> Recv = fun(Sock, To) -> socket:recvmsg(Sock, To) end, InitState = #{domain => inet6, recv => Recv, timeout => 2000}, ok = api_to_receive_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %% %% SOCKET CLOSURE %% %% %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the sockets are cleaned up %% ("removed") when the controlling process terminates (without explicitly %% calling the close function). For a IPv4 TCP (stream) socket. sc_cpe_socket_cleanup_tcp4(suite) -> []; sc_cpe_socket_cleanup_tcp4(doc) -> []; sc_cpe_socket_cleanup_tcp4(_Config) when is_list(_Config) -> ?TT(?SECS(30)), tc_try(sc_cpe_socket_cleanup_tcp4, fun() -> InitState = #{domain => inet, type => stream, protocol => tcp}, ok = sc_cpe_socket_cleanup(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the sockets are cleaned up %% ("removed") when the controlling process terminates (without explicitly %% calling the close function). For a IPv6 TCP (stream) socket. sc_cpe_socket_cleanup_tcp6(suite) -> []; sc_cpe_socket_cleanup_tcp6(doc) -> []; sc_cpe_socket_cleanup_tcp6(_Config) when is_list(_Config) -> ?TT(?SECS(30)), tc_try(sc_cpe_socket_cleanup_tcp6, fun() -> has_support_ipv6() end, fun() -> InitState = #{domain => inet6, type => stream, protocol => tcp}, ok = sc_cpe_socket_cleanup(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the sockets are cleaned up %% ("removed") when the controlling process terminates (without explicitly %% calling the close function). For a Unix Domain (stream) socket (TCP). sc_cpe_socket_cleanup_tcpL(suite) -> []; sc_cpe_socket_cleanup_tcpL(doc) -> []; sc_cpe_socket_cleanup_tcpL(_Config) when is_list(_Config) -> ?TT(?SECS(30)), tc_try(sc_cpe_socket_cleanup_tcpL, fun() -> has_support_unix_domain_socket() end, fun() -> InitState = #{domain => local, type => stream, protocol => default}, ok = sc_cpe_socket_cleanup(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the sockets are cleaned up %% ("removed") when the controlling process terminates (without explicitly %% calling the close function). For a IPv4 UDP (dgram) socket. sc_cpe_socket_cleanup_udp4(suite) -> []; sc_cpe_socket_cleanup_udp4(doc) -> []; sc_cpe_socket_cleanup_udp4(_Config) when is_list(_Config) -> ?TT(?SECS(30)), tc_try(sc_cpe_socket_cleanup_udp4, fun() -> InitState = #{domain => inet, type => dgram, protocol => udp}, ok = sc_cpe_socket_cleanup(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the sockets are cleaned up %% (removed) when the controlling process terminates (without explicitly %% calling the close function). For a IPv6 UDP (dgram) socket. sc_cpe_socket_cleanup_udp6(suite) -> []; sc_cpe_socket_cleanup_udp6(doc) -> []; sc_cpe_socket_cleanup_udp6(_Config) when is_list(_Config) -> ?TT(?SECS(30)), tc_try(sc_cpe_socket_cleanup_udp6, fun() -> has_support_ipv6() end, fun() -> InitState = #{domain => inet6, type => dgram, protocol => udp}, ok = sc_cpe_socket_cleanup(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the sockets are cleaned up %% ("removed") when the controlling process terminates (without explicitly %% calling the close function). For a Unix Domain (dgram) socket (UDP). sc_cpe_socket_cleanup_udpL(suite) -> []; sc_cpe_socket_cleanup_udpL(doc) -> []; sc_cpe_socket_cleanup_udpL(_Config) when is_list(_Config) -> ?TT(?SECS(30)), tc_try(sc_cpe_socket_cleanup_udpL, fun() -> has_support_unix_domain_socket() end, fun() -> InitState = #{domain => local, type => dgram, protocol => default}, ok = sc_cpe_socket_cleanup(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% sc_cpe_socket_cleanup(InitState) -> OwnerSeq = [ %% *** Wait for start order part *** #{desc => "await start (from tester)", cmd => fun(State) -> Tester = ?SEV_AWAIT_START(), {ok, State#{tester => Tester}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "create socket", cmd => fun(#{domain := Domain, type := Type, protocol := Proto} = State) -> case socket:open(Domain, Type, Proto) of {ok, Sock} -> {ok, State#{sock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester, sock := Sock} = _State) -> ?SEV_ANNOUNCE_READY(Tester, init, Sock), ok end}, %% *** The actual test *** %% We *intentially* leave the socket "as is", no explicit close #{desc => "await terminate (from tester)", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], TesterSeq = [ %% *** Init part *** #{desc => "monitor owner", cmd => fun(#{owner := Owner} = _State) -> _MRef = erlang:monitor(process, Owner), ok end}, #{desc => "order (owner) start", cmd => fun(#{owner := Pid} = _State) -> ?SEV_ANNOUNCE_START(Pid), ok end}, #{desc => "await (owner) ready", cmd => fun(#{owner := Pid} = State) -> {ok, Sock} = ?SEV_AWAIT_READY(Pid, owner, init), {ok, State#{sock => Sock}} end}, #{desc => "verify owner as controlling-process", cmd => fun(#{owner := Pid, sock := Sock} = _State) -> case socket:getopt(Sock, otp, controlling_process) of {ok, Pid} -> ok; {ok, Other} -> {error, {unexpected_owner, Other}}; {error, _} = ERROR -> ERROR end end}, #{desc => "order (owner) terminate", cmd => fun(#{owner := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await (owner) termination", cmd => fun(#{owner := Pid} = _State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> ok; {error, _} = ERROR -> ERROR end end}, ?SEV_SLEEP(?SECS(5)), %% The reason we get closed, is that as long as there is a ref to %% the resource (socket), then it will not be garbage collected. %% Note that its still a race that the nif has processed that the %% "controlling process" has terminated. There really is no %% proper timeout for this, but the 5 seconds "should" be enough... %% We should really have some way to subscribe to socket events... #{desc => "verify no socket (closed)", cmd => fun(#{owner := Pid, sock := Sock} = _State) -> case socket:getopt(Sock, otp, controlling_process) of {ok, OtherPid} -> {error, {unexpected_success, Pid, OtherPid}}; {error, closed} -> ok; {error, Reason} -> ?SEV_IPRINT("expected failure: ~p", [Reason]), {error, {unexpected_failure, Reason}} end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], i("start (socket) owner evaluator"), Owner = ?SEV_START("owner", OwnerSeq, InitState), i("start tester evaluator"), TesterInitState = #{owner => Owner#ev.pid}, Tester = ?SEV_START("tester", TesterSeq, TesterInitState), i("await evaluator"), ok = ?SEV_AWAIT_FINISH([Owner, Tester]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test what happens when a socket is %% locally closed while a process is calling the recv function. %% Socket is IPv4. %% %% %% %% We should really have a similar test cases for when the controlling %% process exits and there are other processes in recv, accept, and %% all the other functions. %% %% sc_lc_recv_response_tcp4(suite) -> []; sc_lc_recv_response_tcp4(doc) -> []; sc_lc_recv_response_tcp4(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(sc_lc_recv_response_tcp4, fun() -> Recv = fun(Sock) -> socket:recv(Sock) end, InitState = #{domain => inet, protocol => tcp, recv => Recv}, ok = sc_lc_receive_response_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test what happens when a socket is %% locally closed while the process is calling the recv function. %% Socket is IPv6. sc_lc_recv_response_tcp6(suite) -> []; sc_lc_recv_response_tcp6(doc) -> []; sc_lc_recv_response_tcp6(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(sc_lc_recv_response_tcp6, fun() -> has_support_ipv6() end, fun() -> Recv = fun(Sock) -> socket:recv(Sock) end, InitState = #{domain => inet6, protocol => tcp, recv => Recv}, ok = sc_lc_receive_response_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test what happens when a socket is %% locally closed while the process is calling the recv function. %% Socket is Unix Domain (stream) socket. sc_lc_recv_response_tcpL(suite) -> []; sc_lc_recv_response_tcpL(doc) -> []; sc_lc_recv_response_tcpL(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(sc_lc_recv_response_tcpL, fun() -> has_support_unix_domain_socket() end, fun() -> Recv = fun(Sock) -> socket:recv(Sock) end, InitState = #{domain => local, protocol => default, recv => Recv}, ok = sc_lc_receive_response_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% sc_lc_receive_response_tcp(InitState) -> %% This (acceptor) is the server that accepts connections. %% But it is also suppose to close the connection socket, %% and trigger the read failure (=closed) for the handler process. AcceptorSeq = [ %% *** Wait for start order part *** #{desc => "await start (from tester)", cmd => fun(State) -> Tester = ?SEV_AWAIT_START(), {ok, State#{tester => Tester}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> LSA = which_local_socket_addr(Domain), {ok, State#{lsa => LSA}} end}, #{desc => "create (listen) socket", cmd => fun(#{domain := Domain, protocol := Proto} = State) -> case socket:open(Domain, stream, Proto) of {ok, Sock} -> {ok, State#{lsock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind to local address", cmd => fun(#{domain := local, lsock := LSock, lsa := LSA} = _State) -> ?SEV_IPRINT("bind to LSA: " "~n ~p", [LSA]), case socket:bind(LSock, LSA) of {ok, _Port} -> ok; % We do not care about the port for local {error, _} = ERROR -> ERROR end; (#{lsock := LSock, lsa := LSA} = State) -> case socket:bind(LSock, LSA) of {ok, Port} -> ?SEV_IPRINT("bound to port: ~w", [Port]), {ok, State#{lport => Port}}; {error, _} = ERROR -> ERROR end end}, #{desc => "make listen socket", cmd => fun(#{lsock := LSock}) -> socket:listen(LSock) end}, #{desc => "announce ready (init)", cmd => fun(#{domain := local, tester := Tester, lsa := #{path := Path}}) -> ?SEV_ANNOUNCE_READY(Tester, init, Path), ok; (#{tester := Tester, lport := Port}) -> ?SEV_ANNOUNCE_READY(Tester, init, Port), ok end}, %% The actual test #{desc => "await continue (accept)", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_CONTINUE(Tester, tester, accept) of {ok, {H1, H2, H3}} -> {ok, State#{handler1 => H1, handler2 => H2, handler3 => H3}}; {error, _} = ERROR -> ERROR end end}, #{desc => "await accept", cmd => fun(#{lsock := LSock} = State) -> case socket:accept(LSock) of {ok, Sock} -> ?SEV_IPRINT("connection accepted: " "~n ~p", [socket:sockname(Sock)]), {ok, State#{csock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (accept)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, accept), ok end}, #{desc => "transfer connection to handler 1", cmd => fun(#{handler1 := Handler, csock := Sock}) -> ?SEV_ANNOUNCE_CONTINUE(Handler, transfer, Sock), ok end}, #{desc => "transfer connection to handler 2", cmd => fun(#{handler2 := Handler, csock := Sock}) -> ?SEV_ANNOUNCE_CONTINUE(Handler, transfer, Sock), ok end}, #{desc => "transfer connection to handler 3", cmd => fun(#{handler3 := Handler, csock := Sock}) -> ?SEV_ANNOUNCE_CONTINUE(Handler, transfer, Sock), ok end}, #{desc => "await continue (close)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, close), ok end}, #{desc => "close connection socket", cmd => fun(#{csock := Sock} = State) -> case socket:close(Sock) of ok -> {ok, maps:remove(csock, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (close)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, close), ok end}, %% *** Terminate *** #{desc => "await terminate", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "close listen socket", cmd => fun(#{domain := local, lsock := Sock, lsa := #{path := Path}} = State) -> ok = socket:close(Sock), State1 = unlink_path(Path, fun() ->maps:remove(lsa, State) end, fun() -> State end), State2 = maps:remove(lsock, State1), State3 = maps:remove(lport, State2), {ok, State3}; (#{lsock := Sock} = State) -> case socket:close(Sock) of ok -> State1 = maps:remove(lsock, State), State2 = maps:remove(lport, State1), {ok, State2}; {error, _} = ERROR -> ERROR end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], %% The point of this is to perform the recv for which %% we are testing the reponse. HandlerSeq = [ %% *** Wait for start order part *** #{desc => "await start (from tester)", cmd => fun(State) -> {Tester, Acceptor} = ?SEV_AWAIT_START(), {ok, State#{tester => Tester, acceptor => Acceptor}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, #{desc => "monitor acceptor", cmd => fun(#{acceptor := Acceptor} = _State) -> _MRef = erlang:monitor(process, Acceptor), ok end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, init), ok end}, %% The actual test #{desc => "await continue (transfer)", cmd => fun(#{acceptor := Pid} = State) -> case ?SEV_AWAIT_CONTINUE(Pid, acceptor, transfer) of {ok, Sock} -> {ok, State#{sock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (transfer)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, transfer), ok end}, #{desc => "attempt recv (=> closed)", cmd => fun(#{sock := Sock, recv := Recv} = State) -> %% ok = socket:setopt(Sock, otp, debug, true), case Recv(Sock) of {ok, _Data} -> ?SEV_EPRINT("Unexpected data received"), {error, unexpected_success}; {error, closed} -> ?SEV_IPRINT("received expected 'closed' " "result"), State1 = maps:remove(sock, State), {ok, State1}; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected read failure: " "~n ~p", [Reason]), ERROR end end}, #{desc => "announce ready (recv closed)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv_closed), ok end}, %% *** Terminate *** #{desc => "await terminate", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], %% The point of this is basically just to create the connection. ClientSeq = [ %% *** Wait for start order part *** #{desc => "await start (from tester)", cmd => fun(State) -> Tester = ?SEV_AWAIT_START(), {ok, State#{tester => Tester}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, #{desc => "create socket", cmd => fun(#{domain := Domain, protocol := Proto} = State) -> case socket:open(Domain, stream, Proto) of {ok, Sock} -> {ok, State#{sock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind socket to local address", cmd => fun(#{sock := Sock, local_sa := LSA} = _State) -> ?SEV_IPRINT("bind to LSA: " "~n ~p", [LSA]), case socket:bind(Sock, LSA) of {ok, _} -> ok; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_ANNOUNCE_READY(Tester, init), ok end}, %% The actual test #{desc => "await continue (connect)", cmd => fun(#{domain := local = Domain, tester := Tester} = State) -> case ?SEV_AWAIT_CONTINUE(Tester, tester, connect) of {ok, ServerPath} -> ?SEV_IPRINT("Server Path: " "~n ~s", [ServerPath]), ServerSA = #{family => Domain, path => ServerPath}, {ok, State#{server_sa => ServerSA}}; {error, _} = ERROR -> ERROR end; (#{tester := Tester, local_sa := LSA} = State) -> case ?SEV_AWAIT_CONTINUE(Tester, tester, connect) of {ok, Port} -> ServerSA = LSA#{port => Port}, {ok, State#{server_sa => ServerSA}}; {error, _} = ERROR -> ERROR end end}, #{desc => "connect to server", cmd => fun(#{sock := Sock, server_sa := ServerSA}) -> socket:connect(Sock, ServerSA) end}, #{desc => "announce ready (connect)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_ANNOUNCE_READY(Tester, connect), ok end}, %% *** Terminate *** #{desc => "await terminate (from tester)", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "close socket", cmd => fun(#{domain := local, sock := Sock, local_sa := #{path := Path}} = State) -> sock_close(Sock), State1 = unlink_path(Path, fun() -> maps:remove(local_sa, State) end, fun() -> State end), {ok, maps:remove(sock, State1)}; (#{sock := Sock} = State) -> sock_close(Sock), {ok, maps:remove(sock, State)} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], TesterSeq = [ %% *** Init part *** #{desc => "monitor acceptor", cmd => fun(#{acceptor := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "monitor handler 1", cmd => fun(#{handler1 := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "monitor handler 2", cmd => fun(#{handler2 := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "monitor handler 3", cmd => fun(#{handler3 := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "monitor client", cmd => fun(#{client := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, %% Start the acceptor #{desc => "order acceptor start", cmd => fun(#{acceptor := Pid} = _State) -> ?SEV_ANNOUNCE_START(Pid), ok end}, #{desc => "await acceptor ready (init)", cmd => fun(#{acceptor := Pid} = State) -> case ?SEV_AWAIT_READY(Pid, acceptor, init) of {ok, PortOrPath} -> {ok, State#{server_info => PortOrPath}}; {error, _} = ERROR -> ERROR end end}, %% Start the handler(s) #{desc => "order handler 1 start", cmd => fun(#{acceptor := Acceptor, handler1 := Pid} = _State) -> ?SEV_ANNOUNCE_START(Pid, Acceptor), ok end}, #{desc => "await handler 1 ready (init)", cmd => fun(#{handler1 := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, handler1, init) end}, #{desc => "order handler 2 start", cmd => fun(#{acceptor := Acceptor, handler2 := Pid} = _State) -> ?SEV_ANNOUNCE_START(Pid, Acceptor), ok end}, #{desc => "await handler 2 ready (init)", cmd => fun(#{handler2 := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, handler2, init) end}, #{desc => "order handler 3 start", cmd => fun(#{acceptor := Acceptor, handler3 := Pid} = _State) -> ?SEV_ANNOUNCE_START(Pid, Acceptor), ok end}, #{desc => "await handler 3 ready (init)", cmd => fun(#{handler3 := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, handler3, init) end}, %% Start the client #{desc => "order client start", cmd => fun(#{client := Pid} = _State) -> ?SEV_ANNOUNCE_START(Pid), ok end}, #{desc => "await client ready (init)", cmd => fun(#{client := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, client, init) end}, %% The actual test #{desc => "order acceptor to continue (accept)", cmd => fun(#{acceptor := Pid, handler1 := H1, handler2 := H2, handler3 := H3} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, accept, {H1, H2, H3}), ok end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order client to continue (connect)", cmd => fun(#{client := Pid, server_info := Info} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, connect, Info), ok end}, #{desc => "await acceptor ready (accept)", cmd => fun(#{acceptor := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, acceptor, accept) end}, #{desc => "await client ready (connect)", cmd => fun(#{client := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, client, connect) end}, #{desc => "await handler 1 ready (transfer)", cmd => fun(#{handler1 := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, handler1, transfer) end}, #{desc => "await handler 2 ready (transfer)", cmd => fun(#{handler2 := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, handler2, transfer) end}, #{desc => "await handler 3 ready (transfer)", cmd => fun(#{handler3 := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, handler3, transfer) end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order acceptor to continue (close connection socket)", cmd => fun(#{acceptor := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, close), ok end}, #{desc => "await acceptor ready (close)", cmd => fun(#{acceptor := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, acceptor, close) end}, #{desc => "await handler 1 ready (recv closed)", cmd => fun(#{handler1 := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, handler1, recv_closed) end}, #{desc => "await handler 2 ready (recv closed)", cmd => fun(#{handler2 := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, handler2, recv_closed) end}, #{desc => "await handler 3 ready (recv closed)", cmd => fun(#{handler3 := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, handler3, recv_closed) end}, %% Terminations #{desc => "order client to terminate", cmd => fun(#{client := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await client termination", cmd => fun(#{client := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> {ok, maps:remove(client, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "order handler 1 to terminate", cmd => fun(#{handler1 := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await handler 1 termination", cmd => fun(#{handler1 := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> {ok, maps:remove(handler1, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "order handler 2 to terminate", cmd => fun(#{handler2 := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await handler 2 termination", cmd => fun(#{handler2 := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> {ok, maps:remove(handler2, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "order handler 3 to terminate", cmd => fun(#{handler3 := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await handler 3 termination", cmd => fun(#{handler3 := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> {ok, maps:remove(handler3, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "order acceptor to terminate", cmd => fun(#{acceptor := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await acceptor termination", cmd => fun(#{acceptor := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> {ok, maps:remove(acceptor, State)}; {error, _} = ERROR -> ERROR end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], i("start acceptor evaluator"), AccInitState = InitState, Acceptor = ?SEV_START("acceptor", AcceptorSeq, AccInitState), i("start handler 1 evaluator"), HandlerInitState = #{recv => maps:get(recv, InitState)}, Handler1 = ?SEV_START("handler-1", HandlerSeq, HandlerInitState), i("start handler 2 evaluator"), Handler2 = ?SEV_START("handler-2", HandlerSeq, HandlerInitState), i("start handler 3 evaluator"), Handler3 = ?SEV_START("handler-3", HandlerSeq, HandlerInitState), i("start client evaluator"), ClientInitState = InitState, Client = ?SEV_START("client", ClientSeq, ClientInitState), i("start tester evaluator"), TesterInitState = #{acceptor => Acceptor#ev.pid, handler1 => Handler1#ev.pid, handler2 => Handler2#ev.pid, handler3 => Handler3#ev.pid, client => Client#ev.pid}, Tester = ?SEV_START("tester", TesterSeq, TesterInitState), i("await evaluator"), ok = ?SEV_AWAIT_FINISH([Acceptor, Handler1, Handler2, Handler3, Client, Tester]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test what happens when a socket is %% locally closed while a process is calling the recvfrom function. %% Socket is IPv4. %% sc_lc_recvfrom_response_udp4(suite) -> []; sc_lc_recvfrom_response_udp4(doc) -> []; sc_lc_recvfrom_response_udp4(_Config) when is_list(_Config) -> ?TT(?SECS(30)), tc_try(sc_lc_recvfrom_response_udp4, fun() -> Recv = fun(Sock, To) -> socket:recvfrom(Sock, [], To) end, InitState = #{domain => inet, protocol => udp, recv => Recv}, ok = sc_lc_receive_response_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test what happens when a socket is %% locally closed while the process is calling the recv function. %% Socket is IPv6. sc_lc_recvfrom_response_udp6(suite) -> []; sc_lc_recvfrom_response_udp6(doc) -> []; sc_lc_recvfrom_response_udp6(_Config) when is_list(_Config) -> ?TT(?SECS(30)), tc_try(sc_lc_recvfrom_response_udp6, fun() -> has_support_ipv6() end, fun() -> Recv = fun(Sock, To) -> socket:recvfrom(Sock, [], To) end, InitState = #{domain => inet6, protocol => udp, recv => Recv}, ok = sc_lc_receive_response_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test what happens when a socket is %% locally closed while the process is calling the recv function. %% Socket is Unix Domainm (dgram) socket. sc_lc_recvfrom_response_udpL(suite) -> []; sc_lc_recvfrom_response_udpL(doc) -> []; sc_lc_recvfrom_response_udpL(_Config) when is_list(_Config) -> ?TT(?SECS(30)), tc_try(sc_lc_recvfrom_response_udpL, fun() -> has_support_unix_domain_socket() end, fun() -> Recv = fun(Sock, To) -> socket:recvfrom(Sock, [], To) end, InitState = #{domain => local, protocol => default, recv => Recv}, ok = sc_lc_receive_response_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% sc_lc_receive_response_udp(InitState) -> PrimServerSeq = [ %% *** Wait for start order part *** #{desc => "await start", cmd => fun(State) -> Tester = ?SEV_AWAIT_START(), {ok, State#{tester => Tester}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "local address", cmd => fun(#{domain := Domain} = State) -> LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, #{desc => "open socket", cmd => fun(#{domain := Domain, protocol := Proto} = State) -> Sock = sock_open(Domain, dgram, Proto), SA = sock_sockname(Sock), {ok, State#{sock => Sock, sa => SA}} end}, #{desc => "bind socket", cmd => fun(#{sock := Sock, local_sa := LSA}) -> case socket:bind(Sock, LSA) of {ok, _Port} -> ?SEV_IPRINT("src bound"), ok; {error, Reason} = ERROR -> ?SEV_EPRINT("src bind failed: ~p", [Reason]), ERROR end end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester, sock := Sock}) -> ?SEV_ANNOUNCE_READY(Tester, init, Sock), ok end}, %% The actual test #{desc => "await continue (recv, with timeout)", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_CONTINUE(Tester, tester, recv) of {ok, Timeout} -> {ok, State#{timeout => Timeout}}; {error, _} = ERROR -> ERROR end end}, #{desc => "receive, with timeout", cmd => fun(#{sock := Sock, recv := Recv, timeout := Timeout}) -> case Recv(Sock, Timeout) of {error, timeout} -> ok; {ok, _} -> {error, unexpected_success}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (recv, with timeout)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv), ok end}, #{desc => "await continue (close)", cmd => fun(#{tester := Tester} = _State) -> ok = ?SEV_AWAIT_CONTINUE(Tester, tester, close) end}, #{desc => "close socket", cmd => fun(#{domain := local, sock := Sock, local_sa := #{path := Path}} = State) -> ok = socket:close(Sock), State1 = unlink_path(Path, fun() -> maps:remove(local_sa, State) end, fun() -> State end), {ok, maps:remove(sock, State1)}; (#{sock := Sock} = State) -> case socket:close(Sock) of ok -> {ok, maps:remove(sock, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (close)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, close), ok end}, %% Termination #{desc => "await terminate (from tester)", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, terminate) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], SecServerSeq = [ %% *** Init part *** #{desc => "await start", cmd => fun(State) -> {Tester, Sock} = ?SEV_AWAIT_START(), {ok, State#{tester => Tester, sock => Sock}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, init), ok end}, %% The actual test #{desc => "await continue (recv)", cmd => fun(#{tester := Tester} = _State) -> ok = ?SEV_AWAIT_CONTINUE(Tester, tester, recv) end}, #{desc => "receive", cmd => fun(#{sock := Sock, recv := Recv} = State) -> case Recv(Sock, infinity) of {error, closed} -> {ok, maps:remove(sock, State)}; {ok, _} -> {error, unexpected_success}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (recv closed)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv_closed), ok end}, %% Termination #{desc => "await terminate (from tester)", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], TesterSeq = [ %% *** Init part *** #{desc => "monitor primary server", cmd => fun(#{prim_server := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "monitor secondary server 1", cmd => fun(#{sec_server1 := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "monitor secondary server 2", cmd => fun(#{sec_server2 := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "monitor secondary server 3", cmd => fun(#{sec_server3 := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, %% Start the primary server #{desc => "order 'primary server' start", cmd => fun(#{prim_server := Pid} = _State) -> ?SEV_ANNOUNCE_START(Pid), ok end}, #{desc => "await 'primary server' ready (init)", cmd => fun(#{prim_server := Pid} = State) -> {ok, Sock} = ?SEV_AWAIT_READY(Pid, prim_server, init), {ok, State#{sock => Sock}} end}, %% Start the secondary server 1 #{desc => "order 'secondary server 1' start", cmd => fun(#{sec_server1 := Pid, sock := Sock} = _State) -> ?SEV_ANNOUNCE_START(Pid, Sock), ok end}, #{desc => "await 'secondary server 1' ready (init)", cmd => fun(#{sec_server1 := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, sec_server1, init) end}, %% Start the secondary server 2 #{desc => "order 'secondary server 2' start", cmd => fun(#{sec_server2 := Pid, sock := Sock} = _State) -> ?SEV_ANNOUNCE_START(Pid, Sock), ok end}, #{desc => "await 'secondary server 2' ready (init)", cmd => fun(#{sec_server2 := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, sec_server2, init) end}, %% Start the secondary server 3 #{desc => "order 'secondary server 3' start", cmd => fun(#{sec_server3 := Pid, sock := Sock} = _State) -> ?SEV_ANNOUNCE_START(Pid, Sock), ok end}, #{desc => "await 'secondary server 3' ready (init)", cmd => fun(#{sec_server3 := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, sec_server3, init) end}, %% The actual test %% Make all the seondary servers continue, with an infinit recvfrom %% and then the prim-server with a timed recvfrom. %% After the prim server notifies us (about the timeout) we order it %% to close the socket, which should cause the all the secondary %% server to return with error-closed. #{desc => "order 'secondary server 1' to continue (recv)", cmd => fun(#{sec_server1 := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, recv), ok end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order 'secondary server 2' to continue (recv)", cmd => fun(#{sec_server2 := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, recv), ok end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order 'secondary server 3' to continue (recv)", cmd => fun(#{sec_server3 := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, recv), ok end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order 'primary server' to continue (recv, with timeout)", cmd => fun(#{prim_server := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, recv, ?SECS(5)), ok end}, #{desc => "await 'primary server' ready (recv, with timeout)", cmd => fun(#{prim_server := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, prim_server, recv) end}, #{desc => "order 'primary server' to continue (close)", cmd => fun(#{prim_server := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, close), ok end}, #{desc => "await 'primary server' ready (close)", cmd => fun(#{prim_server := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, prim_server, close) end}, #{desc => "await 'secondary server 1' ready (closed)", cmd => fun(#{sec_server1 := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, sec_server1, recv_closed) end}, #{desc => "await 'secondary server 2' ready (closed)", cmd => fun(#{sec_server2 := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, sec_server2, recv_closed) end}, #{desc => "await 'secondary server 3' ready (closed)", cmd => fun(#{sec_server3 := Pid} = _State) -> ?SEV_AWAIT_READY(Pid, sec_server3, recv_closed) end}, %% Terminations #{desc => "order 'secondary server 3' to terminate", cmd => fun(#{sec_server3 := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await 'secondary server 3' termination", cmd => fun(#{sec_server3 := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> {ok, maps:remove(sec_server3, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "order 'secondary server 2' to terminate", cmd => fun(#{sec_server2 := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await 'secondary server 2' termination", cmd => fun(#{sec_server2 := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> {ok, maps:remove(sec_server2, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "order 'secondary server 1' to terminate", cmd => fun(#{sec_server1 := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await 'secondary server 1' termination", cmd => fun(#{sec_server1 := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> {ok, maps:remove(sec_server1, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "order 'primary server' to terminate", cmd => fun(#{prim_server := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await 'primary server' termination", cmd => fun(#{prim_server := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> {ok, maps:remove(prim_server, State)}; {error, _} = ERROR -> ERROR end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], i("start 'primary server' evaluator"), PrimSrvInitState = InitState, PrimServer = ?SEV_START("prim-server", PrimServerSeq, PrimSrvInitState), i("start 'secondary server 1' evaluator"), SecSrvInitState = #{recv => maps:get(recv, InitState)}, SecServer1 = ?SEV_START("sec-server-1", SecServerSeq, SecSrvInitState), i("start 'secondary server 2' evaluator"), SecServer2 = ?SEV_START("sec-server-2", SecServerSeq, SecSrvInitState), i("start 'secondary server 3' evaluator"), SecServer3 = ?SEV_START("sec-server-3", SecServerSeq, SecSrvInitState), i("start 'tester' evaluator"), TesterInitState = #{prim_server => PrimServer#ev.pid, sec_server1 => SecServer1#ev.pid, sec_server2 => SecServer2#ev.pid, sec_server3 => SecServer3#ev.pid}, Tester = ?SEV_START("tester", TesterSeq, TesterInitState), i("await evaluator"), ok = ?SEV_AWAIT_FINISH([PrimServer, SecServer1, SecServer2, SecServer3, Tester]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test what happens when a socket is %% locally closed while the process is calling the recvmsg function. %% Socket is IPv4. sc_lc_recvmsg_response_tcp4(suite) -> []; sc_lc_recvmsg_response_tcp4(doc) -> []; sc_lc_recvmsg_response_tcp4(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(sc_lc_recvmsg_response_tcp4, fun() -> Recv = fun(Sock) -> socket:recvmsg(Sock) end, InitState = #{domain => inet, protocol => tcp, recv => Recv}, ok = sc_lc_receive_response_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test what happens when a socket is %% locally closed while the process is calling the recvmsg function. %% Socket is IPv6. sc_lc_recvmsg_response_tcp6(suite) -> []; sc_lc_recvmsg_response_tcp6(doc) -> []; sc_lc_recvmsg_response_tcp6(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(sc_recvmsg_response_tcp6, fun() -> has_support_ipv6() end, fun() -> Recv = fun(Sock) -> socket:recvmsg(Sock) end, InitState = #{domain => inet6, protocol => tcp, recv => Recv}, ok = sc_lc_receive_response_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test what happens when a socket is %% locally closed while the process is calling the recvmsg function. %% Socket is Unix Domain (stream) socket. sc_lc_recvmsg_response_tcpL(suite) -> []; sc_lc_recvmsg_response_tcpL(doc) -> []; sc_lc_recvmsg_response_tcpL(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(sc_recvmsg_response_tcpL, fun() -> has_support_unix_domain_socket() end, fun() -> Recv = fun(Sock) -> socket:recvmsg(Sock) end, InitState = #{domain => local, protocol => default, recv => Recv}, ok = sc_lc_receive_response_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test what happens when a socket is %% locally closed while the process is calling the recvmsg function. %% Socket is IPv4. sc_lc_recvmsg_response_udp4(suite) -> []; sc_lc_recvmsg_response_udp4(doc) -> []; sc_lc_recvmsg_response_udp4(_Config) when is_list(_Config) -> tc_try(sc_lc_recvmsg_response_udp4, fun() -> ?TT(?SECS(10)), Recv = fun(Sock, To) -> socket:recvmsg(Sock, To) end, InitState = #{domain => inet, protocol => udp, recv => Recv}, ok = sc_lc_receive_response_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test what happens when a socket is %% locally closed while the process is calling the recvmsg function. %% Socket is IPv6. sc_lc_recvmsg_response_udp6(suite) -> []; sc_lc_recvmsg_response_udp6(doc) -> []; sc_lc_recvmsg_response_udp6(_Config) when is_list(_Config) -> tc_try(sc_recvmsg_response_udp6, fun() -> has_support_ipv6() end, fun() -> ?TT(?SECS(10)), Recv = fun(Sock, To) -> socket:recvmsg(Sock, To) end, InitState = #{domain => inet6, protocol => udp, recv => Recv}, ok = sc_lc_receive_response_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test what happens when a socket is %% locally closed while the process is calling the recvmsg function. %% Socket is Unix Domain (dgram) socket. sc_lc_recvmsg_response_udpL(suite) -> []; sc_lc_recvmsg_response_udpL(doc) -> []; sc_lc_recvmsg_response_udpL(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(sc_recvmsg_response_udpL, fun() -> has_support_unix_domain_socket() end, fun() -> Recv = fun(Sock, To) -> socket:recvmsg(Sock, To) end, InitState = #{domain => local, protocol => default, recv => Recv}, ok = sc_lc_receive_response_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test what happens when a socket is %% locally closed while the process is calling the accept function. %% We test what happens with a non-controlling_process also, since we %% git the setup anyway. %% Socket is IPv4. sc_lc_acceptor_response_tcp4(suite) -> []; sc_lc_acceptor_response_tcp4(doc) -> []; sc_lc_acceptor_response_tcp4(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(sc_lc_acceptor_response_tcp4, fun() -> InitState = #{domain => inet, protocol => tcp}, ok = sc_lc_acceptor_response_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test what happens when a socket is %% locally closed while the process is calling the accept function. %% We test what happens with a non-controlling_process also, since we %% git the setup anyway. %% Socket is IPv6. sc_lc_acceptor_response_tcp6(suite) -> []; sc_lc_acceptor_response_tcp6(doc) -> []; sc_lc_acceptor_response_tcp6(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(sc_lc_acceptor_response_tcp6, fun() -> has_support_ipv6() end, fun() -> InitState = #{domain => inet6, protocol => tcp}, ok = sc_lc_acceptor_response_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test what happens when a socket is %% locally closed while the process is calling the accept function. %% We test what happens with a non-controlling_process also, since we %% git the setup anyway. %% Socket is Unix Domain (stream) socket. sc_lc_acceptor_response_tcpL(suite) -> []; sc_lc_acceptor_response_tcpL(doc) -> []; sc_lc_acceptor_response_tcpL(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(sc_lc_acceptor_response_tcpL, fun() -> has_support_unix_domain_socket() end, fun() -> InitState = #{domain => local, protocol => default}, ok = sc_lc_acceptor_response_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% sc_lc_acceptor_response_tcp(InitState) -> PrimAcceptorSeq = [ %% *** Wait for start order part *** #{desc => "await start (from tester)", cmd => fun(State) -> Tester = ?SEV_AWAIT_START(), {ok, State#{tester => Tester}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> LSA = which_local_socket_addr(Domain), {ok, State#{lsa => LSA}} end}, #{desc => "create (listen) socket", cmd => fun(#{domain := Domain, protocol := Proto} = State) -> case socket:open(Domain, stream, Proto) of {ok, Sock} -> {ok, State#{sock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind to local address", cmd => fun(#{sock := Sock, lsa := LSA} = _State) -> case socket:bind(Sock, LSA) of {ok, _Port} -> ok; {error, _} = ERROR -> ERROR end end}, #{desc => "make listen socket", cmd => fun(#{sock := Sock}) -> socket:listen(Sock) end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester, sock := Sock} = _State) -> ?SEV_ANNOUNCE_READY(Tester, init, Sock), ok end}, %% The actual test #{desc => "await continue (accept)", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_CONTINUE(Tester, tester, accept) of {ok, Timeout} -> {ok, State#{timeout => Timeout}}; {error, _} = ERROR -> ERROR end end}, #{desc => "await connection", cmd => fun(#{sock := LSock, timeout := Timeout} = _State) -> case socket:accept(LSock, Timeout) of {error, timeout} -> ok; {ok, Sock} -> ?SEV_EPRINT("unexpected success"), (catch socket:close(Sock)), {error, unexpected_success}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (accept timeout)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, accept_timeout), ok end}, #{desc => "await continue (close)", cmd => fun(#{tester := Tester} = _State) -> ok = ?SEV_AWAIT_CONTINUE(Tester, tester, close) end}, #{desc => "close socket", cmd => fun(#{domain := local, sock := Sock, lsa := #{path := Path}} = State) -> case socket:close(Sock) of ok -> State1 = unlink_path(Path, fun() -> maps:remove(lsa, State) end, fun() -> State end), {ok, maps:remove(sock, State1)}; {error, _} = ERROR -> unlink_path(Path), ERROR end; (#{sock := Sock} = State) -> case socket:close(Sock) of ok -> {ok, maps:remove(sock, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (close)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, close), ok end}, % Termination #{desc => "await terminate", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], SecAcceptorSeq = [ %% *** Init part *** #{desc => "await start", cmd => fun(State) -> {Tester, Sock} = ?SEV_AWAIT_START(), {ok, State#{tester => Tester, sock => Sock}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, init) end}, %% The actual test #{desc => "await continue (accept)", cmd => fun(#{tester := Tester} = _State) -> ok = ?SEV_AWAIT_CONTINUE(Tester, tester, accept) end}, #{desc => "accept", cmd => fun(#{sock := Sock} = State) -> case socket:accept(Sock) of {error, closed} -> {ok, maps:remove(sock, State)}; {ok, _} -> {error, unexpected_success}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (accept closed)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, accept_closed) end}, %% Termination #{desc => "await terminate (from tester)", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], TesterSeq = [ %% *** Init part *** #{desc => "monitor 'primary acceptor'", cmd => fun(#{prim_acc := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "monitor 'secondary acceptor 1'", cmd => fun(#{sec_acc1 := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "monitor secondary acceptor 2", cmd => fun(#{sec_acc2 := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "monitor secondary acceptor 3", cmd => fun(#{sec_acc3 := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, %% Start the primary server #{desc => "order 'primary acceptor' start", cmd => fun(#{prim_acc := Pid} = _State) -> ?SEV_ANNOUNCE_START(Pid), ok end}, #{desc => "await 'primary acceptor' ready (init)", cmd => fun(#{prim_acc := Pid} = State) -> {ok, Sock} = ?SEV_AWAIT_READY(Pid, prim_acc, init), {ok, State#{sock => Sock}} end}, %% Start the secondary acceptor 1 #{desc => "order 'secondary acceptor 1' start", cmd => fun(#{sec_acc1 := Pid, sock := Sock} = _State) -> ?SEV_ANNOUNCE_START(Pid, Sock), ok end}, #{desc => "await 'secondary acceptor 1' ready (init)", cmd => fun(#{sec_acc1 := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, sec_acc1, init) end}, %% Start the secondary acceptor 2 #{desc => "order 'secondary acceptor 2' start", cmd => fun(#{sec_acc2 := Pid, sock := Sock} = _State) -> ?SEV_ANNOUNCE_START(Pid, Sock), ok end}, #{desc => "await 'secondary acceptor 2' ready (init)", cmd => fun(#{sec_acc2 := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, sec_acc2, init) end}, %% Start the secondary acceptor 3 #{desc => "order 'secondary acceptor 3' start", cmd => fun(#{sec_acc3 := Pid, sock := Sock} = _State) -> ?SEV_ANNOUNCE_START(Pid, Sock), ok end}, #{desc => "await 'secondary acceptor 3' ready (init)", cmd => fun(#{sec_acc3 := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, sec_acc3, init) end}, %% The actual test %% Make all the seondary servers continue, with an infinit recvfrom %% and then the prim-server with a timed recvfrom. %% After the prim server notifies us (about the timeout) we order it %% to close the socket, which should cause the all the secondary %% server to return with error-closed. #{desc => "order 'secondary acceptor 1' to continue (accept)", cmd => fun(#{sec_acc1 := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, accept), ok end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order 'secondary acceptor 2' to continue (accept)", cmd => fun(#{sec_acc2 := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, accept), ok end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order 'secondary acceptor 3' to continue (accept)", cmd => fun(#{sec_acc3 := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, accept), ok end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order 'primary acceptor' to continue", cmd => fun(#{prim_acc := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, accept, ?SECS(5)), ok end}, #{desc => "await 'primary acceptor' ready (accept timeout)", cmd => fun(#{prim_acc := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, prim_acc, accept_timeout) end}, #{desc => "order 'primary acceptor' to continue (close)", cmd => fun(#{prim_acc := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, close), ok end}, #{desc => "await 'primary acceptor' ready (close)", cmd => fun(#{prim_acc := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, prim_acc, close) end}, #{desc => "await 'secondary acceptor 1' ready (accept closed)", cmd => fun(#{sec_acc1 := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, sec_acc1, accept_closed) end}, #{desc => "await 'secondary acceptor 2' ready (accept closed)", cmd => fun(#{sec_acc2 := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, sec_acc2, accept_closed) end}, #{desc => "await 'secondary acceptor 3' ready (accept closed)", cmd => fun(#{sec_acc3 := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, sec_acc3, accept_closed) end}, %% Terminations #{desc => "order 'secondary acceptor 3' to terminate", cmd => fun(#{sec_acc3 := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await 'secondary acceptor 3' termination", cmd => fun(#{sec_acc3 := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> {ok, maps:remove(sec_acc3, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "order 'secondary acceptor 2' to terminate", cmd => fun(#{sec_acc2 := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await 'secondary acceptor 2' termination", cmd => fun(#{sec_acc2 := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> {ok, maps:remove(sec_acc2, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "order 'secondary acceptor 1' to terminate", cmd => fun(#{sec_acc1 := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await 'secondary acceptor 1' termination", cmd => fun(#{sec_acc1 := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> {ok, maps:remove(sec_acc1, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "order 'primary acceptor' to terminate", cmd => fun(#{prim_acc := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await 'primary acceptor' termination", cmd => fun(#{prim_acc := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> {ok, maps:remove(prim_acc, State)}; {error, _} = ERROR -> ERROR end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], i("start 'primary acceptor' evaluator"), PrimAccInitState = InitState, PrimAcc = ?SEV_START("prim-acceptor", PrimAcceptorSeq, PrimAccInitState), i("start 'secondary acceptor 1' evaluator"), SecAccInitState = #{}, SecAcc1 = ?SEV_START("sec-acceptor-1", SecAcceptorSeq, SecAccInitState), i("start 'secondary acceptor 2' evaluator"), SecAcc2 = ?SEV_START("sec-acceptor-2", SecAcceptorSeq, SecAccInitState), i("start 'secondary acceptor 3' evaluator"), SecAcc3 = ?SEV_START("sec-acceptor-3", SecAcceptorSeq, SecAccInitState), i("start 'tester' evaluator"), TesterInitState = #{prim_acc => PrimAcc#ev.pid, sec_acc1 => SecAcc1#ev.pid, sec_acc2 => SecAcc2#ev.pid, sec_acc3 => SecAcc3#ev.pid}, Tester = ?SEV_START("tester", TesterSeq, TesterInitState), i("await evaluator"), ok = ?SEV_AWAIT_FINISH([PrimAcc, SecAcc1, SecAcc2, SecAcc3, Tester]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test what happens when a socket is %% remotely closed while the process is calling the recv function. %% Socket is IPv4. %% %% To minimize the chance of "weirdness", we should really have test cases %% where the two sides of the connection is on different machines. But for %% now, we will make do with different VMs on the same host. %% sc_rc_recv_response_tcp4(suite) -> []; sc_rc_recv_response_tcp4(doc) -> []; sc_rc_recv_response_tcp4(_Config) when is_list(_Config) -> ?TT(?SECS(30)), tc_try(sc_rc_recv_response_tcp4, fun() -> Recv = fun(Sock) -> socket:recv(Sock) end, InitState = #{domain => inet, protocol => tcp, recv => Recv}, ok = sc_rc_receive_response_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test what happens when a socket is %% remotely closed while the process is calling the recv function. %% Socket is IPv6. sc_rc_recv_response_tcp6(suite) -> []; sc_rc_recv_response_tcp6(doc) -> []; sc_rc_recv_response_tcp6(_Config) when is_list(_Config) -> ?TT(?SECS(30)), tc_try(sc_rc_recv_response_tcp6, fun() -> has_support_ipv6() end, fun() -> Recv = fun(Sock) -> socket:recv(Sock) end, InitState = #{domain => inet6, protocol => tcp, recv => Recv}, ok = sc_rc_receive_response_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test what happens when a socket is %% remotely closed while the process is calling the recv function. %% Socket is Unix Domain (stream) socket. sc_rc_recv_response_tcpL(suite) -> []; sc_rc_recv_response_tcpL(doc) -> []; sc_rc_recv_response_tcpL(_Config) when is_list(_Config) -> ?TT(?SECS(30)), tc_try(sc_rc_recv_response_tcpL, fun() -> has_support_unix_domain_socket() end, fun() -> Recv = fun(Sock) -> socket:recv(Sock) end, InitState = #{domain => local, protocol => default, recv => Recv}, ok = sc_rc_receive_response_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% sc_rc_receive_response_tcp(InitState) -> %% Each connection are handled by handler processes. %% These are created (on the fly) and handled internally %% by the server! ServerSeq = [ %% *** Wait for start order part *** #{desc => "await start", cmd => fun(State) -> Tester = ?SEV_AWAIT_START(), {ok, State#{tester => Tester}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, #{desc => "create listen socket", cmd => fun(#{domain := Domain, protocol := Proto} = State) -> case socket:open(Domain, stream, Proto) of {ok, Sock} -> {ok, State#{lsock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind to local address", cmd => fun(#{domain := local, lsock := LSock, lsa := LSA} = _State) -> case socket:bind(LSock, LSA) of {ok, _Port} -> ok; % We do not care about the port for local {error, _} = ERROR -> ERROR end; (#{lsock := LSock, local_sa := LSA} = State) -> case socket:bind(LSock, LSA) of {ok, Port} -> {ok, State#{lport => Port}}; {error, _} = ERROR -> ERROR end end}, #{desc => "make listen socket", cmd => fun(#{lsock := LSock}) -> socket:listen(LSock) end}, #{desc => "announce ready (init)", cmd => fun(#{domain := local, tester := Tester, local_sa := LSA}) -> %% Actually we only need to send the path, %% but to keep it simple, we send the "same" %% as for non-local. ?SEV_ANNOUNCE_READY(Tester, init, LSA), ok; (#{tester := Tester, local_sa := LSA, lport := Port}) -> ServerSA = LSA#{port => Port}, ?SEV_ANNOUNCE_READY(Tester, init, ServerSA), ok end}, %% The actual test #{desc => "await continue (accept all three connections)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Tester, tester, accept) end}, #{desc => "accept 1", cmd => fun(#{lsock := LSock, recv := Recv} = State) -> case socket:accept(LSock) of {ok, Sock} -> ?SEV_IPRINT("accepted: try start handler"), Handler = sc_rc_tcp_handler_start(1, Recv, Sock), ?SEV_IPRINT("handler started"), {ok, State#{csock1 => Sock, handler1 => Handler}}; {error, _} = ERROR -> ERROR end end}, #{desc => "await handler 1 ready (init)", cmd => fun(#{tester := Tester, handler1 := Handler1} = _State) -> ?SEV_AWAIT_READY(Handler1, handler1, init, [{tester, Tester}]) end}, #{desc => "accept 2", cmd => fun(#{lsock := LSock, recv := Recv} = State) -> case socket:accept(LSock) of {ok, Sock} -> ?SEV_IPRINT("accepted: try start handler"), Handler = sc_rc_tcp_handler_start(2, Recv, Sock), ?SEV_IPRINT("handler started"), {ok, State#{csock2 => Sock, handler2 => Handler}}; {error, _} = ERROR -> ERROR end end}, #{desc => "await handler 2 ready (init)", cmd => fun(#{tester := Tester, handler1 := Handler1, handler2 := Handler2} = _State) -> ?SEV_AWAIT_READY(Handler2, handler2, init, [{tester, Tester}, {handler1, Handler1}]) end}, #{desc => "accept 3", cmd => fun(#{lsock := LSock, recv := Recv} = State) -> case socket:accept(LSock) of {ok, Sock} -> ?SEV_IPRINT("accepted: try start handler"), Handler = sc_rc_tcp_handler_start(3, Recv, Sock), ?SEV_IPRINT("handler started"), {ok, State#{csock3 => Sock, handler3 => Handler}}; {error, _} = ERROR -> ERROR end end}, #{desc => "await handler 3 ready (init)", cmd => fun(#{tester := Tester, handler1 := Handler1, handler2 := Handler2, handler3 := Handler3} = _State) -> ?SEV_AWAIT_READY(Handler3, handler3, init, [{tester, Tester}, {handler1, Handler1}, {handler2, Handler2}]) end}, #{desc => "announce ready (accept all three connections)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, accept), ok end}, #{desc => "await continue (recv)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, recv) end}, #{desc => "order handler 1 to receive", cmd => fun(#{handler1 := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, recv), ok end}, #{desc => "order handler 2 to receive", cmd => fun(#{handler2 := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, recv), ok end}, #{desc => "order handler 3 to receive", cmd => fun(#{handler3 := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, recv), ok end}, #{desc => "await ready from handler 1 (recv)", cmd => fun(#{tester := Tester, handler1 := Pid} = _State) -> case ?SEV_AWAIT_READY(Pid, handler1, recv, [{tester, Tester}]) of {ok, Result} -> Result; {error, _} = ERROR -> ERROR end end}, #{desc => "await ready from handler 2 (recv)", cmd => fun(#{tester := Tester, handler2 := Pid} = _State) -> case ?SEV_AWAIT_READY(Pid, handler2, recv, [{tester, Tester}]) of {ok, Result} -> Result; {error, _} = ERROR -> ERROR end end}, #{desc => "await ready from handler 3 (recv)", cmd => fun(#{tester := Tester, handler3 := Pid} = _State) -> case ?SEV_AWAIT_READY(Pid, handler3, recv, [{tester, Tester}]) of {ok, Result} -> Result; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (recv closed from all handlers)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv_closed), ok end}, %% Termination #{desc => "await terminate (from tester)", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "order handler 1 to terminate", cmd => fun(#{handler1 := Pid} = _State) -> %% Pid ! {terminate, self(), ok}, ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await handler 1 termination", cmd => fun(#{handler1 := Pid} = State) -> ?SEV_AWAIT_TERMINATION(Pid), State1 = maps:remove(csock1, State), State2 = maps:remove(handler1, State1), {ok, State2} end}, #{desc => "order handler 2 to terminate", cmd => fun(#{handler2 := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await handler 2 termination", cmd => fun(#{handler2 := Pid} = State) -> ?SEV_AWAIT_TERMINATION(Pid), State1 = maps:remove(csock2, State), State2 = maps:remove(handler2, State1), {ok, State2} end}, #{desc => "order handler 3 to terminate", cmd => fun(#{handler3 := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await handler 3 termination", cmd => fun(#{handler3 := Pid} = State) -> ?SEV_AWAIT_TERMINATION(Pid), State1 = maps:remove(csock3, State), State2 = maps:remove(handler3, State1), {ok, State2} end}, #{desc => "close listen socket", cmd => fun(#{domain := local, lsock := LSock, lsa := #{path := Path}} = State) -> case socket:close(LSock) of ok -> State1 = unlink_path(Path, fun() -> maps:remove(lsa, State) end, fun() -> State end), {ok, maps:remove(lsock, State1)}; {error, _} = ERROR -> unlink_path(Path), ERROR end; (#{lsock := LSock} = State) -> case socket:close(LSock) of ok -> {ok, maps:remove(lsock, State)}; {error, _} = ERROR -> ERROR end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], ClientSeq = [ %% *** Wait for start order part *** #{desc => "await start", cmd => fun(State) -> {Tester, {NodeID, ServerSA}} = ?SEV_AWAIT_START(), {ok, State#{tester => Tester, node_id => NodeID, server_sa => ServerSA}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "create node", cmd => fun(#{host := Host, node_id := NodeID} = State) -> case start_node(Host, l2a(f("client_~w", [NodeID]))) of {ok, Node} -> ?SEV_IPRINT("client node ~p started", [Node]), {ok, State#{node => Node}}; {error, Reason} -> {skip, Reason} end end}, #{desc => "monitor client node 1", cmd => fun(#{node := Node} = _State) -> true = erlang:monitor_node(Node, true), ok end}, #{desc => "start remote client on client node", cmd => fun(#{node := Node} = State) -> Pid = sc_rc_tcp_client_start(Node), ?SEV_IPRINT("client ~p started", [Pid]), {ok, State#{rclient => Pid}} end}, #{desc => "monitor remote client", cmd => fun(#{rclient := Pid}) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "order remote client to start", cmd => fun(#{rclient := Client, server_sa := ServerSA, protocol := Proto}) -> ?SEV_ANNOUNCE_START(Client, {ServerSA, Proto}), ok end}, #{desc => "await remote client ready", cmd => fun(#{tester := Tester, rclient := Client} = _State) -> ?SEV_AWAIT_READY(Client, rclient, init, [{tester, Tester}]) end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, init), ok end}, %% The actual test #{desc => "await continue (connect)", cmd => fun(#{tester := Tester, rclient := Client} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, connect, [{rclient, Client}]), ok end}, #{desc => "order remote client to continue (connect)", cmd => fun(#{rclient := Client}) -> ?SEV_ANNOUNCE_CONTINUE(Client, connect), ok end}, #{desc => "await client process ready (connect)", cmd => fun(#{tester := Tester, rclient := Client} = _State) -> ?SEV_AWAIT_READY(Client, rclient, connect, [{tester, Tester}]) end}, #{desc => "announce ready (connected)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, connect), ok end}, #{desc => "await continue (close)", cmd => fun(#{tester := Tester, rclient := Client} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, close, [{rclient, Client}]), ok end}, #{desc => "order remote client to close", cmd => fun(#{rclient := Client}) -> ?SEV_ANNOUNCE_CONTINUE(Client, close), ok end}, #{desc => "await remote client ready (closed)", cmd => fun(#{tester := Tester, rclient := Client} = _State) -> ?SEV_AWAIT_READY(Client, rclient, close, [{tester, Tester}]) end}, #{desc => "announce ready (close)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, close), ok end}, %% Termination #{desc => "await terminate (from tester)", cmd => fun(#{tester := Tester, rclient := Client} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester, [{rclient, Client}]) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "kill remote client", cmd => fun(#{rclient := Client}) -> ?SEV_ANNOUNCE_TERMINATE(Client), ok end}, #{desc => "await remote client termination", cmd => fun(#{rclient := Client} = State) -> ?SEV_AWAIT_TERMINATION(Client), State1 = maps:remove(rclient, State), {ok, State1} end}, #{desc => "stop client node", cmd => fun(#{node := Node} = _State) -> stop_node(Node) end}, #{desc => "await client node termination", cmd => fun(#{node := Node} = State) -> receive {nodedown, Node} -> State1 = maps:remove(node_id, State), State2 = maps:remove(node, State1), {ok, State2} end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], TesterSeq = [ %% *** Init part *** #{desc => "monitor server", cmd => fun(#{server := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "monitor client 1", cmd => fun(#{client1 := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "monitor client 2", cmd => fun(#{client2 := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "monitor client 3", cmd => fun(#{client3 := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, %% Start the server #{desc => "order server start", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_START(Pid), ok end}, #{desc => "await server ready (init)", cmd => fun(#{server := Pid} = State) -> {ok, ServerSA} = ?SEV_AWAIT_READY(Pid, server, init), {ok, State#{server_sa => ServerSA}} end}, %% Start the client(s) #{desc => "order client 1 start", cmd => fun(#{client1 := Pid, server_sa := ServerSA} = _State) -> ?SEV_ANNOUNCE_START(Pid, {1, ServerSA}), ok end}, #{desc => "await client 1 ready (init)", cmd => fun(#{client1 := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, client1, init) end}, #{desc => "order client 2 start", cmd => fun(#{client2 := Pid, server_sa := ServerSA} = _State) -> ?SEV_ANNOUNCE_START(Pid, {2, ServerSA}), ok end}, #{desc => "await client 2 ready (init)", cmd => fun(#{client2 := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, client2, init) end}, #{desc => "order client 3 start", cmd => fun(#{client3 := Pid, server_sa := ServerSA} = _State) -> ?SEV_ANNOUNCE_START(Pid, {3, ServerSA}), ok end}, #{desc => "await client 3 ready (init)", cmd => fun(#{client3 := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, client3, init) end}, %% The actual test #{desc => "order server continue (accept)", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, accept), ok end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order client 1 continue (connect)", cmd => fun(#{client1 := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, connect), ok end}, #{desc => "await client 1 ready (connect)", cmd => fun(#{server := Server, client1 := Client1, client2 := Client2, client3 := Client3} = _State) -> ?SEV_AWAIT_READY(Client1, client1, connect, [{server, Server}, {client2, Client2}, {client3, Client3}]), ok end}, #{desc => "order client 2 continue (connect)", cmd => fun(#{client2 := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, connect), ok end}, #{desc => "await client 2 ready (connect)", cmd => fun(#{server := Server, client1 := Client1, client2 := Client2, client3 := Client3} = _State) -> ?SEV_AWAIT_READY(Client2, client2, connect, [{server, Server}, {client1, Client1}, {client3, Client3}]), ok end}, #{desc => "order client 3 continue (connect)", cmd => fun(#{client3 := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, connect), ok end}, #{desc => "await client 3 ready (connect)", cmd => fun(#{server := Server, client1 := Client1, client2 := Client2, client3 := Client3} = _State) -> ?SEV_AWAIT_READY(Client3, client3, connect, [{server, Server}, {client1, Client1}, {client2, Client2}]), ok end}, #{desc => "await server ready (accept from all connections)", cmd => fun(#{server := Server, client1 := Client1, client2 := Client2, client3 := Client3} = _State) -> ?SEV_AWAIT_READY(Server, server, accept, [{client1, Client1}, {client2, Client2}, {client3, Client3}]), ok end}, #{desc => "order server continue (recv for all connections)", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, recv), ok end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order client 1 continue (close)", cmd => fun(#{client1 := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, close), ok end}, #{desc => "await client 1 ready (close)", cmd => fun(#{server := Server, client1 := Client1, client2 := Client2, client3 := Client3} = _State) -> ?SEV_AWAIT_READY(Client1, client1, close, [{server, Server}, {client2, Client2}, {client3, Client3}]), ok end}, #{desc => "order client 2 continue (close)", cmd => fun(#{client2 := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, close), ok end}, #{desc => "await client 2 ready (close)", cmd => fun(#{server := Server, client1 := Client1, client2 := Client2, client3 := Client3} = _State) -> ?SEV_AWAIT_READY(Client2, client2, close, [{server, Server}, {client1, Client1}, {client3, Client3}]), ok end}, #{desc => "order client 3 continue (close)", cmd => fun(#{client3 := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, close), ok end}, #{desc => "await client 3 ready (close)", cmd => fun(#{server := Server, client1 := Client1, client2 := Client2, client3 := Client3} = _State) -> ?SEV_AWAIT_READY(Client3, client1, close, [{server, Server}, {client1, Client1}, {client2, Client2}]), ok end}, #{desc => "await server ready (close for all connections)", cmd => fun(#{server := Server, client1 := Client1, client2 := Client2, client3 := Client3} = _State) -> ?SEV_AWAIT_READY(Server, server, recv_closed, [{client1, Client1}, {client2, Client2}, {client3, Client3}]), ok end}, %% Terminations #{desc => "order client 1 to terminate", cmd => fun(#{client1 := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await client 1 termination", cmd => fun(#{client1 := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> State1 = maps:remove(client1, State), {ok, State1}; {error, _} = ERROR -> ERROR end end}, #{desc => "order client 2 to terminate", cmd => fun(#{client2 := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await client 2 termination", cmd => fun(#{client2 := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> State1 = maps:remove(client2, State), {ok, State1}; {error, _} = ERROR -> ERROR end end}, #{desc => "order client 3 to terminate", cmd => fun(#{client3 := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await client 3 termination", cmd => fun(#{client3 := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> State1 = maps:remove(client3, State), {ok, State1}; {error, _} = ERROR -> ERROR end end}, #{desc => "order server to terminate", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await server termination", cmd => fun(#{server := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> State1 = maps:remove(server, State), {ok, State1}; {error, _} = ERROR -> ERROR end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], i("start server evaluator"), ServerInitState = InitState, Server = ?SEV_START("server", ServerSeq, ServerInitState), i("start client evaluator(s)"), ClientInitState = InitState#{host => local_host()}, Client1 = ?SEV_START("client-1", ClientSeq, ClientInitState), Client2 = ?SEV_START("client-2", ClientSeq, ClientInitState), Client3 = ?SEV_START("client-3", ClientSeq, ClientInitState), i("start 'tester' evaluator"), TesterInitState = #{server => Server#ev.pid, client1 => Client1#ev.pid, client2 => Client2#ev.pid, client3 => Client3#ev.pid}, Tester = ?SEV_START("tester", TesterSeq, TesterInitState), i("await evaluator"), ok = ?SEV_AWAIT_FINISH([Server, Client1, Client2, Client3, Tester]). sc_rc_tcp_client_start(Node) -> Self = self(), Fun = fun() -> sc_rc_tcp_client(Self) end, erlang:spawn(Node, Fun). sc_rc_tcp_client(Parent) -> sc_rc_tcp_client_init(Parent), {ServerSA, Proto} = sc_rc_tcp_client_await_start(Parent), Domain = maps:get(family, ServerSA), Sock = sc_rc_tcp_client_create(Domain, Proto), Path = sc_rc_tcp_client_bind(Sock, Domain), sc_rc_tcp_client_announce_ready(Parent, init), sc_rc_tcp_client_await_continue(Parent, connect), sc_rc_tcp_client_connect(Sock, ServerSA), sc_rc_tcp_client_announce_ready(Parent, connect), sc_rc_tcp_client_await_continue(Parent, close), sc_rc_tcp_client_close(Sock, Path), sc_rc_tcp_client_announce_ready(Parent, close), Reason = sc_rc_tcp_client_await_terminate(Parent), ?SEV_IPRINT("terminate"), exit(Reason). sc_rc_tcp_client_init(Parent) -> put(sname, "rclient"), ?SEV_IPRINT("init"), _MRef = erlang:monitor(process, Parent), ok. sc_rc_tcp_client_await_start(Parent) -> i("sc_rc_tcp_client_await_start -> entry"), ?SEV_AWAIT_START(Parent). sc_rc_tcp_client_create(Domain, Proto) -> i("sc_rc_tcp_client_create -> entry"), case socket:open(Domain, stream, Proto) of {ok, Sock} -> case socket:getopt(Sock, otp, fd) of {ok, FD} -> put(sname, f("rclient-~w", [FD])); % Update SName _ -> ok end, Sock; {error, Reason} -> exit({open_failed, Reason}) end. sc_rc_tcp_client_bind(Sock, Domain) -> i("sc_rc_tcp_client_bind -> entry"), LSA = which_local_socket_addr(Domain), case socket:bind(Sock, LSA) of {ok, _} -> case socket:sockname(Sock) of {ok, #{family := local, path := Path}} -> Path; {ok, _} -> undefined; {error, Reason1} -> exit({sockname, Reason1}) end; {error, Reason} -> exit({bind, Reason}) end. sc_rc_tcp_client_announce_ready(Parent, Slogan) -> ?SEV_IPRINT("ready ~w", [Slogan]), ?SEV_ANNOUNCE_READY(Parent, Slogan). sc_rc_tcp_client_await_continue(Parent, Slogan) -> ?SEV_IPRINT("await ~w continue", [Slogan]), ?SEV_AWAIT_CONTINUE(Parent, parent, Slogan). sc_rc_tcp_client_connect(Sock, ServerSA) -> i("sc_rc_tcp_client_connect -> entry"), case socket:connect(Sock, ServerSA) of ok -> ok; {error, Reason} -> exit({connect, Reason}) end. sc_rc_tcp_client_close(Sock, Path) -> i("sc_rc_tcp_client_close -> entry"), case socket:close(Sock) of ok -> unlink_path(Path), ok; {error, Reason} -> ?SEV_EPRINT("failed closing: " "~n Reason: ~p", [Reason]), unlink_path(Path), {error, {close, Reason}} end. sc_rc_tcp_client_await_terminate(Parent) -> i("sc_rc_tcp_client_await_terminate -> entry"), case ?SEV_AWAIT_TERMINATE(Parent, parent) of ok -> ok; {error, Reason} -> Reason end. %% The handlers run on the same node as the server (the local node). sc_rc_tcp_handler_start(ID, Recv, Sock) -> Self = self(), Fun = fun() -> sc_rc_tcp_handler(ID, Self, Recv, Sock) end, {Pid, _} = erlang:spawn_monitor(Fun), Pid. sc_rc_tcp_handler(ID, Parent, Recv, Sock) -> sc_rc_tcp_handler_init(ID, socket:getopt(Sock, otp, fd), Parent), sc_rc_tcp_handler_await(Parent, recv), RecvRes = sc_rc_tcp_handler_recv(Recv, Sock), sc_rc_tcp_handler_announce_ready(Parent, recv, RecvRes), Reason = sc_rc_tcp_handler_await(Parent, terminate), exit(Reason). sc_rc_tcp_handler_init(ID, {ok, FD}, Parent) -> put(sname, f("handler-~w:~w", [ID, FD])), _MRef = erlang:monitor(process, Parent), ?SEV_IPRINT("started"), ?SEV_ANNOUNCE_READY(Parent, init), ok. sc_rc_tcp_handler_await(Parent, terminate) -> ?SEV_IPRINT("await terminate"), ?SEV_AWAIT_TERMINATE(Parent, tester); sc_rc_tcp_handler_await(Parent, Slogan) -> ?SEV_IPRINT("await ~w", [Slogan]), ?SEV_AWAIT_CONTINUE(Parent, parent, Slogan). sc_rc_tcp_handler_recv(Recv, Sock) -> ?SEV_IPRINT("recv"), try Recv(Sock) of {error, closed} -> ok; {ok, _} -> ?SEV_IPRINT("unexpected success"), {error, unexpected_success}; {error, Reason} = ERROR -> ?SEV_IPRINT("receive error: " "~n ~p", [Reason]), ERROR catch C:E:S -> ?SEV_IPRINT("receive failure: " "~n Class: ~p" "~n Error: ~p" "~n Stack: ~p", [C, E, S]), {error, {recv, C, E, S}} end. sc_rc_tcp_handler_announce_ready(Parent, Slogan, Result) -> ?SEV_IPRINT("announce ready"), ?SEV_ANNOUNCE_READY(Parent, Slogan, Result), ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test what happens when a socket is %% remotely closed while the process is calling the recvmsg function. %% Socket is IPv4. sc_rc_recvmsg_response_tcp4(suite) -> []; sc_rc_recvmsg_response_tcp4(doc) -> []; sc_rc_recvmsg_response_tcp4(_Config) when is_list(_Config) -> ?TT(?SECS(30)), tc_try(sc_rc_recvmsg_response_tcp4, fun() -> Recv = fun(Sock) -> socket:recvmsg(Sock) end, InitState = #{domain => inet, protocol => tcp, recv => Recv}, ok = sc_rc_receive_response_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test what happens when a socket is %% remotely closed while the process is calling the recvmsg function. %% Socket is IPv6. sc_rc_recvmsg_response_tcp6(suite) -> []; sc_rc_recvmsg_response_tcp6(doc) -> []; sc_rc_recvmsg_response_tcp6(_Config) when is_list(_Config) -> ?TT(?SECS(30)), tc_try(sc_rc_recvmsg_response_tcp6, fun() -> has_support_ipv6() end, fun() -> Recv = fun(Sock) -> socket:recvmsg(Sock) end, InitState = #{domain => inet6, protocol => tcp, recv => Recv}, ok = sc_rc_receive_response_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test what happens when a socket is %% remotely closed while the process is calling the recvmsg function. %% Socket is Unix Domain (stream) socket. sc_rc_recvmsg_response_tcpL(suite) -> []; sc_rc_recvmsg_response_tcpL(doc) -> []; sc_rc_recvmsg_response_tcpL(_Config) when is_list(_Config) -> ?TT(?SECS(30)), tc_try(sc_rc_recvmsg_response_tcpL, fun() -> has_support_unix_domain_socket() end, fun() -> Recv = fun(Sock) -> socket:recvmsg(Sock) end, InitState = #{domain => local, protocol => default, recv => Recv}, ok = sc_rc_receive_response_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test what happens when a socket is %% remotely closed while the process is calling the recv function. %% The remote client sends data, then shutdown(write) and then the %% reader attempts a recv. %% Socket is IPv4. %% %% To minimize the chance of "weirdness", we should really have test cases %% where the two sides of the connection is on different machines. But for %% now, we will make do with different VMs on the same host. %% This would of course not work for Unix Domain sockets. %% sc_rs_recv_send_shutdown_receive_tcp4(suite) -> []; sc_rs_recv_send_shutdown_receive_tcp4(doc) -> []; sc_rs_recv_send_shutdown_receive_tcp4(_Config) when is_list(_Config) -> ?TT(?SECS(30)), tc_try(sc_rs_recv_send_shutdown_receive_tcp4, fun() -> MsgData = ?DATA, Recv = fun(Sock) -> socket:recv(Sock) end, Send = fun(Sock, Data) -> socket:send(Sock, Data) end, InitState = #{domain => inet, proto => tcp, recv => Recv, send => Send, data => MsgData}, ok = sc_rs_send_shutdown_receive_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test what happens when a socket is %% remotely closed while the process is calling the recv function. %% The remote client sends data, then shutdown(write) and then the %% reader attempts a recv. %% Socket is IPv6. sc_rs_recv_send_shutdown_receive_tcp6(suite) -> []; sc_rs_recv_send_shutdown_receive_tcp6(doc) -> []; sc_rs_recv_send_shutdown_receive_tcp6(_Config) when is_list(_Config) -> tc_try(sc_rs_recv_send_shutdown_receive_tcp6, fun() -> has_support_ipv6() end, fun() -> ?TT(?SECS(10)), MsgData = ?DATA, Recv = fun(Sock) -> socket:recv(Sock) end, Send = fun(Sock, Data) -> socket:send(Sock, Data) end, InitState = #{domain => inet6, proto => tcp, recv => Recv, send => Send, data => MsgData}, ok = sc_rs_send_shutdown_receive_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test what happens when a socket is %% remotely closed while the process is calling the recv function. %% The remote client sends data, then shutdown(write) and then the %% reader attempts a recv. %% Socket is Unix Domain (stream) socket. sc_rs_recv_send_shutdown_receive_tcpL(suite) -> []; sc_rs_recv_send_shutdown_receive_tcpL(doc) -> []; sc_rs_recv_send_shutdown_receive_tcpL(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(sc_rs_recv_send_shutdown_receive_tcpL, fun() -> has_support_unix_domain_socket() end, fun() -> MsgData = ?DATA, Recv = fun(Sock) -> socket:recv(Sock) end, Send = fun(Sock, Data) -> socket:send(Sock, Data) end, InitState = #{domain => local, proto => default, recv => Recv, send => Send, data => MsgData}, ok = sc_rs_send_shutdown_receive_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% sc_rs_send_shutdown_receive_tcp(InitState) -> %% The connection is handled by a handler processes. %% This are created (on the fly) and handled internally %% by the server! ServerSeq = [ %% *** Wait for start order part *** #{desc => "await start", cmd => fun(State) -> Tester = ?SEV_AWAIT_START(), {ok, State#{tester => Tester}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> i("get local address for ~p", [Domain]), LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, #{desc => "create listen socket", cmd => fun(#{domain := Domain, proto := Proto} = State) -> case socket:open(Domain, stream, Proto) of {ok, Sock} -> {ok, State#{lsock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind to local address", cmd => fun(#{domain := local, lsock := LSock, local_sa := LSA} = _State) -> case socket:bind(LSock, LSA) of {ok, _Port} -> ok; % We do not care about the port for local {error, _} = ERROR -> ERROR end; (#{lsock := LSock, local_sa := LSA} = State) -> case socket:bind(LSock, LSA) of {ok, Port} -> ?SEV_IPRINT("bound to port: ~w", [Port]), {ok, State#{lport => Port}}; {error, _} = ERROR -> ERROR end end}, #{desc => "make listen socket", cmd => fun(#{lsock := LSock}) -> socket:listen(LSock) end}, #{desc => "announce ready (init)", cmd => fun(#{domain := local, tester := Tester, local_sa := LSA}) -> ?SEV_ANNOUNCE_READY(Tester, init, LSA), ok; (#{tester := Tester, local_sa := LSA, lport := Port}) -> ServerSA = LSA#{port => Port}, ?SEV_ANNOUNCE_READY(Tester, init, ServerSA), ok end}, %% The actual test #{desc => "await continue (accept)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Tester, tester, accept) end}, #{desc => "accept", cmd => fun(#{lsock := LSock, recv := Recv} = State) -> case socket:accept(LSock) of {ok, Sock} -> ?SEV_IPRINT("accepted: try start handler"), Handler = sc_rs_tcp_handler_start(Recv, Sock), ?SEV_IPRINT("handler started"), {ok, State#{csock => Sock, handler => Handler}}; {error, _} = ERROR -> ERROR end end}, #{desc => "await handler ready (init)", cmd => fun(#{tester := Tester, handler := Handler} = _State) -> ?SEV_AWAIT_READY(Handler, handler, init, [{tester, Tester}]) end}, #{desc => "announce ready (accept)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, accept), ok end}, #{desc => "await continue (first recv)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, recv) end}, #{desc => "order handler to receive (first)", cmd => fun(#{handler := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, recv), ok end}, #{desc => "await ready from handler (first recv)", cmd => fun(#{tester := Tester, handler := Pid} = _State) -> case ?SEV_AWAIT_READY(Pid, handler, recv, [{tester, Tester}]) of {ok, Result} -> ?SEV_IPRINT("first recv: ~p", [Result]), ok; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (first recv)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv), ok end}, #{desc => "await continue (second recv)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, recv) end}, #{desc => "order handler to receive (second)", cmd => fun(#{handler := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, recv), ok end}, #{desc => "await ready from handler (second recv)", cmd => fun(#{tester := Tester, handler := Pid} = _State) -> case ?SEV_AWAIT_READY(Pid, handler, recv, [{tester, Tester}]) of {ok, Result} -> ?SEV_IPRINT("second recv: ~p", [Result]), ok; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (second recv)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv), ok end}, %% Termination #{desc => "await terminate (from tester)", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "order handler to terminate", cmd => fun(#{handler := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await handler termination", cmd => fun(#{handler := Pid} = State) -> ?SEV_AWAIT_TERMINATION(Pid), State1 = maps:remove(csock, State), State2 = maps:remove(handler, State1), {ok, State2} end}, #{desc => "close listen socket", cmd => fun(#{domain := local, lsock := Sock, local_sa := #{path := Path}} = State) -> socket:close(Sock), State1 = unlink_path(Path, fun() -> maps:remove(local_sa, State) end, fun() -> State end), {ok, maps:remove(lsock, State1)}; (#{lsock := LSock} = State) -> case socket:close(LSock) of ok -> {ok, maps:remove(lsock, State)}; {error, _} = ERROR -> ERROR end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], ClientSeq = [ %% *** Wait for start order part *** #{desc => "await start", cmd => fun(State) -> {Tester, ServerSA} = ?SEV_AWAIT_START(), {ok, State#{tester => Tester, server_sa => ServerSA}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "create node", cmd => fun(#{host := Host} = State) -> case start_node(Host, client) of {ok, Node} -> ?SEV_IPRINT("client node ~p started", [Node]), {ok, State#{node => Node}}; {error, Reason} -> {skip, Reason} end end}, #{desc => "monitor client node", cmd => fun(#{node := Node} = _State) -> true = erlang:monitor_node(Node, true), ok end}, #{desc => "start remote client on client node", cmd => fun(#{node := Node, send := Send} = State) -> Pid = sc_rs_tcp_client_start(Node, Send), ?SEV_IPRINT("client ~p started", [Pid]), {ok, State#{rclient => Pid}} end}, #{desc => "monitor remote client", cmd => fun(#{rclient := Pid}) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "order remote client to start", cmd => fun(#{rclient := Client, proto := Proto, server_sa := ServerSA}) -> ?SEV_ANNOUNCE_START(Client, {ServerSA, Proto}), ok end}, #{desc => "await remote client ready", cmd => fun(#{tester := Tester, rclient := Client} = _State) -> ?SEV_AWAIT_READY(Client, rclient, init, [{tester, Tester}]) end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, init), ok end}, %% The actual test #{desc => "await continue (connect)", cmd => fun(#{tester := Tester, rclient := Client} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, connect, [{rclient, Client}]), ok end}, #{desc => "order remote client to continue (connect)", cmd => fun(#{rclient := Client}) -> ?SEV_ANNOUNCE_CONTINUE(Client, connect), ok end}, #{desc => "await client process ready (connect)", cmd => fun(#{tester := Tester, rclient := Client} = _State) -> ?SEV_AWAIT_READY(Client, rclient, connect, [{tester, Tester}]) end}, #{desc => "announce ready (connect)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, connect), ok end}, #{desc => "await continue (send)", cmd => fun(#{tester := Tester, rclient := Client} = State) -> case ?SEV_AWAIT_CONTINUE(Tester, tester, send, [{rclient, Client}]) of {ok, Data} -> {ok, State#{rclient_data => Data}}; {error, _} = ERROR -> ERROR end end}, #{desc => "order remote client to send", cmd => fun(#{rclient := Client, rclient_data := Data}) -> ?SEV_ANNOUNCE_CONTINUE(Client, send, Data), ok end}, #{desc => "await remote client ready (closed)", cmd => fun(#{tester := Tester, rclient := Client} = _State) -> ?SEV_AWAIT_READY(Client, rclient, send, [{tester, Tester}]) end}, #{desc => "announce ready (send)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, send), ok end}, #{desc => "await continue (shutdown)", cmd => fun(#{tester := Tester, rclient := Client} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, shutdown, [{rclient, Client}]), ok end}, #{desc => "order remote client to shutdown", cmd => fun(#{rclient := Client}) -> ?SEV_ANNOUNCE_CONTINUE(Client, shutdown), ok end}, #{desc => "await remote client ready (shiutdown)", cmd => fun(#{tester := Tester, rclient := Client} = _State) -> ?SEV_AWAIT_READY(Client, rclient, shutdown, [{tester, Tester}]) end}, #{desc => "announce ready (shutdown)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, shutdown), ok end}, #{desc => "await continue (close)", cmd => fun(#{tester := Tester, rclient := Client} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, close, [{rclient, Client}]), ok end}, #{desc => "order remote client to close", cmd => fun(#{rclient := Client}) -> ?SEV_ANNOUNCE_CONTINUE(Client, close), ok end}, #{desc => "await remote client ready (closed)", cmd => fun(#{tester := Tester, rclient := Client} = _State) -> ?SEV_AWAIT_READY(Client, rclient, close, [{tester, Tester}]) end}, #{desc => "announce ready (close)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, close), ok end}, %% Termination #{desc => "await terminate (from tester)", cmd => fun(#{tester := Tester, rclient := Client} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester, [{rclient, Client}]) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "kill remote client", cmd => fun(#{rclient := Client}) -> ?SEV_ANNOUNCE_TERMINATE(Client), ok end}, #{desc => "await remote client termination", cmd => fun(#{rclient := Client} = State) -> ?SEV_AWAIT_TERMINATION(Client), State1 = maps:remove(rclient, State), {ok, State1} end}, #{desc => "stop client node", cmd => fun(#{node := Node} = _State) -> stop_node(Node) end}, #{desc => "await client node termination", cmd => fun(#{node := Node} = State) -> receive {nodedown, Node} -> State1 = maps:remove(node_id, State), State2 = maps:remove(node, State1), {ok, State2} end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], TesterSeq = [ %% *** Init part *** #{desc => "monitor server", cmd => fun(#{server := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "monitor client", cmd => fun(#{client := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, %% Start the server #{desc => "order server start", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_START(Pid), ok end}, #{desc => "await server ready (init)", cmd => fun(#{server := Pid} = State) -> {ok, ServerSA} = ?SEV_AWAIT_READY(Pid, server, init), {ok, State#{server_sa => ServerSA}} end}, %% Start the client(s) #{desc => "order client start", cmd => fun(#{client := Pid, server_sa := ServerSA} = _State) -> ?SEV_ANNOUNCE_START(Pid, ServerSA), ok end}, #{desc => "await client ready (init)", cmd => fun(#{client := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, client, init) end}, %% The actual test #{desc => "order server continue (accept)", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, accept), ok end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order client continue (connect)", cmd => fun(#{client := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, connect), ok end}, #{desc => "await client ready (connect)", cmd => fun(#{server := Server, client := Client} = _State) -> ?SEV_AWAIT_READY(Client, client, connect, [{server, Server}]), ok end}, #{desc => "await server ready (accept)", cmd => fun(#{server := Server, client := Client} = _State) -> ?SEV_AWAIT_READY(Server, server, accept, [{client, Client}]), ok end}, #{desc => "order client continue (send)", cmd => fun(#{client := Pid, data := Data} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, send, Data), ok end}, #{desc => "await client ready (send)", cmd => fun(#{server := Server, client := Client} = _State) -> ?SEV_AWAIT_READY(Client, client, send, [{server, Server}]), ok end}, #{desc => "order client continue (shutdown)", cmd => fun(#{client := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, shutdown), ok end}, #{desc => "await client ready (shutdown)", cmd => fun(#{server := Server, client := Client} = _State) -> ?SEV_AWAIT_READY(Client, client, shutdown, [{server, Server}]), ok end}, #{desc => "order server continue (first recv)", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, recv), ok end}, #{desc => "await server ready (first recv)", cmd => fun(#{server := Server, client := Client} = _State) -> ?SEV_AWAIT_READY(Server, server, recv, [{client, Client}]), ok end}, #{desc => "order server continue (second recv)", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, recv), ok end}, #{desc => "await server ready (second recv)", cmd => fun(#{server := Server, client := Client} = _State) -> ?SEV_AWAIT_READY(Server, server, recv, [{client, Client}]), ok end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order client continue (close)", cmd => fun(#{client := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, close), ok end}, #{desc => "await client ready (close)", cmd => fun(#{server := Server, client := Client} = _State) -> ?SEV_AWAIT_READY(Client, client, close, [{server, Server}]), ok end}, %% Terminations #{desc => "order client to terminate", cmd => fun(#{client := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await client termination", cmd => fun(#{client := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> State1 = maps:remove(client, State), {ok, State1}; {error, _} = ERROR -> ERROR end end}, #{desc => "order server to terminate", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await server termination", cmd => fun(#{server := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> State1 = maps:remove(server, State), {ok, State1}; {error, _} = ERROR -> ERROR end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], i("start server evaluator"), ServerInitState = #{domain => maps:get(domain, InitState), proto => maps:get(proto, InitState), recv => maps:get(recv, InitState)}, Server = ?SEV_START("server", ServerSeq, ServerInitState), i("start client evaluator"), ClientInitState = #{host => local_host(), domain => maps:get(domain, InitState), proto => maps:get(proto, InitState), send => maps:get(send, InitState)}, Client = ?SEV_START("client", ClientSeq, ClientInitState), i("start 'tester' evaluator"), TesterInitState = #{server => Server#ev.pid, client => Client#ev.pid, data => maps:get(data, InitState)}, Tester = ?SEV_START("tester", TesterSeq, TesterInitState), i("await evaluator"), ok = ?SEV_AWAIT_FINISH([Server, Client, Tester]). sc_rs_tcp_client_start(Node, Send) -> Self = self(), Fun = fun() -> sc_rs_tcp_client(Self, Send) end, erlang:spawn(Node, Fun). sc_rs_tcp_client(Parent, Send) -> sc_rs_tcp_client_init(Parent), {ServerSA, Proto} = sc_rs_tcp_client_await_start(Parent), Domain = maps:get(family, ServerSA), Sock = sc_rs_tcp_client_create(Domain, Proto), Path = sc_rs_tcp_client_bind(Sock, Domain), sc_rs_tcp_client_announce_ready(Parent, init), sc_rs_tcp_client_await_continue(Parent, connect), sc_rs_tcp_client_connect(Sock, ServerSA), sc_rs_tcp_client_announce_ready(Parent, connect), Data = sc_rs_tcp_client_await_continue(Parent, send), sc_rs_tcp_client_send(Sock, Send, Data), sc_rs_tcp_client_announce_ready(Parent, send), sc_rs_tcp_client_await_continue(Parent, shutdown), sc_rs_tcp_client_shutdown(Sock), sc_rs_tcp_client_announce_ready(Parent, shutdown), sc_rs_tcp_client_await_continue(Parent, close), sc_rs_tcp_client_close(Sock, Path), sc_rs_tcp_client_announce_ready(Parent, close), Reason = sc_rs_tcp_client_await_terminate(Parent), ?SEV_IPRINT("terminate"), exit(Reason). sc_rs_tcp_client_init(Parent) -> put(sname, "rclient"), ?SEV_IPRINT("init"), _MRef = erlang:monitor(process, Parent), ok. sc_rs_tcp_client_await_start(Parent) -> i("sc_rs_tcp_client_await_start -> entry"), ?SEV_AWAIT_START(Parent). sc_rs_tcp_client_create(Domain, Proto) -> i("sc_rs_tcp_client_create -> entry"), case socket:open(Domain, stream, Proto) of {ok, Sock} -> Sock; {error, Reason} -> exit({open_failed, Reason}) end. sc_rs_tcp_client_bind(Sock, Domain) -> i("sc_rs_tcp_client_bind -> entry"), LSA = which_local_socket_addr(Domain), case socket:bind(Sock, LSA) of {ok, _} -> case socket:sockname(Sock) of {ok, #{family := local, path := Path}} -> Path; {ok, _} -> undefined; {error, Reason1} -> exit({sockname, Reason1}) end; {error, Reason} -> exit({bind, Reason}) end. sc_rs_tcp_client_announce_ready(Parent, Slogan) -> ?SEV_ANNOUNCE_READY(Parent, Slogan). sc_rs_tcp_client_await_continue(Parent, Slogan) -> i("sc_rs_tcp_client_await_continue -> entry"), case ?SEV_AWAIT_CONTINUE(Parent, parent, Slogan) of ok -> ok; {ok, Extra} -> Extra; {error, Reason} -> exit({await_continue, Slogan, Reason}) end. sc_rs_tcp_client_connect(Sock, ServerSA) -> i("sc_rs_tcp_client_connect -> entry"), case socket:connect(Sock, ServerSA) of ok -> ok; {error, Reason} -> exit({connect, Reason}) end. sc_rs_tcp_client_send(Sock, Send, Data) -> i("sc_rs_tcp_client_send -> entry"), case Send(Sock, Data) of ok -> ok; {error, Reason} -> exit({send, Reason}) end. sc_rs_tcp_client_shutdown(Sock) -> i("sc_rs_tcp_client_shutdown -> entry"), case socket:shutdown(Sock, write) of ok -> ok; {error, Reason} -> exit({shutdown, Reason}) end. sc_rs_tcp_client_close(Sock, Path) -> i("sc_rs_tcp_client_close -> entry"), case socket:close(Sock) of ok -> unlink_path(Path), ok; {error, Reason} -> ?SEV_EPRINT("failed closing: " "~n Reason: ~p", [Reason]), unlink_path(Path), {error, {close, Reason}} end. sc_rs_tcp_client_await_terminate(Parent) -> i("sc_rs_tcp_client_await_terminate -> entry"), case ?SEV_AWAIT_TERMINATE(Parent, parent) of ok -> ok; {error, Reason} -> Reason end. %% The handlers run on the same node as the server (the local node). sc_rs_tcp_handler_start(Recv, Sock) -> Self = self(), Fun = fun() -> sc_rs_tcp_handler(Self, Recv, Sock) end, {Pid, _} = erlang:spawn_monitor(Fun), Pid. sc_rs_tcp_handler(Parent, Recv, Sock) -> sc_rs_tcp_handler_init(Parent), sc_rs_tcp_handler_await(Parent, recv), ok = sc_rs_tcp_handler_recv(Recv, Sock, true), sc_rs_tcp_handler_announce_ready(Parent, recv, received), sc_rs_tcp_handler_await(Parent, recv), ok = sc_rs_tcp_handler_recv(Recv, Sock, false), sc_rs_tcp_handler_announce_ready(Parent, recv, closed), Reason = sc_rs_tcp_handler_await(Parent, terminate), exit(Reason). sc_rs_tcp_handler_init(Parent) -> put(sname, "handler"), _MRef = erlang:monitor(process, Parent), ?SEV_IPRINT("started"), ?SEV_ANNOUNCE_READY(Parent, init), ok. sc_rs_tcp_handler_await(Parent, terminate) -> ?SEV_IPRINT("await terminate"), ?SEV_AWAIT_TERMINATE(Parent, tester); sc_rs_tcp_handler_await(Parent, Slogan) -> ?SEV_IPRINT("await ~w", [Slogan]), ?SEV_AWAIT_CONTINUE(Parent, parent, Slogan). %% This hould actually work - we leave it for now sc_rs_tcp_handler_recv(Recv, Sock, First) -> ?SEV_IPRINT("recv"), try Recv(Sock) of {ok, _} when (First =:= true) -> ok; {error, closed} when (First =:= false) -> ok; {ok, _} -> ?SEV_IPRINT("unexpected success"), {error, unexpected_success}; {error, Reason} = ERROR -> ?SEV_IPRINT("receive error: " "~n ~p", [Reason]), ERROR catch C:E:S -> ?SEV_IPRINT("receive failure: " "~n Class: ~p" "~n Error: ~p" "~n Stack: ~p", [C, E, S]), {error, {recv, C, E, S}} end. sc_rs_tcp_handler_announce_ready(Parent, Slogan, Result) -> ?SEV_IPRINT("announce ready"), ?SEV_ANNOUNCE_READY(Parent, Slogan, Result), ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test what happens when a socket is %% remotely closed while the process is calling the recvmsg function. %% The remote client sends data, then shutdown(write) and then the %% reader attempts a recv. %% Socket is IPv4. sc_rs_recvmsg_send_shutdown_receive_tcp4(suite) -> []; sc_rs_recvmsg_send_shutdown_receive_tcp4(doc) -> []; sc_rs_recvmsg_send_shutdown_receive_tcp4(_Config) when is_list(_Config) -> tc_try(sc_rs_recvmsg_send_shutdown_receive_tcp4, fun() -> ?TT(?SECS(30)), MsgData = ?DATA, Recv = fun(Sock) -> case socket:recvmsg(Sock) of {ok, #{addr := undefined, iov := [Data]}} -> {ok, Data}; {error, _} = ERROR -> ERROR end end, Send = fun(Sock, Data) when is_binary(Data) -> MsgHdr = #{iov => [Data]}, socket:sendmsg(Sock, MsgHdr) end, InitState = #{domain => inet, proto => tcp, recv => Recv, send => Send, data => MsgData}, ok = sc_rs_send_shutdown_receive_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test what happens when a socket is %% remotely closed while the process is calling the recvmsg function. %% The remote client sends data, then shutdown(write) and then the %% reader attempts a recv. %% Socket is IPv6. sc_rs_recvmsg_send_shutdown_receive_tcp6(suite) -> []; sc_rs_recvmsg_send_shutdown_receive_tcp6(doc) -> []; sc_rs_recvmsg_send_shutdown_receive_tcp6(_Config) when is_list(_Config) -> tc_try(sc_rs_recvmsg_send_shutdown_receive_tcp6, fun() -> has_support_ipv6() end, fun() -> ?TT(?SECS(10)), MsgData = ?DATA, Recv = fun(Sock) -> case socket:recvmsg(Sock) of {ok, #{addr := undefined, iov := [Data]}} -> {ok, Data}; {error, _} = ERROR -> ERROR end end, Send = fun(Sock, Data) when is_binary(Data) -> MsgHdr = #{iov => [Data]}, socket:sendmsg(Sock, MsgHdr) end, InitState = #{domain => inet6, proto => tcp, recv => Recv, send => Send, data => MsgData}, ok = sc_rs_send_shutdown_receive_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test what happens when a socket is %% remotely closed while the process is calling the recvmsg function. %% The remote client sends data, then shutdown(write) and then the %% reader attempts a recv. %% Socket is UNix Domain (stream) socket. sc_rs_recvmsg_send_shutdown_receive_tcpL(suite) -> []; sc_rs_recvmsg_send_shutdown_receive_tcpL(doc) -> []; sc_rs_recvmsg_send_shutdown_receive_tcpL(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(sc_rs_recvmsg_send_shutdown_receive_tcpL, fun() -> has_support_unix_domain_socket() end, fun() -> {ok, CWD} = file:get_cwd(), ?SEV_IPRINT("CWD: ~s", [CWD]), MsgData = ?DATA, Recv = fun(Sock) -> case socket:recvmsg(Sock) of %% On some platforms, the address %% is *not* provided (e.g. FreeBSD) {ok, #{addr := undefined, iov := [Data]}} -> {ok, Data}; %% On some platforms, the address %% *is* provided (e.g. linux) {ok, #{addr := #{family := local}, iov := [Data]}} -> {ok, Data}; {error, _} = ERROR -> ERROR end end, Send = fun(Sock, Data) when is_binary(Data) -> MsgHdr = #{iov => [Data]}, socket:sendmsg(Sock, MsgHdr) end, InitState = #{domain => local, proto => default, recv => Recv, send => Send, data => MsgData}, ok = sc_rs_send_shutdown_receive_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to (simply) test that the counters %% for both read and write. %% So that its easy to extend, we use fun's for read and write. %% We use TCP on IPv4. traffic_send_and_recv_counters_tcp4(suite) -> []; traffic_send_and_recv_counters_tcp4(doc) -> []; traffic_send_and_recv_counters_tcp4(_Config) when is_list(_Config) -> ?TT(?SECS(15)), tc_try(traffic_send_and_recv_counters_tcp4, fun() -> InitState = #{domain => inet, proto => tcp, recv => fun(S) -> socket:recv(S) end, send => fun(S, D) -> socket:send(S, D) end}, ok = traffic_send_and_recv_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to (simply) test that the counters %% for both read and write. %% So that its easy to extend, we use fun's for read and write. %% We use TCP on IPv6. traffic_send_and_recv_counters_tcp6(suite) -> []; traffic_send_and_recv_counters_tcp6(doc) -> []; traffic_send_and_recv_counters_tcp6(_Config) when is_list(_Config) -> ?TT(?SECS(15)), tc_try(traffic_send_and_recv_counters_tcp6, fun() -> has_support_ipv6() end, fun() -> InitState = #{domain => inet6, proto => tcp, recv => fun(S) -> socket:recv(S) end, send => fun(S, D) -> socket:send(S, D) end}, ok = traffic_send_and_recv_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to (simply) test that the counters %% for both read and write. %% So that its easy to extend, we use fun's for read and write. %% We use default (TCP) on local. traffic_send_and_recv_counters_tcpL(suite) -> []; traffic_send_and_recv_counters_tcpL(doc) -> []; traffic_send_and_recv_counters_tcpL(_Config) when is_list(_Config) -> ?TT(?SECS(15)), tc_try(traffic_send_and_recv_counters_tcpL, fun() -> has_support_unix_domain_socket() end, fun() -> InitState = #{domain => local, proto => default, recv => fun(S) -> socket:recv(S) end, send => fun(S, D) -> socket:send(S, D) end}, ok = traffic_send_and_recv_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to (simply) test that the counters %% for both read and write. %% So that its easy to extend, we use fun's for read and write. %% We use TCP on IPv4. traffic_sendmsg_and_recvmsg_counters_tcp4(suite) -> []; traffic_sendmsg_and_recvmsg_counters_tcp4(doc) -> []; traffic_sendmsg_and_recvmsg_counters_tcp4(_Config) when is_list(_Config) -> ?TT(?SECS(15)), tc_try(traffic_sendmsg_and_recvmsg_counters_tcp4, fun() -> InitState = #{domain => inet, proto => tcp, recv => fun(S) -> case socket:recvmsg(S) of {ok, #{addr := _Source, iov := [Data]}} -> {ok, Data}; {error, _} = ERROR -> ERROR end end, send => fun(S, Data) -> MsgHdr = #{iov => [Data]}, socket:sendmsg(S, MsgHdr) end}, ok = traffic_send_and_recv_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to (simply) test that the counters %% for both read and write. %% So that its easy to extend, we use fun's for read and write. %% We use TCP on IPv6. traffic_sendmsg_and_recvmsg_counters_tcp6(suite) -> []; traffic_sendmsg_and_recvmsg_counters_tcp6(doc) -> []; traffic_sendmsg_and_recvmsg_counters_tcp6(_Config) when is_list(_Config) -> ?TT(?SECS(15)), tc_try(traffic_sendmsg_and_recvmsg_counters_tcp6, fun() -> has_support_ipv6() end, fun() -> InitState = #{domain => inet6, proto => tcp, recv => fun(S) -> case socket:recvmsg(S) of {ok, #{addr := _Source, iov := [Data]}} -> {ok, Data}; {error, _} = ERROR -> ERROR end end, send => fun(S, Data) -> MsgHdr = #{iov => [Data]}, socket:sendmsg(S, MsgHdr) end}, ok = traffic_send_and_recv_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to (simply) test that the counters %% for both read and write. %% So that its easy to extend, we use fun's for read and write. %% We use default (TCP) on local. traffic_sendmsg_and_recvmsg_counters_tcpL(suite) -> []; traffic_sendmsg_and_recvmsg_counters_tcpL(doc) -> []; traffic_sendmsg_and_recvmsg_counters_tcpL(_Config) when is_list(_Config) -> ?TT(?SECS(15)), tc_try(traffic_sendmsg_and_recvmsg_counters_tcpL, fun() -> has_support_unix_domain_socket() end, fun() -> InitState = #{domain => local, proto => default, recv => fun(S) -> case socket:recvmsg(S) of {ok, #{addr := _Source, iov := [Data]}} -> {ok, Data}; {error, _} = ERROR -> ERROR end end, send => fun(S, Data) -> MsgHdr = #{iov => [Data]}, socket:sendmsg(S, MsgHdr) end}, ok = traffic_send_and_recv_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% traffic_send_and_recv_tcp(InitState) -> ServerSeq = [ %% *** Wait for start order part *** #{desc => "await start", cmd => fun(State) -> Tester = ?SEV_AWAIT_START(), {ok, State#{tester => Tester}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, #{desc => "create listen socket", cmd => fun(#{domain := Domain, proto := Proto} = State) -> case socket:open(Domain, stream, Proto) of {ok, Sock} -> {ok, State#{lsock => Sock}}; {error, eafnosupport = Reason} -> {skip, Reason}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind to local address", cmd => fun(#{domain := local, lsock := LSock, local_sa := LSA} = _State) -> case socket:bind(LSock, LSA) of {ok, _Port} -> ok; % We do not care about the port for local {error, _} = ERROR -> ERROR end; (#{lsock := LSock, local_sa := LSA} = State) -> case socket:bind(LSock, LSA) of {ok, Port} -> {ok, State#{lport => Port}}; {error, _} = ERROR -> ERROR end end}, #{desc => "make listen socket", cmd => fun(#{lsock := LSock}) -> socket:listen(LSock) end}, #{desc => "announce ready (init)", cmd => fun(#{domain := local, tester := Tester, local_sa := #{path := Path}}) -> ?SEV_ANNOUNCE_READY(Tester, init, Path), ok; (#{tester := Tester, lport := Port}) -> ?SEV_ANNOUNCE_READY(Tester, init, Port), ok end}, %% The actual test #{desc => "await continue (accept)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, accept) end}, #{desc => "accept", cmd => fun(#{lsock := LSock} = State) -> case socket:accept(LSock) of {ok, Sock} -> {ok, State#{csock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "initial counter validation (=zero)", cmd => fun(#{csock := Sock} = _State) -> try socket:info(Sock) of #{counters := Counters} -> ?SEV_IPRINT("Validate initial counters: " "~n ~p", [Counters]), traffic_sar_counters_validation(Counters) catch C:E:S -> ?SEV_EPRINT("Failed get socket info: " "~n Class: ~p" "~n Error: ~p" "~n Stack: ~p", [C, E, S]), {error, {socket_info_failed, {C, E, S}}} end end}, #{desc => "announce ready (accept)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, accept), ok end}, #{desc => "await continue (recv_and_validate 1)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, recv_and_validate) end}, #{desc => "recv (1)", cmd => fun(#{csock := Sock, recv := Recv} = State) -> case Recv(Sock) of {ok, Data} -> ?SEV_IPRINT("recv ~p bytes", [size(Data)]), {ok, State#{read_pkg => 1, read_byte => size(Data)}}; {error, _} = ERROR -> ERROR end end}, #{desc => "validate (recv 1)", cmd => fun(#{csock := Sock, read_pkg := Pkg, read_byte := Byte} = _State) -> try socket:info(Sock) of #{counters := Counters} -> ?SEV_IPRINT("validate counters: " "~n ~p", [Counters]), traffic_sar_counters_validation( Counters, [{read_pkg, Pkg}, {read_byte, Byte}, {read_tries, any}]) catch C:E:S -> ?SEV_EPRINT("Failed get socket info: " "~n Class: ~p" "~n Error: ~p" "~n Stack: ~p", [C, E, S]), {error, {socket_info_failed, {C, E, S}}} end end}, #{desc => "announce ready (recv_and_validate 1)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv_and_validate), ok end}, #{desc => "await continue (send_and_validate 1)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, send_and_validate) end}, #{desc => "send (1)", cmd => fun(#{csock := Sock, send := Send} = State) -> Data = ?DATA, case Send(Sock, Data) of ok -> ?SEV_IPRINT("sent ~p bytes", [size(Data)]), {ok, State#{write_pkg => 1, write_byte => size(Data)}}; {error, _} = ERROR -> ERROR end end}, #{desc => "validate (send 1)", cmd => fun(#{csock := Sock, read_pkg := RPkg, read_byte := RByte, write_pkg := SPkg, write_byte := SByte} = _State) -> try socket:info(Sock) of #{counters := Counters} -> ?SEV_IPRINT("validate counters: " "~n ~p", [Counters]), traffic_sar_counters_validation( Counters, [{read_pkg, RPkg}, {read_byte, RByte}, {write_pkg, SPkg}, {write_byte, SByte}, {read_tries, any}, {write_tries, any}]) catch C:E:S -> ?SEV_EPRINT("Failed get socket info: " "~n Class: ~p" "~n Error: ~p" "~n Stack: ~p", [C, E, S]), {error, {socket_info_failed, {C, E, S}}} end end}, #{desc => "announce ready (send_and_validate 1)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, send_and_validate), ok end}, #{desc => "await continue (recv_and_validate 2)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, recv_and_validate) end}, #{desc => "recv (2)", cmd => fun(#{csock := Sock, recv := Recv, read_pkg := Pkg, read_byte := Byte} = State) -> case Recv(Sock) of {ok, Data} -> ?SEV_IPRINT("recv ~p bytes", [size(Data)]), {ok, State#{read_pkg => Pkg + 1, read_byte => Byte + size(Data)}}; {error, _} = ERROR -> ERROR end end}, #{desc => "validate (recv 2)", cmd => fun(#{csock := Sock, read_pkg := RPkg, read_byte := RByte, write_pkg := SPkg, write_byte := SByte} = _State) -> try socket:info(Sock) of #{counters := Counters} -> ?SEV_IPRINT("validate counters: " "~n ~p", [Counters]), traffic_sar_counters_validation( Counters, [{read_pkg, RPkg}, {read_byte, RByte}, {write_pkg, SPkg}, {write_byte, SByte}, {read_tries, any}, {write_tries, any}]) catch C:E:S -> ?SEV_EPRINT("Failed get socket info: " "~n Class: ~p" "~n Error: ~p" "~n Stack: ~p", [C, E, S]), {error, {socket_info_failed, {C, E, S}}} end end}, #{desc => "announce ready (recv_and_validate 2)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv_and_validate), ok end}, #{desc => "await continue (send_and_validate 2)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, send_and_validate) end}, #{desc => "send (2)", cmd => fun(#{csock := Sock, send := Send, write_pkg := Pkg, write_byte := Byte} = State) -> Data = ?DATA, case Send(Sock, Data) of ok -> ?SEV_IPRINT("sent ~p bytes", [size(Data)]), {ok, State#{write_pkg => Pkg + 1, write_byte => Byte + size(Data)}}; {error, _} = ERROR -> ERROR end end}, #{desc => "validate (send 2)", cmd => fun(#{csock := Sock, read_pkg := RPkg, read_byte := RByte, write_pkg := SPkg, write_byte := SByte} = _State) -> try socket:info(Sock) of #{counters := Counters} -> ?SEV_IPRINT("validate counters: " "~n ~p", [Counters]), traffic_sar_counters_validation( Counters, [{read_pkg, RPkg}, {read_byte, RByte}, {write_pkg, SPkg}, {write_byte, SByte}, {read_tries, any}, {write_tries, any}]) catch C:E:S -> ?SEV_EPRINT("Failed get socket info: " "~n Class: ~p" "~n Error: ~p" "~n Stack: ~p", [C, E, S]), {error, {socket_info_failed, {C, E, S}}} end end}, #{desc => "announce ready (send_and_validate 2)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, send_and_validate), ok end}, %% Termination #{desc => "await terminate (from tester)", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "close connection socket (just in case)", cmd => fun(#{csock := Sock} = State) -> (catch socket:close(Sock)), {ok, maps:remove(csock, State)} end}, #{desc => "close listen socket", cmd => fun(#{domain := local, lsock := Sock, local_sa := #{path := Path}} = State) -> ok = socket:close(Sock), State1 = unlink_path(Path, fun() -> maps:remove(local_sa, State) end, fun() -> State end), {ok, maps:remove(lsock, State1)}; (#{lsock := Sock} = State) -> (catch socket:close(Sock)), {ok, maps:remove(lsock, State)} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], ClientSeq = [ %% *** Wait for start order part *** #{desc => "await start (from tester)", cmd => fun(#{domain := local} = State) -> {Tester, Path} = ?SEV_AWAIT_START(), {ok, State#{tester => Tester, server_path => Path}}; (State) -> {Tester, Port} = ?SEV_AWAIT_START(), {ok, State#{tester => Tester, server_port => Port}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "which server (local) address", cmd => fun(#{domain := local = Domain, server_path := Path} = State) -> LSA = which_local_socket_addr(Domain), SSA = #{family => Domain, path => Path}, {ok, State#{local_sa => LSA, server_sa => SSA}}; (#{domain := Domain, server_port := Port} = State) -> LSA = which_local_socket_addr(Domain), SSA = LSA#{port => Port}, {ok, State#{local_sa => LSA, server_sa => SSA}} end}, #{desc => "create socket", cmd => fun(#{domain := Domain, proto := Proto} = State) -> case socket:open(Domain, stream, Proto) of {ok, Sock} -> {ok, State#{sock => Sock}}; {error, eafnosupport = Reason} -> {skip, Reason}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind to local address", cmd => fun(#{sock := Sock, local_sa := LSA} = _State) -> case socket:bind(Sock, LSA) of {ok, _Port} -> ok; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, init), ok end}, %% The actual test #{desc => "await continue (connect)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, connect), ok end}, #{desc => "connect to server", cmd => fun(#{sock := Sock, server_sa := SSA}) -> socket:connect(Sock, SSA) end}, #{desc => "announce ready (connect)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, connect), ok end}, #{desc => "await continue (send_and_validate 1)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, send_and_validate) end}, #{desc => "send (1)", cmd => fun(#{sock := Sock, send := Send} = State) -> Data = ?DATA, case Send(Sock, Data) of ok -> ?SEV_IPRINT("sent ~p bytes", [size(Data)]), {ok, State#{write_pkg => 1, write_byte => size(Data)}}; {error, _} = ERROR -> ERROR end end}, #{desc => "validate (send 1)", cmd => fun(#{sock := Sock, write_pkg := SPkg, write_byte := SByte} = _State) -> try socket:info(Sock) of #{counters := Counters} -> ?SEV_IPRINT("validate counters: " "~n ~p", [Counters]), traffic_sar_counters_validation( Counters, [{write_pkg, SPkg}, {write_byte, SByte}, {write_tries, any}]) catch C:E:S -> ?SEV_EPRINT("Failed get socket info: " "~n Class: ~p" "~n Error: ~p" "~n Stack: ~p", [C, E, S]), {error, {socket_info_failed, {C, E, S}}} end end}, #{desc => "announce ready (send_and_validate 1)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, send_and_validate), ok end}, #{desc => "await continue (recv_and_validate 1)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, recv_and_validate) end}, #{desc => "recv (1)", cmd => fun(#{sock := Sock, recv := Recv} = State) -> case Recv(Sock) of {ok, Data} -> ?SEV_IPRINT("recv ~p bytes", [size(Data)]), {ok, State#{read_pkg => 1, read_byte => size(Data)}}; {error, _} = ERROR -> ERROR end end}, #{desc => "validate (recv 1)", cmd => fun(#{sock := Sock, read_pkg := RPkg, read_byte := RByte, write_pkg := SPkg, write_byte := SByte} = _State) -> try socket:info(Sock) of #{counters := Counters} -> ?SEV_IPRINT("validate counters: " "~n ~p", [Counters]), traffic_sar_counters_validation( Counters, [{read_pkg, RPkg}, {read_byte, RByte}, {write_pkg, SPkg}, {write_byte, SByte}, {read_tries, any}, {write_tries, any}]) catch C:E:S -> ?SEV_EPRINT("Failed get socket info: " "~n Class: ~p" "~n Error: ~p" "~n Stack: ~p", [C, E, S]), {error, {socket_info_failed, {C, E, S}}} end end}, #{desc => "announce ready (recv_and_validate 1)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv_and_validate), ok end}, #{desc => "await continue (send_and_validate 2)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, send_and_validate) end}, #{desc => "send (2)", cmd => fun(#{sock := Sock, send := Send, write_pkg := SPkg, write_byte := SByte} = State) -> Data = ?DATA, case Send(Sock, Data) of ok -> ?SEV_IPRINT("sent ~p bytes", [size(Data)]), {ok, State#{write_pkg => SPkg + 1, write_byte => SByte + size(Data)}}; {error, _} = ERROR -> ERROR end end}, #{desc => "validate (send 2)", cmd => fun(#{sock := Sock, read_pkg := RPkg, read_byte := RByte, write_pkg := SPkg, write_byte := SByte} = _State) -> try socket:info(Sock) of #{counters := Counters} -> ?SEV_IPRINT("validate counters: " "~n ~p", [Counters]), traffic_sar_counters_validation( Counters, [{read_pkg, RPkg}, {read_byte, RByte}, {write_pkg, SPkg}, {write_byte, SByte}, {read_tries, any}, {write_tries, any}]) catch C:E:S -> ?SEV_EPRINT("Failed get socket info: " "~n Class: ~p" "~n Error: ~p" "~n Stack: ~p", [C, E, S]), {error, {socket_info_failed, {C, E, S}}} end end}, #{desc => "announce ready (send_and_validate 2)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, send_and_validate), ok end}, #{desc => "await continue (recv_and_validate 2)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, recv_and_validate) end}, #{desc => "recv (2)", cmd => fun(#{sock := Sock, recv := Recv, read_pkg := RPkg, read_byte := RByte} = State) -> case Recv(Sock) of {ok, Data} -> ?SEV_IPRINT("recv ~p bytes", [size(Data)]), {ok, State#{read_pkg => RPkg + 1, read_byte => RByte + size(Data)}}; {error, _} = ERROR -> ERROR end end}, #{desc => "validate (recv 2)", cmd => fun(#{sock := Sock, read_pkg := RPkg, read_byte := RByte, write_pkg := SPkg, write_byte := SByte} = _State) -> try socket:info(Sock) of #{counters := Counters} -> ?SEV_IPRINT("validate counters: " "~n ~p", [Counters]), traffic_sar_counters_validation( Counters, [{read_pkg, RPkg}, {read_byte, RByte}, {write_pkg, SPkg}, {write_byte, SByte}, {read_tries, any}, {write_tries, any}]) catch C:E:S -> ?SEV_EPRINT("Failed get socket info: " "~n Class: ~p" "~n Error: ~p" "~n Stack: ~p", [C, E, S]), {error, {socket_info_failed, {C, E, S}}} end end}, #{desc => "announce ready (recv_and_validate 2)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv_and_validate), ok end}, %% Termination #{desc => "await terminate (from tester)", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "close connection socket", cmd => fun(#{domain := local, sock := Sock, local_sa := #{path := Path}} = State) -> ok = socket:close(Sock), State1 = unlink_path(Path, fun() -> maps:remove(local_sa, State) end, fun() -> State end), {ok, maps:remove(sock, State1)}; (#{sock := Sock} = State) -> socket:close(Sock), {ok, maps:remove(sock, State)} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], TesterSeq = [ %% *** Init part *** #{desc => "monitor server", cmd => fun(#{server := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "monitor client", cmd => fun(#{client := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, %% Start the server #{desc => "order server start", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_START(Pid), ok end}, #{desc => "await server ready (init)", cmd => fun(#{domain := local, server := Pid} = State) -> {ok, Path} = ?SEV_AWAIT_READY(Pid, server, init), {ok, State#{path => Path}}; (#{server := Pid} = State) -> {ok, Port} = ?SEV_AWAIT_READY(Pid, server, init), {ok, State#{port => Port}} end}, %% Start the client #{desc => "order client start", cmd => fun(#{domain := local, client := Pid, path := Path} = _State) -> ?SEV_ANNOUNCE_START(Pid, Path), ok; (#{client := Pid, port := Port} = _State) -> ?SEV_ANNOUNCE_START(Pid, Port), ok end}, #{desc => "await client ready (init)", cmd => fun(#{client := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, client, init) end}, %% *** The actual test *** #{desc => "order server to continue (with accept)", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Server, accept), ok end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order client to continue (with connect)", cmd => fun(#{client := Client} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Client, connect), ok end}, #{desc => "await client ready (connect)", cmd => fun(#{client := Client} = _State) -> ?SEV_AWAIT_READY(Client, client, connect) end}, #{desc => "await server ready (accept)", cmd => fun(#{server := Server} = _State) -> ?SEV_AWAIT_READY(Server, server, accept) end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order server to continue (recv_and_validate 1)", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Server, recv_and_validate), ok end}, #{desc => "order client to continue (send_and_validate 1)", cmd => fun(#{client := Client} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Client, send_and_validate), ok end}, #{desc => "await client ready (send_and_validate 1)", cmd => fun(#{client := Client} = _State) -> ?SEV_AWAIT_READY(Client, client, send_and_validate) end}, #{desc => "await server ready (recv_and_validate 1)", cmd => fun(#{server := Server} = _State) -> ?SEV_AWAIT_READY(Server, server, recv_and_validate) end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order client to continue (recv_and_validate 1)", cmd => fun(#{client := Client} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Client, recv_and_validate), ok end}, #{desc => "order server to continue (send_and_validate 1)", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Server, send_and_validate), ok end}, #{desc => "await server ready (send_and_validate 1)", cmd => fun(#{server := Server} = _State) -> ?SEV_AWAIT_READY(Server, server, send_and_validate) end}, #{desc => "await client ready (recv_and_validate 1)", cmd => fun(#{client := Client} = _State) -> ?SEV_AWAIT_READY(Client, client, recv_and_validate) end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order server to continue (recv_and_validate 2)", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Server, recv_and_validate), ok end}, #{desc => "order client to continue (send_and_validate 2)", cmd => fun(#{client := Client} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Client, send_and_validate), ok end}, #{desc => "await client ready (send_and_validate 2)", cmd => fun(#{client := Client} = _State) -> ?SEV_AWAIT_READY(Client, client, send_and_validate) end}, #{desc => "await server ready (recv_and_validate 2)", cmd => fun(#{server := Server} = _State) -> ?SEV_AWAIT_READY(Server, server, recv_and_validate) end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order client to continue (recv_and_validate 2)", cmd => fun(#{client := Client} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Client, recv_and_validate), ok end}, #{desc => "order server to continue (send_and_validate 2)", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Server, send_and_validate), ok end}, #{desc => "await server ready (send_and_validate 2)", cmd => fun(#{server := Server} = _State) -> ?SEV_AWAIT_READY(Server, server, send_and_validate) end}, #{desc => "await client ready (recv_and_validate 2)", cmd => fun(#{client := Client} = _State) -> ?SEV_AWAIT_READY(Client, client, recv_and_validate) end}, %% *** Termination *** #{desc => "order client to terminate", cmd => fun(#{client := Client} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Client), ok end}, #{desc => "await client termination", cmd => fun(#{client := Client} = State) -> ?SEV_AWAIT_TERMINATION(Client), State1 = maps:remove(client, State), {ok, State1} end}, #{desc => "order server to terminate", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Server), ok end}, #{desc => "await server termination", cmd => fun(#{server := Server} = State) -> ?SEV_AWAIT_TERMINATION(Server), State1 = maps:remove(server, State), {ok, State1} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], i("start server evaluator"), ServerInitState = InitState#{host => local_host()}, Server = ?SEV_START("server", ServerSeq, ServerInitState), i("start client evaluator(s)"), ClientInitState = InitState#{host => local_host()}, Client = ?SEV_START("client", ClientSeq, ClientInitState), i("start 'tester' evaluator"), TesterInitState = #{server => Server#ev.pid, client => Client#ev.pid}, Tester = ?SEV_START("tester", TesterSeq, TesterInitState), i("await evaluator"), ok = ?SEV_AWAIT_FINISH([Server, Client, Tester]). traffic_sar_counters_validation(Counters) -> traffic_sar_counters_validation(Counters, []). traffic_sar_counters_validation(Counters, []) -> (catch lists:foreach( fun({_Cnt, 0}) -> ok; ({Cnt, Val}) -> throw({error, {invalid_counter, Cnt, Val}}) end, Counters)); traffic_sar_counters_validation(Counters, [{Cnt, Val}|ValidateCounters]) -> case lists:keysearch(Cnt, 1, Counters) of {value, {Cnt, Val}} -> Counters2 = lists:keydelete(Cnt, 1, Counters), traffic_sar_counters_validation(Counters2, ValidateCounters); {value, {Cnt, _Val}} when (Val =:= any) -> Counters2 = lists:keydelete(Cnt, 1, Counters), traffic_sar_counters_validation(Counters2, ValidateCounters); {value, {Cnt, InvVal}} -> {error, {invalid_counter, Cnt, InvVal, Val}}; false -> {error, {unknown_counter, Cnt, Counters}} end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to (simply) test that the counters %% for both read and write. %% So that its easy to extend, we use fun's for read and write. %% We use UDP on IPv4. traffic_sendto_and_recvfrom_counters_udp4(suite) -> []; traffic_sendto_and_recvfrom_counters_udp4(doc) -> []; traffic_sendto_and_recvfrom_counters_udp4(_Config) when is_list(_Config) -> ?TT(?SECS(15)), tc_try(traffic_sendto_and_recvfrom_counters_udp4, fun() -> InitState = #{domain => inet, proto => udp, recv => fun(S) -> socket:recvfrom(S) end, send => fun(S, Data, Dest) -> socket:sendto(S, Data, Dest) end}, ok = traffic_send_and_recv_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to (simply) test that the counters %% for both read and write. %% So that its easy to extend, we use fun's for read and write. %% We use UDP on IPv6. traffic_sendto_and_recvfrom_counters_udp6(suite) -> []; traffic_sendto_and_recvfrom_counters_udp6(doc) -> []; traffic_sendto_and_recvfrom_counters_udp6(_Config) when is_list(_Config) -> ?TT(?SECS(15)), tc_try(traffic_sendto_and_recvfrom_counters_udp6, fun() -> has_support_ipv6() end, fun() -> InitState = #{domain => inet6, proto => udp, recv => fun(S) -> socket:recvfrom(S) end, send => fun(S, Data, Dest) -> socket:sendto(S, Data, Dest) end}, ok = traffic_send_and_recv_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to (simply) test that the counters %% for both read and write. %% So that its easy to extend, we use fun's for read and write. %% We use default (UDP) on local. traffic_sendto_and_recvfrom_counters_udpL(suite) -> []; traffic_sendto_and_recvfrom_counters_udpL(doc) -> []; traffic_sendto_and_recvfrom_counters_udpL(_Config) when is_list(_Config) -> ?TT(?SECS(15)), tc_try(traffic_sendto_and_recvfrom_counters_udp4, fun() -> has_support_unix_domain_socket() end, fun() -> InitState = #{domain => local, proto => default, recv => fun(S) -> socket:recvfrom(S) end, send => fun(S, Data, Dest) -> socket:sendto(S, Data, Dest) end}, ok = traffic_send_and_recv_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to (simply) test that the counters %% for both read and write. %% So that its easy to extend, we use fun's for read and write. %% We use UDP on IPv4. traffic_sendmsg_and_recvmsg_counters_udp4(suite) -> []; traffic_sendmsg_and_recvmsg_counters_udp4(doc) -> []; traffic_sendmsg_and_recvmsg_counters_udp4(_Config) when is_list(_Config) -> ?TT(?SECS(15)), tc_try(traffic_sendmsg_and_recvmsg_counters_udp4, fun() -> InitState = #{domain => inet, proto => udp, recv => fun(S) -> case socket:recvmsg(S) of {ok, #{addr := Source, iov := [Data]}} -> {ok, {Source, Data}}; {error, _} = ERROR -> ERROR end end, send => fun(S, Data, Dest) -> MsgHdr = #{addr => Dest, iov => [Data]}, socket:sendmsg(S, MsgHdr) end}, ok = traffic_send_and_recv_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to (simply) test that the counters %% for both read and write. %% So that its easy to extend, we use fun's for read and write. %% We use UDP on IPv6. traffic_sendmsg_and_recvmsg_counters_udp6(suite) -> []; traffic_sendmsg_and_recvmsg_counters_udp6(doc) -> []; traffic_sendmsg_and_recvmsg_counters_udp6(_Config) when is_list(_Config) -> ?TT(?SECS(15)), tc_try(traffic_sendmsg_and_recvmsg_counters_udp6, fun() -> has_support_ipv6() end, fun() -> InitState = #{domain => inet6, proto => udp, recv => fun(S) -> case socket:recvmsg(S) of {ok, #{addr := Source, iov := [Data]}} -> {ok, {Source, Data}}; {error, _} = ERROR -> ERROR end end, send => fun(S, Data, Dest) -> MsgHdr = #{addr => Dest, iov => [Data]}, socket:sendmsg(S, MsgHdr) end}, ok = traffic_send_and_recv_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to (simply) test that the counters %% for both read and write. %% So that its easy to extend, we use fun's for read and write. %% We use default (UDP) on local. traffic_sendmsg_and_recvmsg_counters_udpL(suite) -> []; traffic_sendmsg_and_recvmsg_counters_udpL(doc) -> []; traffic_sendmsg_and_recvmsg_counters_udpL(_Config) when is_list(_Config) -> ?TT(?SECS(15)), tc_try(traffic_sendmsg_and_recvmsg_counters_udpL, fun() -> has_support_unix_domain_socket() end, fun() -> InitState = #{domain => local, proto => default, recv => fun(S) -> case socket:recvmsg(S) of {ok, #{addr := Source, iov := [Data]}} -> {ok, {Source, Data}}; {error, _} = ERROR -> ERROR end end, send => fun(S, Data, Dest) -> MsgHdr = #{addr => Dest, iov => [Data]}, socket:sendmsg(S, MsgHdr) end}, ok = traffic_send_and_recv_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% traffic_send_and_recv_udp(InitState) -> ServerSeq = [ %% *** Wait for start order part *** #{desc => "await start", cmd => fun(State) -> Tester = ?SEV_AWAIT_START(), {ok, State#{tester => Tester}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, #{desc => "create socket", cmd => fun(#{domain := Domain, proto := Proto} = State) -> case socket:open(Domain, dgram, Proto) of {ok, Sock} -> {ok, State#{sock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind to local address", cmd => fun(#{domain := local, sock := Sock, local_sa := LSA} = _State) -> case socket:bind(Sock, LSA) of {ok, _Port} -> ok; % We do not care about the port for local {error, _} = ERROR -> ERROR end; (#{sock := LSock, local_sa := LSA} = State) -> case socket:bind(LSock, LSA) of {ok, Port} -> {ok, State#{lport => Port}}; {error, _} = ERROR -> ERROR end end}, #{desc => "initial counter validation (=zero)", cmd => fun(#{sock := Sock} = _State) -> try socket:info(Sock) of #{counters := Counters} -> ?SEV_IPRINT("Validate initial counters: " "~n ~p", [Counters]), traffic_sar_counters_validation(Counters) catch C:E:S -> ?SEV_EPRINT("Failed get socket info: " "~n Class: ~p" "~n Error: ~p" "~n Stack: ~p", [C, E, S]), {error, {socket_info_failed, {C, E, S}}} end end}, #{desc => "announce ready (init)", cmd => fun(#{domain := local, tester := Tester, local_sa := #{path := Path}}) -> ?SEV_ANNOUNCE_READY(Tester, init, Path), ok; (#{tester := Tester, lport := Port}) -> ?SEV_ANNOUNCE_READY(Tester, init, Port), ok end}, %% The actual test #{desc => "await continue (recv_and_validate 1)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, recv_and_validate) end}, #{desc => "recv (1)", cmd => fun(#{sock := Sock, recv := Recv} = State) -> case Recv(Sock) of {ok, {ClientSA, Data}} -> ?SEV_IPRINT("recv ~p bytes", [size(Data)]), {ok, State#{client_sa => ClientSA, read_pkg => 1, read_byte => size(Data)}}; {error, _} = ERROR -> ERROR end end}, #{desc => "validate (recv 1)", cmd => fun(#{sock := Sock, read_pkg := Pkg, read_byte := Byte} = _State) -> try socket:info(Sock) of #{counters := Counters} -> ?SEV_IPRINT("validate counters: " "~n ~p", [Counters]), traffic_sar_counters_validation( Counters, [{read_pkg, Pkg}, {read_byte, Byte}, {read_tries, any}]) catch C:E:S -> ?SEV_EPRINT("Failed get socket info: " "~n Class: ~p" "~n Error: ~p" "~n Stack: ~p", [C, E, S]), {error, {socket_info_failed, {C, E, S}}} end end}, #{desc => "announce ready (recv_and_validate 1)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv_and_validate), ok end}, #{desc => "await continue (send_and_validate 1)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, send_and_validate) end}, #{desc => "send (1)", cmd => fun(#{sock := Sock, send := Send, client_sa := ClientSA} = State) -> Data = ?DATA, case Send(Sock, Data, ClientSA) of ok -> ?SEV_IPRINT("sent ~p bytes", [size(Data)]), {ok, State#{write_pkg => 1, write_byte => size(Data)}}; {error, _} = ERROR -> ERROR end end}, #{desc => "validate (send 1)", cmd => fun(#{sock := Sock, read_pkg := RPkg, read_byte := RByte, write_pkg := SPkg, write_byte := SByte} = _State) -> try socket:info(Sock) of #{counters := Counters} -> ?SEV_IPRINT("validate counters: " "~n ~p", [Counters]), traffic_sar_counters_validation( Counters, [{read_pkg, RPkg}, {read_byte, RByte}, {write_pkg, SPkg}, {write_byte, SByte}, {read_tries, any}, {write_tries, any}]) catch C:E:S -> ?SEV_EPRINT("Failed get socket info: " "~n Class: ~p" "~n Error: ~p" "~n Stack: ~p", [C, E, S]), {error, {socket_info_failed, {C, E, S}}} end end}, #{desc => "announce ready (send_and_validate 1)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, send_and_validate), ok end}, #{desc => "await continue (recv_and_validate 2)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, recv_and_validate) end}, #{desc => "recv (2)", cmd => fun(#{sock := Sock, recv := Recv, read_pkg := Pkg, read_byte := Byte} = State) -> case Recv(Sock) of {ok, {Source, Data}} -> ?SEV_IPRINT("recv ~p bytes", [size(Data)]), {ok, State#{client_sa => Source, read_pkg => Pkg + 1, read_byte => Byte + size(Data)}}; {error, _} = ERROR -> ERROR end end}, #{desc => "validate (recv 2)", cmd => fun(#{sock := Sock, read_pkg := RPkg, read_byte := RByte, write_pkg := SPkg, write_byte := SByte} = _State) -> try socket:info(Sock) of #{counters := Counters} -> ?SEV_IPRINT("validate counters: " "~n ~p", [Counters]), traffic_sar_counters_validation( Counters, [{read_pkg, RPkg}, {read_byte, RByte}, {write_pkg, SPkg}, {write_byte, SByte}, {read_tries, any}, {write_tries, any}]) catch C:E:S -> ?SEV_EPRINT("Failed get socket info: " "~n Class: ~p" "~n Error: ~p" "~n Stack: ~p", [C, E, S]), {error, {socket_info_failed, {C, E, S}}} end end}, #{desc => "announce ready (recv_and_validate 2)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv_and_validate), ok end}, #{desc => "await continue (send_and_validate 2)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, send_and_validate) end}, #{desc => "send (2)", cmd => fun(#{sock := Sock, client_sa := ClientSA, send := Send, write_pkg := Pkg, write_byte := Byte} = State) -> Data = ?DATA, case Send(Sock, Data, ClientSA) of ok -> ?SEV_IPRINT("sent ~p bytes", [size(Data)]), {ok, State#{write_pkg => Pkg + 1, write_byte => Byte + size(Data)}}; {error, _} = ERROR -> ERROR end end}, #{desc => "validate (send 2)", cmd => fun(#{sock := Sock, read_pkg := RPkg, read_byte := RByte, write_pkg := SPkg, write_byte := SByte} = _State) -> try socket:info(Sock) of #{counters := Counters} -> ?SEV_IPRINT("validate counters: " "~n ~p", [Counters]), traffic_sar_counters_validation( Counters, [{read_pkg, RPkg}, {read_byte, RByte}, {write_pkg, SPkg}, {write_byte, SByte}, {read_tries, any}, {write_tries, any}]) catch C:E:S -> ?SEV_EPRINT("Failed get socket info: " "~n Class: ~p" "~n Error: ~p" "~n Stack: ~p", [C, E, S]), {error, {socket_info_failed, {C, E, S}}} end end}, #{desc => "announce ready (send_and_validate 2)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, send_and_validate), ok end}, %% Termination #{desc => "await terminate (from tester)", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "close socket (just in case)", cmd => fun(#{domain := local, sock := Sock, local_sa := #{path := Path}} = State) -> ok = socket:close(Sock), State1 = unlink_path(Path, fun() -> maps:remove(local_sa, State) end, fun() -> State end), {ok, maps:remove(lsock, State1)}; (#{sock := Sock} = State) -> (catch socket:close(Sock)), {ok, maps:remove(sock, State)} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], ClientSeq = [ %% *** Wait for start order part *** #{desc => "await start (from tester)", cmd => fun(#{domain := local} = State) -> {Tester, Path} = ?SEV_AWAIT_START(), {ok, State#{tester => Tester, server_path => Path}}; (State) -> {Tester, Port} = ?SEV_AWAIT_START(), {ok, State#{tester => Tester, server_port => Port}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "which server (local) address", cmd => fun(#{domain := local = Domain, server_path := Path} = State) -> LSA = which_local_socket_addr(Domain), SSA = #{family => Domain, path => Path}, {ok, State#{local_sa => LSA, server_sa => SSA}}; (#{domain := Domain, server_port := Port} = State) -> LSA = which_local_socket_addr(Domain), SSA = LSA#{port => Port}, {ok, State#{local_sa => LSA, server_sa => SSA}} end}, #{desc => "create socket", cmd => fun(#{domain := Domain, proto := Proto} = State) -> case socket:open(Domain, dgram, Proto) of {ok, Sock} -> {ok, State#{sock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind to local address", cmd => fun(#{sock := Sock, local_sa := LSA} = _State) -> case socket:bind(Sock, LSA) of {ok, _Port} -> ok; {error, _} = ERROR -> ERROR end end}, #{desc => "initial counter validation (=zero)", cmd => fun(#{sock := Sock} = _State) -> try socket:info(Sock) of #{counters := Counters} -> ?SEV_IPRINT("Validate initial counters: " "~n ~p", [Counters]), traffic_sar_counters_validation(Counters) catch C:E:S -> ?SEV_EPRINT("Failed get socket info: " "~n Class: ~p" "~n Error: ~p" "~n Stack: ~p", [C, E, S]), {error, {socket_info_failed, {C, E, S}}} end end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, init), ok end}, %% The actual test #{desc => "await continue (send_and_validate 1)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, send_and_validate) end}, #{desc => "send (1)", cmd => fun(#{sock := Sock, send := Send, server_sa := ServerSA} = State) -> Data = ?DATA, case Send(Sock, Data, ServerSA) of ok -> ?SEV_IPRINT("sent ~p bytes", [size(Data)]), {ok, State#{write_pkg => 1, write_byte => size(Data)}}; {error, _} = ERROR -> ERROR end end}, #{desc => "validate (send 1)", cmd => fun(#{sock := Sock, write_pkg := SPkg, write_byte := SByte} = _State) -> try socket:info(Sock) of #{counters := Counters} -> ?SEV_IPRINT("validate counters: " "~n ~p", [Counters]), traffic_sar_counters_validation( Counters, [{write_pkg, SPkg}, {write_byte, SByte}, {write_tries, any}]) catch C:E:S -> ?SEV_EPRINT("Failed get socket info: " "~n Class: ~p" "~n Error: ~p" "~n Stack: ~p", [C, E, S]), {error, {socket_info_failed, {C, E, S}}} end end}, #{desc => "announce ready (send_and_validate 1)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, send_and_validate), ok end}, #{desc => "await continue (recv_and_validate 1)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, recv_and_validate) end}, #{desc => "recv (1)", cmd => fun(#{sock := Sock, recv := Recv, server_sa := #{family := local} = ServerSA} = State) -> case Recv(Sock) of {ok, {ServerSA, Data}} -> ?SEV_IPRINT("recv ~p bytes", [size(Data)]), {ok, State#{read_pkg => 1, read_byte => size(Data)}}; {error, _} = ERROR -> ERROR end; (#{sock := Sock, recv := Recv, server_sa := #{addr := Addr, port := Port}} = State) -> case Recv(Sock) of {ok, {#{addr := Addr, port := Port}, Data}} -> ?SEV_IPRINT("recv ~p bytes", [size(Data)]), {ok, State#{read_pkg => 1, read_byte => size(Data)}}; {error, _} = ERROR -> ERROR end end}, #{desc => "validate (recv 1)", cmd => fun(#{sock := Sock, read_pkg := RPkg, read_byte := RByte, write_pkg := SPkg, write_byte := SByte} = _State) -> try socket:info(Sock) of #{counters := Counters} -> ?SEV_IPRINT("validate counters: " "~n ~p", [Counters]), traffic_sar_counters_validation( Counters, [{read_pkg, RPkg}, {read_byte, RByte}, {write_pkg, SPkg}, {write_byte, SByte}, {read_tries, any}, {write_tries, any}]) catch C:E:S -> ?SEV_EPRINT("Failed get socket info: " "~n Class: ~p" "~n Error: ~p" "~n Stack: ~p", [C, E, S]), {error, {socket_info_failed, {C, E, S}}} end end}, #{desc => "announce ready (recv_and_validate 1)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv_and_validate), ok end}, #{desc => "await continue (send_and_validate 2)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, send_and_validate) end}, #{desc => "send (2)", cmd => fun(#{sock := Sock, send := Send, server_sa := ServerSA, write_pkg := SPkg, write_byte := SByte} = State) -> Data = ?DATA, case Send(Sock, Data, ServerSA) of ok -> ?SEV_IPRINT("sent ~p bytes", [size(Data)]), {ok, State#{write_pkg => SPkg + 1, write_byte => SByte + size(Data)}}; {error, _} = ERROR -> ERROR end end}, #{desc => "validate (send 2)", cmd => fun(#{sock := Sock, read_pkg := RPkg, read_byte := RByte, write_pkg := SPkg, write_byte := SByte} = _State) -> try socket:info(Sock) of #{counters := Counters} -> ?SEV_IPRINT("validate counters: " "~n ~p", [Counters]), traffic_sar_counters_validation( Counters, [{read_pkg, RPkg}, {read_byte, RByte}, {write_pkg, SPkg}, {write_byte, SByte}, {read_tries, any}, {write_tries, any}]) catch C:E:S -> ?SEV_EPRINT("Failed get socket info: " "~n Class: ~p" "~n Error: ~p" "~n Stack: ~p", [C, E, S]), {error, {socket_info_failed, {C, E, S}}} end end}, #{desc => "announce ready (send_and_validate 2)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, send_and_validate), ok end}, #{desc => "await continue (recv_and_validate 2)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, recv_and_validate) end}, #{desc => "recv (2)", cmd => fun(#{sock := Sock, server_sa := #{family := local} = ServerSA, recv := Recv, read_pkg := RPkg, read_byte := RByte} = State) -> case Recv(Sock) of {ok, {ServerSA, Data}} -> ?SEV_IPRINT("recv ~p bytes", [size(Data)]), {ok, State#{read_pkg => RPkg + 1, read_byte => RByte + size(Data)}}; {error, _} = ERROR -> ERROR end; (#{sock := Sock, server_sa := #{addr := Addr, port := Port}, recv := Recv, read_pkg := RPkg, read_byte := RByte} = State) -> case Recv(Sock) of {ok, {#{addr := Addr, port := Port}, Data}} -> ?SEV_IPRINT("recv ~p bytes", [size(Data)]), {ok, State#{read_pkg => RPkg + 1, read_byte => RByte + size(Data)}}; {error, _} = ERROR -> ERROR end end}, #{desc => "validate (recv 2)", cmd => fun(#{sock := Sock, read_pkg := RPkg, read_byte := RByte, write_pkg := SPkg, write_byte := SByte} = _State) -> try socket:info(Sock) of #{counters := Counters} -> ?SEV_IPRINT("validate counters: " "~n ~p", [Counters]), traffic_sar_counters_validation( Counters, [{read_pkg, RPkg}, {read_byte, RByte}, {write_pkg, SPkg}, {write_byte, SByte}, {read_tries, any}, {write_tries, any}]) catch C:E:S -> ?SEV_EPRINT("Failed get socket info: " "~n Class: ~p" "~n Error: ~p" "~n Stack: ~p", [C, E, S]), {error, {socket_info_failed, {C, E, S}}} end end}, #{desc => "announce ready (recv_and_validate 2)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, recv_and_validate), ok end}, %% Termination #{desc => "await terminate (from tester)", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "close connection socket", cmd => fun(#{domain := local, sock := Sock, local_sa := #{path := Path}} = State) -> ok = socket:close(Sock), State1 = unlink_path(Path, fun() -> maps:remove(local_sa, State) end, fun() -> State end), {ok, maps:remove(sock, State1)}; (#{sock := Sock} = State) -> socket:close(Sock), {ok, maps:remove(sock, State)} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], TesterSeq = [ %% *** Init part *** #{desc => "monitor server", cmd => fun(#{server := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "monitor client", cmd => fun(#{client := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, %% Start the server #{desc => "order server start", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_START(Pid), ok end}, #{desc => "await server ready (init)", cmd => fun(#{domain := local, server := Pid} = State) -> {ok, Path} = ?SEV_AWAIT_READY(Pid, server, init), {ok, State#{path => Path}}; (#{server := Pid} = State) -> {ok, Port} = ?SEV_AWAIT_READY(Pid, server, init), {ok, State#{port => Port}} end}, %% Start the client #{desc => "order client start", cmd => fun(#{domain := local, client := Pid, path := Path} = _State) -> ?SEV_ANNOUNCE_START(Pid, Path), ok; (#{client := Pid, port := Port} = _State) -> ?SEV_ANNOUNCE_START(Pid, Port), ok end}, #{desc => "await client ready (init)", cmd => fun(#{client := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, client, init) end}, %% *** The actual test *** #{desc => "order server to continue (recv_and_validate 1)", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Server, recv_and_validate), ok end}, #{desc => "order client to continue (send_and_validate 1)", cmd => fun(#{client := Client} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Client, send_and_validate), ok end}, #{desc => "await client ready (send_and_validate 1)", cmd => fun(#{client := Client} = _State) -> ?SEV_AWAIT_READY(Client, client, send_and_validate) end}, #{desc => "await server ready (recv_and_validate 1)", cmd => fun(#{server := Server} = _State) -> ?SEV_AWAIT_READY(Server, server, recv_and_validate) end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order client to continue (recv_and_validate 1)", cmd => fun(#{client := Client} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Client, recv_and_validate), ok end}, #{desc => "order server to continue (send_and_validate 1)", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Server, send_and_validate), ok end}, #{desc => "await server ready (send_and_validate 1)", cmd => fun(#{server := Server} = _State) -> ?SEV_AWAIT_READY(Server, server, send_and_validate) end}, #{desc => "await client ready (recv_and_validate 1)", cmd => fun(#{client := Client} = _State) -> ?SEV_AWAIT_READY(Client, client, recv_and_validate) end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order server to continue (recv_and_validate 2)", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Server, recv_and_validate), ok end}, #{desc => "order client to continue (send_and_validate 2)", cmd => fun(#{client := Client} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Client, send_and_validate), ok end}, #{desc => "await client ready (send_and_validate 2)", cmd => fun(#{client := Client} = _State) -> ?SEV_AWAIT_READY(Client, client, send_and_validate) end}, #{desc => "await server ready (recv_and_validate 2)", cmd => fun(#{server := Server} = _State) -> ?SEV_AWAIT_READY(Server, server, recv_and_validate) end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order client to continue (recv_and_validate 2)", cmd => fun(#{client := Client} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Client, recv_and_validate), ok end}, #{desc => "order server to continue (send_and_validate 2)", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Server, send_and_validate), ok end}, #{desc => "await server ready (send_and_validate 2)", cmd => fun(#{server := Server} = _State) -> ?SEV_AWAIT_READY(Server, server, send_and_validate) end}, #{desc => "await client ready (recv_and_validate 2)", cmd => fun(#{client := Client} = _State) -> ?SEV_AWAIT_READY(Client, client, recv_and_validate) end}, %% *** Termination *** #{desc => "order client to terminate", cmd => fun(#{client := Client} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Client), ok end}, #{desc => "await client termination", cmd => fun(#{client := Client} = State) -> ?SEV_AWAIT_TERMINATION(Client), State1 = maps:remove(client, State), {ok, State1} end}, #{desc => "order server to terminate", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Server), ok end}, #{desc => "await server termination", cmd => fun(#{server := Server} = State) -> ?SEV_AWAIT_TERMINATION(Server), State1 = maps:remove(server, State), {ok, State1} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], i("start server evaluator"), ServerInitState = InitState#{host => local_host()}, Server = ?SEV_START("server", ServerSeq, ServerInitState), i("start client evaluator(s)"), ClientInitState = InitState#{host => local_host()}, Client = ?SEV_START("client", ClientSeq, ClientInitState), i("start 'tester' evaluator"), TesterInitState = #{server => Server#ev.pid, client => Client#ev.pid}, Tester = ?SEV_START("tester", TesterSeq, TesterInitState), i("await evaluator"), ok = ?SEV_AWAIT_FINISH([Server, Client, Tester]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the send and recv functions %% behave as expected when sending and/or reading chunks. %% First send data in one "big" chunk, and read it in "small" chunks. %% Second, send in a bunch of "small" chunks, and read in one "big" chunk. %% Socket is IPv4. traffic_send_and_recv_chunks_tcp4(suite) -> []; traffic_send_and_recv_chunks_tcp4(doc) -> []; traffic_send_and_recv_chunks_tcp4(_Config) when is_list(_Config) -> ?TT(?SECS(30)), tc_try(traffic_send_and_recv_chunks_tcp4, fun() -> InitState = #{domain => inet, proto => tcp}, ok = traffic_send_and_recv_chunks_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the send and recv functions %% behave as expected when sending and/or reading chunks. %% First send data in one "big" chunk, and read it in "small" chunks. %% Second, send in a bunch of "small" chunks, and read in one "big" chunk. %% Socket is IPv6. traffic_send_and_recv_chunks_tcp6(suite) -> []; traffic_send_and_recv_chunks_tcp6(doc) -> []; traffic_send_and_recv_chunks_tcp6(_Config) when is_list(_Config) -> ?TT(?SECS(30)), tc_try(traffic_send_and_recv_chunks_tcp6, fun() -> has_support_ipv6() end, fun() -> InitState = #{domain => inet6, proto => tcp}, ok = traffic_send_and_recv_chunks_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the send and recv functions %% behave as expected when sending and/or reading chunks. %% First send data in one "big" chunk, and read it in "small" chunks. %% Second, send in a bunch of "small" chunks, and read in one "big" chunk. %% Socket is UNix Domain (Stream) socket. traffic_send_and_recv_chunks_tcpL(suite) -> []; traffic_send_and_recv_chunks_tcpL(doc) -> []; traffic_send_and_recv_chunks_tcpL(_Config) when is_list(_Config) -> ?TT(?SECS(30)), tc_try(traffic_send_and_recv_chunks_tcp6, fun() -> has_support_unix_domain_socket() end, fun() -> InitState = #{domain => local, proto => default}, ok = traffic_send_and_recv_chunks_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% traffic_send_and_recv_chunks_tcp(InitState) -> ServerSeq = [ %% *** Wait for start order part *** #{desc => "await start", cmd => fun(State) -> Tester = ?SEV_AWAIT_START(), {ok, State#{tester => Tester}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, #{desc => "create listen socket", cmd => fun(#{domain := Domain, proto := Proto} = State) -> case socket:open(Domain, stream, Proto) of {ok, Sock} -> {ok, State#{lsock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind to local address", cmd => fun(#{domain := local, lsock := LSock, local_sa := LSA} = _State) -> case socket:bind(LSock, LSA) of {ok, _Port} -> ok; % We do not care about the port for local {error, _} = ERROR -> ERROR end; (#{lsock := LSock, local_sa := LSA} = State) -> case socket:bind(LSock, LSA) of {ok, Port} -> {ok, State#{lport => Port}}; {error, _} = ERROR -> ERROR end end}, #{desc => "make listen socket", cmd => fun(#{lsock := LSock}) -> socket:listen(LSock) end}, #{desc => "announce ready (init)", cmd => fun(#{domain := local, tester := Tester, local_sa := LSA}) -> ?SEV_ANNOUNCE_READY(Tester, init, LSA), ok; (#{tester := Tester, local_sa := LSA, lport := Port}) -> ServerSA = LSA#{port => Port}, ?SEV_ANNOUNCE_READY(Tester, init, ServerSA), ok end}, %% The actual test #{desc => "await continue (accept)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, accept) end}, #{desc => "accept", cmd => fun(#{lsock := LSock} = State) -> case socket:accept(LSock) of {ok, Sock} -> {ok, State#{csock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (accept)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, accept), ok end}, #{desc => "await continue (recv-many-small)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, recv_many_small) end}, #{desc => "recv chunk 1", cmd => fun(#{csock := Sock} = State) -> case socket:recv(Sock, 100) of {ok, Chunk} -> ?SEV_IPRINT("recv of chunk 1 of ~p bytes", [size(Chunk)]), {ok, State#{chunks => [b2l(Chunk)]}}; {error, _} = ERROR -> ERROR end end}, #{desc => "recv chunk 2", cmd => fun(#{csock := Sock, chunks := Chunks} = State) -> case socket:recv(Sock, 100) of {ok, Chunk} -> ?SEV_IPRINT("recv of chunk 2 of ~p bytes", [size(Chunk)]), {ok, State#{chunks => [b2l(Chunk)|Chunks]}}; {error, _} = ERROR -> ERROR end end}, #{desc => "recv chunk 3", cmd => fun(#{csock := Sock, chunks := Chunks} = State) -> case socket:recv(Sock, 100) of {ok, Chunk} -> ?SEV_IPRINT("recv of chunk 3 of ~p bytes", [size(Chunk)]), {ok, State#{chunks => [b2l(Chunk)|Chunks]}}; {error, _} = ERROR -> ERROR end end}, #{desc => "recv chunk 4", cmd => fun(#{csock := Sock, chunks := Chunks} = State) -> case socket:recv(Sock, 100) of {ok, Chunk} -> ?SEV_IPRINT("recv of chunk 4 of ~p bytes", [size(Chunk)]), {ok, State#{chunks => [b2l(Chunk)|Chunks]}}; {error, _} = ERROR -> ERROR end end}, #{desc => "recv chunk 5", cmd => fun(#{csock := Sock, chunks := Chunks} = State) -> case socket:recv(Sock, 100) of {ok, Chunk} -> ?SEV_IPRINT("recv of chunk 5 of ~p bytes", [size(Chunk)]), {ok, State#{chunks => [b2l(Chunk)|Chunks]}}; {error, _} = ERROR -> ERROR end end}, #{desc => "recv chunk 6", cmd => fun(#{csock := Sock, chunks := Chunks} = State) -> case socket:recv(Sock, 100) of {ok, Chunk} -> ?SEV_IPRINT("recv of chunk 6 of ~p bytes", [size(Chunk)]), {ok, State#{chunks => [b2l(Chunk)|Chunks]}}; {error, _} = ERROR -> ERROR end end}, #{desc => "recv chunk 7", cmd => fun(#{csock := Sock, chunks := Chunks} = State) -> case socket:recv(Sock, 100) of {ok, Chunk} -> ?SEV_IPRINT("recv of chunk 7 of ~p bytes", [size(Chunk)]), {ok, State#{chunks => [b2l(Chunk)|Chunks]}}; {error, _} = ERROR -> ERROR end end}, #{desc => "recv chunk 8", cmd => fun(#{csock := Sock, chunks := Chunks} = State) -> case socket:recv(Sock, 100) of {ok, Chunk} -> ?SEV_IPRINT("recv of chunk 8 of ~p bytes", [size(Chunk)]), {ok, State#{chunks => [b2l(Chunk)|Chunks]}}; {error, _} = ERROR -> ERROR end end}, #{desc => "recv chunk 9", cmd => fun(#{csock := Sock, chunks := Chunks} = State) -> case socket:recv(Sock, 100) of {ok, Chunk} -> ?SEV_IPRINT("recv of chunk 9 of ~p bytes", [size(Chunk)]), {ok, State#{chunks => [b2l(Chunk)|Chunks]}}; {error, _} = ERROR -> ERROR end end}, #{desc => "recv chunk 10", cmd => fun(#{csock := Sock, chunks := Chunks} = State) -> case socket:recv(Sock, 100) of {ok, Chunk} -> ?SEV_IPRINT("recv of chunk 10 of ~p bytes", [size(Chunk)]), {ok, State#{chunks => [b2l(Chunk)|Chunks]}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (recv-many-small)", cmd => fun(#{tester := Tester, chunks := Chunks} = State) -> Data = lists:flatten(lists:reverse(Chunks)), ?SEV_ANNOUNCE_READY(Tester, recv_many_small, Data), {ok, maps:remove(chunks, State)} end}, #{desc => "await continue (recv-one-big)", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_CONTINUE(Tester, tester, recv_one_big) of {ok, Size} -> {ok, State#{size => Size}}; {error, _} = ERROR -> ERROR end end}, #{desc => "recv (one big)", cmd => fun(#{tester := Tester, csock := Sock, size := Size} = _State) -> %% socket:setopt(Sock, otp, debug, true), case socket:recv(Sock, Size) of {ok, Data} -> ?SEV_ANNOUNCE_READY(Tester, recv_one_big, b2l(Data)), ok; {error, _} = ERROR -> ERROR end end}, #{desc => "await terminate (from tester)", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "close connection socket (just in case)", cmd => fun(#{csock := Sock} = State) -> (catch socket:close(Sock)), {ok, maps:remove(csock, State)} end}, #{desc => "close listen socket", cmd => fun(#{domain := local, lsock := Sock, local_sa := #{path := Path}} = State) -> ok = socket:close(Sock), State1 = unlink_path(Path, fun() -> maps:remove(local_sa, State) end, fun() -> State end), {ok, maps:remove(lsock, State1)}; (#{lsock := Sock} = State) -> (catch socket:close(Sock)), {ok, maps:remove(lsock, State)} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], ClientSeq = [ %% *** Wait for start order part *** #{desc => "await start", cmd => fun(State) -> {Tester, ServerSA} = ?SEV_AWAIT_START(), {ok, State#{tester => Tester, server_sa => ServerSA}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "create node", cmd => fun(#{host := Host} = State) -> case start_node(Host, client) of {ok, Node} -> ?SEV_IPRINT("(remote) client node ~p started", [Node]), {ok, State#{node => Node}}; {error, Reason} -> {skip, Reason} end end}, #{desc => "monitor client node", cmd => fun(#{node := Node} = _State) -> true = erlang:monitor_node(Node, true), ok end}, #{desc => "start remote client", cmd => fun(#{node := Node} = State) -> Pid = traffic_snr_tcp_client_start(Node), ?SEV_IPRINT("client ~p started", [Pid]), {ok, State#{rclient => Pid}} end}, #{desc => "monitor remote client", cmd => fun(#{rclient := Pid}) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "order remote client to start", cmd => fun(#{rclient := Client, server_sa := ServerSA, proto := Proto}) -> ?SEV_ANNOUNCE_START(Client, {ServerSA, Proto}), ok end}, #{desc => "await remote client ready", cmd => fun(#{tester := Tester, rclient := Client} = _State) -> ?SEV_AWAIT_READY(Client, rclient, init, [{tester, Tester}]) end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, init), ok end}, %% The actual test #{desc => "await continue (connect)", cmd => fun(#{tester := Tester, rclient := Client} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, connect, [{rclient, Client}]), ok end}, #{desc => "order remote client to continue (connect)", cmd => fun(#{rclient := Client}) -> ?SEV_ANNOUNCE_CONTINUE(Client, connect), ok end}, #{desc => "await client process ready (connect)", cmd => fun(#{tester := Tester, rclient := Client} = _State) -> ?SEV_AWAIT_READY(Client, rclient, connect, [{tester, Tester}]) end}, #{desc => "announce ready (connect)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, connect), ok end}, #{desc => "await continue (send-one-big)", cmd => fun(#{tester := Tester, rclient := Client} = State) -> case ?SEV_AWAIT_CONTINUE(Tester, tester, send_one_big, [{rclient, Client}]) of {ok, Data} -> {ok, State#{data => Data}}; {error, _} = ERROR -> ERROR end end}, #{desc => "order remote client to continue (send)", cmd => fun(#{rclient := Client, data := Data}) -> ?SEV_ANNOUNCE_CONTINUE(Client, send, Data), ok end}, #{desc => "await client process ready (send)", cmd => fun(#{tester := Tester, rclient := Client} = _State) -> case ?SEV_AWAIT_READY(Client, rclient, send, [{tester, Tester}]) of {ok, Result} -> Result; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (send-one-big)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, send_one_big), ok end}, #{desc => "await continue (send-many-small)", cmd => fun(#{tester := Tester, rclient := Client} = State) -> case ?SEV_AWAIT_CONTINUE(Tester, tester, send_many_small, [{rclient, Client}]) of {ok, Data} -> {ok, State#{data => Data}}; {error, _} = ERROR -> ERROR end end}, #{desc => "order remote client to continue (send chunk 1)", cmd => fun(#{rclient := Client, data := Data} = State) -> {Chunk, RestData} = lists:split(100, Data), %% ?SEV_IPRINT("order send of chunk 1: " %% "~n Size: ~p" %% "~n ~p", [length(Chunk), Chunk]), ?SEV_ANNOUNCE_CONTINUE(Client, send, Chunk), {ok, State#{data => RestData}} end}, #{desc => "await client process ready (send chunk 1)", cmd => fun(#{tester := Tester, rclient := Client} = _State) -> case ?SEV_AWAIT_READY(Client, rclient, send, [{tester, Tester}]) of {ok, Result} -> Result; {error, _} = ERROR -> ERROR end end}, #{desc => "order remote client to continue (send chunk 2)", cmd => fun(#{rclient := Client, data := Data} = State) -> {Chunk, RestData} = lists:split(100, Data), %% ?SEV_IPRINT("order send of chunk 2: " %% "~n Size: ~p" %% "~n ~p", [length(Chunk), Chunk]), ?SEV_ANNOUNCE_CONTINUE(Client, send, Chunk), {ok, State#{data => RestData}} end}, #{desc => "await client process ready (send chunk 2)", cmd => fun(#{tester := Tester, rclient := Client} = _State) -> case ?SEV_AWAIT_READY(Client, rclient, send, [{tester, Tester}]) of {ok, Result} -> Result; {error, _} = ERROR -> ERROR end end}, #{desc => "order remote client to continue (send chunk 3)", cmd => fun(#{rclient := Client, data := Data} = State) -> {Chunk, RestData} = lists:split(100, Data), %% ?SEV_IPRINT("order send of chunk 3: " %% "~n Size: ~p" %% "~n ~p", [length(Chunk), Chunk]), ?SEV_ANNOUNCE_CONTINUE(Client, send, Chunk), {ok, State#{data => RestData}} end}, #{desc => "await client process ready (send chunk 3)", cmd => fun(#{tester := Tester, rclient := Client} = _State) -> case ?SEV_AWAIT_READY(Client, rclient, send, [{tester, Tester}]) of {ok, Result} -> Result; {error, _} = ERROR -> ERROR end end}, #{desc => "order remote client to continue (send chunk 4)", cmd => fun(#{rclient := Client, data := Data} = State) -> {Chunk, RestData} = lists:split(100, Data), %% ?SEV_IPRINT("order send of chunk 4: " %% "~n Size: ~p" %% "~n ~p", [length(Chunk), Chunk]), ?SEV_ANNOUNCE_CONTINUE(Client, send, Chunk), {ok, State#{data => RestData}} end}, #{desc => "await client process ready (send chunk 4)", cmd => fun(#{tester := Tester, rclient := Client} = _State) -> case ?SEV_AWAIT_READY(Client, rclient, send, [{tester, Tester}]) of {ok, Result} -> Result; {error, _} = ERROR -> ERROR end end}, #{desc => "order remote client to continue (send chunk 5)", cmd => fun(#{rclient := Client, data := Data} = State) -> {Chunk, RestData} = lists:split(100, Data), %% ?SEV_IPRINT("order send of chunk 5: " %% "~n Size: ~p" %% "~n ~p", [length(Chunk), Chunk]), ?SEV_ANNOUNCE_CONTINUE(Client, send, Chunk), {ok, State#{data => RestData}} end}, #{desc => "await client process ready (send chunk 5)", cmd => fun(#{tester := Tester, rclient := Client} = _State) -> case ?SEV_AWAIT_READY(Client, rclient, send, [{tester, Tester}]) of {ok, Result} -> Result; {error, _} = ERROR -> ERROR end end}, #{desc => "order remote client to continue (send chunk 6)", cmd => fun(#{rclient := Client, data := Data} = State) -> {Chunk, RestData} = lists:split(100, Data), %% ?SEV_IPRINT("order send of chunk 6: " %% "~n Size: ~p" %% "~n ~p", [length(Chunk), Chunk]), ?SEV_ANNOUNCE_CONTINUE(Client, send, Chunk), {ok, State#{data => RestData}} end}, #{desc => "await client process ready (send chunk 6)", cmd => fun(#{tester := Tester, rclient := Client} = _State) -> case ?SEV_AWAIT_READY(Client, rclient, send, [{tester, Tester}]) of {ok, Result} -> Result; {error, _} = ERROR -> ERROR end end}, #{desc => "order remote client to continue (send chunk 7)", cmd => fun(#{rclient := Client, data := Data} = State) -> {Chunk, RestData} = lists:split(100, Data), %% ?SEV_IPRINT("order send of chunk 7: " %% "~n Size: ~p" %% "~n ~p", [length(Chunk), Chunk]), ?SEV_ANNOUNCE_CONTINUE(Client, send, Chunk), {ok, State#{data => RestData}} end}, #{desc => "await client process ready (send chunk 7)", cmd => fun(#{tester := Tester, rclient := Client} = _State) -> case ?SEV_AWAIT_READY(Client, rclient, send, [{tester, Tester}]) of {ok, Result} -> Result; {error, _} = ERROR -> ERROR end end}, #{desc => "order remote client to continue (send chunk 8)", cmd => fun(#{rclient := Client, data := Data} = State) -> {Chunk, RestData} = lists:split(100, Data), %% ?SEV_IPRINT("order send of chunk 8: " %% "~n Size: ~p" %% "~n ~p", [length(Chunk), Chunk]), ?SEV_ANNOUNCE_CONTINUE(Client, send, Chunk), {ok, State#{data => RestData}} end}, #{desc => "await client process ready (send chunk 8)", cmd => fun(#{tester := Tester, rclient := Client} = _State) -> case ?SEV_AWAIT_READY(Client, rclient, send, [{tester, Tester}]) of {ok, Result} -> Result; {error, _} = ERROR -> ERROR end end}, #{desc => "order remote client to continue (send chunk 9)", cmd => fun(#{rclient := Client, data := Data} = State) -> {Chunk, RestData} = lists:split(100, Data), %% ?SEV_IPRINT("order send of chunk 9: " %% "~n Size: ~p" %% "~n ~p", [length(Chunk), Chunk]), ?SEV_ANNOUNCE_CONTINUE(Client, send, Chunk), {ok, State#{data => RestData}} end}, #{desc => "await client process ready (send chunk 9)", cmd => fun(#{tester := Tester, rclient := Client} = _State) -> case ?SEV_AWAIT_READY(Client, rclient, send, [{tester, Tester}]) of {ok, Result} -> Result; {error, _} = ERROR -> ERROR end end}, #{desc => "order remote client to continue (send chunk 10)", cmd => fun(#{rclient := Client, data := Data} = State) -> {Chunk, []} = lists:split(100, Data), %% ?SEV_IPRINT("order send of chunk 10: " %% "~n Size: ~p" %% "~n ~p", [length(Chunk), Chunk]), ?SEV_ANNOUNCE_CONTINUE(Client, send, Chunk), {ok, maps:remove(data, State)} end}, #{desc => "await client process ready (send chunk 10)", cmd => fun(#{tester := Tester, rclient := Client} = _State) -> case ?SEV_AWAIT_READY(Client, rclient, send, [{tester, Tester}]) of {ok, Result} -> Result; {error, _} = ERROR -> ERROR end end}, #{desc => "order remote client to continue (send stop)", cmd => fun(#{rclient := Client} = State) -> ?SEV_ANNOUNCE_CONTINUE(Client, send, stop), {ok, maps:remove(data, State)} end}, #{desc => "await client process ready (send stop)", cmd => fun(#{tester := Tester, rclient := Client} = _State) -> case ?SEV_AWAIT_READY(Client, rclient, send, [{tester, Tester}]) of {ok, Result} -> Result; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (send-many-small)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, send_many_small), ok end}, %% Termination #{desc => "await terminate (from tester)", cmd => fun(#{tester := Tester, rclient := Client} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester, [{rclient, Client}]) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "kill remote client", cmd => fun(#{rclient := Client}) -> ?SEV_ANNOUNCE_TERMINATE(Client), ok end}, #{desc => "await remote client termination", cmd => fun(#{rclient := Client} = State) -> ?SEV_AWAIT_TERMINATION(Client), State1 = maps:remove(rclient, State), {ok, State1} end}, #{desc => "stop client node", cmd => fun(#{node := Node} = _State) -> stop_node(Node) end}, #{desc => "await client node termination", cmd => fun(#{node := Node} = State) -> receive {nodedown, Node} -> {ok, maps:remove(node, State)} end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], TesterSeq = [ %% *** Init part *** #{desc => "monitor server", cmd => fun(#{server := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "monitor client", cmd => fun(#{client := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, %% Start the server #{desc => "order server start", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_START(Pid), ok end}, #{desc => "await server ready (init)", cmd => fun(#{server := Pid} = State) -> {ok, ServerSA} = ?SEV_AWAIT_READY(Pid, server, init), {ok, State#{server_sa => ServerSA}} end}, %% Start the client #{desc => "order client start", cmd => fun(#{client := Pid, server_sa := ServerSA} = _State) -> ?SEV_ANNOUNCE_START(Pid, ServerSA), ok end}, #{desc => "await client ready (init)", cmd => fun(#{client := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, client, init) end}, %% The actual test #{desc => "order server continue (accept)", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, accept), ok end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order client continue (connect)", cmd => fun(#{client := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, connect), ok end}, #{desc => "await server ready (accept)", cmd => fun(#{server := Server, client := Client} = _State) -> ?SEV_AWAIT_READY(Server, server, accept, [{client, Client}]), ok end}, #{desc => "await client ready (connect)", cmd => fun(#{server := Server, client := Client} = _State) -> ?SEV_AWAIT_READY(Client, client, connect, [{server, Server}]) end}, #{desc => "generate data", cmd => fun(State) -> D1 = lists:seq(1,250), D2 = lists:duplicate(4, D1), D3 = lists:flatten(D2), {ok, State#{data => D3}} end}, %% (client) Send one big and (server) recv may small #{desc => "order server continue (recv-many-small)", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, recv_many_small), ok end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order client continue (send-one-big)", cmd => fun(#{client := Pid, data := Data} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, send_one_big, Data), ok end}, #{desc => "await client ready (send-one-big)", cmd => fun(#{server := Server, client := Client} = _State) -> ok = ?SEV_AWAIT_READY(Client, client, send_one_big, [{server, Server}]) end}, #{desc => "await server ready (recv-many-small)", cmd => fun(#{server := Server, client := Client, data := Data} = _State) -> case ?SEV_AWAIT_READY(Server, server, recv_many_small, [{client, Client}]) of {ok, Data} -> ok; {ok, OtherData} -> {error, {mismatched_data, Data, OtherData}}; {error, _} = ERROR -> ERROR end end}, #{desc => "order server continue (recv-one-big)", cmd => fun(#{server := Pid, data := Data} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, recv_one_big, length(Data)), ok end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order client continue (send-many-small)", cmd => fun(#{client := Pid, data := Data} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, send_many_small, Data), ok end}, #{desc => "await client ready (send-many-small)", cmd => fun(#{server := Server, client := Client} = _State) -> ok = ?SEV_AWAIT_READY(Client, client, send_many_small, [{server, Server}]) end}, #{desc => "await server ready (recv-one-big)", cmd => fun(#{server := Server, client := Client, data := Data} = State) -> case ?SEV_AWAIT_READY(Server, server, recv_one_big, [{client, Client}]) of {ok, Data} -> {ok, maps:remove(data, State)}; {ok, OtherData} -> {error, {mismatched_data, Data, OtherData}}; {error, _} = ERROR -> ERROR end end}, %% Terminations #{desc => "order client to terminate", cmd => fun(#{client := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await client termination", cmd => fun(#{client := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> State1 = maps:remove(client, State), {ok, State1}; {error, _} = ERROR -> ERROR end end}, #{desc => "order server to terminate", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await server termination", cmd => fun(#{server := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> State1 = maps:remove(server, State), {ok, State1}; {error, _} = ERROR -> ERROR end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], i("start server evaluator"), ServerInitState = InitState, Server = ?SEV_START("server", ServerSeq, ServerInitState), i("start client evaluator(s)"), ClientInitState = InitState#{host => local_host()}, Client = ?SEV_START("client", ClientSeq, ClientInitState), i("start 'tester' evaluator"), TesterInitState = #{server => Server#ev.pid, client => Client#ev.pid}, Tester = ?SEV_START("tester", TesterSeq, TesterInitState), i("await evaluator"), ok = ?SEV_AWAIT_FINISH([Server, Client, Tester]). traffic_snr_tcp_client_start(Node) -> Self = self(), Fun = fun() -> traffic_snr_tcp_client(Self) end, erlang:spawn(Node, Fun). traffic_snr_tcp_client(Parent) -> {Sock, ServerSA, Path} = traffic_snr_tcp_client_init(Parent), traffic_snr_tcp_client_announce_ready(Parent, init), traffic_snr_tcp_client_await_continue(Parent, connect), traffic_snr_tcp_client_connect(Sock, ServerSA), traffic_snr_tcp_client_announce_ready(Parent, connect), traffic_snr_tcp_client_send_loop(Parent, Sock), Reason = traffic_snr_tcp_client_await_terminate(Parent), traffic_snr_tcp_client_close(Sock, Path), exit(Reason). traffic_snr_tcp_client_send_loop(Parent, Sock) -> case ?SEV_AWAIT_CONTINUE(Parent, parent, send) of {ok, stop} -> % Breakes the loop ?SEV_ANNOUNCE_READY(Parent, send, ok), ok; {ok, Data} -> case socket:send(Sock, Data) of ok -> ?SEV_ANNOUNCE_READY(Parent, send, ok), traffic_snr_tcp_client_send_loop(Parent, Sock); {error, Reason} = ERROR -> ?SEV_ANNOUNCE_READY(Parent, send, ERROR), exit({send, Reason}) end; {error, Reason} -> exit({await_continue, Reason}) end. traffic_snr_tcp_client_init(Parent) -> put(sname, "rclient"), ?SEV_IPRINT("init"), _MRef = erlang:monitor(process, Parent), {ServerSA, Proto} = traffic_snr_tcp_client_await_start(Parent), Domain = maps:get(family, ServerSA), Sock = traffic_snr_tcp_client_create(Domain, Proto), Path = traffic_snr_tcp_client_bind(Sock, Domain), {Sock, ServerSA, Path}. traffic_snr_tcp_client_await_start(Parent) -> i("traffic_snr_tcp_client_await_start -> entry"), ?SEV_AWAIT_START(Parent). traffic_snr_tcp_client_create(Domain, Proto) -> i("traffic_snr_tcp_client_create -> entry"), case socket:open(Domain, stream, Proto) of {ok, Sock} -> Sock; {error, Reason} -> exit({open_failed, Reason}) end. traffic_snr_tcp_client_bind(Sock, Domain) -> i("traffic_snr_tcp_client_bind -> entry"), LSA = which_local_socket_addr(Domain), case socket:bind(Sock, LSA) of {ok, _} -> case socket:sockname(Sock) of {ok, #{family := local, path := Path}} -> Path; {ok, _} -> undefined; {error, Reason1} -> exit({sockname, Reason1}) end; {error, Reason} -> exit({bind, Reason}) end. traffic_snr_tcp_client_announce_ready(Parent, Slogan) -> ?SEV_ANNOUNCE_READY(Parent, Slogan). traffic_snr_tcp_client_await_continue(Parent, Slogan) -> i("traffic_snr_tcp_client_await_continue -> entry"), ?SEV_AWAIT_CONTINUE(Parent, parent, Slogan). traffic_snr_tcp_client_connect(Sock, ServerSA) -> i("traffic_snr_tcp_client_connect -> entry"), case socket:connect(Sock, ServerSA) of ok -> ok; {error, Reason} -> exit({connect, Reason}) end. traffic_snr_tcp_client_close(Sock, Path) -> i("traffic_snr_tcp_client_close -> entry"), case socket:close(Sock) of ok -> unlink_path(Path), ok; {error, Reason} -> ?SEV_EPRINT("failed closing: " "~n Reason: ~p", [Reason]), unlink_path(Path), {error, {close, Reason}} end. traffic_snr_tcp_client_await_terminate(Parent) -> i("traffic_snr_tcp_client_await_terminate -> entry"), case ?SEV_AWAIT_TERMINATE(Parent, parent) of ok -> ok; {error, Reason} -> Reason end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the send and recv functions %% by repeatedly sending a meassage between two entities. %% The same basic test case is used for three different message sizes; %% small (8 bytes), medium (8K) and large (8M). %% The message is sent from A to B and then back again. This is %% repeated a set number of times (more times the small the message). %% This is the 'small' message test case, for IPv4. traffic_ping_pong_small_send_and_recv_tcp4(suite) -> []; traffic_ping_pong_small_send_and_recv_tcp4(doc) -> []; traffic_ping_pong_small_send_and_recv_tcp4(_Config) when is_list(_Config) -> ?TT(?SECS(15)), Msg = l2b(?TPP_SMALL), Num = ?TPP_SMALL_NUM, tc_try(traffic_ping_pong_small_send_and_recv_tcp4, fun() -> InitState = #{domain => inet, proto => tcp, msg => Msg, num => Num}, ok = traffic_ping_pong_send_and_recv_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the send and recv functions %% by repeatedly sending a meassage between two entities. %% The same basic test case is used for three different message sizes; %% small (8 bytes), medium (8K) and large (8M). %% The message is sent from A to B and then back again. This is %% repeated a set number of times (more times the small the message). %% This is the 'small' message test case, for IPv6. traffic_ping_pong_small_send_and_recv_tcp6(suite) -> []; traffic_ping_pong_small_send_and_recv_tcp6(doc) -> []; traffic_ping_pong_small_send_and_recv_tcp6(_Config) when is_list(_Config) -> ?TT(?SECS(15)), Msg = l2b(?TPP_SMALL), Num = ?TPP_SMALL_NUM, tc_try(traffic_ping_pong_small_send_and_recv_tcp6, fun() -> has_support_ipv6() end, fun() -> InitState = #{domain => inet6, proto => tcp, msg => Msg, num => Num}, ok = traffic_ping_pong_send_and_recv_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the send and recv functions %% by repeatedly sending a meassage between two entities. %% The same basic test case is used for three different message sizes; %% small (8 bytes), medium (8K) and large (8M). %% The message is sent from A to B and then back again. This is %% repeated a set number of times (more times the small the message). %% This is the 'small' message test case, for Unix Domain (stream) socket. traffic_ping_pong_small_send_and_recv_tcpL(suite) -> []; traffic_ping_pong_small_send_and_recv_tcpL(doc) -> []; traffic_ping_pong_small_send_and_recv_tcpL(_Config) when is_list(_Config) -> ?TT(?SECS(15)), Msg = l2b(?TPP_SMALL), Num = ?TPP_SMALL_NUM, tc_try(traffic_ping_pong_small_send_and_recv_tcpL, fun() -> has_support_unix_domain_socket() end, fun() -> InitState = #{domain => local, proto => default, msg => Msg, num => Num}, ok = traffic_ping_pong_send_and_recv_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the send and recv functions %% by repeatedly sending a meassage between two entities. %% The same basic test case is used for three different message sizes; %% small (8 bytes), medium (8K) and large (8M). %% The message is sent from A to B and then back again. This is %% repeated a set number of times (more times the small the message). %% This is the 'medium' message test case, for IPv4. traffic_ping_pong_medium_send_and_recv_tcp4(suite) -> []; traffic_ping_pong_medium_send_and_recv_tcp4(doc) -> []; traffic_ping_pong_medium_send_and_recv_tcp4(_Config) when is_list(_Config) -> Msg = l2b(?TPP_MEDIUM), Num = ?TPP_MEDIUM_NUM, tc_try(traffic_ping_pong_medium_send_and_recv_tcp4, fun() -> ?TT(?SECS(30)), InitState = #{domain => inet, proto => tcp, msg => Msg, num => Num}, ok = traffic_ping_pong_send_and_recv_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the send and recv functions %% by repeatedly sending a meassage between two entities. %% The same basic test case is used for three different message sizes; %% small (8 bytes), medium (8K) and large (8M). %% The message is sent from A to B and then back again. This is %% repeated a set number of times (more times the small the message). %% This is the 'medium' message test case, for IPv6. traffic_ping_pong_medium_send_and_recv_tcp6(suite) -> []; traffic_ping_pong_medium_send_and_recv_tcp6(doc) -> []; traffic_ping_pong_medium_send_and_recv_tcp6(_Config) when is_list(_Config) -> Msg = l2b(?TPP_MEDIUM), Num = ?TPP_MEDIUM_NUM, tc_try(traffic_ping_pong_medium_send_and_recv_tcp6, fun() -> has_support_ipv6() end, fun() -> ?TT(?SECS(30)), InitState = #{domain => inet6, proto => tcp, msg => Msg, num => Num}, ok = traffic_ping_pong_send_and_recv_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the send and recv functions %% by repeatedly sending a meassage between two entities. %% The same basic test case is used for three different message sizes; %% small (8 bytes), medium (8K) and large (8M). %% The message is sent from A to B and then back again. This is %% repeated a set number of times (more times the small the message). %% This is the 'medium' message test case, for Unix Domain (stream) socket. traffic_ping_pong_medium_send_and_recv_tcpL(suite) -> []; traffic_ping_pong_medium_send_and_recv_tcpL(doc) -> []; traffic_ping_pong_medium_send_and_recv_tcpL(_Config) when is_list(_Config) -> ?TT(?SECS(30)), Msg = l2b(?TPP_MEDIUM), Num = ?TPP_MEDIUM_NUM, tc_try(traffic_ping_pong_medium_send_and_recv_tcpL, fun() -> has_support_unix_domain_socket() end, fun() -> InitState = #{domain => local, proto => default, msg => Msg, num => Num}, ok = traffic_ping_pong_send_and_recv_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the send and recv functions %% by repeatedly sending a meassage between two entities. %% The same basic test case is used for three different message sizes; %% small (8 bytes), medium (8K) and large (8M). %% The message is sent from A to B and then back again. This is %% repeated a set number of times (more times the small the message). %% This is the 'large' message test case, for IPv4. traffic_ping_pong_large_send_and_recv_tcp4(suite) -> []; traffic_ping_pong_large_send_and_recv_tcp4(doc) -> []; traffic_ping_pong_large_send_and_recv_tcp4(_Config) when is_list(_Config) -> ?TT(?SECS(45)), Msg = l2b(?TPP_LARGE), Num = ?TPP_LARGE_NUM, tc_try(traffic_ping_pong_large_send_and_recv_tcp4, fun() -> is_old_fedora16() end, fun() -> InitState = #{domain => inet, proto => tcp, msg => Msg, num => Num}, ok = traffic_ping_pong_send_and_recv_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the send and recv functions %% by repeatedly sending a meassage between two entities. %% The same basic test case is used for three different message sizes; %% small (8 bytes), medium (8K) and large (8M). %% The message is sent from A to B and then back again. This is %% repeated a set number of times (more times the small the message). %% This is the 'large' message test case, for IPv6. traffic_ping_pong_large_send_and_recv_tcp6(suite) -> []; traffic_ping_pong_large_send_and_recv_tcp6(doc) -> []; traffic_ping_pong_large_send_and_recv_tcp6(_Config) when is_list(_Config) -> Msg = l2b(?TPP_LARGE), Num = ?TPP_LARGE_NUM, tc_try(traffic_ping_pong_large_send_and_recv_tcp6, fun() -> is_old_fedora16(), has_support_ipv6() end, fun() -> ?TT(?SECS(45)), InitState = #{domain => inet6, proto => tcp, msg => Msg, num => Num}, ok = traffic_ping_pong_send_and_recv_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the send and recv functions %% by repeatedly sending a meassage between two entities. %% The same basic test case is used for three different message sizes; %% small (8 bytes), medium (8K) and large (8M). %% The message is sent from A to B and then back again. This is %% repeated a set number of times (more times the small the message). %% This is the 'large' message test case, for UNix Domain (stream) socket. traffic_ping_pong_large_send_and_recv_tcpL(suite) -> []; traffic_ping_pong_large_send_and_recv_tcpL(doc) -> []; traffic_ping_pong_large_send_and_recv_tcpL(_Config) when is_list(_Config) -> ?TT(?SECS(45)), Msg = l2b(?TPP_LARGE), Num = ?TPP_LARGE_NUM, tc_try(traffic_ping_pong_large_send_and_recv_tcpL, fun() -> has_support_unix_domain_socket(), traffic_ping_pong_large_host_cond() end, fun() -> InitState = #{domain => local, proto => default, msg => Msg, num => Num}, ok = traffic_ping_pong_send_and_recv_tcp(InitState) end). %% This test case is a bit extreme and fails on some hosts %% (e.g. OpenIndiana Hipster), so exclude them. traffic_ping_pong_large_host_cond() -> traffic_ping_pong_large_host_cond(os:type(), os:version()). traffic_ping_pong_large_host_cond({unix, sunos}, _) -> skip("TC does not work on platform"); traffic_ping_pong_large_host_cond({unix, linux}, _) -> traffic_ping_pong_large_host_cond2(string:trim(os:cmd("cat /etc/issue"))); traffic_ping_pong_large_host_cond(_, _) -> ok. traffic_ping_pong_large_host_cond2("Welcome to SUSE Linux Enterprise Server 10 SP1 (i586)" ++ _) -> skip("TC does not work on platform"); traffic_ping_pong_large_host_cond2("Fedora release 16 " ++ _) -> skip("Very slow VM"); traffic_ping_pong_large_host_cond2(_) -> ok. is_old_fedora16() -> is_old_fedora16(string:trim(os:cmd("cat /etc/issue"))). %% We actually only have one host running this, a slow VM. is_old_fedora16("Fedora release 16 " ++ _) -> skip("Very slow VM"); is_old_fedora16(_) -> ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the sendto and recvfrom %% functions by repeatedly sending a meassage between two entities. %% The same basic test case is used for two different message sizes; %% small (8 bytes) and medium (8K). %% The message is sent from A to B and then back again. This is %% repeated a set number of times (more times the small the message). %% This is the 'small' message test case, for IPv4. traffic_ping_pong_small_sendto_and_recvfrom_udp4(suite) -> []; traffic_ping_pong_small_sendto_and_recvfrom_udp4(doc) -> []; traffic_ping_pong_small_sendto_and_recvfrom_udp4(_Config) when is_list(_Config) -> Msg = l2b(?TPP_SMALL), Num = ?TPP_SMALL_NUM, tc_try(traffic_ping_pong_small_sendto_and_recvfrom_udp4, fun() -> ?TT(?SECS(45)), InitState = #{domain => inet, proto => udp, msg => Msg, num => Num}, ok = traffic_ping_pong_sendto_and_recvfrom_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the sendto and recvfrom %% functions by repeatedly sending a meassage between two entities. %% The same basic test case is used for two different message sizes; %% small (8 bytes) and medium (8K). %% The message is sent from A to B and then back again. This is %% repeated a set number of times (more times the small the message). %% This is the 'small' message test case, for IPv6. traffic_ping_pong_small_sendto_and_recvfrom_udp6(suite) -> []; traffic_ping_pong_small_sendto_and_recvfrom_udp6(doc) -> []; traffic_ping_pong_small_sendto_and_recvfrom_udp6(_Config) when is_list(_Config) -> Msg = l2b(?TPP_SMALL), Num = ?TPP_SMALL_NUM, tc_try(traffic_ping_pong_small_sendto_and_recvfrom_udp6, fun() -> has_support_ipv6() end, fun() -> ?TT(?SECS(45)), InitState = #{domain => inet6, proto => udp, msg => Msg, num => Num}, ok = traffic_ping_pong_sendto_and_recvfrom_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the sendto and recvfrom %% functions by repeatedly sending a meassage between two entities. %% The same basic test case is used for two different message sizes; %% small (8 bytes) and medium (8K). %% The message is sent from A to B and then back again. This is %% repeated a set number of times (more times the small the message). %% This is the 'small' message test case, for Unix Domain (dgram) socket. traffic_ping_pong_small_sendto_and_recvfrom_udpL(suite) -> []; traffic_ping_pong_small_sendto_and_recvfrom_udpL(doc) -> []; traffic_ping_pong_small_sendto_and_recvfrom_udpL(_Config) when is_list(_Config) -> Msg = l2b(?TPP_SMALL), Num = ?TPP_SMALL_NUM, tc_try(traffic_ping_pong_small_sendto_and_recvfrom_udpL, fun() -> has_support_unix_domain_socket() end, fun() -> ?TT(?SECS(45)), InitState = #{domain => local, proto => default, msg => Msg, num => Num}, ok = traffic_ping_pong_sendto_and_recvfrom_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the sendto and recvfrom %% functions by repeatedly sending a meassage between two entities. %% The same basic test case is used for two different message sizes; %% small (8 bytes) and medium (8K). %% The message is sent from A to B and then back again. This is %% repeated a set number of times (more times the small the message). %% This is the 'medium' message test case, for IPv4. traffic_ping_pong_medium_sendto_and_recvfrom_udp4(suite) -> []; traffic_ping_pong_medium_sendto_and_recvfrom_udp4(doc) -> []; traffic_ping_pong_medium_sendto_and_recvfrom_udp4(_Config) when is_list(_Config) -> Msg = l2b(?TPP_MEDIUM), Num = ?TPP_MEDIUM_NUM, tc_try(traffic_ping_pong_medium_sendto_and_recvfrom_udp4, fun() -> ?TT(?SECS(45)), InitState = #{domain => inet, proto => udp, msg => Msg, num => Num}, ok = traffic_ping_pong_sendto_and_recvfrom_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the sendto and recvfrom %% functions by repeatedly sending a meassage between two entities. %% The same basic test case is used for two different message sizes; %% small (8 bytes) and medium (8K). %% The message is sent from A to B and then back again. This is %% repeated a set number of times (more times the small the message). %% This is the 'medium' message test case, for IPv6. traffic_ping_pong_medium_sendto_and_recvfrom_udp6(suite) -> []; traffic_ping_pong_medium_sendto_and_recvfrom_udp6(doc) -> []; traffic_ping_pong_medium_sendto_and_recvfrom_udp6(_Config) when is_list(_Config) -> Msg = l2b(?TPP_MEDIUM), Num = ?TPP_MEDIUM_NUM, tc_try(traffic_ping_pong_medium_sendto_and_recvfrom_udp6, fun() -> has_support_ipv6() end, fun() -> ?TT(?SECS(45)), InitState = #{domain => inet6, proto => udp, msg => Msg, num => Num}, ok = traffic_ping_pong_sendto_and_recvfrom_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the sendto and recvfrom %% functions by repeatedly sending a meassage between two entities. %% The same basic test case is used for two different message sizes; %% small (8 bytes) and medium (8K). %% The message is sent from A to B and then back again. This is %% repeated a set number of times (more times the small the message). %% This is the 'medium' message test case, for Unix Domain (dgram) socket. traffic_ping_pong_medium_sendto_and_recvfrom_udpL(suite) -> []; traffic_ping_pong_medium_sendto_and_recvfrom_udpL(doc) -> []; traffic_ping_pong_medium_sendto_and_recvfrom_udpL(_Config) when is_list(_Config) -> Msg = l2b(?TPP_MEDIUM), Num = ?TPP_MEDIUM_NUM, tc_try(traffic_ping_pong_medium_sendto_and_recvfrom_udpL, fun() -> has_support_unix_domain_socket() end, fun() -> ?TT(?SECS(45)), InitState = #{domain => local, proto => default, msg => Msg, num => Num}, ok = traffic_ping_pong_sendto_and_recvfrom_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the sendmsg and recvmsg %% functions by repeatedly sending a meassage between two entities. %% The same basic test case is used for three different message sizes; %% small (8 bytes), medium (8K) and large (8M). %% The message is sent from A to B and then back again. This is %% repeated a set number of times (more times the small the message). %% This is the 'small' message test case, for IPv4. traffic_ping_pong_small_sendmsg_and_recvmsg_tcp4(suite) -> []; traffic_ping_pong_small_sendmsg_and_recvmsg_tcp4(doc) -> []; traffic_ping_pong_small_sendmsg_and_recvmsg_tcp4(_Config) when is_list(_Config) -> Msg = l2b(?TPP_SMALL), Num = ?TPP_SMALL_NUM, tc_try(traffic_ping_pong_small_sendmsg_and_recvmsg_tcp4, fun() -> ?TT(?SECS(20)), InitState = #{domain => inet, proto => tcp, msg => Msg, num => Num}, ok = traffic_ping_pong_sendmsg_and_recvmsg_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the sendmsg and recvmsg functions %% by repeatedly sending a meassage between two entities. %% The same basic test case is used for three different message sizes; %% small (8 bytes), medium (8K) and large (8M). %% The message is sent from A to B and then back again. This is %% repeated a set number of times (more times the small the message). %% This is the 'small' message test case, for IPv6. traffic_ping_pong_small_sendmsg_and_recvmsg_tcp6(suite) -> []; traffic_ping_pong_small_sendmsg_and_recvmsg_tcp6(doc) -> []; traffic_ping_pong_small_sendmsg_and_recvmsg_tcp6(_Config) when is_list(_Config) -> Msg = l2b(?TPP_SMALL), Num = ?TPP_SMALL_NUM, tc_try(traffic_ping_pong_small_sendmsg_and_recvmsg_tcp6, fun() -> has_support_ipv6() end, fun() -> ?TT(?SECS(20)), InitState = #{domain => inet6, proto => tcp, msg => Msg, num => Num}, ok = traffic_ping_pong_sendmsg_and_recvmsg_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the sendmsg and recvmsg functions %% by repeatedly sending a meassage between two entities. %% The same basic test case is used for three different message sizes; %% small (8 bytes), medium (8K) and large (8M). %% The message is sent from A to B and then back again. This is %% repeated a set number of times (more times the small the message). %% This is the 'small' message test case, for Unix Domain (stream) socket. traffic_ping_pong_small_sendmsg_and_recvmsg_tcpL(suite) -> []; traffic_ping_pong_small_sendmsg_and_recvmsg_tcpL(doc) -> []; traffic_ping_pong_small_sendmsg_and_recvmsg_tcpL(_Config) when is_list(_Config) -> Msg = l2b(?TPP_SMALL), Num = ?TPP_SMALL_NUM, tc_try(traffic_ping_pong_small_sendmsg_and_recvmsg_tcpL, fun() -> has_support_unix_domain_socket() end, fun() -> ?TT(?SECS(20)), InitState = #{domain => local, proto => default, msg => Msg, num => Num}, ok = traffic_ping_pong_sendmsg_and_recvmsg_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the sendmsg and recvmsg %% functions by repeatedly sending a meassage between two entities. %% The same basic test case is used for three different message sizes; %% small (8 bytes), medium (8K) and large (8M). %% The message is sent from A to B and then back again. This is %% repeated a set number of times (more times the small the message). %% This is the 'medium' message test case, for IPv4. traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp4(suite) -> []; traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp4(doc) -> []; traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp4(_Config) when is_list(_Config) -> Msg = l2b(?TPP_MEDIUM), Num = ?TPP_MEDIUM_NUM, tc_try(traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp4, fun() -> ?TT(?SECS(30)), InitState = #{domain => inet, proto => tcp, msg => Msg, num => Num}, ok = traffic_ping_pong_sendmsg_and_recvmsg_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the sendmsg and recvmsg functions %% by repeatedly sending a meassage between two entities. %% The same basic test case is used for three different message sizes; %% small (8 bytes), medium (8K) and large (8M). %% The message is sent from A to B and then back again. This is %% repeated a set number of times (more times the small the message). %% This is the 'medium' message test case, for IPv6. traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp6(suite) -> []; traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp6(doc) -> []; traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp6(_Config) when is_list(_Config) -> Msg = l2b(?TPP_MEDIUM), Num = ?TPP_MEDIUM_NUM, tc_try(traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp6, fun() -> has_support_ipv6() end, fun() -> ?TT(?SECS(30)), InitState = #{domain => inet6, proto => tcp, msg => Msg, num => Num}, ok = traffic_ping_pong_sendmsg_and_recvmsg_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the sendmsg and recvmsg functions %% by repeatedly sending a meassage between two entities. %% The same basic test case is used for three different message sizes; %% small (8 bytes), medium (8K) and large (8M). %% The message is sent from A to B and then back again. This is %% repeated a set number of times (more times the small the message). %% This is the 'medium' message test case, for Unix Domain (stream) socket. traffic_ping_pong_medium_sendmsg_and_recvmsg_tcpL(suite) -> []; traffic_ping_pong_medium_sendmsg_and_recvmsg_tcpL(doc) -> []; traffic_ping_pong_medium_sendmsg_and_recvmsg_tcpL(_Config) when is_list(_Config) -> Msg = l2b(?TPP_MEDIUM), Num = ?TPP_MEDIUM_NUM, tc_try(traffic_ping_pong_medium_sendmsg_and_recvmsg_tcpL, fun() -> has_support_unix_domain_socket() end, fun() -> ?TT(?SECS(30)), InitState = #{domain => local, proto => default, msg => Msg, num => Num}, ok = traffic_ping_pong_sendmsg_and_recvmsg_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the sendmsg and recvmsg %% functions by repeatedly sending a meassage between two entities. %% The same basic test case is used for three different message sizes; %% small (8 bytes), medium (8K) and large (8M). %% The message is sent from A to B and then back again. This is %% repeated a set number of times (more times the small the message). %% This is the 'large' message test case, for IPv4. traffic_ping_pong_large_sendmsg_and_recvmsg_tcp4(suite) -> []; traffic_ping_pong_large_sendmsg_and_recvmsg_tcp4(doc) -> []; traffic_ping_pong_large_sendmsg_and_recvmsg_tcp4(_Config) when is_list(_Config) -> Msg = l2b(?TPP_LARGE), Num = ?TPP_LARGE_NUM, tc_try(traffic_ping_pong_large_sendmsg_and_recvmsg_tcp4, fun() -> traffic_ping_pong_large_sendmsg_and_recvmsg_cond() end, fun() -> ?TT(?SECS(60)), InitState = #{domain => inet, proto => tcp, msg => Msg, num => Num}, ok = traffic_ping_pong_sendmsg_and_recvmsg_tcp(InitState) end). traffic_ping_pong_large_sendmsg_and_recvmsg_cond() -> traffic_ping_pong_large_sendmsg_and_recvmsg_cond(os:type(), os:version()). traffic_ping_pong_large_sendmsg_and_recvmsg_cond({unix, linux}, {M, _, _}) when (M < 3) -> skip("TC may not work on this version"); traffic_ping_pong_large_sendmsg_and_recvmsg_cond(_, _) -> ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the sendmsg and recvmsg functions %% by repeatedly sending a meassage between two entities. %% The same basic test case is used for three different message sizes; %% small (8 bytes), medium (8K) and large (8M). %% The message is sent from A to B and then back again. This is %% repeated a set number of times (more times the small the message). %% This is the 'large' message test case, for IPv6. traffic_ping_pong_large_sendmsg_and_recvmsg_tcp6(suite) -> []; traffic_ping_pong_large_sendmsg_and_recvmsg_tcp6(doc) -> []; traffic_ping_pong_large_sendmsg_and_recvmsg_tcp6(_Config) when is_list(_Config) -> Msg = l2b(?TPP_LARGE), Num = ?TPP_LARGE_NUM, tc_try(traffic_ping_pong_large_sendmsg_and_recvmsg_tcp6, fun() -> has_support_ipv6(), traffic_ping_pong_large_sendmsg_and_recvmsg_cond() end, fun() -> ?TT(?SECS(60)), InitState = #{domain => inet6, proto => tcp, msg => Msg, num => Num}, ok = traffic_ping_pong_sendmsg_and_recvmsg_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the sendmsg and recvmsg functions %% by repeatedly sending a meassage between two entities. %% The same basic test case is used for three different message sizes; %% small (8 bytes), medium (8K) and large (8M). %% The message is sent from A to B and then back again. This is %% repeated a set number of times (more times the small the message). %% This is the 'large' message test case, for Unix Domain (stream) socket. traffic_ping_pong_large_sendmsg_and_recvmsg_tcpL(suite) -> []; traffic_ping_pong_large_sendmsg_and_recvmsg_tcpL(doc) -> []; traffic_ping_pong_large_sendmsg_and_recvmsg_tcpL(_Config) when is_list(_Config) -> Msg = l2b(?TPP_LARGE), Num = ?TPP_LARGE_NUM, tc_try(traffic_ping_pong_large_sendmsg_and_recvmsg_tcpL, fun() -> has_support_unix_domain_socket() end, fun() -> ?TT(?SECS(60)), InitState = #{domain => local, proto => default, msg => Msg, num => Num}, ok = traffic_ping_pong_sendmsg_and_recvmsg_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the sendmsg and recvmsg %% functions by repeatedly sending a meassage between two entities. %% The same basic test case is used for three different message sizes; %% small (8 bytes) and medium (8K). %% The message is sent from A to B and then back again. This is %% repeated a set number of times (more times the small the message). %% This is the 'small' message test case, for IPv4. traffic_ping_pong_small_sendmsg_and_recvmsg_udp4(suite) -> []; traffic_ping_pong_small_sendmsg_and_recvmsg_udp4(doc) -> []; traffic_ping_pong_small_sendmsg_and_recvmsg_udp4(_Config) when is_list(_Config) -> Msg = l2b(?TPP_SMALL), Num = ?TPP_SMALL_NUM, tc_try(traffic_ping_pong_small_sendmsg_and_recvmsg_udp4, fun() -> ?TT(?SECS(60)), InitState = #{domain => inet, proto => udp, msg => Msg, num => Num}, ok = traffic_ping_pong_sendmsg_and_recvmsg_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the sendmsg and recvmsg functions %% by repeatedly sending a meassage between two entities. %% The same basic test case is used for three different message sizes; %% small (8 bytes) and medium (8K). %% The message is sent from A to B and then back again. This is %% repeated a set number of times (more times the small the message). %% This is the 'small' message test case, for IPv6. traffic_ping_pong_small_sendmsg_and_recvmsg_udp6(suite) -> []; traffic_ping_pong_small_sendmsg_and_recvmsg_udp6(doc) -> []; traffic_ping_pong_small_sendmsg_and_recvmsg_udp6(_Config) when is_list(_Config) -> Msg = l2b(?TPP_SMALL), Num = ?TPP_SMALL_NUM, tc_try(traffic_ping_pong_small_sendmsg_and_recvmsg_udp6, fun() -> has_support_ipv6() end, fun() -> ?TT(?SECS(60)), InitState = #{domain => inet6, proto => udp, msg => Msg, num => Num}, ok = traffic_ping_pong_sendmsg_and_recvmsg_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the sendmsg and recvmsg functions %% by repeatedly sending a meassage between two entities. %% The same basic test case is used for three different message sizes; %% small (8 bytes) and medium (8K). %% The message is sent from A to B and then back again. This is %% repeated a set number of times (more times the small the message). %% This is the 'small' message test case, for Unix Domain (dgram) socket. traffic_ping_pong_small_sendmsg_and_recvmsg_udpL(suite) -> []; traffic_ping_pong_small_sendmsg_and_recvmsg_udpL(doc) -> []; traffic_ping_pong_small_sendmsg_and_recvmsg_udpL(_Config) when is_list(_Config) -> Msg = l2b(?TPP_SMALL), Num = ?TPP_SMALL_NUM, tc_try(traffic_ping_pong_small_sendmsg_and_recvmsg_udpL, fun() -> has_support_unix_domain_socket() end, fun() -> ?TT(?SECS(60)), InitState = #{domain => local, proto => default, msg => Msg, num => Num}, ok = traffic_ping_pong_sendmsg_and_recvmsg_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the sendmsg and recvmsg %% functions by repeatedly sending a meassage between two entities. %% The same basic test case is used for three different message sizes; %% small (8 bytes) and medium (8K). %% The message is sent from A to B and then back again. This is %% repeated a set number of times (more times the small the message). %% This is the 'medium' message test case, for IPv4. traffic_ping_pong_medium_sendmsg_and_recvmsg_udp4(suite) -> []; traffic_ping_pong_medium_sendmsg_and_recvmsg_udp4(doc) -> []; traffic_ping_pong_medium_sendmsg_and_recvmsg_udp4(_Config) when is_list(_Config) -> Msg = l2b(?TPP_MEDIUM), Num = ?TPP_MEDIUM_NUM, tc_try(traffic_ping_pong_medium_sendmsg_and_recvmsg_udp4, fun() -> ?TT(?SECS(60)), InitState = #{domain => inet, proto => udp, msg => Msg, num => Num}, ok = traffic_ping_pong_sendmsg_and_recvmsg_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the sendmsg and recvmsg %% functions by repeatedly sending a meassage between two entities. %% The same basic test case is used for three different message sizes; %% small (8 bytes) and medium (8K). %% The message is sent from A to B and then back again. This is %% repeated a set number of times (more times the small the message). %% This is the 'medium' message test case, for IPv6. traffic_ping_pong_medium_sendmsg_and_recvmsg_udp6(suite) -> []; traffic_ping_pong_medium_sendmsg_and_recvmsg_udp6(doc) -> []; traffic_ping_pong_medium_sendmsg_and_recvmsg_udp6(_Config) when is_list(_Config) -> Msg = l2b(?TPP_MEDIUM), Num = ?TPP_MEDIUM_NUM, tc_try(traffic_ping_pong_medium_sendmsg_and_recvmsg_udp6, fun() -> has_support_ipv6() end, fun() -> ?TT(?SECS(60)), InitState = #{domain => inet6, proto => udp, msg => Msg, num => Num}, ok = traffic_ping_pong_sendmsg_and_recvmsg_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the sendmsg and recvmsg %% functions by repeatedly sending a meassage between two entities. %% The same basic test case is used for three different message sizes; %% small (8 bytes) and medium (8K). %% The message is sent from A to B and then back again. This is %% repeated a set number of times (more times the small the message). %% This is the 'medium' message test case, for Unix Domain (dgram) socket. traffic_ping_pong_medium_sendmsg_and_recvmsg_udpL(suite) -> []; traffic_ping_pong_medium_sendmsg_and_recvmsg_udpL(doc) -> []; traffic_ping_pong_medium_sendmsg_and_recvmsg_udpL(_Config) when is_list(_Config) -> Msg = l2b(?TPP_MEDIUM), Num = ?TPP_MEDIUM_NUM, tc_try(traffic_ping_pong_medium_sendmsg_and_recvmsg_udpL, fun() -> has_support_unix_domain_socket() end, fun() -> ?TT(?SECS(60)), InitState = #{domain => local, proto => default, msg => Msg, num => Num}, ok = traffic_ping_pong_sendmsg_and_recvmsg_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Ping-Pong for TCP traffic_ping_pong_send_and_recv_tcp(InitState) -> Send = fun(Sock, Data) -> socket:send(Sock, Data) end, Recv = fun(Sock, Sz) -> socket:recv(Sock, Sz) end, InitState2 = InitState#{send => Send, % Send function recv => Recv % Receive function }, traffic_ping_pong_send_and_receive_tcp(InitState2). traffic_ping_pong_sendmsg_and_recvmsg_tcp(#{domain := local} = InitState) -> Recv = fun(Sock, Sz) -> case socket:recvmsg(Sock, Sz, 0) of %% On some platforms, the address %% is *not* provided (e.g. FreeBSD) {ok, #{addr := undefined, iov := [Data]}} -> {ok, Data}; %% On some platforms, the address %% *is* provided (e.g. linux) {ok, #{addr := #{family := local}, iov := [Data]}} -> {ok, Data}; {error, _} = ERROR -> ERROR end end, InitState2 = InitState#{recv => Recv}, % Receive function traffic_ping_pong_sendmsg_and_recvmsg_tcp2(InitState2); traffic_ping_pong_sendmsg_and_recvmsg_tcp(InitState) -> Recv = fun(Sock, Sz) -> case socket:recvmsg(Sock, Sz, 0) of {ok, #{addr := undefined, iov := [Data]}} -> {ok, Data}; {error, _} = ERROR -> ERROR end end, InitState2 = InitState#{recv => Recv}, % Receive function traffic_ping_pong_sendmsg_and_recvmsg_tcp2(InitState2). traffic_ping_pong_sendmsg_and_recvmsg_tcp2(InitState) -> Send = fun(Sock, Data) when is_binary(Data) -> MsgHdr = #{iov => [Data]}, socket:sendmsg(Sock, MsgHdr); (Sock, Data) when is_list(Data) -> %% We assume iovec... MsgHdr = #{iov => Data}, socket:sendmsg(Sock, MsgHdr) end, InitState2 = InitState#{send => Send}, % Send function traffic_ping_pong_send_and_receive_tcp(InitState2). traffic_ping_pong_send_and_receive_tcp(#{msg := Msg} = InitState) -> Fun = fun(Sock) -> {ok, RcvSz} = socket:getopt(Sock, socket, rcvbuf), ?SEV_IPRINT("RcvBuf is ~p (needs atleast ~p)", [RcvSz, 16+size(Msg)]), if (RcvSz < size(Msg)) -> NewRcvSz = 1024+size(Msg), case socket:setopt(Sock, socket, rcvbuf, NewRcvSz) of ok -> ok; {error, enobufs} -> skip(?F("Change ~w buffer size (to ~w) " "not allowed", [rcvbuf, NewRcvSz])); {error, Reason1} -> ?FAIL({rcvbuf, Reason1}) end; true -> ok end, {ok, SndSz} = socket:getopt(Sock, socket, sndbuf), ?SEV_IPRINT("SndBuf is ~p (needs atleast ~p)", [SndSz, 16+size(Msg)]), if (SndSz < size(Msg)) -> NewSndSz = 1024+size(Msg), case socket:setopt(Sock, socket, sndbuf, NewSndSz) of ok -> ok; {error, enobufs} -> skip(?F("Change ~w buffer size (to ~w) " "not allowed", [sndbuf, NewSndSz])); {error, Reason2} -> ?FAIL({sndbuf, Reason2}) end; true -> ok end, ok = socket:setopt(Sock, otp, rcvbuf, {12, 1024}) end, traffic_ping_pong_send_and_receive_tcp2(InitState#{buf_init => Fun}). traffic_ping_pong_send_and_receive_tcp2(InitState) -> ServerSeq = [ %% *** Wait for start order part *** #{desc => "await start", cmd => fun(State) -> Tester = ?SEV_AWAIT_START(), {ok, State#{tester => Tester}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, #{desc => "create listen socket", cmd => fun(#{domain := Domain, proto := Proto} = State) -> case socket:open(Domain, stream, Proto) of {ok, Sock} -> {ok, State#{lsock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind to local address", cmd => fun(#{domain := local, lsock := LSock, lsa := LSA} = _State) -> case socket:bind(LSock, LSA) of {ok, _Port} -> ok; % We do not care about the port for local {error, _} = ERROR -> ERROR end; (#{lsock := LSock, local_sa := LSA} = State) -> case socket:bind(LSock, LSA) of {ok, Port} -> ?SEV_IPRINT("bound to port: ~w", [Port]), {ok, State#{lport => Port}}; {error, _} = ERROR -> ERROR end end}, #{desc => "maybe init buffers", cmd => fun(#{lsock := LSock, buf_init := BufInit} = _State) -> BufInit(LSock) end}, #{desc => "make listen socket", cmd => fun(#{lsock := LSock}) -> socket:listen(LSock) end}, #{desc => "announce ready (init)", cmd => fun(#{domain := local, tester := Tester, local_sa := LSA}) -> ?SEV_ANNOUNCE_READY(Tester, init, LSA), ok; (#{tester := Tester, local_sa := LSA, lport := Port}) -> ServerSA = LSA#{port => Port}, ?SEV_ANNOUNCE_READY(Tester, init, ServerSA), ok end}, %% The actual test #{desc => "await continue (accept)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, accept) end}, #{desc => "accept", cmd => fun(#{lsock := LSock} = State) -> case socket:accept(LSock) of {ok, Sock} -> {ok, State#{csock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "create handler", cmd => fun(State) -> Handler = tpp_tcp_handler_create(), ?SEV_IPRINT("handler created: ~p", [Handler]), {ok, State#{handler => Handler}} end}, #{desc => "monitor handler", cmd => fun(#{handler := Handler} = _State) -> _MRef = erlang:monitor(process, Handler), ok end}, #{desc => "transfer connection socket ownership to handler", cmd => fun(#{handler := Handler, csock := Sock} = _State) -> socket:setopt(Sock, otp, controlling_process, Handler) end}, #{desc => "start handler", cmd => fun(#{handler := Handler, csock := Sock, send := Send, recv := Recv} = _State) -> ?SEV_ANNOUNCE_START(Handler, {Sock, Send, Recv}), ok end}, #{desc => "await handler ready (init)", cmd => fun(#{tester := Tester, handler := Handler} = State) -> case ?SEV_AWAIT_READY(Handler, handler, init, [{tester, Tester}]) of ok -> {ok, maps:remove(csock, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (accept)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, accept), ok end}, #{desc => "await continue (recv)", cmd => fun(#{tester := Tester, handler := Handler} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, recv, [{handler, Handler}]) end}, #{desc => "order handler to recv", cmd => fun(#{handler := Handler} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Handler, recv), ok end}, #{desc => "await handler ready (recv)", cmd => fun(#{tester := Tester, handler := Handler} = State) -> case ?SEV_AWAIT_READY(Handler, handler, recv, [{tester, Tester}]) of {ok, Result} -> %% ?SEV_IPRINT("Result: ~p", [Result]), {ok, State#{result => Result}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (recv)", cmd => fun(#{tester := Tester, result := Result} = State) -> ?SEV_ANNOUNCE_READY(Tester, recv, Result), {ok, maps:remove(result, State)} end}, %% Termination #{desc => "await terminate (from tester)", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "stop handler", cmd => fun(#{handler := Handler}) -> ?SEV_ANNOUNCE_TERMINATE(Handler), ok end}, #{desc => "await handler termination", cmd => fun(#{handler := Handler} = State) -> ?SEV_AWAIT_TERMINATION(Handler), State1 = maps:remove(handler, State), {ok, State1} end}, #{desc => "close listen socket", cmd => fun(#{domain := local, lsock := Sock, local_sa := #{path := Path}} = State) -> (catch socket:close(Sock)), State1 = unlink_path(Path, fun() -> maps:remove(local_sa, State) end, fun() -> State end), {ok, maps:remove(lsock, State1)}; (#{lsock := Sock} = State) -> (catch socket:close(Sock)), {ok, maps:remove(lsock, State)} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], ClientSeq = [ %% *** Wait for start order part *** #{desc => "await start", cmd => fun(State) -> {Tester, ServerSA} = ?SEV_AWAIT_START(), {ok, State#{tester => Tester, server_sa => ServerSA}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "create node", cmd => fun(#{host := Host} = State) -> case start_node(Host, client) of {ok, Node} -> ?SEV_IPRINT("(remote) client node ~p started", [Node]), {ok, State#{node => Node}}; {error, Reason} -> {skip, Reason} end end}, #{desc => "monitor client node", cmd => fun(#{node := Node} = _State) -> true = erlang:monitor_node(Node, true), ok end}, #{desc => "create remote client", cmd => fun(#{node := Node} = State) -> Pid = tpp_tcp_client_create(Node), ?SEV_IPRINT("remote client created: ~p", [Pid]), {ok, State#{rclient => Pid}} end}, #{desc => "monitor remote client", cmd => fun(#{rclient := Pid}) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "order remote client to start", cmd => fun(#{rclient := RClient, proto := Proto, server_sa := ServerSA, buf_init := BufInit, send := Send, recv := Recv}) -> ?SEV_ANNOUNCE_START(RClient, {ServerSA, Proto, BufInit, Send, Recv}), ok end}, #{desc => "await remote client ready", cmd => fun(#{tester := Tester, rclient := RClient} = _State) -> ?SEV_AWAIT_READY(RClient, rclient, init, [{tester, Tester}]) end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, init), ok end}, %% The actual test #{desc => "await continue (connect)", cmd => fun(#{tester := Tester, rclient := RClient} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, connect, [{rclient, RClient}]), ok end}, #{desc => "order remote client to continue (connect)", cmd => fun(#{rclient := RClient}) -> ?SEV_ANNOUNCE_CONTINUE(RClient, connect), ok end}, #{desc => "await remote client ready (connect)", cmd => fun(#{tester := Tester, rclient := RClient} = _State) -> ?SEV_AWAIT_READY(RClient, rclient, connect, [{tester, Tester}]) end}, #{desc => "announce ready (connect)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, connect), ok end}, #{desc => "await continue (send)", cmd => fun(#{tester := Tester, rclient := RClient} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, send, [{rclient, RClient}]) end}, #{desc => "order remote client to continue (send)", cmd => fun(#{rclient := RClient, msg := Msg, num := Num} = State) -> Data = {Msg, Num}, ?SEV_ANNOUNCE_CONTINUE(RClient, send, Data), {ok, maps:remove(data, State)} end}, #{desc => "await remote client ready (send)", cmd => fun(#{tester := Tester, rclient := RClient} = State) -> case ?SEV_AWAIT_READY(RClient, rclient, send, [{tester, Tester}]) of {ok, Result} -> %% ?SEV_IPRINT("remote client result: " %% "~n ~p", [Result]), {ok, State#{result => Result}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (send)", cmd => fun(#{tester := Tester, result := Result} = State) -> ?SEV_ANNOUNCE_READY(Tester, send, Result), {ok, maps:remove(result, State)} end}, %% Termination #{desc => "await terminate (from tester)", cmd => fun(#{tester := Tester, rclient := RClient} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester, [{rclient, RClient}]) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "stop remote client", cmd => fun(#{rclient := RClient}) -> ?SEV_ANNOUNCE_TERMINATE(RClient), ok end}, #{desc => "await remote client termination", cmd => fun(#{rclient := RClient} = State) -> ?SEV_AWAIT_TERMINATION(RClient), State1 = maps:remove(rclient, State), {ok, State1} end}, #{desc => "stop client node", cmd => fun(#{node := Node} = _State) -> stop_node(Node) end}, #{desc => "await client node termination", cmd => fun(#{node := Node} = State) -> receive {nodedown, Node} -> {ok, maps:remove(node, State)} end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], TesterSeq = [ %% *** Init part *** #{desc => "monitor server", cmd => fun(#{server := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "monitor client", cmd => fun(#{client := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, %% Start the server #{desc => "order server start", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_START(Pid), ok end}, #{desc => "await server ready (init)", cmd => fun(#{server := Pid} = State) -> {ok, ServerSA} = ?SEV_AWAIT_READY(Pid, server, init), {ok, State#{server_sa => ServerSA}} end}, %% Start the client #{desc => "order client start", cmd => fun(#{client := Pid, server_sa := ServerSA} = _State) -> ?SEV_ANNOUNCE_START(Pid, ServerSA), ok end}, #{desc => "await client ready (init)", cmd => fun(#{client := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, client, init) end}, %% The actual test #{desc => "order server continue (accept)", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, accept), ok end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order client continue (connect)", cmd => fun(#{client := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, connect), ok end}, #{desc => "await server ready (accept)", cmd => fun(#{server := Server, client := Client} = _State) -> ?SEV_AWAIT_READY(Server, server, accept, [{client, Client}]), ok end}, #{desc => "await client ready (connect)", cmd => fun(#{server := Server, client := Client} = _State) -> ?SEV_AWAIT_READY(Client, client, connect, [{server, Server}]) end}, #{desc => "order server continue (recv)", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, recv), ok end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order client continue (send)", cmd => fun(#{client := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, send), ok end}, #{desc => "await client ready (send)", cmd => fun(#{server := Server, client := Client} = State) -> case ?SEV_AWAIT_READY(Client, client, send, [{server, Server}]) of {ok, {_, _, _, _} = Result} -> ?SEV_IPRINT("client result: " "~n ~p", [Result]), {ok, State#{client_result => Result}}; {ok, BadResult} -> ?SEV_EPRINT("client result: " "~n ~p", [BadResult]), {error, {invalid_client_result, BadResult}}; {error, _} = ERROR -> ERROR end end}, #{desc => "await server ready (recv)", cmd => fun(#{server := Server, client := Client, num := Num} = State) -> case ?SEV_AWAIT_READY(Server, server, recv, [{client, Client}]) of {ok, {Num, _, _, _, _} = Result} -> ?SEV_IPRINT("server result: " "~n ~p", [Result]), Result2 = erlang:delete_element(1, Result), {ok, State#{server_result => Result2}}; {ok, BadResult} -> ?SEV_EPRINT("bad server result: " "~n ~p", [BadResult]), {error, {invalid_server_result, BadResult}}; {error, _} = ERROR -> ERROR end end}, #{desc => "present result", cmd => fun(#{server_result := SRes, client_result := CRes, num := Num} = State) -> {SSent, SReceived, SStart, SStop} = SRes, {CSent, CReceived, CStart, CStop} = CRes, STime = tdiff(SStart, SStop), CTime = tdiff(CStart, CStop), %% Note that the sizes we are counting is only %% the "data" part of the messages. There is also %% fixed header for each message, which of cource %% is small for the large messages, but comparatively %% big for the small messages! ?SEV_IPRINT("Results: ~w messages exchanged" "~n Server: ~w msec" "~n ~.2f msec/message (roundtrip)" "~n ~.2f messages/msec (roundtrip)" "~n ~w bytes/msec sent" "~n ~w bytes/msec received" "~n Client: ~w msec" "~n ~.2f msec/message (roundtrip)" "~n ~.2f messages/msec (roundtrip)" "~n ~w bytes/msec sent" "~n ~w bytes/msec received", [Num, STime, STime / Num, Num / STime, SSent div STime, SReceived div STime, CTime, CTime / Num, Num / CTime, CSent div CTime, CReceived div CTime]), State1 = maps:remove(server_result, State), State2 = maps:remove(client_result, State1), {ok, State2} end}, %% Terminations #{desc => "order client to terminate", cmd => fun(#{client := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await client termination", cmd => fun(#{client := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> State1 = maps:remove(client, State), {ok, State1}; {error, _} = ERROR -> ERROR end end}, #{desc => "order server to terminate", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await server termination", cmd => fun(#{server := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> State1 = maps:remove(server, State), {ok, State1}; {error, _} = ERROR -> ERROR end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], i("start server evaluator"), ServerInitState = #{domain => maps:get(domain, InitState), proto => maps:get(proto, InitState), recv => maps:get(recv, InitState), send => maps:get(send, InitState), buf_init => maps:get(buf_init, InitState)}, Server = ?SEV_START("server", ServerSeq, ServerInitState), i("start client evaluator(s)"), ClientInitState = InitState#{host => local_host()}, Client = ?SEV_START("client", ClientSeq, ClientInitState), i("start 'tester' evaluator"), TesterInitState = #{server => Server#ev.pid, client => Client#ev.pid, num => maps:get(num, InitState)}, Tester = ?SEV_START("tester", TesterSeq, TesterInitState), i("await evaluator"), ok = ?SEV_AWAIT_FINISH([Server, Client, Tester]). tpp_tcp_handler_create() -> Self = self(), erlang:spawn(fun() -> tpp_tcp_handler(Self) end). tpp_tcp_handler(Parent) -> tpp_tcp_handler_init(Parent), {Sock, Send, Recv} = tpp_tcp_handler_await_start(Parent), tpp_tcp_handler_announce_ready(Parent, init), tpp_tcp_handler_await_continue(Parent, recv), Result = tpp_tcp_handler_msg_exchange(Sock, Send, Recv), tpp_tcp_handler_announce_ready(Parent, recv, Result), Reason = tpp_tcp_handler_await_terminate(Parent), ?SEV_IPRINT("terminating"), exit(Reason). tpp_tcp_handler_init(Parent) -> put(sname, "handler"), ?SEV_IPRINT("init"), _MRef = erlang:monitor(process, Parent), ok. tpp_tcp_handler_await_start(Parent) -> ?SEV_IPRINT("await start"), ?SEV_AWAIT_START(Parent). tpp_tcp_handler_announce_ready(Parent, Slogan) -> ?SEV_IPRINT("announce ready (~p)", [Slogan]), ?SEV_ANNOUNCE_READY(Parent, Slogan). tpp_tcp_handler_announce_ready(Parent, Slogan, Extra) -> ?SEV_IPRINT("announce ready (~p)", [Slogan]), ?SEV_ANNOUNCE_READY(Parent, Slogan, Extra). tpp_tcp_handler_await_continue(Parent, Slogan) -> ?SEV_IPRINT("await continue (~p)", [Slogan]), case ?SEV_AWAIT_CONTINUE(Parent, parent, Slogan) of ok -> %% ?SEV_IPRINT("continue (~p): ok", [Slogan]), ok; {error, Reason} -> ?SEV_EPRINT("continue (~p): error" "~n ~p", [Slogan, Reason]), exit({continue, Slogan, Reason}) end. tpp_tcp_handler_await_terminate(Parent) -> ?SEV_IPRINT("await terminate"), case ?SEV_AWAIT_TERMINATE(Parent, parent) of ok -> ok; {error, Reason} -> Reason end. tpp_tcp_handler_msg_exchange(Sock, Send, Recv) -> tpp_tcp_handler_msg_exchange_loop(Sock, Send, Recv, 0, 0, 0, undefined). tpp_tcp_handler_msg_exchange_loop(Sock, Send, Recv, N, Sent, Received, Start) -> %% ?SEV_IPRINT("[~w] try receive", [N]), case tpp_tcp_recv_req(Sock, Recv) of {ok, Msg, RecvSz} -> NewStart = if (Start =:= undefined) -> ?LIB:timestamp(); true -> Start end, %% ?SEV_IPRINT("[~w] received - now try send", [N]), case tpp_tcp_send_rep(Sock, Send, Msg) of {ok, SendSz} -> tpp_tcp_handler_msg_exchange_loop(Sock, Send, Recv, N+1, Sent+SendSz, Received+RecvSz, NewStart); {error, SReason} -> ?SEV_EPRINT("send (~w): ~p", [N, SReason]), exit({send, SReason, N}) end; {error, closed} -> ?SEV_IPRINT("closed - we are done: ~w, ~w, ~w", [N, Sent, Received]), Stop = ?LIB:timestamp(), {N, Sent, Received, Start, Stop}; {error, RReason} -> ?SEV_EPRINT("recv (~w): ~p", [N, RReason]), exit({recv, RReason, N}) end. %% The (remote) client process tpp_tcp_client_create(Node) -> Self = self(), Fun = fun() -> tpp_tcp_client(Self) end, erlang:spawn(Node, Fun). tpp_tcp_client(Parent) -> tpp_tcp_client_init(Parent), {ServerSA, Proto, BufInit, Send, Recv} = tpp_tcp_client_await_start(Parent), Domain = maps:get(family, ServerSA), Sock = tpp_tcp_client_sock_open(Domain, Proto, BufInit), Path = tpp_tcp_client_sock_bind(Sock, Domain), tpp_tcp_client_announce_ready(Parent, init), tpp_tcp_client_await_continue(Parent, connect), tpp_tcp_client_sock_connect(Sock, ServerSA), tpp_tcp_client_announce_ready(Parent, connect), {InitMsg, Num} = tpp_tcp_client_await_continue(Parent, send), Result = tpp_tcp_client_msg_exchange(Sock, Send, Recv, InitMsg, Num), tpp_tcp_client_announce_ready(Parent, send, Result), Reason = tpp_tcp_client_await_terminate(Parent), tpp_tcp_client_sock_close(Sock, Path), ?SEV_IPRINT("terminating"), exit(Reason). tpp_tcp_client_init(Parent) -> put(sname, "rclient"), ?SEV_IPRINT("init"), _MRef = erlang:monitor(process, Parent), ok. tpp_tcp_client_await_start(Parent) -> ?SEV_IPRINT("await start"), ?SEV_AWAIT_START(Parent). tpp_tcp_client_announce_ready(Parent, Slogan) -> ?SEV_IPRINT("announce ready (~p)", [Slogan]), ?SEV_ANNOUNCE_READY(Parent, Slogan). tpp_tcp_client_announce_ready(Parent, Slogan, Extra) -> ?SEV_IPRINT("announce ready (~p): ~p", [Slogan, Extra]), ?SEV_ANNOUNCE_READY(Parent, Slogan, Extra). tpp_tcp_client_await_continue(Parent, Slogan) -> ?SEV_IPRINT("await continue (~p)", [Slogan]), case ?SEV_AWAIT_CONTINUE(Parent, parent, Slogan) of ok -> ?SEV_IPRINT("continue (~p): ok", [Slogan]), ok; {ok, Data} -> ?SEV_IPRINT("continue (~p): ok with data", [Slogan]), Data; {error, Reason} -> ?SEV_EPRINT("continue (~p): error" "~n ~p", [Slogan, Reason]), exit({continue, Slogan, Reason}) end. tpp_tcp_client_await_terminate(Parent) -> ?SEV_IPRINT("await terminate"), case ?SEV_AWAIT_TERMINATE(Parent, parent) of ok -> ?SEV_IPRINT("termination received: normal"), normal; {error, Reason} -> ?SEV_IPRINT("termination received: ~w", [Reason]), Reason end. tpp_tcp_client_msg_exchange(Sock, Send, Recv, InitMsg, Num) -> Start = ?LIB:timestamp(), tpp_tcp_client_msg_exchange_loop(Sock, Send, Recv, InitMsg, Num, 0, 0, 0, Start). tpp_tcp_client_msg_exchange_loop(Sock, _Send, _Recv, _Msg, Num, Num, Sent, Received, Start) -> Stop = ?LIB:timestamp(), case socket:close(Sock) of ok -> {Sent, Received, Start, Stop}; {error, Reason} -> exit({failed_closing, Reason}) end; tpp_tcp_client_msg_exchange_loop(Sock, Send, Recv, Data, Num, N, Sent, Received, Start) -> %% d("tpp_tcp_client_msg_exchange_loop(~w,~w) try send ~w", [Num,N,size(Data)]), case tpp_tcp_send_req(Sock, Send, Data) of {ok, SendSz} -> %% d("tpp_tcp_client_msg_exchange_loop(~w,~w) sent - " %% "now try recv", [Num,N]), case tpp_tcp_recv_rep(Sock, Recv) of {ok, NewData, RecvSz} -> tpp_tcp_client_msg_exchange_loop(Sock, Send, Recv, NewData, Num, N+1, Sent+SendSz, Received+RecvSz, Start); {error, RReason} -> ?SEV_EPRINT("recv (~w of ~w): ~p: " "~n ~p", [N, Num, RReason, mq()]), exit({recv, RReason, N}) end; {error, SReason} -> ?SEV_EPRINT("send (~w of ~w): ~p" "~n ~p", [N, Num, SReason, mq()]), exit({send, SReason, N}) end. tpp_tcp_client_sock_open(Domain, Proto, BufInit) -> case socket:open(Domain, stream, Proto) of {ok, Sock} -> ok = BufInit(Sock), Sock; {error, Reason} -> exit({open_failed, Reason}) end. tpp_tcp_client_sock_bind(Sock, Domain) -> LSA = which_local_socket_addr(Domain), case socket:bind(Sock, LSA) of {ok, _} -> case socket:sockname(Sock) of {ok, #{family := local, path := Path}} -> Path; {ok, _} -> undefined; {error, Reason1} -> exit({sockname, Reason1}) end; {error, Reason2} -> exit({bind, Reason2}) end. tpp_tcp_client_sock_connect(Sock, ServerSA) -> case socket:connect(Sock, ServerSA) of ok -> ok; {error, Reason} -> exit({connect, Reason}) end. tpp_tcp_client_sock_close(Sock, Path) -> case socket:close(Sock) of ok -> unlink_path(Path), ok; {error, Reason} -> ?SEV_EPRINT("failed closing: " "~n Reason: ~p", [Reason]), unlink_path(Path), {error, {close, Reason}} end. -define(TPP_REQUEST, 1). -define(TPP_REPLY, 2). tpp_tcp_recv_req(Sock, Recv) -> tpp_tcp_recv(Sock, Recv, ?TPP_REQUEST). tpp_tcp_recv_rep(Sock, Recv) -> tpp_tcp_recv(Sock, Recv, ?TPP_REPLY). tpp_tcp_recv(Sock, Recv, Tag) -> case Recv(Sock, 0) of {ok, <> = Msg} when (Sz =:= size(Data)) -> %% We got it all {ok, Data, size(Msg)}; {ok, <> = Msg} -> Remains = Sz - size(Data), tpp_tcp_recv(Sock, Recv, Tag, Remains, size(Msg), [Data]); {ok, <>} -> {error, {invalid_msg_tag, Tag}}; {error, _R} = ERROR -> ERROR end. tpp_tcp_recv(Sock, Recv, Tag, Remaining, AccSz, Acc) -> case Recv(Sock, Remaining) of {ok, Data} when (Remaining =:= size(Data)) -> %% We got the rest TotSz = AccSz + size(Data), {ok, erlang:iolist_to_binary(lists:reverse([Data | Acc])), TotSz}; {ok, Data} when (Remaining > size(Data)) -> tpp_tcp_recv(Sock, Recv, Tag, Remaining - size(Data), AccSz + size(Data), [Data | Acc]); {error, _R} = ERROR -> ERROR end. tpp_tcp_send_req(Sock, Send, Data) -> tpp_tcp_send(Sock, Send, ?TPP_REQUEST, Data). tpp_tcp_send_rep(Sock, Send, Data) -> tpp_tcp_send(Sock, Send, ?TPP_REPLY, Data). tpp_tcp_send(Sock, Send, Tag, Data) -> DataSz = size(Data), Msg = <>, tpp_tcp_send_msg(Sock, Send, Msg, 0). tpp_tcp_send_msg(Sock, Send, Msg, AccSz) when is_binary(Msg) -> case Send(Sock, Msg) of ok -> {ok, AccSz+size(Msg)}; {ok, Rest} -> % This is an IOVec RestBin = list_to_binary(Rest), tpp_tcp_send_msg(Sock, Send, RestBin, AccSz+(size(Msg)-size(RestBin))); {error, _} = ERROR -> ERROR end. %% size_of_data(Data) when is_binary(Data) -> %% size(Data); %% size_of_data(Data) when is_list(Data) -> %% size_of_iovec(Data, 0). %% size_of_iovec([], Sz) -> %% Sz; %% size_of_iovec([B|IOVec], Sz) -> %% size_of_iovec(IOVec, Sz+size(B)). mq() -> mq(self()). mq(Pid) when is_pid(Pid) -> Tag = messages, {Tag, Msgs} = process_info(Pid, Tag), Msgs. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Ping-Pong for UDP traffic_ping_pong_sendto_and_recvfrom_udp(InitState) -> Send = fun(Sock, Data, Dest) -> socket:sendto(Sock, Data, Dest) end, Recv = fun(Sock, Sz) -> socket:recvfrom(Sock, Sz) end, InitState2 = InitState#{send => Send, % Send function recv => Recv % Receive function }, traffic_ping_pong_send_and_receive_udp(InitState2). traffic_ping_pong_sendmsg_and_recvmsg_udp(InitState) -> Send = fun(Sock, Data, Dest) when is_binary(Data) -> MsgHdr = #{addr => Dest, iov => [Data]}, socket:sendmsg(Sock, MsgHdr); (Sock, Data, Dest) when is_list(Data) -> %% We assume iovec... MsgHdr = #{addr => Dest, iov => Data}, socket:sendmsg(Sock, MsgHdr) end, Recv = fun(Sock, Sz) -> case socket:recvmsg(Sock, Sz, 0) of {ok, #{addr := Source, iov := [Data]}} -> {ok, {Source, Data}}; {error, _} = ERROR -> ERROR end end, InitState2 = InitState#{send => Send, % Send function recv => Recv % Receive function }, traffic_ping_pong_send_and_receive_udp(InitState2). traffic_ping_pong_send_and_receive_udp(#{msg := Msg} = InitState) -> Fun = fun(Sock) -> {ok, RcvSz} = socket:getopt(Sock, socket, rcvbuf), if (RcvSz =< (8+size(Msg))) -> i("adjust socket rcvbuf buffer size"), ok = socket:setopt(Sock, socket, rcvbuf, 1024+size(Msg)); true -> ok end, {ok, SndSz} = socket:getopt(Sock, socket, sndbuf), if (SndSz =< (8+size(Msg))) -> i("adjust socket sndbuf buffer size"), ok = socket:setopt(Sock, socket, sndbuf, 1024+size(Msg)); true -> ok end, {ok, OtpRcvBuf} = socket:getopt(Sock, otp, rcvbuf), if (OtpRcvBuf =< (8+size(Msg))) -> i("adjust otp rcvbuf buffer size"), ok = socket:setopt(Sock, otp, rcvbuf, 1024+size(Msg)); true -> ok end end, traffic_ping_pong_send_and_receive_udp2(InitState#{buf_init => Fun}). traffic_ping_pong_send_and_receive_udp2(InitState) -> ServerSeq = [ %% *** Wait for start order part *** #{desc => "await start", cmd => fun(State) -> Tester = ?SEV_AWAIT_START(), {ok, State#{tester => Tester}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, #{desc => "create socket", cmd => fun(#{domain := Domain, proto := Proto} = State) -> case socket:open(Domain, dgram, Proto) of {ok, Sock} -> {ok, State#{sock => Sock}}; {error, _} = ERROR -> ERROR end end}, #{desc => "bind to local address", cmd => fun(#{domain := local, sock := Sock, local_sa := LSA} = _State) -> case socket:bind(Sock, LSA) of {ok, _} -> ok; {error, _} = ERROR -> ERROR end; (#{sock := Sock, local_sa := LSA} = State) -> case socket:bind(Sock, LSA) of {ok, Port} -> {ok, State#{port => Port}}; {error, _} = ERROR -> ERROR end end}, #{desc => "maybe init buffers", cmd => fun(#{sock := Sock, buf_init := BufInit} = _State) -> BufInit(Sock) end}, #{desc => "create handler", cmd => fun(State) -> Handler = tpp_udp_server_handler_create(), ?SEV_IPRINT("handler created: ~p", [Handler]), {ok, State#{handler => Handler}} end}, #{desc => "monitor handler", cmd => fun(#{handler := Handler} = _State) -> _MRef = erlang:monitor(process, Handler), ok end}, #{desc => "start handler", cmd => fun(#{handler := Handler, sock := Sock, send := Send, recv := Recv} = _State) -> ?SEV_ANNOUNCE_START(Handler, {Sock, Send, Recv}), ok end}, #{desc => "await handler ready (init)", cmd => fun(#{tester := Tester, handler := Handler} = State) -> case ?SEV_AWAIT_READY(Handler, handler, init, [{tester, Tester}]) of ok -> {ok, maps:remove(csock, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (init)", cmd => fun(#{domain := local, tester := Tester, local_sa := LSA}) -> ?SEV_ANNOUNCE_READY(Tester, init, LSA), ok; (#{tester := Tester, local_sa := LSA, port := Port}) -> ServerSA = LSA#{port => Port}, ?SEV_ANNOUNCE_READY(Tester, init, ServerSA), ok end}, %% The actual test #{desc => "await continue (recv)", cmd => fun(#{tester := Tester, handler := Handler} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, recv, [{handler, Handler}]) end}, #{desc => "order handler to recv", cmd => fun(#{handler := Handler, sock := _Sock} = _State) -> %% socket:setopt(Sock, otp, debug, true), ?SEV_ANNOUNCE_CONTINUE(Handler, recv), ok end}, #{desc => "await continue (close)", cmd => fun(#{tester := Tester, handler := Handler} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, close, [{handler, Handler}]) end}, ?SEV_SLEEP(?SECS(1)), #{desc => "close socket", cmd => fun(#{sock := Sock} = State) -> %% socket:setopt(Sock, otp, debug, true), case socket:close(Sock) of ok -> {ok, maps:remove(sock, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "(maybe) unlink socket", cmd => fun(#{domain := local, local_sa := #{path := Path}} = State) -> unlink_path(Path, fun() -> {ok, maps:remove(local_sa, State)} end, fun() -> ok end); (_) -> ok end}, #{desc => "announce ready (close)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_ANNOUNCE_READY(Tester, close), ok end}, #{desc => "await handler ready (recv)", cmd => fun(#{tester := Tester, handler := Handler} = State) -> case ?SEV_AWAIT_READY(Handler, handler, recv, [{tester, Tester}]) of {ok, Result} -> %% ?SEV_IPRINT("Result: ~p", [Result]), {ok, State#{result => Result}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (recv)", cmd => fun(#{tester := Tester, result := Result} = State) -> ?SEV_ANNOUNCE_READY(Tester, recv, Result), {ok, maps:remove(result, State)} end}, %% Termination #{desc => "await terminate (from tester)", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "stop handler", cmd => fun(#{handler := Handler}) -> ?SEV_ANNOUNCE_TERMINATE(Handler), ok end}, #{desc => "await handler termination", cmd => fun(#{handler := Handler} = State) -> ?SEV_AWAIT_TERMINATION(Handler), State1 = maps:remove(handler, State), {ok, State1} end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], ClientSeq = [ %% *** Wait for start order part *** #{desc => "await start", cmd => fun(State) -> {Tester, ServerSA} = ?SEV_AWAIT_START(), {ok, State#{tester => Tester, server_sa => ServerSA}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "create node", cmd => fun(#{host := Host} = State) -> case start_node(Host, client) of {ok, Node} -> ?SEV_IPRINT("(remote) client node ~p started", [Node]), {ok, State#{node => Node}}; {error, Reason} -> {skip, Reason} end end}, #{desc => "monitor client node", cmd => fun(#{node := Node} = _State) -> true = erlang:monitor_node(Node, true), ok end}, #{desc => "create (remote) handler", cmd => fun(#{node := Node} = State) -> Pid = tpp_udp_client_handler_create(Node), ?SEV_IPRINT("handler created: ~p", [Pid]), {ok, State#{handler => Pid}} end}, #{desc => "monitor remote handler", cmd => fun(#{handler := Pid}) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "order remote handler to start", cmd => fun(#{handler := Handler, server_sa := ServerSA, proto := Proto, buf_init := BufInit, send := Send, recv := Recv}) -> ?SEV_ANNOUNCE_START(Handler, {ServerSA, Proto, BufInit, Send, Recv}), ok end}, #{desc => "await (remote) handler ready", cmd => fun(#{tester := Tester, handler := Handler} = _State) -> ?SEV_AWAIT_READY(Handler, handler, init, [{tester, Tester}]) end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, init), ok end}, %% The actual test #{desc => "await continue (send)", cmd => fun(#{tester := Tester, handler := Handler} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, send, [{handler, Handler}]) end}, #{desc => "order handler to continue (send)", cmd => fun(#{handler := Handler, msg := Msg, num := Num} = State) -> Data = {Msg, Num}, ?SEV_ANNOUNCE_CONTINUE(Handler, send, Data), {ok, maps:remove(data, State)} end}, #{desc => "await remote handler ready (send)", cmd => fun(#{tester := Tester, handler := Handler} = State) -> case ?SEV_AWAIT_READY(Handler, handler, send, [{tester, Tester}]) of {ok, Result} -> %% ?SEV_IPRINT("remote client result: " %% "~n ~p", [Result]), {ok, State#{result => Result}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (send)", cmd => fun(#{tester := Tester, result := Result} = State) -> ?SEV_ANNOUNCE_READY(Tester, send, Result), {ok, maps:remove(result, State)} end}, %% Termination #{desc => "await terminate (from tester)", cmd => fun(#{tester := Tester, handler := Handler} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester, [{handler, Handler}]) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "stop (remote) handler", cmd => fun(#{handler := Handler}) -> ?SEV_ANNOUNCE_TERMINATE(Handler), ok end}, #{desc => "await (remote) handler termination", cmd => fun(#{handler := Handler} = State) -> ?SEV_AWAIT_TERMINATION(Handler), State1 = maps:remove(handler, State), {ok, State1} end}, #{desc => "stop client node", cmd => fun(#{node := Node} = _State) -> stop_node(Node) end}, #{desc => "await client node termination", cmd => fun(#{node := Node} = State) -> receive {nodedown, Node} -> {ok, maps:remove(node, State)} end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], TesterSeq = [ %% *** Init part *** #{desc => "monitor server", cmd => fun(#{server := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "monitor client", cmd => fun(#{client := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, %% Start the server #{desc => "order server start", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_START(Pid), ok end}, #{desc => "await server ready (init)", cmd => fun(#{server := Pid} = State) -> {ok, ServerSA} = ?SEV_AWAIT_READY(Pid, server, init), {ok, State#{server_sa => ServerSA}} end}, %% Start the client #{desc => "order client start", cmd => fun(#{client := Pid, server_sa := ServerSA} = _State) -> ?SEV_ANNOUNCE_START(Pid, ServerSA), ok end}, #{desc => "await client ready (init)", cmd => fun(#{client := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, client, init) end}, %% The actual test #{desc => "order server continue (recv)", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, recv), ok end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order client continue (send)", cmd => fun(#{client := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, send), ok end}, #{desc => "await client ready (send)", cmd => fun(#{server := Server, client := Client} = State) -> case ?SEV_AWAIT_READY(Client, client, send, [{server, Server}]) of {ok, {_, _, _, _} = Result} -> ?SEV_IPRINT("client result: " "~n ~p", [Result]), {ok, State#{client_result => Result}}; {ok, BadResult} -> ?SEV_EPRINT("client result: " "~n ~p", [BadResult]), {error, {invalid_client_result, BadResult}}; {error, _} = ERROR -> ERROR end end}, #{desc => "order server continue (close)", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Pid, close), ok end}, #{desc => "await server ready (close)", cmd => fun(#{server := Pid} = _State) -> ok = ?SEV_AWAIT_READY(Pid, server, close) end}, %% Because of the way we control the server, there is no real %% point in collecting statistics from it (the time will include %% our communication with it). #{desc => "await server ready (recv)", cmd => fun(#{server := Server, client := Client} = _State) -> case ?SEV_AWAIT_READY(Server, server, recv, [{client, Client}]) of {ok, _Result} -> ok; {error, _} = ERROR -> ERROR end end}, #{desc => "present result", cmd => fun(#{client_result := CRes, num := Num} = State) -> {CSent, CReceived, CStart, CStop} = CRes, CTime = tdiff(CStart, CStop), %% Note that the sizes we are counting is only %% the "data" part of the messages. There is also %% fixed header for each message, which of cource %% is small for the large messages, but comparatively %% big for the small messages! ?SEV_IPRINT("Results: ~w messages exchanged" "~n Client: ~w msec" "~n ~.2f msec/message (roundtrip)" "~n ~.2f messages/msec (roundtrip)" "~n ~w bytes/msec sent" "~n ~w bytes/msec received", [Num, CTime, CTime / Num, Num / CTime, CSent div CTime, CReceived div CTime]), State1 = maps:remove(client_result, State), {ok, State1} end}, %% Terminations #{desc => "order client to terminate", cmd => fun(#{client := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await client termination", cmd => fun(#{client := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> State1 = maps:remove(client, State), {ok, State1}; {error, _} = ERROR -> ERROR end end}, #{desc => "order server to terminate", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Pid), ok end}, #{desc => "await server termination", cmd => fun(#{server := Pid} = State) -> case ?SEV_AWAIT_TERMINATION(Pid) of ok -> State1 = maps:remove(server, State), {ok, State1}; {error, _} = ERROR -> ERROR end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], i("start server evaluator"), ServerInitState = #{domain => maps:get(domain, InitState), proto => maps:get(proto, InitState), recv => maps:get(recv, InitState), send => maps:get(send, InitState), buf_init => maps:get(buf_init, InitState)}, Server = ?SEV_START("server", ServerSeq, ServerInitState), i("start client evaluator(s)"), ClientInitState = InitState#{host => local_host()}, Client = ?SEV_START("client", ClientSeq, ClientInitState), i("start 'tester' evaluator"), TesterInitState = #{server => Server#ev.pid, client => Client#ev.pid, num => maps:get(num, InitState)}, Tester = ?SEV_START("tester", TesterSeq, TesterInitState), i("await evaluator"), ok = ?SEV_AWAIT_FINISH([Server, Client, Tester]). %% Server side handler process %% We don't actually need a separate process for this socket, %% but we do it anyway to simplify the sequence. tpp_udp_server_handler_create() -> Self = self(), erlang:spawn(fun() -> tpp_udp_server_handler(Self) end). tpp_udp_server_handler(Parent) -> tpp_udp_server_handler_init(Parent), {Sock, Send, Recv} = tpp_udp_handler_await_start(Parent), tpp_udp_handler_announce_ready(Parent, init), tpp_udp_handler_await_continue(Parent, recv), Result = tpp_udp_server_handler_msg_exchange(Sock, Send, Recv), tpp_udp_handler_announce_ready(Parent, recv, Result), Reason = tpp_udp_handler_await_terminate(Parent), ?SEV_IPRINT("terminating"), exit(Reason). tpp_udp_server_handler_init(Parent) -> put(sname, "shandler"), ?SEV_IPRINT("init"), _MRef = erlang:monitor(process, Parent), ok. tpp_udp_server_handler_msg_exchange(Sock, Send, Recv) -> tpp_udp_server_handler_msg_exchange_loop(Sock, Send, Recv, 0, 0, 0, undefined). tpp_udp_server_handler_msg_exchange_loop(Sock, Send, Recv, N, Sent, Received, Start) -> %% ?SEV_IPRINT("[~w] try receive", [N]), %% if %% (N =:= (?TPP_SMALL_NUM-2)) -> %% ?SEV_IPRINT("[~w] try receive", [N]), %% socket:setopt(Sock, otp, debug, true); %% true -> ok %% end, try tpp_udp_recv_req(Sock, Recv) of {ok, Msg, RecvSz, From} -> NewStart = if (Start =:= undefined) -> ?LIB:timestamp(); true -> Start end, %% ?SEV_IPRINT("[~w] received - now try send", [N]), try tpp_udp_send_rep(Sock, Send, Msg, From) of {ok, SendSz} -> tpp_udp_server_handler_msg_exchange_loop(Sock, Send, Recv, N+1, Sent+SendSz, Received+RecvSz, NewStart); {error, SReason} -> ?SEV_EPRINT("send (~w): ~p", [N, SReason]), exit({send, SReason, N}) catch SC:SE:SS -> exit({send, {SC, SE, SS}, N}) end; {error, closed} -> ?SEV_IPRINT("closed - we are done: ~w, ~w, ~w", [N, Sent, Received]), Stop = ?LIB:timestamp(), {N, Sent, Received, Start, Stop}; {error, RReason} -> ?SEV_EPRINT("recv (~w): ~p", [N, RReason]), exit({recv, RReason, N}) catch RC:RE:RS -> exit({recv, {RC, RE, RS}, N}) end. %% The (remote) client side handler process tpp_udp_client_handler_create(Node) -> Self = self(), Fun = fun() -> put(sname, "chandler"), tpp_udp_client_handler(Self) end, erlang:spawn(Node, Fun). tpp_udp_client_handler(Parent) -> tpp_udp_client_handler_init(Parent), ?SEV_IPRINT("await start command"), {ServerSA, Proto, BufInit, Send, Recv} = tpp_udp_handler_await_start(Parent), ?SEV_IPRINT("start command with" "~n ServerSA: ~p", [ServerSA]), Domain = maps:get(family, ServerSA), Sock = tpp_udp_sock_open(Domain, Proto, BufInit), Path = tpp_udp_sock_bind(Sock, Domain), ?SEV_IPRINT("announce ready", []), tpp_udp_handler_announce_ready(Parent, init), {InitMsg, Num} = tpp_udp_handler_await_continue(Parent, send), ?SEV_IPRINT("received continue with" "~n Num: ~p", [Num]), Result = tpp_udp_client_handler_msg_exchange(Sock, ServerSA, Send, Recv, InitMsg, Num), ?SEV_IPRINT("ready"), tpp_udp_handler_announce_ready(Parent, send, Result), ?SEV_IPRINT("await terminate"), Reason = tpp_udp_handler_await_terminate(Parent), ?SEV_IPRINT("terminate with ~p", [Reason]), tpp_udp_sock_close(Sock, Path), ?SEV_IPRINT("terminating"), exit(Reason). tpp_udp_client_handler_init(Parent) -> put(sname, "chandler"), ?SEV_IPRINT("init"), _MRef = erlang:monitor(process, Parent), ok. tpp_udp_client_handler_msg_exchange(Sock, ServerSA, Send, Recv, InitMsg, Num) -> Start = ?LIB:timestamp(), tpp_udp_client_handler_msg_exchange_loop(Sock, ServerSA, Send, Recv, InitMsg, Num, 0, 0, 0, Start). tpp_udp_client_handler_msg_exchange_loop(_Sock, _Dest, _Send, _Recv, _Msg, Num, Num, Sent, Received, Start) -> Stop = ?LIB:timestamp(), {Sent, Received, Start, Stop}; tpp_udp_client_handler_msg_exchange_loop(Sock, #{family := local} = Dest, Send, Recv, Data, Num, N, Sent, Received, Start) -> case tpp_udp_send_req(Sock, Send, Data, Dest) of {ok, SendSz} -> case tpp_udp_recv_rep(Sock, Recv) of {ok, NewData, RecvSz, Dest} -> tpp_udp_client_handler_msg_exchange_loop(Sock, Dest, Send, Recv, NewData, Num, N+1, Sent+SendSz, Received+RecvSz, Start); {error, RReason} -> ?SEV_EPRINT("recv (~w of ~w): ~p", [N, Num, RReason]), exit({recv, RReason, N}) end; {error, SReason} -> ?SEV_EPRINT("send (~w of ~w): ~p", [N, Num, SReason]), exit({send, SReason, N}) end; tpp_udp_client_handler_msg_exchange_loop(Sock, #{addr := Addr, port := Port} = Dest0, Send, Recv, Data, Num, N, Sent, Received, Start) -> case tpp_udp_send_req(Sock, Send, Data, Dest0) of {ok, SendSz} -> case tpp_udp_recv_rep(Sock, Recv) of {ok, NewData, RecvSz, #{addr := Addr, port := Port} = Dest1} -> tpp_udp_client_handler_msg_exchange_loop(Sock, Dest1, Send, Recv, NewData, Num, N+1, Sent+SendSz, Received+RecvSz, Start); {error, RReason} -> ?SEV_EPRINT("recv (~w of ~w): ~p", [N, Num, RReason]), exit({recv, RReason, N}) end; {error, SReason} -> ?SEV_EPRINT("send (~w of ~w): ~p", [N, Num, SReason]), exit({send, SReason, N}) end. tpp_udp_recv_req(Sock, Recv) -> tpp_udp_recv(Sock, Recv, ?TPP_REQUEST). tpp_udp_recv_rep(Sock, Recv) -> tpp_udp_recv(Sock, Recv, ?TPP_REPLY). tpp_udp_recv(Sock, Recv, Tag) -> %% ok = socket:setopt(Sock, otp, debug, true), try Recv(Sock, 0) of {ok, {Source, <> = Msg}} when (Sz =:= size(Data)) -> %% ok = socket:setopt(Sock, otp, debug, false), %% We got it all %% ?SEV_IPRINT("tpp_udp_recv -> got all: " %% "~n Source: ~p" %% "~n Tag: ~p" %% "~n Sz: ~p" %% "~n size(Data): ~p", %% [Source, Tag, Sz, size(Data)]), {ok, Data, size(Msg), Source}; {ok, {_Source, <>}} -> %% ok = socket:setopt(Sock, otp, debug, false), {error, {invalid_msg, Sz, size(Data)}}; {ok, {_, <>}} -> %% ok = socket:setopt(Sock, otp, debug, false), {error, {invalid_msg_tag, Tag}}; {error, _} = ERROR -> %% ok = socket:setopt(Sock, otp, debug, false), ERROR catch C:E:S -> {error, {catched, C, E, S}} end. tpp_udp_send_req(Sock, Send, Data, Dest) -> tpp_udp_send(Sock, Send, ?TPP_REQUEST, Data, Dest). tpp_udp_send_rep(Sock, Send, Data, Dest) -> tpp_udp_send(Sock, Send, ?TPP_REPLY, Data, Dest). tpp_udp_send(Sock, Send, Tag, Data, Dest) -> DataSz = size(Data), Msg = <>, tpp_udp_send_msg(Sock, Send, Msg, Dest, 0). tpp_udp_send_msg(Sock, Send, Msg, Dest, AccSz) when is_binary(Msg) -> case Send(Sock, Msg, Dest) of ok -> {ok, AccSz+size(Msg)}; {ok, Rest} -> % This is an IOVec RestBin = list_to_binary(Rest), tpp_udp_send_msg(Sock, Send, RestBin, Dest, AccSz+(size(Msg)-size(RestBin))); {error, _} = ERROR -> ERROR end. tpp_udp_handler_await_start(Parent) -> ?SEV_IPRINT("await start"), ?SEV_AWAIT_START(Parent). tpp_udp_handler_announce_ready(Parent, Slogan) -> ?SEV_IPRINT("announce ready (~p)", [Slogan]), ?SEV_ANNOUNCE_READY(Parent, Slogan). tpp_udp_handler_announce_ready(Parent, Slogan, Extra) -> ?SEV_IPRINT("announce ready (~p)", [Slogan]), ?SEV_ANNOUNCE_READY(Parent, Slogan, Extra). tpp_udp_handler_await_continue(Parent, Slogan) -> ?SEV_IPRINT("await continue (~p)", [Slogan]), case ?SEV_AWAIT_CONTINUE(Parent, parent, Slogan) of ok -> ?SEV_IPRINT("continue (~p): ok", [Slogan]), ok; {ok, Data} -> ?SEV_IPRINT("continue (~p): ok with data", [Slogan]), Data; {error, Reason} -> ?SEV_EPRINT("continue (~p): error" "~n ~p", [Slogan, Reason]), exit({continue, Slogan, Reason}) end. tpp_udp_handler_await_terminate(Parent) -> ?SEV_IPRINT("await terminate"), case ?SEV_AWAIT_TERMINATE(Parent, parent) of ok -> ok; {error, Reason} -> Reason end. tpp_udp_sock_open(Domain, Proto, BufInit) -> case socket:open(Domain, dgram, Proto) of {ok, Sock} -> ok = BufInit(Sock), Sock; {error, Reason} -> exit({open_failed, Reason}) end. tpp_udp_sock_bind(Sock, Domain) -> LSA = which_local_socket_addr(Domain), case socket:bind(Sock, LSA) of {ok, _} -> ok; {error, Reason} -> exit({bind, Reason}) end. tpp_udp_sock_close(Sock, Path) -> case socket:close(Sock) of ok -> unlink_path(Path), ok; {error, Reason} -> ?SEV_EPRINT("Failed closing socket: " "~n ~p", [Reason]), unlink_path(Path), {error, {close, Reason}} end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = gen_tcp, Active = false %% Message Size: small (=1) %% Domain: inet %% ttest_sgenf_cgenf_small_tcp4(suite) -> []; ttest_sgenf_cgenf_small_tcp4(doc) -> []; ttest_sgenf_cgenf_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_cgenf_small_tcp4, Runtime, inet, gen, false, gen, false, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = gen_tcp, Active = false %% Message Size: small (=1) %% Domain: inet6 %% ttest_sgenf_cgenf_small_tcp6(suite) -> []; ttest_sgenf_cgenf_small_tcp6(doc) -> []; ttest_sgenf_cgenf_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_cgenf_small_tcp6, Runtime, inet6, gen, false, gen, false, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = gen_tcp, Active = false %% Message Size: medium (=2) %% Domain: inet %% ttest_sgenf_cgenf_medium_tcp4(suite) -> []; ttest_sgenf_cgenf_medium_tcp4(doc) -> []; ttest_sgenf_cgenf_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_cgenf_medium_tcp4, Runtime, inet, gen, false, gen, false, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = gen_tcp, Active = false %% Message Size: medium (=2) %% Domain: inet6 %% ttest_sgenf_cgenf_medium_tcp6(suite) -> []; ttest_sgenf_cgenf_medium_tcp6(doc) -> []; ttest_sgenf_cgenf_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_cgenf_medium_tcp6, Runtime, inet6, gen, false, gen, false, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = gen_tcp, Active = false %% Message Size: large (=3) %% Domain: inet %% ttest_sgenf_cgenf_large_tcp4(suite) -> []; ttest_sgenf_cgenf_large_tcp4(doc) -> []; ttest_sgenf_cgenf_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_cgenf_large_tcp4, Runtime, inet, gen, false, gen, false, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = gen_tcp, Active = false %% Message Size: large (=3) %% Domain: inet6 %% ttest_sgenf_cgenf_large_tcp6(suite) -> []; ttest_sgenf_cgenf_large_tcp6(doc) -> []; ttest_sgenf_cgenf_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_cgenf_large_tcp6, Runtime, inet6, gen, false, gen, false, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = gen_tcp, Active = once %% Message Size: small (=1) %% Domain: inet %% ttest_sgenf_cgeno_small_tcp4(suite) -> []; ttest_sgenf_cgeno_small_tcp4(doc) -> []; ttest_sgenf_cgeno_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_cgeno_small_tcp4, Runtime, inet, gen, false, gen, once, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = gen_tcp, Active = once %% Message Size: small (=1) %% Domain: inet6 %% ttest_sgenf_cgeno_small_tcp6(suite) -> []; ttest_sgenf_cgeno_small_tcp6(doc) -> []; ttest_sgenf_cgeno_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_cgeno_small_tcp6, Runtime, inet6, gen, false, gen, once, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = gen_tcp, Active = once %% Message Size: medium (=2) %% Domain: inet %% ttest_sgenf_cgeno_medium_tcp4(suite) -> []; ttest_sgenf_cgeno_medium_tcp4(doc) -> []; ttest_sgenf_cgeno_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_cgeno_medium_tcp4, Runtime, inet, gen, false, gen, once, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = gen_tcp, Active = once %% Message Size: medium (=2) %% Domain: inet6 %% ttest_sgenf_cgeno_medium_tcp6(suite) -> []; ttest_sgenf_cgeno_medium_tcp6(doc) -> []; ttest_sgenf_cgeno_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_cgeno_medium_tcp6, Runtime, inet6, gen, false, gen, once, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = gen_tcp, Active = once %% Message Size: large (=3) %% Domain: inet %% ttest_sgenf_cgeno_large_tcp4(suite) -> []; ttest_sgenf_cgeno_large_tcp4(doc) -> []; ttest_sgenf_cgeno_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_cgeno_large_tcp4, Runtime, inet, gen, false, gen, once, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = gen_tcp, Active = once %% Message Size: large (=3) %% Domain: inet6 %% ttest_sgenf_cgeno_large_tcp6(suite) -> []; ttest_sgenf_cgeno_large_tcp6(doc) -> []; ttest_sgenf_cgeno_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_cgeno_large_tcp6, Runtime, inet6, gen, false, gen, once, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = gen_tcp, Active = true %% Message Size: small (=1) %% Domain: inet %% ttest_sgenf_cgent_small_tcp4(suite) -> []; ttest_sgenf_cgent_small_tcp4(doc) -> []; ttest_sgenf_cgent_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_cgent_small_tcp4, Runtime, inet, gen, false, gen, true, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = gen_tcp, Active = true %% Message Size: small (=1) %% Domain: inet6 %% ttest_sgenf_cgent_small_tcp6(suite) -> []; ttest_sgenf_cgent_small_tcp6(doc) -> []; ttest_sgenf_cgent_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_cgeno_small_tcp6, Runtime, inet6, gen, false, gen, true, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = gen_tcp, Active = true %% Message Size: medium (=2) %% Domain: inet %% ttest_sgenf_cgent_medium_tcp4(suite) -> []; ttest_sgenf_cgent_medium_tcp4(doc) -> []; ttest_sgenf_cgent_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_cgent_medium_tcp4, Runtime, inet, gen, false, gen, true, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = gen_tcp, Active = true %% Message Size: medium (=2) %% Domain: inet6 %% ttest_sgenf_cgent_medium_tcp6(suite) -> []; ttest_sgenf_cgent_medium_tcp6(doc) -> []; ttest_sgenf_cgent_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_cgent_medium_tcp6, Runtime, inet6, gen, false, gen, true, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = gen_tcp, Active = true %% Message Size: large (=3) %% Domain: inet %% ttest_sgenf_cgent_large_tcp4(suite) -> []; ttest_sgenf_cgent_large_tcp4(doc) -> []; ttest_sgenf_cgent_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_cgent_large_tcp4, Runtime, inet, gen, false, gen, true, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = gen_tcp, Active = true %% Message Size: large (=3) %% Domain: inet6 %% ttest_sgenf_cgent_large_tcp6(suite) -> []; ttest_sgenf_cgent_large_tcp6(doc) -> []; ttest_sgenf_cgent_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_cgent_large_tcp6, Runtime, inet6, gen, false, gen, true, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = socket(tcp), Active = false %% Message Size: small (=1) %% Domain: inet %% ttest_sgenf_csockf_small_tcp4(suite) -> []; ttest_sgenf_csockf_small_tcp4(doc) -> []; ttest_sgenf_csockf_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_csockf_small_tcp4, Runtime, inet, gen, false, sock, false, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = socket(tcp), Active = false %% Message Size: small (=1) %% Domain: inet6 %% ttest_sgenf_csockf_small_tcp6(suite) -> []; ttest_sgenf_csockf_small_tcp6(doc) -> []; ttest_sgenf_csockf_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_csockf_small_tcp6, Runtime, inet6, gen, false, sock, false, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = socket(tcp), Active = false %% Message Size: medium (=2) %% Domain: inet %% ttest_sgenf_csockf_medium_tcp4(suite) -> []; ttest_sgenf_csockf_medium_tcp4(doc) -> []; ttest_sgenf_csockf_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_csockf_medium_tcp4, Runtime, inet, gen, false, sock, false, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = socket(tcp), Active = false %% Message Size: medium (=2) %% Domain: inet6 %% ttest_sgenf_csockf_medium_tcp6(suite) -> []; ttest_sgenf_csockf_medium_tcp6(doc) -> []; ttest_sgenf_csockf_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_csockf_medium_tcp6, Runtime, inet6, gen, false, sock, false, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = socket(tcp), Active = false %% Message Size: large (=3) %% Domain: inet %% ttest_sgenf_csockf_large_tcp4(suite) -> []; ttest_sgenf_csockf_large_tcp4(doc) -> []; ttest_sgenf_csockf_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_csockf_large_tcp4, Runtime, inet, gen, false, sock, false, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = socket(tcp), Active = false %% Message Size: large (=3) %% Domain: inet6 %% ttest_sgenf_csockf_large_tcp6(suite) -> []; ttest_sgenf_csockf_large_tcp6(doc) -> []; ttest_sgenf_csockf_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_csockf_large_tcp6, Runtime, inet6, gen, false, sock, false, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = socket(tcp), Active = once %% Message Size: small (=1) %% Domain: inet %% ttest_sgenf_csocko_small_tcp4(suite) -> []; ttest_sgenf_csocko_small_tcp4(doc) -> []; ttest_sgenf_csocko_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_csocko_small_tcp4, Runtime, inet, gen, false, sock, once, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = socket(tcp), Active = once %% Message Size: small (=1) %% Domain: inet6 %% ttest_sgenf_csocko_small_tcp6(suite) -> []; ttest_sgenf_csocko_small_tcp6(doc) -> []; ttest_sgenf_csocko_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_csocko_small_tcp6, Runtime, inet6, gen, false, sock, once, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = socket(tcp), Active = once %% Message Size: medium (=2) %% Domain: inet %% ttest_sgenf_csocko_medium_tcp4(suite) -> []; ttest_sgenf_csocko_medium_tcp4(doc) -> []; ttest_sgenf_csocko_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_csocko_medium_tcp4, Runtime, inet, gen, false, sock, once, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = socket(tcp), Active = once %% Message Size: medium (=2) %% Domain: inet6 %% ttest_sgenf_csocko_medium_tcp6(suite) -> []; ttest_sgenf_csocko_medium_tcp6(doc) -> []; ttest_sgenf_csocko_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_csocko_medium_tcp6, Runtime, inet6, gen, false, sock, once, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = socket(tcp), Active = once %% Message Size: large (=3) %% Domain: inet %% ttest_sgenf_csocko_large_tcp4(suite) -> []; ttest_sgenf_csocko_large_tcp4(doc) -> []; ttest_sgenf_csocko_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_csocko_large_tcp4, Runtime, inet, gen, false, sock, once, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = socket(tcp), Active = once %% Message Size: large (=3) %% Domain: inet6 %% ttest_sgenf_csocko_large_tcp6(suite) -> []; ttest_sgenf_csocko_large_tcp6(doc) -> []; ttest_sgenf_csocko_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_csocko_large_tcp6, Runtime, inet6, gen, false, sock, once, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = socket(tcp), Active = true %% Message Size: small (=1) %% Domain: inet %% ttest_sgenf_csockt_small_tcp4(suite) -> []; ttest_sgenf_csockt_small_tcp4(doc) -> []; ttest_sgenf_csockt_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_csockt_small_tcp4, Runtime, inet, gen, false, sock, true, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = socket(tcp), Active = true %% Message Size: small (=1) %% Domain: inet6 %% ttest_sgenf_csockt_small_tcp6(suite) -> []; ttest_sgenf_csockt_small_tcp6(doc) -> []; ttest_sgenf_csockt_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_csocko_small_tcp6, Runtime, inet6, gen, false, sock, true, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = socket(tcp), Active = true %% Message Size: medium (=2) %% Domain: inet %% ttest_sgenf_csockt_medium_tcp4(suite) -> []; ttest_sgenf_csockt_medium_tcp4(doc) -> []; ttest_sgenf_csockt_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_csockt_medium_tcp4, Runtime, inet, gen, false, sock, true, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = socket(tcp), Active = true %% Message Size: medium (=2) %% Domain: inet6 %% ttest_sgenf_csockt_medium_tcp6(suite) -> []; ttest_sgenf_csockt_medium_tcp6(doc) -> []; ttest_sgenf_csockt_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_csockt_medium_tcp6, Runtime, inet6, gen, false, sock, true, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = socket(tcp), Active = true %% Message Size: large (=3) %% Domain: inet %% ttest_sgenf_csockt_large_tcp4(suite) -> []; ttest_sgenf_csockt_large_tcp4(doc) -> []; ttest_sgenf_csockt_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_csockt_large_tcp4, Runtime, inet, gen, false, sock, true, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = false %% Client: Transport = socket(tcp), Active = true %% Message Size: large (=3) %% Domain: inet6 %% ttest_sgenf_csockt_large_tcp6(suite) -> []; ttest_sgenf_csockt_large_tcp6(doc) -> []; ttest_sgenf_csockt_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgenf_csockt_large_tcp6, Runtime, inet6, gen, false, sock, true, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = gen_tcp, Active = false %% Message Size: small (=1) %% Domain: inet %% ttest_sgeno_cgenf_small_tcp4(suite) -> []; ttest_sgeno_cgenf_small_tcp4(doc) -> []; ttest_sgeno_cgenf_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_cgenf_small_tcp4, Runtime, inet, gen, once, gen, false, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = gen_tcp, Active = false %% Message Size: small (=1) %% Domain: inet6 %% ttest_sgeno_cgenf_small_tcp6(suite) -> []; ttest_sgeno_cgenf_small_tcp6(doc) -> []; ttest_sgeno_cgenf_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_cgenf_small_tcp6, Runtime, inet6, gen, once, gen, false, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = gen_tcp, Active = false %% Message Size: medium (=2) %% Domain: inet %% ttest_sgeno_cgenf_medium_tcp4(suite) -> []; ttest_sgeno_cgenf_medium_tcp4(doc) -> []; ttest_sgeno_cgenf_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_cgenf_medium_tcp4, Runtime, inet, gen, once, gen, false, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = gen_tcp, Active = false %% Message Size: medium (=2) %% Domain: inet6 %% ttest_sgeno_cgenf_medium_tcp6(suite) -> []; ttest_sgeno_cgenf_medium_tcp6(doc) -> []; ttest_sgeno_cgenf_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_cgenf_medium_tcp6, Runtime, inet6, gen, once, gen, false, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = gen_tcp, Active = false %% Message Size: large (=3) %% Domain: inet %% ttest_sgeno_cgenf_large_tcp4(suite) -> []; ttest_sgeno_cgenf_large_tcp4(doc) -> []; ttest_sgeno_cgenf_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_cgenf_large_tcp4, Runtime, inet, gen, once, gen, false, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = gen_tcp, Active = false %% Message Size: large (=3) %% Domain: inet6 %% ttest_sgeno_cgenf_large_tcp6(suite) -> []; ttest_sgeno_cgenf_large_tcp6(doc) -> []; ttest_sgeno_cgenf_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_cgenf_large_tcp6, Runtime, inet6, gen, once, gen, false, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = gen_tcp, Active = once %% Message Size: small (=1) %% Domain: inet %% ttest_sgeno_cgeno_small_tcp4(suite) -> []; ttest_sgeno_cgeno_small_tcp4(doc) -> []; ttest_sgeno_cgeno_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_cgeno_small_tcp4, Runtime, inet, gen, once, gen, once, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = gen_tcp, Active = once %% Message Size: small (=1) %% Domain: inet6 %% ttest_sgeno_cgeno_small_tcp6(suite) -> []; ttest_sgeno_cgeno_small_tcp6(doc) -> []; ttest_sgeno_cgeno_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_cgeno_small_tcp6, Runtime, inet6, gen, once, gen, once, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = gen_tcp, Active = once %% Message Size: medium (=2) %% Domain: inet %% ttest_sgeno_cgeno_medium_tcp4(suite) -> []; ttest_sgeno_cgeno_medium_tcp4(doc) -> []; ttest_sgeno_cgeno_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_cgeno_medium_tcp4, Runtime, inet, gen, once, gen, once, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = gen_tcp, Active = once %% Message Size: medium (=2) %% Domain: inet6 %% ttest_sgeno_cgeno_medium_tcp6(suite) -> []; ttest_sgeno_cgeno_medium_tcp6(doc) -> []; ttest_sgeno_cgeno_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_cgeno_medium_tcp6, Runtime, inet6, gen, once, gen, once, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = gen_tcp, Active = once %% Message Size: large (=3) %% Domain: inet %% ttest_sgeno_cgeno_large_tcp4(suite) -> []; ttest_sgeno_cgeno_large_tcp4(doc) -> []; ttest_sgeno_cgeno_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_cgeno_large_tcp4, Runtime, inet, gen, once, gen, once, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = gen_tcp, Active = once %% Message Size: large (=3) %% Domain: inet6 %% ttest_sgeno_cgeno_large_tcp6(suite) -> []; ttest_sgeno_cgeno_large_tcp6(doc) -> []; ttest_sgeno_cgeno_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_cgeno_large_tcp6, Runtime, inet6, gen, once, gen, once, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = gen_tcp, Active = true %% Message Size: small (=1) %% Domain: inet %% ttest_sgeno_cgent_small_tcp4(suite) -> []; ttest_sgeno_cgent_small_tcp4(doc) -> []; ttest_sgeno_cgent_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_cgent_small_tcp4, Runtime, inet, gen, once, gen, true, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = gen_tcp, Active = true %% Message Size: small (=1) %% Domain: inet6 %% ttest_sgeno_cgent_small_tcp6(suite) -> []; ttest_sgeno_cgent_small_tcp6(doc) -> []; ttest_sgeno_cgent_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_cgeno_small_tcp6, Runtime, inet6, gen, once, gen, true, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = gen_tcp, Active = true %% Message Size: medium (=2) %% Domain: inet %% ttest_sgeno_cgent_medium_tcp4(suite) -> []; ttest_sgeno_cgent_medium_tcp4(doc) -> []; ttest_sgeno_cgent_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_cgent_medium_tcp4, Runtime, inet, gen, once, gen, true, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = gen_tcp, Active = true %% Message Size: medium (=2) %% Domain: inet6 %% ttest_sgeno_cgent_medium_tcp6(suite) -> []; ttest_sgeno_cgent_medium_tcp6(doc) -> []; ttest_sgeno_cgent_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_cgent_medium_tcp6, Runtime, inet6, gen, once, gen, true, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = gen_tcp, Active = true %% Message Size: large (=3) %% Domain: inet %% ttest_sgeno_cgent_large_tcp4(suite) -> []; ttest_sgeno_cgent_large_tcp4(doc) -> []; ttest_sgeno_cgent_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_cgent_large_tcp4, Runtime, inet, gen, once, gen, true, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = gen_tcp, Active = true %% Message Size: large (=3) %% Domain: inet6 %% ttest_sgeno_cgent_large_tcp6(suite) -> []; ttest_sgeno_cgent_large_tcp6(doc) -> []; ttest_sgeno_cgent_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_cgent_large_tcp6, Runtime, inet6, gen, once, gen, true, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = socket(tcp), Active = false %% Message Size: small (=1) %% Domain: inet %% ttest_sgeno_csockf_small_tcp4(suite) -> []; ttest_sgeno_csockf_small_tcp4(doc) -> []; ttest_sgeno_csockf_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_csockf_small_tcp4, Runtime, inet, gen, once, sock, false, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = socket(tcp), Active = false %% Message Size: small (=1) %% Domain: inet6 %% ttest_sgeno_csockf_small_tcp6(suite) -> []; ttest_sgeno_csockf_small_tcp6(doc) -> []; ttest_sgeno_csockf_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_csockf_small_tcp6, Runtime, inet6, gen, once, sock, false, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = socket(tcp), Active = false %% Message Size: medium (=2) %% Domain: inet %% ttest_sgeno_csockf_medium_tcp4(suite) -> []; ttest_sgeno_csockf_medium_tcp4(doc) -> []; ttest_sgeno_csockf_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_csockf_medium_tcp4, Runtime, inet, gen, once, sock, false, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = socket(tcp), Active = false %% Message Size: medium (=2) %% Domain: inet6 %% ttest_sgeno_csockf_medium_tcp6(suite) -> []; ttest_sgeno_csockf_medium_tcp6(doc) -> []; ttest_sgeno_csockf_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_csockf_medium_tcp6, Runtime, inet6, gen, once, sock, false, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = socket(tcp), Active = false %% Message Size: large (=3) %% Domain: inet %% ttest_sgeno_csockf_large_tcp4(suite) -> []; ttest_sgeno_csockf_large_tcp4(doc) -> []; ttest_sgeno_csockf_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_csockf_large_tcp4, Runtime, inet, gen, once, sock, false, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = socket(tcp), Active = false %% Message Size: large (=3) %% Domain: inet6 %% ttest_sgeno_csockf_large_tcp6(suite) -> []; ttest_sgeno_csockf_large_tcp6(doc) -> []; ttest_sgeno_csockf_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_csockf_large_tcp6, Runtime, inet6, gen, once, sock, false, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = socket(tcp), Active = once %% Message Size: small (=1) %% Domain: inet %% ttest_sgeno_csocko_small_tcp4(suite) -> []; ttest_sgeno_csocko_small_tcp4(doc) -> []; ttest_sgeno_csocko_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_csocko_small_tcp4, Runtime, inet, gen, once, sock, once, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = socket(tcp), Active = once %% Message Size: small (=1) %% Domain: inet6 %% ttest_sgeno_csocko_small_tcp6(suite) -> []; ttest_sgeno_csocko_small_tcp6(doc) -> []; ttest_sgeno_csocko_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_csocko_small_tcp6, Runtime, inet6, gen, once, sock, once, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = socket(tcp), Active = once %% Message Size: medium (=2) %% Domain: inet %% ttest_sgeno_csocko_medium_tcp4(suite) -> []; ttest_sgeno_csocko_medium_tcp4(doc) -> []; ttest_sgeno_csocko_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_csocko_medium_tcp4, Runtime, inet, gen, once, sock, once, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = socket(tcp), Active = once %% Message Size: medium (=2) %% Domain: inet6 %% ttest_sgeno_csocko_medium_tcp6(suite) -> []; ttest_sgeno_csocko_medium_tcp6(doc) -> []; ttest_sgeno_csocko_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_csocko_medium_tcp6, Runtime, inet6, gen, once, sock, once, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = socket(tcp), Active = once %% Message Size: large (=3) %% Domain: inet %% ttest_sgeno_csocko_large_tcp4(suite) -> []; ttest_sgeno_csocko_large_tcp4(doc) -> []; ttest_sgeno_csocko_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_csocko_large_tcp4, Runtime, inet, gen, once, sock, once, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = socket(tcp), Active = once %% Message Size: large (=3) %% Domain: inet6 %% ttest_sgeno_csocko_large_tcp6(suite) -> []; ttest_sgeno_csocko_large_tcp6(doc) -> []; ttest_sgeno_csocko_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_csocko_large_tcp6, Runtime, inet6, gen, once, sock, once, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = socket(tcp), Active = true %% Message Size: small (=1) %% Domain: inet %% ttest_sgeno_csockt_small_tcp4(suite) -> []; ttest_sgeno_csockt_small_tcp4(doc) -> []; ttest_sgeno_csockt_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_csockt_small_tcp4, Runtime, inet, gen, once, sock, true, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = socket(tcp), Active = true %% Message Size: small (=1) %% Domain: inet6 %% ttest_sgeno_csockt_small_tcp6(suite) -> []; ttest_sgeno_csockt_small_tcp6(doc) -> []; ttest_sgeno_csockt_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_csocko_small_tcp6, Runtime, inet6, gen, once, sock, true, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = socket(tcp), Active = true %% Message Size: medium (=2) %% Domain: inet %% ttest_sgeno_csockt_medium_tcp4(suite) -> []; ttest_sgeno_csockt_medium_tcp4(doc) -> []; ttest_sgeno_csockt_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_csockt_medium_tcp4, Runtime, inet, gen, once, sock, true, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = socket(tcp), Active = true %% Message Size: medium (=2) %% Domain: inet6 %% ttest_sgeno_csockt_medium_tcp6(suite) -> []; ttest_sgeno_csockt_medium_tcp6(doc) -> []; ttest_sgeno_csockt_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_csockt_medium_tcp6, Runtime, inet6, gen, once, sock, true, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = socket(tcp), Active = true %% Message Size: large (=3) %% Domain: inet %% ttest_sgeno_csockt_large_tcp4(suite) -> []; ttest_sgeno_csockt_large_tcp4(doc) -> []; ttest_sgeno_csockt_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_csockt_large_tcp4, Runtime, inet, gen, once, sock, true, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = once %% Client: Transport = socket(tcp), Active = true %% Message Size: large (=3) %% Domain: inet6 %% ttest_sgeno_csockt_large_tcp6(suite) -> []; ttest_sgeno_csockt_large_tcp6(doc) -> []; ttest_sgeno_csockt_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgeno_csockt_large_tcp6, Runtime, inet6, gen, once, sock, true, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = gen_tcp, Active = false %% Message Size: small (=1) %% Domain: inet %% ttest_sgent_cgenf_small_tcp4(suite) -> []; ttest_sgent_cgenf_small_tcp4(doc) -> []; ttest_sgent_cgenf_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_cgenf_small_tcp4, Runtime, inet, gen, true, gen, false, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = gen_tcp, Active = false %% Message Size: small (=1) %% Domain: inet6 %% ttest_sgent_cgenf_small_tcp6(suite) -> []; ttest_sgent_cgenf_small_tcp6(doc) -> []; ttest_sgent_cgenf_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_cgenf_small_tcp6, Runtime, inet6, gen, true, gen, false, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = gen_tcp, Active = false %% Message Size: medium (=2) %% Domain: inet %% ttest_sgent_cgenf_medium_tcp4(suite) -> []; ttest_sgent_cgenf_medium_tcp4(doc) -> []; ttest_sgent_cgenf_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_cgenf_medium_tcp4, Runtime, inet, gen, true, gen, false, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = gen_tcp, Active = false %% Message Size: medium (=2) %% Domain: inet6 %% ttest_sgent_cgenf_medium_tcp6(suite) -> []; ttest_sgent_cgenf_medium_tcp6(doc) -> []; ttest_sgent_cgenf_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_cgenf_medium_tcp6, Runtime, inet6, gen, true, gen, false, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = gen_tcp, Active = false %% Message Size: large (=3) %% Domain: inet %% ttest_sgent_cgenf_large_tcp4(suite) -> []; ttest_sgent_cgenf_large_tcp4(doc) -> []; ttest_sgent_cgenf_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_cgenf_large_tcp4, Runtime, inet, gen, true, gen, false, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = gen_tcp, Active = false %% Message Size: large (=3) %% Domain: inet6 %% ttest_sgent_cgenf_large_tcp6(suite) -> []; ttest_sgent_cgenf_large_tcp6(doc) -> []; ttest_sgent_cgenf_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_cgenf_large_tcp6, Runtime, inet6, gen, true, gen, false, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = gen_tcp, Active = once %% Message Size: small (=1) %% Domain: inet %% ttest_sgent_cgeno_small_tcp4(suite) -> []; ttest_sgent_cgeno_small_tcp4(doc) -> []; ttest_sgent_cgeno_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_cgeno_small_tcp4, Runtime, inet, gen, true, gen, once, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = gen_tcp, Active = once %% Message Size: small (=1) %% Domain: inet6 %% ttest_sgent_cgeno_small_tcp6(suite) -> []; ttest_sgent_cgeno_small_tcp6(doc) -> []; ttest_sgent_cgeno_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_cgeno_small_tcp6, Runtime, inet6, gen, true, gen, once, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = gen_tcp, Active = once %% Message Size: medium (=2) %% Domain: inet %% ttest_sgent_cgeno_medium_tcp4(suite) -> []; ttest_sgent_cgeno_medium_tcp4(doc) -> []; ttest_sgent_cgeno_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_cgeno_medium_tcp4, Runtime, inet, gen, true, gen, once, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = gen_tcp, Active = once %% Message Size: medium (=2) %% Domain: inet6 %% ttest_sgent_cgeno_medium_tcp6(suite) -> []; ttest_sgent_cgeno_medium_tcp6(doc) -> []; ttest_sgent_cgeno_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_cgeno_medium_tcp6, Runtime, inet6, gen, true, gen, once, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = gen_tcp, Active = once %% Message Size: large (=3) %% Domain: inet %% ttest_sgent_cgeno_large_tcp4(suite) -> []; ttest_sgent_cgeno_large_tcp4(doc) -> []; ttest_sgent_cgeno_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_cgeno_large_tcp4, Runtime, inet, gen, true, gen, once, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = gen_tcp, Active = once %% Message Size: large (=3) %% Domain: inet6 %% ttest_sgent_cgeno_large_tcp6(suite) -> []; ttest_sgent_cgeno_large_tcp6(doc) -> []; ttest_sgent_cgeno_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_cgeno_large_tcp6, Runtime, inet6, gen, true, gen, once, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = gen_tcp, Active = true %% Message Size: small (=1) %% Domain: inet %% ttest_sgent_cgent_small_tcp4(suite) -> []; ttest_sgent_cgent_small_tcp4(doc) -> []; ttest_sgent_cgent_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_cgent_small_tcp4, Runtime, inet, gen, true, gen, true, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = gen_tcp, Active = true %% Message Size: small (=1) %% Domain: inet6 %% ttest_sgent_cgent_small_tcp6(suite) -> []; ttest_sgent_cgent_small_tcp6(doc) -> []; ttest_sgent_cgent_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_cgeno_small_tcp6, Runtime, inet6, gen, true, gen, true, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = gen_tcp, Active = true %% Message Size: medium (=2) %% Domain: inet %% ttest_sgent_cgent_medium_tcp4(suite) -> []; ttest_sgent_cgent_medium_tcp4(doc) -> ["Server(gen,true), Client(gen,true), Domain=inet, msg=medium"]; ttest_sgent_cgent_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_cgent_medium_tcp4, Runtime, inet, gen, true, gen, true, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = gen_tcp, Active = true %% Message Size: medium (=2) %% Domain: inet6 %% ttest_sgent_cgent_medium_tcp6(suite) -> []; ttest_sgent_cgent_medium_tcp6(doc) -> ["Server(gen,true), Client(gen,true), Domain=inet6, msg=medium"]; ttest_sgent_cgent_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_cgent_medium_tcp6, Runtime, inet6, gen, true, gen, true, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = gen_tcp, Active = true %% Message Size: large (=3) %% Domain: inet %% ttest_sgent_cgent_large_tcp4(suite) -> []; ttest_sgent_cgent_large_tcp4(doc) -> ["Server(gen,true), Client(gen,true), Domain=inet, msg=large"]; ttest_sgent_cgent_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_cgent_large_tcp4, Runtime, inet, gen, true, gen, true, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = gen_tcp, Active = true %% Message Size: large (=3) %% Domain: inet6 %% ttest_sgent_cgent_large_tcp6(suite) -> []; ttest_sgent_cgent_large_tcp6(doc) -> ["Server(gen,true), Client(gen,true), Domain=inet6, msg=large"]; ttest_sgent_cgent_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_cgent_large_tcp6, Runtime, inet6, gen, true, gen, true, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = socket(tcp), Active = false %% Message Size: small (=1) %% Domain: inet %% ttest_sgent_csockf_small_tcp4(suite) -> []; ttest_sgent_csockf_small_tcp4(doc) -> []; ttest_sgent_csockf_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_csockf_small_tcp4, Runtime, inet, gen, true, sock, false, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = socket(tcp), Active = false %% Message Size: small (=1) %% Domain: inet6 %% ttest_sgent_csockf_small_tcp6(suite) -> []; ttest_sgent_csockf_small_tcp6(doc) -> []; ttest_sgent_csockf_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_csockf_small_tcp6, Runtime, inet6, gen, true, sock, false, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = socket(tcp), Active = false %% Message Size: medium (=2) %% Domain: inet %% ttest_sgent_csockf_medium_tcp4(suite) -> []; ttest_sgent_csockf_medium_tcp4(doc) -> []; ttest_sgent_csockf_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_csockf_medium_tcp4, Runtime, inet, gen, true, sock, false, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = socket(tcp), Active = false %% Message Size: medium (=2) %% Domain: inet6 %% ttest_sgent_csockf_medium_tcp6(suite) -> []; ttest_sgent_csockf_medium_tcp6(doc) -> []; ttest_sgent_csockf_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_csockf_medium_tcp6, Runtime, inet6, gen, true, sock, false, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = socket(tcp), Active = false %% Message Size: large (=3) %% Domain: inet %% ttest_sgent_csockf_large_tcp4(suite) -> []; ttest_sgent_csockf_large_tcp4(doc) -> []; ttest_sgent_csockf_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_csockf_large_tcp4, Runtime, inet, gen, true, sock, false, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = socket(tcp), Active = false %% Message Size: large (=3) %% Domain: inet6 %% ttest_sgent_csockf_large_tcp6(suite) -> []; ttest_sgent_csockf_large_tcp6(doc) -> []; ttest_sgent_csockf_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_csockf_large_tcp6, Runtime, inet6, gen, true, sock, false, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = socket(tcp), Active = once %% Message Size: small (=1) %% Domain: inet %% ttest_sgent_csocko_small_tcp4(suite) -> []; ttest_sgent_csocko_small_tcp4(doc) -> []; ttest_sgent_csocko_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_csocko_small_tcp4, Runtime, inet, gen, true, sock, once, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = socket(tcp), Active = once %% Message Size: small (=1) %% Domain: inet6 %% ttest_sgent_csocko_small_tcp6(suite) -> []; ttest_sgent_csocko_small_tcp6(doc) -> []; ttest_sgent_csocko_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_csocko_small_tcp6, Runtime, inet6, gen, true, sock, once, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = socket(tcp), Active = once %% Message Size: medium (=2) %% Domain: inet %% ttest_sgent_csocko_medium_tcp4(suite) -> []; ttest_sgent_csocko_medium_tcp4(doc) -> []; ttest_sgent_csocko_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_csocko_medium_tcp4, Runtime, inet, gen, true, sock, once, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = socket(tcp), Active = once %% Message Size: medium (=2) %% Domain: inet6 %% ttest_sgent_csocko_medium_tcp6(suite) -> []; ttest_sgent_csocko_medium_tcp6(doc) -> []; ttest_sgent_csocko_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_csocko_medium_tcp6, Runtime, inet6, gen, true, sock, once, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = socket(tcp), Active = once %% Message Size: large (=3) %% Domain: inet %% ttest_sgent_csocko_large_tcp4(suite) -> []; ttest_sgent_csocko_large_tcp4(doc) -> []; ttest_sgent_csocko_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_csocko_large_tcp4, Runtime, inet, gen, true, sock, once, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = socket(tcp), Active = once %% Message Size: large (=3) %% Domain: inet6 %% ttest_sgent_csocko_large_tcp6(suite) -> []; ttest_sgent_csocko_large_tcp6(doc) -> []; ttest_sgent_csocko_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_csocko_large_tcp6, Runtime, inet6, gen, true, sock, once, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = socket(tcp), Active = true %% Message Size: small (=1) %% Domain: inet %% ttest_sgent_csockt_small_tcp4(suite) -> []; ttest_sgent_csockt_small_tcp4(doc) -> []; ttest_sgent_csockt_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_csockt_small_tcp4, Runtime, inet, gen, true, sock, true, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = socket(tcp), Active = true %% Message Size: small (=1) %% Domain: inet6 %% ttest_sgent_csockt_small_tcp6(suite) -> []; ttest_sgent_csockt_small_tcp6(doc) -> []; ttest_sgent_csockt_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_csocko_small_tcp6, Runtime, inet6, gen, true, sock, true, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = socket(tcp), Active = true %% Message Size: medium (=2) %% Domain: inet %% ttest_sgent_csockt_medium_tcp4(suite) -> []; ttest_sgent_csockt_medium_tcp4(doc) -> []; ttest_sgent_csockt_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_csockt_medium_tcp4, Runtime, inet, gen, true, sock, true, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = socket(tcp), Active = true %% Message Size: medium (=2) %% Domain: inet6 %% ttest_sgent_csockt_medium_tcp6(suite) -> []; ttest_sgent_csockt_medium_tcp6(doc) -> []; ttest_sgent_csockt_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_csockt_medium_tcp6, Runtime, inet6, gen, true, sock, true, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = socket(tcp), Active = true %% Message Size: large (=3) %% Domain: inet %% ttest_sgent_csockt_large_tcp4(suite) -> []; ttest_sgent_csockt_large_tcp4(doc) -> []; ttest_sgent_csockt_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_csockt_large_tcp4, Runtime, inet, gen, true, sock, true, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = gen_tcp, Active = true %% Client: Transport = socket(tcp), Active = true %% Message Size: large (=3) %% Domain: inet6 %% ttest_sgent_csockt_large_tcp6(suite) -> []; ttest_sgent_csockt_large_tcp6(doc) -> []; ttest_sgent_csockt_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_sgent_csockt_large_tcp6, Runtime, inet6, gen, true, sock, true, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = gen_tcp, Active = false %% Message Size: small (=1) %% Domain: inet %% ttest_ssockf_cgenf_small_tcp4(suite) -> []; ttest_ssockf_cgenf_small_tcp4(doc) -> []; ttest_ssockf_cgenf_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_cgenf_small_tcp4, Runtime, inet, sock, false, gen, false, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = gen_tcp, Active = false %% Message Size: small (=1) %% Domain: inet6 %% ttest_ssockf_cgenf_small_tcp6(suite) -> []; ttest_ssockf_cgenf_small_tcp6(doc) -> []; ttest_ssockf_cgenf_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_cgenf_small_tcp6, Runtime, inet6, sock, false, gen, false, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = gen_tcp, Active = false %% Message Size: medium (=2) %% Domain: inet %% ttest_ssockf_cgenf_medium_tcp4(suite) -> []; ttest_ssockf_cgenf_medium_tcp4(doc) -> []; ttest_ssockf_cgenf_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_cgenf_medium_tcp4, Runtime, inet, sock, false, gen, false, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = gen_tcp, Active = false %% Message Size: medium (=2) %% Domain: inet6 %% ttest_ssockf_cgenf_medium_tcp6(suite) -> []; ttest_ssockf_cgenf_medium_tcp6(doc) -> []; ttest_ssockf_cgenf_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_cgenf_medium_tcp6, Runtime, inet6, sock, false, gen, false, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = gen_tcp, Active = false %% Message Size: large (=3) %% Domain: inet %% ttest_ssockf_cgenf_large_tcp4(suite) -> []; ttest_ssockf_cgenf_large_tcp4(doc) -> []; ttest_ssockf_cgenf_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_cgenf_large_tcp4, Runtime, inet, sock, false, gen, false, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = gen_tcp, Active = false %% Message Size: large (=3) %% Domain: inet6 %% ttest_ssockf_cgenf_large_tcp6(suite) -> []; ttest_ssockf_cgenf_large_tcp6(doc) -> []; ttest_ssockf_cgenf_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_cgenf_large_tcp6, Runtime, inet6, sock, false, gen, false, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = gen_tcp, Active = once %% Message Size: small (=1) %% Domain: inet %% ttest_ssockf_cgeno_small_tcp4(suite) -> []; ttest_ssockf_cgeno_small_tcp4(doc) -> []; ttest_ssockf_cgeno_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_cgeno_small_tcp4, Runtime, inet, sock, false, gen, once, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = gen_tcp, Active = once %% Message Size: small (=1) %% Domain: inet6 %% ttest_ssockf_cgeno_small_tcp6(suite) -> []; ttest_ssockf_cgeno_small_tcp6(doc) -> []; ttest_ssockf_cgeno_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_cgeno_small_tcp6, Runtime, inet6, sock, false, gen, once, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = gen_tcp, Active = once %% Message Size: medium (=2) %% Domain: inet %% ttest_ssockf_cgeno_medium_tcp4(suite) -> []; ttest_ssockf_cgeno_medium_tcp4(doc) -> []; ttest_ssockf_cgeno_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_cgeno_medium_tcp4, Runtime, inet, sock, false, gen, once, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = gen_tcp, Active = once %% Message Size: medium (=2) %% Domain: inet6 %% ttest_ssockf_cgeno_medium_tcp6(suite) -> []; ttest_ssockf_cgeno_medium_tcp6(doc) -> []; ttest_ssockf_cgeno_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_cgeno_medium_tcp6, Runtime, inet6, sock, false, gen, once, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = gen_tcp, Active = once %% Message Size: large (=3) %% Domain: inet %% ttest_ssockf_cgeno_large_tcp4(suite) -> []; ttest_ssockf_cgeno_large_tcp4(doc) -> []; ttest_ssockf_cgeno_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_cgeno_large_tcp4, Runtime, inet, sock, false, gen, once, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = gen_tcp, Active = once %% Message Size: large (=3) %% Domain: inet6 %% ttest_ssockf_cgeno_large_tcp6(suite) -> []; ttest_ssockf_cgeno_large_tcp6(doc) -> []; ttest_ssockf_cgeno_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_cgeno_large_tcp6, Runtime, inet6, sock, false, gen, once, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = gen_tcp, Active = true %% Message Size: small (=1) %% Domain: inet %% ttest_ssockf_cgent_small_tcp4(suite) -> []; ttest_ssockf_cgent_small_tcp4(doc) -> []; ttest_ssockf_cgent_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_cgent_small_tcp4, Runtime, inet, sock, false, gen, true, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = gen_tcp, Active = true %% Message Size: small (=1) %% Domain: inet6 %% ttest_ssockf_cgent_small_tcp6(suite) -> []; ttest_ssockf_cgent_small_tcp6(doc) -> []; ttest_ssockf_cgent_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_cgeno_small_tcp6, Runtime, inet6, sock, false, gen, true, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = gen_tcp, Active = true %% Message Size: medium (=2) %% Domain: inet %% ttest_ssockf_cgent_medium_tcp4(suite) -> []; ttest_ssockf_cgent_medium_tcp4(doc) -> []; ttest_ssockf_cgent_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_cgent_medium_tcp4, Runtime, inet, sock, false, gen, true, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = gen_tcp, Active = true %% Message Size: medium (=2) %% Domain: inet6 %% ttest_ssockf_cgent_medium_tcp6(suite) -> []; ttest_ssockf_cgent_medium_tcp6(doc) -> []; ttest_ssockf_cgent_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_cgent_medium_tcp6, Runtime, inet6, sock, false, gen, true, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = gen_tcp, Active = true %% Message Size: large (=3) %% Domain: inet %% ttest_ssockf_cgent_large_tcp4(suite) -> []; ttest_ssockf_cgent_large_tcp4(doc) -> []; ttest_ssockf_cgent_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_cgent_large_tcp4, Runtime, inet, sock, false, gen, true, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = gen_tcp, Active = true %% Message Size: large (=3) %% Domain: inet6 %% ttest_ssockf_cgent_large_tcp6(suite) -> []; ttest_ssockf_cgent_large_tcp6(doc) -> []; ttest_ssockf_cgent_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_cgent_large_tcp6, Runtime, inet6, sock, false, gen, true, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = false %% Message Size: small (=1) %% Domain: inet %% ttest_ssockf_csockf_small_tcp4(suite) -> []; ttest_ssockf_csockf_small_tcp4(doc) -> []; ttest_ssockf_csockf_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_csockf_small_tcp4, Runtime, inet, sock, false, sock, false, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = false %% Message Size: small (=1) %% Domain: inet6 %% ttest_ssockf_csockf_small_tcp6(suite) -> []; ttest_ssockf_csockf_small_tcp6(doc) -> []; ttest_ssockf_csockf_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_csockf_small_tcp6, Runtime, inet6, sock, false, sock, false, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = false %% Message Size: small (=1) %% Domain: local %% ttest_ssockf_csockf_small_tcpL(suite) -> []; ttest_ssockf_csockf_small_tcpL(doc) -> []; ttest_ssockf_csockf_small_tcpL(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_csockf_small_tcpL, Runtime, local, sock, false, sock, false, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = false %% Message Size: medium (=2) %% Domain: inet %% ttest_ssockf_csockf_medium_tcp4(suite) -> []; ttest_ssockf_csockf_medium_tcp4(doc) -> []; ttest_ssockf_csockf_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_csockf_medium_tcp4, Runtime, inet, sock, false, sock, false, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = false %% Message Size: medium (=2) %% Domain: inet6 %% ttest_ssockf_csockf_medium_tcp6(suite) -> []; ttest_ssockf_csockf_medium_tcp6(doc) -> []; ttest_ssockf_csockf_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_csockf_medium_tcp6, Runtime, inet6, sock, false, sock, false, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = false %% Message Size: medium (=2) %% Domain: local %% ttest_ssockf_csockf_medium_tcpL(suite) -> []; ttest_ssockf_csockf_medium_tcpL(doc) -> []; ttest_ssockf_csockf_medium_tcpL(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_csockf_medium_tcpL, Runtime, local, sock, false, sock, false, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = false %% Message Size: large (=3) %% Domain: inet %% ttest_ssockf_csockf_large_tcp4(suite) -> []; ttest_ssockf_csockf_large_tcp4(doc) -> []; ttest_ssockf_csockf_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_csockf_large_tcp4, Runtime, inet, sock, false, sock, false, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = false %% Message Size: large (=3) %% Domain: inet6 %% ttest_ssockf_csockf_large_tcp6(suite) -> []; ttest_ssockf_csockf_large_tcp6(doc) -> []; ttest_ssockf_csockf_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_csockf_large_tcp6, Runtime, inet6, sock, false, sock, false, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = false %% Message Size: large (=3) %% Domain: local %% ttest_ssockf_csockf_large_tcpL(suite) -> []; ttest_ssockf_csockf_large_tcpL(doc) -> []; ttest_ssockf_csockf_large_tcpL(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_csockf_large_tcpL, Runtime, local, sock, false, sock, false, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = once %% Message Size: small (=1) %% Domain: inet %% ttest_ssockf_csocko_small_tcp4(suite) -> []; ttest_ssockf_csocko_small_tcp4(doc) -> []; ttest_ssockf_csocko_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_csocko_small_tcp4, Runtime, inet, sock, false, sock, once, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = once %% Message Size: small (=1) %% Domain: inet6 %% ttest_ssockf_csocko_small_tcp6(suite) -> []; ttest_ssockf_csocko_small_tcp6(doc) -> []; ttest_ssockf_csocko_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_csocko_small_tcp6, Runtime, inet6, sock, false, sock, once, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = once %% Message Size: small (=1) %% Domain: local %% ttest_ssockf_csocko_small_tcpL(suite) -> []; ttest_ssockf_csocko_small_tcpL(doc) -> []; ttest_ssockf_csocko_small_tcpL(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_csocko_small_tcpL, Runtime, local, sock, false, sock, once, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = once %% Message Size: medium (=2) %% Domain: inet %% ttest_ssockf_csocko_medium_tcp4(suite) -> []; ttest_ssockf_csocko_medium_tcp4(doc) -> []; ttest_ssockf_csocko_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_csocko_medium_tcp4, Runtime, inet, sock, false, sock, once, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = once %% Message Size: medium (=2) %% Domain: inet6 %% ttest_ssockf_csocko_medium_tcp6(suite) -> []; ttest_ssockf_csocko_medium_tcp6(doc) -> []; ttest_ssockf_csocko_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_csocko_medium_tcp6, Runtime, inet6, sock, false, sock, once, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = once %% Message Size: medium (=2) %% Domain: local %% ttest_ssockf_csocko_medium_tcpL(suite) -> []; ttest_ssockf_csocko_medium_tcpL(doc) -> []; ttest_ssockf_csocko_medium_tcpL(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_csocko_medium_tcpL, Runtime, local, sock, false, sock, once, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = once %% Message Size: large (=3) %% Domain: inet %% ttest_ssockf_csocko_large_tcp4(suite) -> []; ttest_ssockf_csocko_large_tcp4(doc) -> []; ttest_ssockf_csocko_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_csocko_large_tcp4, Runtime, inet, sock, false, sock, once, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = once %% Message Size: large (=3) %% Domain: inet6 %% ttest_ssockf_csocko_large_tcp6(suite) -> []; ttest_ssockf_csocko_large_tcp6(doc) -> []; ttest_ssockf_csocko_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_csocko_large_tcp6, Runtime, inet6, sock, false, sock, once, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = once %% Message Size: large (=3) %% Domain: local %% ttest_ssockf_csocko_large_tcpL(suite) -> []; ttest_ssockf_csocko_large_tcpL(doc) -> []; ttest_ssockf_csocko_large_tcpL(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_csocko_large_tcpL, Runtime, local, sock, false, sock, once, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = true %% Message Size: small (=1) %% Domain: inet %% ttest_ssockf_csockt_small_tcp4(suite) -> []; ttest_ssockf_csockt_small_tcp4(doc) -> []; ttest_ssockf_csockt_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_csockt_small_tcp4, Runtime, inet, sock, false, sock, true, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = true %% Message Size: small (=1) %% Domain: inet6 %% ttest_ssockf_csockt_small_tcp6(suite) -> []; ttest_ssockf_csockt_small_tcp6(doc) -> []; ttest_ssockf_csockt_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_csocko_small_tcp6, Runtime, inet6, sock, false, sock, true, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = true %% Message Size: small (=1) %% Domain: local %% ttest_ssockf_csockt_small_tcpL(suite) -> []; ttest_ssockf_csockt_small_tcpL(doc) -> []; ttest_ssockf_csockt_small_tcpL(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_csocko_small_tcpL, Runtime, local, sock, false, sock, true, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = true %% Message Size: medium (=2) %% Domain: inet %% ttest_ssockf_csockt_medium_tcp4(suite) -> []; ttest_ssockf_csockt_medium_tcp4(doc) -> []; ttest_ssockf_csockt_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_csockt_medium_tcp4, Runtime, inet, sock, false, sock, true, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = true %% Message Size: medium (=2) %% Domain: inet6 %% ttest_ssockf_csockt_medium_tcp6(suite) -> []; ttest_ssockf_csockt_medium_tcp6(doc) -> []; ttest_ssockf_csockt_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_csockt_medium_tcp6, Runtime, inet6, sock, false, sock, true, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = true %% Message Size: medium (=2) %% Domain: local %% ttest_ssockf_csockt_medium_tcpL(suite) -> []; ttest_ssockf_csockt_medium_tcpL(doc) -> []; ttest_ssockf_csockt_medium_tcpL(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_csockt_medium_tcpL, Runtime, local, sock, false, sock, true, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = true %% Message Size: large (=3) %% Domain: inet %% ttest_ssockf_csockt_large_tcp4(suite) -> []; ttest_ssockf_csockt_large_tcp4(doc) -> []; ttest_ssockf_csockt_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_csockt_large_tcp4, Runtime, inet, sock, false, sock, true, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = true %% Message Size: large (=3) %% Domain: inet6 %% ttest_ssockf_csockt_large_tcp6(suite) -> []; ttest_ssockf_csockt_large_tcp6(doc) -> []; ttest_ssockf_csockt_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_csockt_large_tcp6, Runtime, inet6, sock, false, sock, true, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = true %% Message Size: large (=3) %% Domain: local %% ttest_ssockf_csockt_large_tcpL(suite) -> []; ttest_ssockf_csockt_large_tcpL(doc) -> []; ttest_ssockf_csockt_large_tcpL(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockf_csockt_large_tcpL, Runtime, local, sock, false, sock, true, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = gen_tcp, Active = false %% Message Size: small (=1) %% Domain: inet %% ttest_ssocko_cgenf_small_tcp4(suite) -> []; ttest_ssocko_cgenf_small_tcp4(doc) -> []; ttest_ssocko_cgenf_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_cgenf_small_tcp4, Runtime, inet, sock, once, gen, false, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = gen_tcp, Active = false %% Message Size: small (=1) %% Domain: inet6 %% ttest_ssocko_cgenf_small_tcp6(suite) -> []; ttest_ssocko_cgenf_small_tcp6(doc) -> []; ttest_ssocko_cgenf_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_cgenf_small_tcp6, Runtime, inet6, sock, once, gen, false, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = gen_tcp, Active = false %% Message Size: medium (=2) %% Domain: inet %% ttest_ssocko_cgenf_medium_tcp4(suite) -> []; ttest_ssocko_cgenf_medium_tcp4(doc) -> []; ttest_ssocko_cgenf_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_cgenf_medium_tcp4, Runtime, inet, sock, once, gen, false, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = gen_tcp, Active = false %% Message Size: medium (=2) %% Domain: inet6 %% ttest_ssocko_cgenf_medium_tcp6(suite) -> []; ttest_ssocko_cgenf_medium_tcp6(doc) -> []; ttest_ssocko_cgenf_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_cgenf_medium_tcp6, Runtime, inet6, sock, once, gen, false, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = gen_tcp, Active = false %% Message Size: large (=3) %% Domain: inet %% ttest_ssocko_cgenf_large_tcp4(suite) -> []; ttest_ssocko_cgenf_large_tcp4(doc) -> []; ttest_ssocko_cgenf_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_cgenf_large_tcp4, Runtime, inet, sock, once, gen, false, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = gen_tcp, Active = false %% Message Size: large (=3) %% Domain: inet6 %% ttest_ssocko_cgenf_large_tcp6(suite) -> []; ttest_ssocko_cgenf_large_tcp6(doc) -> []; ttest_ssocko_cgenf_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_cgenf_large_tcp6, Runtime, inet6, sock, once, gen, false, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = gen_tcp, Active = once %% Message Size: small (=1) %% Domain: inet %% ttest_ssocko_cgeno_small_tcp4(suite) -> []; ttest_ssocko_cgeno_small_tcp4(doc) -> []; ttest_ssocko_cgeno_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_cgeno_small_tcp4, Runtime, inet, sock, once, gen, once, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = gen_tcp, Active = once %% Message Size: small (=1) %% Domain: inet6 %% ttest_ssocko_cgeno_small_tcp6(suite) -> []; ttest_ssocko_cgeno_small_tcp6(doc) -> []; ttest_ssocko_cgeno_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_cgeno_small_tcp6, Runtime, inet6, sock, once, gen, once, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = gen_tcp, Active = once %% Message Size: medium (=2) %% Domain: inet %% ttest_ssocko_cgeno_medium_tcp4(suite) -> []; ttest_ssocko_cgeno_medium_tcp4(doc) -> []; ttest_ssocko_cgeno_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_cgeno_medium_tcp4, Runtime, inet, sock, once, gen, once, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = gen_tcp, Active = once %% Message Size: medium (=2) %% Domain: inet6 %% ttest_ssocko_cgeno_medium_tcp6(suite) -> []; ttest_ssocko_cgeno_medium_tcp6(doc) -> []; ttest_ssocko_cgeno_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_cgeno_medium_tcp6, Runtime, inet6, sock, once, gen, once, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = gen_tcp, Active = once %% Message Size: large (=3) %% Domain: inet %% ttest_ssocko_cgeno_large_tcp4(suite) -> []; ttest_ssocko_cgeno_large_tcp4(doc) -> []; ttest_ssocko_cgeno_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_cgeno_large_tcp4, Runtime, inet, sock, once, gen, once, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = gen_tcp, Active = once %% Message Size: large (=3) %% Domain: inet6 %% ttest_ssocko_cgeno_large_tcp6(suite) -> []; ttest_ssocko_cgeno_large_tcp6(doc) -> []; ttest_ssocko_cgeno_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_cgeno_large_tcp6, Runtime, inet6, sock, once, gen, once, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = gen_tcp, Active = true %% Message Size: small (=1) %% Domain: inet %% ttest_ssocko_cgent_small_tcp4(suite) -> []; ttest_ssocko_cgent_small_tcp4(doc) -> []; ttest_ssocko_cgent_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_cgent_small_tcp4, Runtime, inet, sock, once, gen, true, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = gen_tcp, Active = true %% Message Size: small (=1) %% Domain: inet6 %% ttest_ssocko_cgent_small_tcp6(suite) -> []; ttest_ssocko_cgent_small_tcp6(doc) -> []; ttest_ssocko_cgent_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_cgent_small_tcp6, Runtime, inet6, sock, once, gen, true, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = gen_tcp, Active = true %% Message Size: medium (=2) %% Domain: inet %% ttest_ssocko_cgent_medium_tcp4(suite) -> []; ttest_ssocko_cgent_medium_tcp4(doc) -> []; ttest_ssocko_cgent_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_cgent_medium_tcp4, Runtime, inet, sock, once, gen, true, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = gen_tcp, Active = true %% Message Size: medium (=2) %% Domain: inet6 %% ttest_ssocko_cgent_medium_tcp6(suite) -> []; ttest_ssocko_cgent_medium_tcp6(doc) -> []; ttest_ssocko_cgent_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_cgent_medium_tcp6, Runtime, inet6, sock, once, gen, true, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = gen_tcp, Active = true %% Message Size: large (=3) %% Domain: inet %% ttest_ssocko_cgent_large_tcp4(suite) -> []; ttest_ssocko_cgent_large_tcp4(doc) -> []; ttest_ssocko_cgent_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_cgent_large_tcp4, Runtime, inet, sock, once, gen, true, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = gen_tcp, Active = true %% Message Size: large (=3) %% Domain: inet6 %% ttest_ssocko_cgent_large_tcp6(suite) -> []; ttest_ssocko_cgent_large_tcp6(doc) -> []; ttest_ssocko_cgent_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_cgent_large_tcp6, Runtime, inet6, sock, once, gen, true, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = false %% Message Size: small (=1) %% Domain: inet %% ttest_ssocko_csockf_small_tcp4(suite) -> []; ttest_ssocko_csockf_small_tcp4(doc) -> []; ttest_ssocko_csockf_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_csockf_small_tcp4, Runtime, inet, sock, once, sock, false, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = false %% Message Size: small (=1) %% Domain: inet6 %% ttest_ssocko_csockf_small_tcp6(suite) -> []; ttest_ssocko_csockf_small_tcp6(doc) -> []; ttest_ssocko_csockf_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_csockf_small_tcp6, Runtime, inet6, sock, once, sock, false, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = false %% Message Size: small (=1) %% Domain: local %% ttest_ssocko_csockf_small_tcpL(suite) -> []; ttest_ssocko_csockf_small_tcpL(doc) -> []; ttest_ssocko_csockf_small_tcpL(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_csockf_small_tcpL, Runtime, local, sock, once, sock, false, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = false %% Message Size: medium (=2) %% Domain: inet %% ttest_ssocko_csockf_medium_tcp4(suite) -> []; ttest_ssocko_csockf_medium_tcp4(doc) -> []; ttest_ssocko_csockf_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_csockf_medium_tcp4, Runtime, inet, sock, once, sock, false, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = false %% Message Size: medium (=2) %% Domain: inet6 %% ttest_ssocko_csockf_medium_tcp6(suite) -> []; ttest_ssocko_csockf_medium_tcp6(doc) -> []; ttest_ssocko_csockf_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_csockf_medium_tcp6, Runtime, inet6, sock, once, sock, false, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = false %% Message Size: medium (=2) %% Domain: local %% ttest_ssocko_csockf_medium_tcpL(suite) -> []; ttest_ssocko_csockf_medium_tcpL(doc) -> []; ttest_ssocko_csockf_medium_tcpL(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_csockf_medium_tcpL, Runtime, local, sock, once, sock, false, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = false %% Message Size: large (=3) %% Domain: inet %% ttest_ssocko_csockf_large_tcp4(suite) -> []; ttest_ssocko_csockf_large_tcp4(doc) -> []; ttest_ssocko_csockf_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_csockf_large_tcp4, Runtime, inet, sock, once, sock, false, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = false %% Message Size: large (=3) %% Domain: inet6 %% ttest_ssocko_csockf_large_tcp6(suite) -> []; ttest_ssocko_csockf_large_tcp6(doc) -> []; ttest_ssocko_csockf_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_csockf_large_tcp6, Runtime, inet6, sock, once, sock, false, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = false %% Message Size: large (=3) %% Domain: local %% ttest_ssocko_csockf_large_tcpL(suite) -> []; ttest_ssocko_csockf_large_tcpL(doc) -> []; ttest_ssocko_csockf_large_tcpL(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_csockf_large_tcpL, Runtime, local, sock, once, sock, false, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = once %% Message Size: small (=1) %% Domain: inet %% ttest_ssocko_csocko_small_tcp4(suite) -> []; ttest_ssocko_csocko_small_tcp4(doc) -> []; ttest_ssocko_csocko_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_csocko_small_tcp4, Runtime, inet, sock, once, sock, once, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = once %% Message Size: small (=1) %% Domain: inet6 %% ttest_ssocko_csocko_small_tcp6(suite) -> []; ttest_ssocko_csocko_small_tcp6(doc) -> []; ttest_ssocko_csocko_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_csocko_small_tcp6, Runtime, inet6, sock, once, sock, once, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = once %% Message Size: small (=1) %% Domain: local %% ttest_ssocko_csocko_small_tcpL(suite) -> []; ttest_ssocko_csocko_small_tcpL(doc) -> []; ttest_ssocko_csocko_small_tcpL(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_csocko_small_tcpL, Runtime, local, sock, once, sock, once, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = once %% Message Size: medium (=2) %% Domain: inet %% ttest_ssocko_csocko_medium_tcp4(suite) -> []; ttest_ssocko_csocko_medium_tcp4(doc) -> []; ttest_ssocko_csocko_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_csocko_medium_tcp4, Runtime, inet, sock, once, sock, once, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = once %% Message Size: medium (=2) %% Domain: inet6 %% ttest_ssocko_csocko_medium_tcp6(suite) -> []; ttest_ssocko_csocko_medium_tcp6(doc) -> []; ttest_ssocko_csocko_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_csocko_medium_tcp6, Runtime, inet6, sock, once, sock, once, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = once %% Message Size: medium (=2) %% Domain: local %% ttest_ssocko_csocko_medium_tcpL(suite) -> []; ttest_ssocko_csocko_medium_tcpL(doc) -> []; ttest_ssocko_csocko_medium_tcpL(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_csocko_medium_tcpL, Runtime, local, sock, once, sock, once, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = once %% Message Size: large (=3) %% Domain: inet %% ttest_ssocko_csocko_large_tcp4(suite) -> []; ttest_ssocko_csocko_large_tcp4(doc) -> []; ttest_ssocko_csocko_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_csocko_large_tcp4, Runtime, inet, sock, once, sock, once, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = once %% Message Size: large (=3) %% Domain: inet6 %% ttest_ssocko_csocko_large_tcp6(suite) -> []; ttest_ssocko_csocko_large_tcp6(doc) -> []; ttest_ssocko_csocko_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_csocko_large_tcp6, Runtime, inet6, sock, once, sock, once, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = once %% Message Size: large (=3) %% Domain: local %% ttest_ssocko_csocko_large_tcpL(suite) -> []; ttest_ssocko_csocko_large_tcpL(doc) -> []; ttest_ssocko_csocko_large_tcpL(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_csocko_large_tcpL, Runtime, local, sock, once, sock, once, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = true %% Message Size: small (=1) %% Domain: inet %% ttest_ssocko_csockt_small_tcp4(suite) -> []; ttest_ssocko_csockt_small_tcp4(doc) -> []; ttest_ssocko_csockt_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_csockt_small_tcp4, Runtime, inet, sock, once, sock, true, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = true %% Message Size: small (=1) %% Domain: inet6 %% ttest_ssocko_csockt_small_tcp6(suite) -> []; ttest_ssocko_csockt_small_tcp6(doc) -> []; ttest_ssocko_csockt_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_csocko_small_tcp6, Runtime, inet6, sock, once, sock, true, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = true %% Message Size: small (=1) %% Domain: local %% ttest_ssocko_csockt_small_tcpL(suite) -> []; ttest_ssocko_csockt_small_tcpL(doc) -> []; ttest_ssocko_csockt_small_tcpL(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_csocko_small_tcpL, Runtime, local, sock, once, sock, true, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = true %% Message Size: medium (=2) %% Domain: inet %% ttest_ssocko_csockt_medium_tcp4(suite) -> []; ttest_ssocko_csockt_medium_tcp4(doc) -> []; ttest_ssocko_csockt_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_csockt_medium_tcp4, Runtime, inet, sock, once, sock, true, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = true %% Message Size: medium (=2) %% Domain: inet6 %% ttest_ssocko_csockt_medium_tcp6(suite) -> []; ttest_ssocko_csockt_medium_tcp6(doc) -> []; ttest_ssocko_csockt_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_csockt_medium_tcp6, Runtime, inet6, sock, once, sock, true, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = true %% Message Size: medium (=2) %% Domain: local %% ttest_ssocko_csockt_medium_tcpL(suite) -> []; ttest_ssocko_csockt_medium_tcpL(doc) -> []; ttest_ssocko_csockt_medium_tcpL(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_csockt_medium_tcpL, Runtime, local, sock, once, sock, true, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = true %% Message Size: large (=3) %% Domain: inet %% ttest_ssocko_csockt_large_tcp4(suite) -> []; ttest_ssocko_csockt_large_tcp4(doc) -> []; ttest_ssocko_csockt_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_csockt_large_tcp4, Runtime, inet, sock, once, sock, true, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = true %% Message Size: large (=3) %% Domain: inet6 %% ttest_ssocko_csockt_large_tcp6(suite) -> []; ttest_ssocko_csockt_large_tcp6(doc) -> []; ttest_ssocko_csockt_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_csockt_large_tcp6, Runtime, inet6, sock, once, sock, true, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = true %% Message Size: large (=3) %% Domain: local %% ttest_ssocko_csockt_large_tcpL(suite) -> []; ttest_ssocko_csockt_large_tcpL(doc) -> []; ttest_ssocko_csockt_large_tcpL(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssocko_csockt_large_tcpL, Runtime, local, sock, once, sock, true, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = gen_tcp, Active = false %% Message Size: small (=1) %% Domain: inet %% ttest_ssockt_cgenf_small_tcp4(suite) -> []; ttest_ssockt_cgenf_small_tcp4(doc) -> []; ttest_ssockt_cgenf_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_cgenf_small_tcp4, Runtime, inet, sock, true, gen, false, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = gen_tcp, Active = false %% Message Size: small (=1) %% Domain: inet6 %% ttest_ssockt_cgenf_small_tcp6(suite) -> []; ttest_ssockt_cgenf_small_tcp6(doc) -> []; ttest_ssockt_cgenf_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_cgenf_small_tcp6, Runtime, inet6, sock, true, gen, false, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = gen_tcp, Active = false %% Message Size: medium (=2) %% Domain: inet %% ttest_ssockt_cgenf_medium_tcp4(suite) -> []; ttest_ssockt_cgenf_medium_tcp4(doc) -> []; ttest_ssockt_cgenf_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_cgenf_medium_tcp4, Runtime, inet, sock, true, gen, false, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = gen_tcp, Active = false %% Message Size: medium (=2) %% Domain: inet6 %% ttest_ssockt_cgenf_medium_tcp6(suite) -> []; ttest_ssockt_cgenf_medium_tcp6(doc) -> []; ttest_ssockt_cgenf_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_cgenf_medium_tcp6, Runtime, inet6, sock, true, gen, false, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = gen_tcp, Active = false %% Message Size: large (=3) %% Domain: inet %% ttest_ssockt_cgenf_large_tcp4(suite) -> []; ttest_ssockt_cgenf_large_tcp4(doc) -> []; ttest_ssockt_cgenf_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_cgenf_large_tcp4, Runtime, inet, sock, true, gen, false, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = gen_tcp, Active = false %% Message Size: large (=3) %% Domain: inet6 %% ttest_ssockt_cgenf_large_tcp6(suite) -> []; ttest_ssockt_cgenf_large_tcp6(doc) -> []; ttest_ssockt_cgenf_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_cgenf_large_tcp6, Runtime, inet6, sock, true, gen, false, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = gen_tcp, Active = once %% Message Size: small (=1) %% Domain: inet %% ttest_ssockt_cgeno_small_tcp4(suite) -> []; ttest_ssockt_cgeno_small_tcp4(doc) -> []; ttest_ssockt_cgeno_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_cgeno_small_tcp4, Runtime, inet, sock, true, gen, once, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = gen_tcp, Active = once %% Message Size: small (=1) %% Domain: inet6 %% ttest_ssockt_cgeno_small_tcp6(suite) -> []; ttest_ssockt_cgeno_small_tcp6(doc) -> []; ttest_ssockt_cgeno_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_cgeno_small_tcp6, Runtime, inet6, sock, true, gen, once, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = gen_tcp, Active = once %% Message Size: medium (=2) %% Domain: inet %% ttest_ssockt_cgeno_medium_tcp4(suite) -> []; ttest_ssockt_cgeno_medium_tcp4(doc) -> []; ttest_ssockt_cgeno_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_cgeno_medium_tcp4, Runtime, inet, sock, true, gen, once, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = gen_tcp, Active = once %% Message Size: medium (=2) %% Domain: inet6 %% ttest_ssockt_cgeno_medium_tcp6(suite) -> []; ttest_ssockt_cgeno_medium_tcp6(doc) -> []; ttest_ssockt_cgeno_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_cgeno_medium_tcp6, Runtime, inet6, sock, true, gen, once, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = gen_tcp, Active = once %% Message Size: large (=3) %% Domain: inet %% ttest_ssockt_cgeno_large_tcp4(suite) -> []; ttest_ssockt_cgeno_large_tcp4(doc) -> []; ttest_ssockt_cgeno_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_cgeno_large_tcp4, Runtime, inet, sock, true, gen, once, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = gen_tcp, Active = once %% Message Size: large (=3) %% Domain: inet6 %% ttest_ssockt_cgeno_large_tcp6(suite) -> []; ttest_ssockt_cgeno_large_tcp6(doc) -> []; ttest_ssockt_cgeno_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_cgeno_large_tcp6, Runtime, inet6, sock, true, gen, once, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = gen_tcp, Active = true %% Message Size: small (=1) %% Domain: inet %% ttest_ssockt_cgent_small_tcp4(suite) -> []; ttest_ssockt_cgent_small_tcp4(doc) -> []; ttest_ssockt_cgent_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_cgent_small_tcp4, Runtime, inet, sock, true, gen, true, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = gen_tcp, Active = true %% Message Size: small (=1) %% Domain: inet6 %% ttest_ssockt_cgent_small_tcp6(suite) -> []; ttest_ssockt_cgent_small_tcp6(doc) -> []; ttest_ssockt_cgent_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_cgent_small_tcp6, Runtime, inet6, sock, true, gen, true, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = gen_tcp, Active = true %% Message Size: medium (=2) %% Domain: inet %% ttest_ssockt_cgent_medium_tcp4(suite) -> []; ttest_ssockt_cgent_medium_tcp4(doc) -> []; ttest_ssockt_cgent_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_cgent_medium_tcp4, Runtime, inet, sock, true, gen, true, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = gen_tcp, Active = true %% Message Size: medium (=2) %% Domain: inet6 %% ttest_ssockt_cgent_medium_tcp6(suite) -> []; ttest_ssockt_cgent_medium_tcp6(doc) -> []; ttest_ssockt_cgent_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_cgent_medium_tcp6, Runtime, inet6, sock, true, gen, true, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = gen_tcp, Active = true %% Message Size: large (=3) %% Domain: inet %% ttest_ssockt_cgent_large_tcp4(suite) -> []; ttest_ssockt_cgent_large_tcp4(doc) -> []; ttest_ssockt_cgent_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_cgent_large_tcp4, Runtime, inet, sock, true, gen, true, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = gen_tcp, Active = true %% Message Size: large (=3) %% Domain: inet6 %% ttest_ssockt_cgent_large_tcp6(suite) -> []; ttest_ssockt_cgent_large_tcp6(doc) -> []; ttest_ssockt_cgent_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_cgent_large_tcp6, Runtime, inet6, sock, true, gen, true, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = false %% Message Size: small (=1) %% Domain: inet %% ttest_ssockt_csockf_small_tcp4(suite) -> []; ttest_ssockt_csockf_small_tcp4(doc) -> []; ttest_ssockt_csockf_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_csockf_small_tcp4, Runtime, inet, sock, true, sock, false, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = false %% Message Size: small (=1) %% Domain: inet6 %% ttest_ssockt_csockf_small_tcp6(suite) -> []; ttest_ssockt_csockf_small_tcp6(doc) -> []; ttest_ssockt_csockf_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_csockf_small_tcp6, Runtime, inet6, sock, true, sock, false, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = false %% Message Size: small (=1) %% Domain: local %% ttest_ssockt_csockf_small_tcpL(suite) -> []; ttest_ssockt_csockf_small_tcpL(doc) -> []; ttest_ssockt_csockf_small_tcpL(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_csockf_small_tcpL, Runtime, local, sock, true, sock, false, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = false %% Message Size: medium (=2) %% Domain: inet %% ttest_ssockt_csockf_medium_tcp4(suite) -> []; ttest_ssockt_csockf_medium_tcp4(doc) -> []; ttest_ssockt_csockf_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_csockf_medium_tcp4, Runtime, inet, sock, true, sock, false, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = false %% Message Size: medium (=2) %% Domain: inet6 %% ttest_ssockt_csockf_medium_tcp6(suite) -> []; ttest_ssockt_csockf_medium_tcp6(doc) -> []; ttest_ssockt_csockf_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_csockf_medium_tcp6, Runtime, inet6, sock, true, sock, false, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = false %% Message Size: medium (=2) %% Domain: local %% ttest_ssockt_csockf_medium_tcpL(suite) -> []; ttest_ssockt_csockf_medium_tcpL(doc) -> []; ttest_ssockt_csockf_medium_tcpL(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_csockf_medium_tcpL, Runtime, local, sock, true, sock, false, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = false %% Message Size: large (=3) %% Domain: inet %% ttest_ssockt_csockf_large_tcp4(suite) -> []; ttest_ssockt_csockf_large_tcp4(doc) -> []; ttest_ssockt_csockf_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_csockf_large_tcp4, Runtime, inet, sock, true, sock, false, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = false %% Message Size: large (=3) %% Domain: inet6 %% ttest_ssockt_csockf_large_tcp6(suite) -> []; ttest_ssockt_csockf_large_tcp6(doc) -> []; ttest_ssockt_csockf_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_csockf_large_tcp6, Runtime, inet6, sock, true, sock, false, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = false %% Message Size: large (=3) %% Domain: local %% ttest_ssockt_csockf_large_tcpL(suite) -> []; ttest_ssockt_csockf_large_tcpL(doc) -> []; ttest_ssockt_csockf_large_tcpL(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_csockf_large_tcpL, Runtime, local, sock, true, sock, false, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = once %% Message Size: small (=1) %% Domain: inet %% ttest_ssockt_csocko_small_tcp4(suite) -> []; ttest_ssockt_csocko_small_tcp4(doc) -> []; ttest_ssockt_csocko_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_csocko_small_tcp4, Runtime, inet, sock, true, sock, once, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = once %% Message Size: small (=1) %% Domain: inet6 %% ttest_ssockt_csocko_small_tcp6(suite) -> []; ttest_ssockt_csocko_small_tcp6(doc) -> []; ttest_ssockt_csocko_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_csocko_small_tcp6, Runtime, inet6, sock, true, sock, once, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = once %% Message Size: small (=1) %% Domain: local %% ttest_ssockt_csocko_small_tcpL(suite) -> []; ttest_ssockt_csocko_small_tcpL(doc) -> []; ttest_ssockt_csocko_small_tcpL(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_csocko_small_tcpL, Runtime, local, sock, true, sock, once, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = once %% Message Size: medium (=2) %% Domain: inet %% ttest_ssockt_csocko_medium_tcp4(suite) -> []; ttest_ssockt_csocko_medium_tcp4(doc) -> []; ttest_ssockt_csocko_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_csocko_medium_tcp4, Runtime, inet, sock, true, sock, once, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = once %% Message Size: medium (=2) %% Domain: inet6 %% ttest_ssockt_csocko_medium_tcp6(suite) -> []; ttest_ssockt_csocko_medium_tcp6(doc) -> []; ttest_ssockt_csocko_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_csocko_medium_tcp6, Runtime, inet6, sock, true, sock, once, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = once %% Message Size: medium (=2) %% Domain: local %% ttest_ssockt_csocko_medium_tcpL(suite) -> []; ttest_ssockt_csocko_medium_tcpL(doc) -> []; ttest_ssockt_csocko_medium_tcpL(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_csocko_medium_tcpL, Runtime, local, sock, true, sock, once, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = once %% Message Size: large (=3) %% Domain: inet %% ttest_ssockt_csocko_large_tcp4(suite) -> []; ttest_ssockt_csocko_large_tcp4(doc) -> []; ttest_ssockt_csocko_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_csocko_large_tcp4, Runtime, inet, sock, true, sock, once, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = once %% Message Size: large (=3) %% Domain: inet6 %% ttest_ssockt_csocko_large_tcp6(suite) -> []; ttest_ssockt_csocko_large_tcp6(doc) -> []; ttest_ssockt_csocko_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_csocko_large_tcp6, Runtime, inet6, sock, true, sock, once, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = once %% Message Size: large (=3) %% Domain: local %% ttest_ssockt_csocko_large_tcpL(suite) -> []; ttest_ssockt_csocko_large_tcpL(doc) -> []; ttest_ssockt_csocko_large_tcpL(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_csocko_large_tcpL, Runtime, local, sock, true, sock, once, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = true %% Message Size: small (=1) %% Domain: inet %% ttest_ssockt_csockt_small_tcp4(suite) -> []; ttest_ssockt_csockt_small_tcp4(doc) -> []; ttest_ssockt_csockt_small_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_csockt_small_tcp4, Runtime, inet, sock, true, sock, true, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = true %% Message Size: small (=1) %% Domain: inet6 %% ttest_ssockt_csockt_small_tcp6(suite) -> []; ttest_ssockt_csockt_small_tcp6(doc) -> []; ttest_ssockt_csockt_small_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_csocko_small_tcp6, Runtime, inet6, sock, true, sock, true, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = true %% Message Size: small (=1) %% Domain: local %% ttest_ssockt_csockt_small_tcpL(suite) -> []; ttest_ssockt_csockt_small_tcpL(doc) -> []; ttest_ssockt_csockt_small_tcpL(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_csocko_small_tcpL, Runtime, local, sock, true, sock, true, 1, 200). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = true %% Message Size: medium (=2) %% Domain: inet %% ttest_ssockt_csockt_medium_tcp4(suite) -> []; ttest_ssockt_csockt_medium_tcp4(doc) -> []; ttest_ssockt_csockt_medium_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_csockt_medium_tcp4, Runtime, inet, sock, true, sock, true, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = true %% Message Size: medium (=2) %% Domain: inet6 %% ttest_ssockt_csockt_medium_tcp6(suite) -> []; ttest_ssockt_csockt_medium_tcp6(doc) -> []; ttest_ssockt_csockt_medium_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_csockt_medium_tcp6, Runtime, inet6, sock, true, sock, true, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = true %% Message Size: medium (=2) %% Domain: local %% ttest_ssockt_csockt_medium_tcpL(suite) -> []; ttest_ssockt_csockt_medium_tcpL(doc) -> []; ttest_ssockt_csockt_medium_tcpL(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_csockt_medium_tcpL, Runtime, local, sock, true, sock, true, 2, 20). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = true %% Message Size: large (=3) %% Domain: inet %% ttest_ssockt_csockt_large_tcp4(suite) -> []; ttest_ssockt_csockt_large_tcp4(doc) -> []; ttest_ssockt_csockt_large_tcp4(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_csockt_large_tcp4, Runtime, inet, sock, true, sock, true, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = true %% Message Size: large (=3) %% Domain: inet6 %% ttest_ssockt_csockt_large_tcp6(suite) -> []; ttest_ssockt_csockt_large_tcp6(doc) -> []; ttest_ssockt_csockt_large_tcp6(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_csockt_large_tcp6, Runtime, inet6, sock, true, sock, true, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = true %% Message Size: large (=3) %% Domain: local %% ttest_ssockt_csockt_large_tcpL(suite) -> []; ttest_ssockt_csockt_large_tcpL(doc) -> []; ttest_ssockt_csockt_large_tcpL(Config) when is_list(Config) -> Runtime = which_ttest_runtime(Config), ttest_tcp(ttest_ssockt_csockt_large_tcpL, Runtime, local, sock, true, sock, true, 3, 2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% which_ttest_runtime(Config) when is_list(Config) -> case lists:keysearch(esock_test_ttest_runtime, 1, Config) of {value, {esock_test_ttest_runtime, Runtime}} -> Runtime; false -> which_ttest_runtime_env() end. which_ttest_runtime_env() -> which_ttest_runtime_env(os:getenv("ESOCK_TEST_TTEST_RUNTIME")). which_ttest_runtime_env(TStr) when is_list(TStr) -> which_ttest_runtime_env2(lists:reverse(TStr)); which_ttest_runtime_env(false) -> ?TTEST_RUNTIME. %% The format is: [unit] %% where the optional unit can be: %% ms: milliseconds %% s: seconds (default) %% m: minutes which_ttest_runtime_env2([$s, $m | MS]) when (length(MS) > 0) -> convert_time(MS, fun(X) -> X end); which_ttest_runtime_env2([$m | M]) when (length(M) > 0) -> convert_time(M, fun(X) -> ?MINS(X) end); which_ttest_runtime_env2([$s | S]) when (length(S) > 0) -> convert_time(S, fun(X) -> ?SECS(X) end); which_ttest_runtime_env2(S) -> convert_time(S, fun(X) -> ?SECS(X) end). convert_time(TStrRev, Convert) -> try list_to_integer(lists:reverse(TStrRev)) of I -> Convert(I) catch _:_ -> ?TTEST_RUNTIME end. %% ttest_tcp(TC, %% Domain, %% ServerMod, ServerActive, %% ClientMod, ClientActive, %% MsgID, MaxOutstanding) -> %% ttest_tcp(TC, %% ?TTEST_RUNTIME, %% Domain, %% ServerMod, ServerActive, %% ClientMod, ClientActive, %% MsgID, MaxOutstanding). ttest_tcp(TC, Runtime, Domain, ServerMod, ServerActive, ClientMod, ClientActive, MsgID, MaxOutstanding) -> tc_try(TC, fun() -> if (Domain =:= local) -> has_support_unix_domain_socket(); (Domain =:= inet6) -> has_support_ipv6(); true -> ok end end, fun() -> %% This may be overkill, depending on the runtime, %% but better safe then sorry... ?TT(Runtime + ?SECS(60)), InitState = #{domain => Domain, msg_id => MsgID, max_outstanding => MaxOutstanding, runtime => Runtime, server_mod => ServerMod, server_active => ServerActive, client_mod => ClientMod, client_active => ClientActive}, ok = ttest_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ttest_tcp(InitState) -> ServerSeq = [ %% *** Wait for start order part *** #{desc => "await start", cmd => fun(State) -> Tester = ?SEV_AWAIT_START(), {ok, State#{tester => Tester}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "create node", cmd => fun(#{host := Host} = State) -> case start_node(Host, server) of {ok, Node} -> {ok, State#{node => Node}}; {error, Reason} -> {skip, Reason} end end}, #{desc => "monitor server node", cmd => fun(#{node := Node} = _State) -> true = erlang:monitor_node(Node, true), ok end}, #{desc => "start ttest (remote) server", cmd => fun(#{domain := local = Domain, mod := Mod, active := Active, node := Node} = State) -> case ttest_tcp_server_start(Node, Domain, Mod, Active) of {ok, {{Pid, _}, Path}} -> {ok, State#{rserver => Pid, path => Path}}; {error, _} = ERROR -> ERROR end; (#{domain := Domain, mod := Mod, active := Active, node := Node} = State) -> case ttest_tcp_server_start(Node, Domain, Mod, Active) of {ok, {{Pid, _}, {Addr, Port}}} -> {ok, State#{rserver => Pid, addr => Addr, port => Port}}; {error, _} = ERROR -> ERROR end end}, #{desc => "announce ready (init)", cmd => fun(#{domain := local, tester := Tester, path := Path}) -> ?SEV_ANNOUNCE_READY(Tester, init, Path), ok; (#{tester := Tester, addr := Addr, port := Port}) -> ?SEV_ANNOUNCE_READY(Tester, init, {Addr, Port}), ok end}, %% *** Termination *** #{desc => "await terminate (from tester)", cmd => fun(#{tester := Tester, rserver := RServer} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester, [{rserver, RServer}]) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, %% The remote server is in a accept, with a timeout of 5 seconds, %% so may have to wait a bit... #{desc => "order (remote) ttest server terminate", cmd => fun(#{node := _Node, rserver := RServer}) -> ttest_tcp_server_stop(RServer), ok end}, #{desc => "await ttest (remote) server termination", cmd => fun(#{rserver := RServer} = State) -> ?SEV_AWAIT_TERMINATION(RServer), State1 = maps:remove(rserver, State), {ok, State1} end}, #{desc => "stop (server) node", cmd => fun(#{node := Node} = _State) -> stop_node(Node) end}, #{desc => "await (server) node termination", cmd => fun(#{node := Node} = State) -> receive {nodedown, Node} -> {ok, maps:remove(node, State)} end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], ClientSeq = [ %% *** Wait for start order part *** #{desc => "await start", cmd => fun(#{domain := local} = State) -> {Tester, ServerPath} = ?SEV_AWAIT_START(), {ok, State#{tester => Tester, server_path => ServerPath}}; (State) -> {Tester, {ServerAddr, ServerPort}} = ?SEV_AWAIT_START(), {ok, State#{tester => Tester, server_addr => ServerAddr, server_port => ServerPort}} end}, #{desc => "monitor tester", cmd => fun(#{tester := Tester} = _State) -> _MRef = erlang:monitor(process, Tester), ok end}, %% *** Init part *** #{desc => "create node", cmd => fun(#{host := Host} = State) -> case start_node(Host, client) of {ok, Node} -> {ok, State#{node => Node}}; {error, Reason} -> {skip, Reason} end end}, #{desc => "monitor client node", cmd => fun(#{node := Node} = _State) -> true = erlang:monitor_node(Node, true), ok end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester}) -> ?SEV_ANNOUNCE_READY(Tester, init), ok end}, %% The actual test #{desc => "await continue (ttest)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_AWAIT_CONTINUE(Tester, tester, ttest), ok end}, #{desc => "start ttest (remote) client", cmd => fun(#{domain := local = Domain, node := Node, mod := Mod, active := Active, msg_id := MsgID, max_outstanding := MaxOutstanding, runtime := RunTime, server_path := Path} = State) -> Self = self(), Notify = fun(Result) -> ?SEV_ANNOUNCE_READY(Self, ttest, Result) end, case ttest_tcp_client_start(Node, Notify, Domain, Mod, Path, Active, MsgID, MaxOutstanding, RunTime) of {ok, {Pid, _MRef}} -> {ok, State#{rclient => Pid}}; {error, _} = ERROR -> ERROR end; (#{domain := Domain, node := Node, mod := Mod, active := Active, msg_id := MsgID, max_outstanding := MaxOutstanding, runtime := RunTime, server_addr := Addr, server_port := Port} = State) -> Self = self(), Notify = fun(Result) -> ?SEV_ANNOUNCE_READY(Self, ttest, Result) end, case ttest_tcp_client_start(Node, Notify, Domain, Mod, {Addr, Port}, Active, MsgID, MaxOutstanding, RunTime) of {ok, {Pid, _MRef}} -> {ok, State#{rclient => Pid}}; {error, _} = ERROR -> ERROR end end}, #{desc => "await ttest ready", cmd => fun(#{tester := Tester, rclient := RClient} = State) -> case ?SEV_AWAIT_READY(RClient, rclient, ttest, [{tester, Tester}]) of {ok, Result} -> {ok, State#{result => Result}}; {error, _} = ERROR -> ERROR end end}, #{desc => "await ttest (remote) client termination", cmd => fun(#{rclient := RClient} = State) -> ?SEV_AWAIT_TERMINATION(RClient), State1 = maps:remove(rclient, State), {ok, State1} end}, #{desc => "announce ready (ttest)", cmd => fun(#{tester := Tester, result := Result} = State) -> ?SEV_ANNOUNCE_READY(Tester, ttest, Result), {ok, maps:remove(result, State)} end}, %% *** Termination *** #{desc => "await terminate (from tester)", cmd => fun(#{tester := Tester} = State) -> case ?SEV_AWAIT_TERMINATE(Tester, tester) of ok -> {ok, maps:remove(tester, State)}; {error, _} = ERROR -> ERROR end end}, #{desc => "stop (client) node", cmd => fun(#{node := Node} = _State) -> stop_node(Node) end}, #{desc => "await (client) node termination", cmd => fun(#{node := Node} = State) -> receive {nodedown, Node} -> {ok, maps:remove(node, State)} end end}, %% *** We are done *** ?SEV_FINISH_NORMAL ], TesterSeq = [ %% *** Init part *** #{desc => "monitor server", cmd => fun(#{server := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, #{desc => "monitor client", cmd => fun(#{client := Pid} = _State) -> _MRef = erlang:monitor(process, Pid), ok end}, %% Start the server #{desc => "order server start", cmd => fun(#{server := Pid} = _State) -> ?SEV_ANNOUNCE_START(Pid), ok end}, #{desc => "await server ready (init)", cmd => fun(#{domain := local, server := Pid} = State) -> {ok, Path} = ?SEV_AWAIT_READY(Pid, server, init), {ok, State#{server_path => Path}}; (#{server := Pid} = State) -> {ok, {Addr, Port}} = ?SEV_AWAIT_READY(Pid, server, init), {ok, State#{server_addr => Addr, server_port => Port}} end}, %% Start the client #{desc => "order client start", cmd => fun(#{domain := local, client := Pid, server_path := Path} = _State) -> ?SEV_ANNOUNCE_START(Pid, Path), ok; (#{client := Pid, server_addr := Addr, server_port := Port} = _State) -> ?SEV_ANNOUNCE_START(Pid, {Addr, Port}), ok end}, #{desc => "await client ready (init)", cmd => fun(#{client := Client} = _State) -> ok = ?SEV_AWAIT_READY(Client, client, init) end}, %% The actual test #{desc => "order client continue (ttest)", cmd => fun(#{client := Client} = _State) -> ?SEV_ANNOUNCE_CONTINUE(Client, ttest), ok end}, #{desc => "await client ready (ttest)", cmd => fun(#{server := Server, client := Client} = State) -> case ?SEV_AWAIT_READY(Client, client, ttest, [{server, Server}]) of {ok, Result} -> {ok, State#{result => Result}}; {error, _} = ERROR -> ERROR end end}, %% *** Terminate server *** #{desc => "order client terminate", cmd => fun(#{client := Client} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Client), ok end}, #{desc => "await client down", cmd => fun(#{client := Client} = State) -> ?SEV_AWAIT_TERMINATION(Client), State1 = maps:remove(client, State), {ok, State1} end}, #{desc => "order server terminate", cmd => fun(#{server := Server} = _State) -> ?SEV_ANNOUNCE_TERMINATE(Server), ok end}, #{desc => "await server down", cmd => fun(#{server := Server} = _State) -> ?SEV_AWAIT_TERMINATION(Server), ok end}, %% Present the results #{desc => "present the results", cmd => fun(#{result := Result, domain := Domain, server_mod := ServerTrans, server_active := ServerActive, client_mod := ClientTrans, client_active := ClientActive, msg_id := MsgID} = State) -> case Result of #{status := ok, runtime := RunTime, cnt := Cnt, bcnt := BCnt} -> ttest_report(Domain, ServerTrans, ServerActive, ClientTrans, ClientActive, MsgID, RunTime, BCnt, Cnt), ?SEV_IPRINT( "TTest results: " "~n Run Time: ~s" "~n Byte Count: ~s" "~n Number of message exchanges: ~s" "~n~n", [ ?TTEST_LIB:format_time(RunTime), if ((BCnt =:= 0) orelse (RunTime =:= 0)) -> ?TTEST_LIB:format("~w, ~w", [BCnt, RunTime]); true -> ?TTEST_LIB:format("~p => ~p byte / ms", [BCnt, BCnt div RunTime]) end, if (RunTime =:= 0) -> "-"; true -> ?TTEST_LIB:format("~p => ~p iterations / ms", [Cnt, Cnt div RunTime]) end ]), {ok, maps:remove(result, State)}; #{status := Failure, runtime := RunTime, sid := SID, rid := RID, scnt := SCnt, rcnt := RCnt, bcnt := BCnt, num := Num} -> ?SEV_EPRINT("Time Test failed: " "~n ~p" "~n" "~nwhen" "~n" "~n Run Time: ~s" "~n Send ID: ~p" "~n Recv ID: ~p" "~n Send Count: ~p" "~n Recv Count: ~p" "~n Byte Count: ~p" "~n Num Iterations: ~p", [Failure, ?TTEST_LIB:format_time(RunTime), SID, RID, SCnt, RCnt, BCnt, Num]), {error, Failure} end end}, %% This is just so that the printout above shall have time to come %% out before then end of the test case. ?SEV_SLEEP(?SECS(1)), %% *** We are done *** ?SEV_FINISH_NORMAL ], Domain = maps:get(domain, InitState), LHost = local_host(), LAddr = which_local_addr(Domain), i("start server evaluator"), ServerInitState = #{host => LHost, addr => LAddr, domain => Domain, mod => maps:get(server_mod, InitState), active => maps:get(server_active, InitState)}, Server = ?SEV_START("server", ServerSeq, ServerInitState), i("start client evaluator"), ClientInitState = #{host => LHost, addr => LAddr, domain => Domain, mod => maps:get(client_mod, InitState), active => maps:get(client_active, InitState), msg_id => maps:get(msg_id, InitState), max_outstanding => maps:get(max_outstanding, InitState), runtime => maps:get(runtime, InitState)}, Client = ?SEV_START("client", ClientSeq, ClientInitState), i("start 'tester' evaluator"), TesterInitState = #{domain => Domain, msg_id => maps:get(msg_id, InitState), client => Client#ev.pid, client_mod => maps:get(client_mod, InitState), client_active => maps:get(client_active, InitState), server => Server#ev.pid, server_mod => maps:get(server_mod, InitState), server_active => maps:get(server_active, InitState)}, Tester = ?SEV_START("tester", TesterSeq, TesterInitState), i("await evaluator(s)"), ok = ?SEV_AWAIT_FINISH([Server, Client, Tester]). ttest_tcp_server_start(Node, Domain, gen, Active) -> TransportMod = socket_test_ttest_tcp_gen, Transport = {TransportMod, #{domain => Domain}}, socket_test_ttest_tcp_server:start_monitor(Node, Transport, Active); ttest_tcp_server_start(Node, Domain, sock, Active) -> TransportMod = socket_test_ttest_tcp_socket, Transport = {TransportMod, #{domain => Domain, async => true, method => plain}}, socket_test_ttest_tcp_server:start_monitor(Node, Transport, Active). ttest_tcp_server_stop(Pid) -> socket_test_ttest_tcp_server:stop(Pid). ttest_tcp_client_start(Node, Notify, Domain, gen, ServerInfo, Active, MsgID, MaxOutstanding, RunTime) -> TransportMod = socket_test_ttest_tcp_gen, Transport = {TransportMod, #{domain => Domain}}, socket_test_ttest_tcp_client:start_monitor(Node, Notify, Transport, ServerInfo, Active, MsgID, MaxOutstanding, RunTime); ttest_tcp_client_start(Node, Notify, Domain, sock, ServerInfo, Active, MsgID, MaxOutstanding, RunTime) -> TransportMod = socket_test_ttest_tcp_socket, Transport = {TransportMod, #{domain => Domain, async => true, method => plain}}, socket_test_ttest_tcp_client:start_monitor(Node, Notify, Transport, ServerInfo, Active, MsgID, MaxOutstanding, RunTime). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -define(TTEST_MANAGER, esock_ttest_manager). -record(ttest_report_id, {domain :: socket:domain(), serv_trans :: gen | sock, serv_active :: once | boolean(), client_trans :: gen | sock, client_active :: once | boolean(), msg_id :: small | medium | large}). -record(ttest_report, {id :: #ttest_report_id{}, time :: non_neg_integer(), bytes :: non_neg_integer(), msgs :: non_neg_integer()}). -spec ttest_report(Domain :: socket:domain(), ServTrans :: gen | sock, ServActive :: once | boolean(), ClientTrans :: gen | sock, ClientActive :: once | boolean(), MsgID :: 1 | 2 | 3, RunTime :: non_neg_integer(), NumBytes :: non_neg_integer(), NumMsgs :: non_neg_integer()) -> ok. ttest_report(Domain, ServTrans, ServActive, ClientTrans, ClientActive, MsgID, RunTime, NumBytes, NumMsgs) -> ID = #ttest_report_id{domain = Domain, serv_trans = ServTrans, serv_active = ServActive, client_trans = ClientTrans, client_active = ClientActive, msg_id = ttest_msg_id_num_to_name(MsgID)}, Report = #ttest_report{id = ID, time = RunTime, bytes = NumBytes, msgs = NumMsgs}, %% If we run just one test case, the group init has never been run %% and therefor the ttest manager is not running (we also don't actually %% care about collecting reports in that case). (catch global:send(?TTEST_MANAGER, Report)), ok. ttest_msg_id_num_to_name(1) -> small; ttest_msg_id_num_to_name(2) -> medium; ttest_msg_id_num_to_name(3) -> large. ttest_manager_start() -> Self = self(), {Pid, MRef} = spawn_monitor(fun() -> ttest_manager_init(Self) end), receive {ttest_manager_started, Pid} -> erlang:demonitor(MRef, [flush]), ok; {'DOWN', MRef, process, Pid, Reason} -> exit({failed_starting, ttest_manager, Reason}) after 5000 -> exit(Pid, kill), exit({failed_starting, ttest_manager, timeout}) end. ttest_manager_stop() -> case global:whereis_name(?TTEST_MANAGER) of Pid when is_pid(Pid) -> erlang:monitor(process, Pid), global:send(?TTEST_MANAGER, stop), receive {'DOWN', _MRef, process, Pid, _} -> ok after 10000 -> exit(Pid, kill), ok end; _ -> ok end. ttest_manager_init(Parent) -> yes = global:register_name(?TTEST_MANAGER, self()), ets:new(?TTEST_MANAGER, [{keypos, #ttest_report.id}, named_table, protected, ordered_set]), Parent ! {ttest_manager_started, self()}, ttest_manager_loop(). ttest_manager_loop() -> receive stop -> ?LOGGER:format("manager stopping~n", []), ttest_manager_done(); #ttest_report{id = _ID, time = _RunTime, bytes = _NumBytes, msgs = _NumMsgs} = Report -> true = ets:insert_new(?TTEST_MANAGER, Report), ttest_manager_loop() end. %% We are supposed to pretty print the result here... ttest_manager_done() -> format_reports(inet), %% format_reports(inet6), ets:delete(?TTEST_MANAGER), exit(normal). format_reports(Domain) -> ?LOGGER:format("Domain ~w reports:~n~n", [Domain]), format_reports(Domain, small), format_reports(Domain, medium), format_reports(Domain, large). format_reports(Domain, MsgID) when is_atom(MsgID) -> case which_ttest_reports(Domain, MsgID) of [] -> ?LOGGER:format(" No ~w reports~n~n", [MsgID]); Reports -> ?LOGGER:format(" ~w reports: ~n", [MsgID]), lists:foreach(fun(R) -> format_report(R) end, Reports) end. %% This should really be a table like this: %% %% client %% server gen(false) gen(once) gen(true) sock(false) sock(once) sock(true) %% gen(false) nnn %% gen(once) nnn %% gen(true) nnn %% sock(false) nnn %% sock(once) nnn %% sock(true) nnn %% format_report(#ttest_report{id = #ttest_report_id{serv_trans = STrans, serv_active = SActive, client_trans = CTrans, client_active = CActive}, time = RunTime, bytes = BCnt, msgs = MCnt}) -> ?LOGGER:format(" server ~w[~w] - client ~w[~w] => " "~n Run Time: ~s" "~n Bytes: ~s" "~n Messages: ~s" "~n", [STrans, SActive, CTrans, CActive, ?TTEST_LIB:format_time(RunTime), if ((BCnt =:= 0) orelse (RunTime =:= 0)) -> ?TTEST_LIB:format("~w, ~w", [BCnt, RunTime]); true -> ?TTEST_LIB:format("~p => ~p byte / ms", [BCnt, BCnt div RunTime]) end, if (RunTime =:= 0) -> "-"; true -> ?TTEST_LIB:format("~p => ~p iterations / ms", [MCnt, MCnt div RunTime]) end]), ok. which_ttest_reports(Domain, all) -> [R || R = #ttest_report{id = #ttest_report_id{domain = D}} <- ets:tab2list(?TTEST_MANAGER), Domain =:= D]; which_ttest_reports(Domain, MsgID) -> [R || R = #ttest_report{id = #ttest_report_id{domain = D, msg_id = MID}} <- ets:tab2list(?TTEST_MANAGER), (Domain =:= D) andalso (MsgID =:= MID)]. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This mechanism has only one purpose: So that we are able to kill %% the node-starter process if it takes to long. The node-starter %% runs on the local node. %% This crapola is hopefully temporary, but we have seen that on %% some platforms the ct_slave:start simply hangs. -define(NODE_START_TIMEOUT, 10000). start_node(Host, NodeName) -> start_node(Host, NodeName, ?NODE_START_TIMEOUT). start_node(Host, NodeName, Timeout) -> {NodeStarter, _} = spawn_monitor(fun() -> exit(start_unique_node(Host, NodeName)) end), receive {'DOWN', _, process, NodeStarter, Result} -> %% i("Node Starter (~p) reported: ~p", [NodeStarter, Result]), Result after Timeout -> exit(NodeStarter, kill), {error, {failed_starting_node, NodeName, timeout}} end. start_unique_node(Host, NodeName) -> UniqueNodeName = f("~w_~w", [NodeName, erlang:system_time(millisecond)]), case do_start_node(Host, UniqueNodeName) of {ok, _} = OK -> global:sync(), %% i("Node ~p started: " %% "~n Nodes: ~p" %% "~n Logger: ~p" %% "~n Global Names: ~p", %% [NodeName, nodes(), %% global:whereis_name(socket_test_logger), %% global:registered_names()]), OK; {error, Reason, _} -> {error, Reason} end. do_start_node(Host, NodeName) when is_list(NodeName) -> do_start_node(Host, list_to_atom(NodeName)); do_start_node(Host, NodeName) when is_atom(NodeName) -> Dir = filename:dirname(code:which(?MODULE)), Flags = "-pa " ++ Dir, Opts = [{monitor_master, true}, {erl_flags, Flags}], ct_slave:start(Host, NodeName, Opts). stop_node(Node) -> case ct_slave:stop(Node) of {ok, _} -> ok; {error, _} = ERROR -> ERROR end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% sock_open(Domain, Type, Proto) -> try socket:open(Domain, Type, Proto) of {ok, Socket} -> Socket; {error, Reason} -> ?FAIL({open, Reason}) catch C:E:S -> ?FAIL({open, C, E, S}) end. sock_connect(Sock, SockAddr) -> try socket:connect(Sock, SockAddr) of ok -> ok; {error, Reason} -> ?FAIL({connect, Reason}) catch C:E:S -> ?FAIL({connect, C, E, S}) end. sock_sockname(Sock) -> try socket:sockname(Sock) of {ok, SockAddr} -> SockAddr; {error, Reason} -> ?FAIL({sockname, Reason}) catch C:E:S -> ?FAIL({sockname, C, E, S}) end. sock_close(Sock) -> try socket:close(Sock) of ok -> ok; {error, Reason} -> i("sock_close -> error: ~p", [Reason]), ?FAIL({close, Reason}) catch C:E:S -> i("sock_close -> failed: ~p, ~p, ~p", [C, E, S]), ?FAIL({close, C, E, S}) end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% local_host() -> try net_adm:localhost() of Host when is_list(Host) -> %% Convert to shortname if long case string:tokens(Host, [$.]) of [H|_] -> list_to_atom(H) end catch C:E:S -> erlang:raise(C, E, S) end. %% The point of this is to "ensure" that paths from different test runs %% don't clash. mk_unique_path() -> [NodeName | _] = string:tokens(atom_to_list(node()), [$@]), Path = ?LIB:f("/tmp/esock_~s_~w", [NodeName, erlang:system_time(nanosecond)]), ensure_unique_path(Path). ensure_unique_path(Path) -> case file:read_file_info(Path) of {ok, _} -> % Ouch, append a unique ID and try again ensure_unique_path(Path, 1); {error, _} -> %% We assume this means it does not exist yet... %% If we have several process in paralell trying to create %% (unique) path's, then we are in trouble. To *really* be %% on the safe side we should have a (central) path registry... Path end. ensure_unique_path(Path, ID) when (ID < 100) -> % If this is not enough... NewPath = ?LIB:f("~s_~w", [Path, ID]), case file:read_file_info(NewPath) of {ok, _} -> % Ouch, this also existed, increment and try again ensure_unique_path(Path, ID + 1); {error, _} -> % We assume this means it does not exist yet... NewPath end; ensure_unique_path(_, _) -> skip("Could not create unique path"). which_local_socket_addr(local = Domain) -> #{family => Domain, path => mk_unique_path()}; %% This gets the local socket address (not 127.0...) %% We should really implement this using the (new) net module, %% but until that gets the necessary functionality... which_local_socket_addr(Domain) -> case ?LIB:which_local_host_info(Domain) of {ok, #{addr := Addr}} -> #{family => Domain, addr => Addr}; {error, Reason} -> ?FAIL(Reason) end. which_local_addr(local = _Domain) -> mk_unique_path(); %% This gets the local address (not 127.0...) %% We should really implement this using the (new) net module, %% but until that gets the necessary functionality... which_local_addr(Domain) -> ?LIB:which_local_addr(Domain). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Here are all the *general* test case condition functions. %% We also need (be able) to figure out the the multicast address, %% which we only support for some platforms (linux and sunos). %% We don't do that here, but since we can only do that (find a %% multicast address) for specific platforms, we check that we are %% on of those platforms here. has_support_ip_multicast() -> case os:type() of {unix, OsName} when (OsName =:= linux) orelse (OsName =:= sunos) -> case ?LIB:which_local_host_info(inet) of {ok, #{flags := Flags}} -> case lists:member(multicast, Flags) of true -> ok; false -> not_supported(multicast) end; {error, Reason} -> not_supported({multicast, Reason}) end; {unix, OsName} -> skip(?F("Not Supported: platform ~w", [OsName])); Type -> skip(?F("Not Supported: platform ~p", [Type])) end. has_support_sock_acceptconn() -> has_support_socket_option_sock(acceptconn). has_support_sock_bindtodevice() -> has_support_socket_option_sock(bindtodevice). has_support_sock_broadcast() -> has_support_socket_option_sock(broadcast), case ?LIB:which_local_host_info(inet) of {ok, #{flags := Flags}} -> case lists:member(broadcast, Flags) of true -> ok; false -> not_supported({broadcast, Flags}) end; {error, Reason} -> not_supported({broadcast, Reason}) end. has_support_sock_debug() -> has_support_socket_option_sock(debug). has_support_sock_domain() -> has_support_socket_option_sock(domain). has_support_sock_dontroute() -> has_support_socket_option_sock(dontroute). has_support_sock_keepalive() -> has_support_socket_option_sock(keepalive). has_support_ip_add_membership() -> has_support_socket_option_ip(add_membership). has_support_ip_drop_membership() -> has_support_socket_option_ip(drop_membership). has_support_socket_option_ip(Opt) -> has_support_socket_option(ip, Opt). has_support_socket_option_sock(Opt) -> has_support_socket_option(socket, Opt). has_support_socket_option(Level, Option) -> case socket:supports(options, Level, Option) of true -> ok; false -> skip(?F("Not Supported: ~w option ~w", [Level, Option])) end. unix_domain_socket_host_cond() -> unix_domain_socket_host_cond(os:type(), os:version()). unix_domain_socket_host_cond({unix, linux}, {M, _, _}) when (M < 3) -> skip("TC may not work on this version"); unix_domain_socket_host_cond(_, _) -> ok. has_support_unix_domain_socket() -> case os:type() of {win32, _} -> skip("Not supported"); _ -> case socket:supports(local) of true -> ok; false -> skip("Not supported") end end. %% The idea is that this function shall test if the test host has %% support for IPv6. If not, there is no point in running IPv6 tests. %% Currently we just skip. has_support_ipv6() -> ?LIB:has_support_ipv6(). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% unlink_path(Path) -> unlink_path(Path, fun() -> ok end, fun() -> ok end). unlink_path(Path, Success, Failure) when is_list(Path) andalso is_function(Success, 0) andalso is_function(Failure, 0) -> ?SEV_IPRINT("try unlink path: " "~n ~s", [Path]), case os:cmd("unlink " ++ Path) of "" -> ?SEV_IPRINT("path unlinked: " "~n Path: ~s", [Path]), Success(); Result -> ?SEV_EPRINT("unlink maybe failed: " "~n Path: ~s" "~n Res: ~s", [Path, Result]), Failure() end; unlink_path(_, _, _) -> ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% not_supported(What) -> skip({not_supported, What}). not_yet_implemented() -> skip("not yet implemented"). skip(Reason) -> throw({skip, Reason}). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% t() -> ts(ms). ts(ms) -> erlang:monotonic_time(milli_seconds). tdiff({A1, B1, C1} = _T1x, {A2, B2, C2} = _T2x) -> T1 = A1*1000000000+B1*1000+(C1 div 1000), T2 = A2*1000000000+B2*1000+(C2 div 1000), T2 - T1. formated_timestamp() -> format_timestamp(os:timestamp()). format_timestamp({_N1, _N2, _N3} = TS) -> {_Date, Time} = calendar:now_to_local_time(TS), %% {YYYY,MM,DD} = Date, {Hour,Min,Sec} = Time, %% FormatTS = %% io_lib:format("~.4w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w.~w", %% [YYYY, MM, DD, Hour, Min, Sec, N3]), FormatTS = io_lib:format("~.2.0w:~.2.0w:~.2.0w", [Hour, Min, Sec]), lists:flatten(FormatTS). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% set_tc_name(N) when is_atom(N) -> set_tc_name(atom_to_list(N)); set_tc_name(N) when is_list(N) -> put(tc_name, N). %% get_tc_name() -> %% get(tc_name). tc_begin(TC) -> OldVal = process_flag(trap_exit, true), put(old_trap_exit, OldVal), set_tc_name(TC), tc_print("begin ***", "~n----------------------------------------------------~n", ""). tc_end(Result) when is_list(Result) -> OldVal = erase(old_trap_exit), process_flag(trap_exit, OldVal), tc_print("done: ~s", [Result], "", "----------------------------------------------------~n~n"), ok. %% *** tc_try/2,3 *** %% Case: Basically the test case name %% TCCondFun: A fun that is evaluated before the actual test case %% The point of this is that it can performs checks to %% see if we shall run the test case at all. %% For instance, the test case may only work in specific %% conditions. %% FCFun: The test case fun tc_try(Case, TCFun) -> TCCondFun = fun() -> ok end, tc_try(Case, TCCondFun, TCFun). tc_try(Case, TCCondFun, TCFun) when is_atom(Case) andalso is_function(TCCondFun, 0) andalso is_function(TCFun, 0) -> tc_begin(Case), try TCCondFun() of ok -> try begin TCFun(), ?SLEEP(?SECS(1)), tc_end("ok") end catch C:{skip, _} = SKIP when ((C =:= throw) orelse (C =:= exit)) -> %% i("catched[tc] (skip): " %% "~n C: ~p" %% "~n SKIP: ~p" %% "~n", [C, SKIP]), tc_end( f("skipping(catched,~w,tc)", [C]) ), SKIP; C:E:S -> %% i("catched[tc]: " %% "~n C: ~p" %% "~n E: ~p" %% "~n S: ~p" %% "~n", [C, E, S]), tc_end( f("failed(catched,~w,tc)", [C]) ), erlang:raise(C, E, S) end; {skip, _} = SKIP -> tc_end("skipping(tc)"), SKIP; {error, Reason} -> tc_end("failed(tc)"), exit({tc_cond_failed, Reason}) catch C:{skip, _} = SKIP when ((C =:= throw) orelse (C =:= exit)) -> %% i("catched[cond] (skip): " %% "~n C: ~p" %% "~n SKIP: ~p" %% "~n", [C, SKIP]), tc_end( f("skipping(catched,~w,cond)", [C]) ), SKIP; C:E:S -> %% i("catched[cond]: " %% "~n C: ~p" %% "~n E: ~p" %% "~n S: ~p" %% "~n", [C, E, S]), tc_end( f("failed(catched,~w,cond)", [C]) ), erlang:raise(C, E, S) end. tc_print(F, Before, After) -> tc_print(F, [], Before, After). tc_print(F, A, Before, After) -> Name = tc_which_name(), FStr = f("*** [~s][~s][~p] " ++ F ++ "~n", [formated_timestamp(),Name,self()|A]), io:format(user, Before ++ FStr ++ After, []). tc_which_name() -> case get(tc_name) of undefined -> case get(sname) of undefined -> ""; SName when is_list(SName) -> SName end; Name when is_list(Name) -> Name end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% l2a(S) when is_list(S) -> list_to_atom(S). l2b(L) when is_list(L) -> list_to_binary(L). b2l(B) when is_binary(B) -> binary_to_list(B). f(F, A) -> lists:flatten(io_lib:format(F, A)). %% p(F) -> %% p(F, []). %% p(F, A) -> %% p(F, A, "", ""). %% p(F, A, Before, After) when is_list(Before) andalso is_list(After) -> %% TcName = %% case get(tc_name) of %% undefined -> %% case get(sname) of %% undefined -> %% ""; %% SName when is_list(SName) -> %% SName %% end; %% Name when is_list(Name) -> %% Name %% end, %% FStr = f("*** [~s][~s][~p] " ++ F ++ "~n", %% [formated_timestamp(),TcName,self()|A]), %% i(Before ++ FStr ++ After, []). %% d(F, A) -> %% d(get(dbg_fd), F, A). %% d(undefined, F, A) -> %% [NodeNameStr|_] = string:split(atom_to_list(node()), [$@]), %% DbgFileName = f("~s-dbg.txt", [NodeNameStr]), %% case file:open(DbgFileName, [write]) of %% {ok, FD} -> %% put(dbg_fd, FD), %% d(FD, F, A); %% {error, Reason} -> %% exit({failed_open_dbg_file, Reason}) %% end; %% d(FD, F, A) -> %% io:format(FD, "~s~n", [f("[~s] " ++ F, [formated_timestamp()|A])]). i(F) -> i(F, []). i(F, A) -> FStr = f("[~s] " ++ F, [formated_timestamp()|A]), io:format(user, FStr ++ "~n", []), io:format(FStr, []).