From b76907abc160fdbb192e81f0a8dadde9455db9ea Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Wed, 10 Jul 2019 12:45:43 +0200 Subject: [esock] Add test case for socket option acceptconn Add test case for the socket option acceptconn. Also make minor correction (error when trying to set this option was incorrect). Doc was also incorrect (spelled wrong). OTP-15904 --- erts/doc/src/socket_usage.xml | 2 +- erts/emulator/test/socket_SUITE.erl | 465 +++++++++++++++++++++++++++++++++++- erts/preloaded/ebin/socket.beam | Bin 76320 -> 76408 bytes erts/preloaded/src/socket.erl | 2 + 4 files changed, 467 insertions(+), 2 deletions(-) (limited to 'erts') diff --git a/erts/doc/src/socket_usage.xml b/erts/doc/src/socket_usage.xml index 7e65bcbf70..77c606b1c1 100644 --- a/erts/doc/src/socket_usage.xml +++ b/erts/doc/src/socket_usage.xml @@ -197,7 +197,7 @@ Other Requirements and comments - acceptcon + acceptconn boolean() no yes diff --git a/erts/emulator/test/socket_SUITE.erl b/erts/emulator/test/socket_SUITE.erl index 786a6fc2fc..f15e4cde44 100644 --- a/erts/emulator/test/socket_SUITE.erl +++ b/erts/emulator/test/socket_SUITE.erl @@ -121,6 +121,7 @@ api_opt_simple_otp_options/1, api_opt_simple_otp_rcvbuf_option/1, api_opt_simple_otp_controlling_process/1, + api_opt_sock_acceptconn/1, api_opt_ip_add_drop_membership/1, %% *** API Operation Timeout *** @@ -619,7 +620,12 @@ groups() -> {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_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()}, @@ -758,7 +764,12 @@ api_async_cases() -> api_options_cases() -> [ {group, api_options_otp}, - {group, api_options_ip} + {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() -> @@ -768,11 +779,20 @@ api_options_otp_cases() -> api_opt_simple_otp_controlling_process ]. +api_options_socket_cases() -> + [ + api_opt_sock_acceptconn + ]. + api_options_ip_cases() -> [ api_opt_ip_add_drop_membership ]. +%% api_options_ipv6_cases() -> +%% [ +%% ]. + api_op_with_timeout_cases() -> [ api_to_connect_tcp4, @@ -8339,6 +8359,443 @@ api_opt_simple_otp_controlling_process() -> +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Tests the socket option acceptcon. This should be possible to get +%% but not set. + +api_opt_sock_acceptconn(suite) -> + []; +api_opt_sock_acceptconn(doc) -> + []; +api_opt_sock_acceptconn(_Config) when is_list(_Config) -> + ?TT(?SECS(30)), + tc_try(api_opt_sock_acceptconn, + fun() -> + has_sock_acceptconn_support() + end, + fun() -> api_opt_sock_acceptconn() end). + + + +api_opt_sock_acceptconn() -> + 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 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] verify UDP 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, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), + ERROR + end + end}, + #{desc => "[set] verify UDP 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 UDP 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 UDP 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 UDP 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}, + + #{desc => "close UDP socket", + cmd => fun(#{sock := Sock} = State) -> + socket:close(Sock), + {ok, maps:remove(sock, State)} + end}, + + ?SEV_SLEEP(?SECS(1)), + + #{desc => "create TCP 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 TCP 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, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), + ERROR + end + end}, + #{desc => "[set] verify TCP 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 TCP 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 TCP 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 TCP 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 TCP listen socket accept connections", + cmd => fun(#{lsock := Sock} = _State) -> + case socket:listen(Sock) of + ok -> + ok; + {error, _} = ERROR -> + ERROR + end + end}, + + #{desc => "[get] verify TCP 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 TCP 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 TCP (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 TCP 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 TCP 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 TCP 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 TCP 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 TCP 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 TCP 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 TCP 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 TCP 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 TCP 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 TCP 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 TCP listen socket", + cmd => fun(#{lsock := Sock} = State) -> + socket:close(Sock), + {ok, maps:remove(lsock, State)} + end}, + + %% *** We are done *** + ?SEV_FINISH_NORMAL + ], + + + i("get multicast address"), + 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 that the add_mambership and drop_membership ip options work. @@ -27076,6 +27533,9 @@ has_support_ip_multicast() -> not_supported({multicast, Type}) end. +has_support_sock_acceptconn() -> + has_support_socket_option_sock(acceptconn). + has_support_ip_add_membership() -> has_support_socket_option_ip(add_membership). @@ -27086,6 +27546,9 @@ has_support_ip_drop_membership() -> has_support_socket_option_ip(Opt) -> has_support_socket_option(ip, Opt). +has_socket_option_sock_support(Opt) -> + has_socket_option_support(socket, Opt). + has_support_socket_option(Level, Option) -> case socket:supports(options, Level, Option) of true -> diff --git a/erts/preloaded/ebin/socket.beam b/erts/preloaded/ebin/socket.beam index 648519149f..7f7ba46e04 100644 Binary files a/erts/preloaded/ebin/socket.beam and b/erts/preloaded/ebin/socket.beam differ diff --git a/erts/preloaded/src/socket.erl b/erts/preloaded/src/socket.erl index 910c8be294..b80ef13e1e 100644 --- a/erts/preloaded/src/socket.erl +++ b/erts/preloaded/src/socket.erl @@ -3377,6 +3377,8 @@ enc_sockopt_key(otp = L, Opt, _, _, _, _) -> %% +++ SOCKET socket options +++ enc_sockopt_key(socket = _L, acceptconn = _Opt, get = _Dir, _D, _T, _P) -> ?SOCKET_OPT_SOCK_ACCEPTCONN; +enc_sockopt_key(socket = L, acceptconn = Opt, Dir, _D, _T, _P) -> + not_supported({L, Opt, Dir}); enc_sockopt_key(socket = L, acceptfilter = Opt, _Dir, _D, _T, _P) -> not_supported({L, Opt}); %% Before linux 3.8, this socket option could be set. -- cgit v1.2.3 From 151c6bd2c9a374f3ac5dfd940993caa679cf5c17 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Wed, 10 Jul 2019 13:03:26 +0200 Subject: [esock|test] Add placeholder test case for socket option acceptfilter OTP-15904 --- erts/emulator/test/socket_SUITE.erl | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'erts') diff --git a/erts/emulator/test/socket_SUITE.erl b/erts/emulator/test/socket_SUITE.erl index f15e4cde44..9bda605b02 100644 --- a/erts/emulator/test/socket_SUITE.erl +++ b/erts/emulator/test/socket_SUITE.erl @@ -122,6 +122,7 @@ api_opt_simple_otp_rcvbuf_option/1, api_opt_simple_otp_controlling_process/1, api_opt_sock_acceptconn/1, + api_opt_sock_acceptfilter/1, api_opt_ip_add_drop_membership/1, %% *** API Operation Timeout *** @@ -781,7 +782,8 @@ api_options_otp_cases() -> api_options_socket_cases() -> [ - api_opt_sock_acceptconn + api_opt_sock_acceptconn, + api_opt_sock_acceptfilter ]. api_options_ip_cases() -> @@ -8796,6 +8798,22 @@ api_opt_sock_acceptconn() -> +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% 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 that the add_mambership and drop_membership ip options work. -- cgit v1.2.3 From ab78a0e3c0655efe5a8aab3569aca0859811dd4a Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Wed, 10 Jul 2019 16:17:49 +0200 Subject: [esock] Add test case for socket option bindtodevice Add test case for the socket option bindtodevice. Also make correction in the nif code. Used the wrong option (broadcast). Also added more info to doc. Note sure if this test case actually works. Set and get "works", but the value returned by get is always "". So either we should extend the test to made sure the bind actually has the expected effect or... Something for a rainy day maybe... OTP-15904 --- erts/doc/src/socket_usage.xml | 4 +- erts/emulator/nifs/common/socket_nif.c | 2 +- erts/emulator/test/socket_SUITE.erl | 267 ++++++++++++++++++++++++++++++++- erts/preloaded/src/socket.erl | 4 +- 4 files changed, 272 insertions(+), 5 deletions(-) (limited to 'erts') diff --git a/erts/doc/src/socket_usage.xml b/erts/doc/src/socket_usage.xml index 77c606b1c1..2d0865d45f 100644 --- a/erts/doc/src/socket_usage.xml +++ b/erts/doc/src/socket_usage.xml @@ -208,7 +208,9 @@ string() yes yes - none + Before Linux 3.8, this socket option could be set, but not get. + Only works for some socket types (e.g. inet). + If empty value is set, the binding is removed. broadcast diff --git a/erts/emulator/nifs/common/socket_nif.c b/erts/emulator/nifs/common/socket_nif.c index 211f21cb40..362e584bd3 100644 --- a/erts/emulator/nifs/common/socket_nif.c +++ b/erts/emulator/nifs/common/socket_nif.c @@ -11919,7 +11919,7 @@ ERL_NIF_TERM ngetopt_lvl_sock_bindtodevice(ErlNifEnv* env, SSDBG( descP, ("SOCKET", "ngetopt_lvl_sock_bindtodevice -> entry with\r\n") ); - return ngetopt_str_opt(env, descP, SOL_SOCKET, SO_BROADCAST, IFNAMSIZ+1); + return ngetopt_str_opt(env, descP, SOL_SOCKET, SO_BINDTODEVICE, IFNAMSIZ+1); } #endif diff --git a/erts/emulator/test/socket_SUITE.erl b/erts/emulator/test/socket_SUITE.erl index 9bda605b02..83dc396a4d 100644 --- a/erts/emulator/test/socket_SUITE.erl +++ b/erts/emulator/test/socket_SUITE.erl @@ -123,6 +123,7 @@ api_opt_simple_otp_controlling_process/1, api_opt_sock_acceptconn/1, api_opt_sock_acceptfilter/1, + api_opt_sock_bindtodevice/1, api_opt_ip_add_drop_membership/1, %% *** API Operation Timeout *** @@ -783,7 +784,8 @@ api_options_otp_cases() -> api_options_socket_cases() -> [ api_opt_sock_acceptconn, - api_opt_sock_acceptfilter + api_opt_sock_acceptfilter, + api_opt_sock_bindtodevice ]. api_options_ip_cases() -> @@ -8814,6 +8816,266 @@ api_opt_sock_acceptfilter(_Config) when is_list(_Config) -> +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% 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_sock_bindtodevice_support() 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 which_local_host_info(Domain) of + {ok, {Name, _, 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, 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, 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(#{tsock1 := Sock, dev := Dev} = _State) -> + case Set(Sock, Dev) of + ok -> + ?SEV_IPRINT("Expected Success"), + ok; + {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 := 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 := 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 := 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 := 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 + ], + + i("get multicast address"), + 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 that the add_mambership and drop_membership ip options work. @@ -27554,6 +27816,9 @@ has_support_ip_multicast() -> has_support_sock_acceptconn() -> has_support_socket_option_sock(acceptconn). +has_support_sock_bindtodevice() -> + has_support_socket_option_sock(bindtodevice). + has_support_ip_add_membership() -> has_support_socket_option_ip(add_membership). diff --git a/erts/preloaded/src/socket.erl b/erts/preloaded/src/socket.erl index b80ef13e1e..016b479c4d 100644 --- a/erts/preloaded/src/socket.erl +++ b/erts/preloaded/src/socket.erl @@ -3381,8 +3381,8 @@ enc_sockopt_key(socket = L, acceptconn = Opt, Dir, _D, _T, _P) -> not_supported({L, Opt, Dir}); enc_sockopt_key(socket = L, acceptfilter = Opt, _Dir, _D, _T, _P) -> not_supported({L, Opt}); -%% Before linux 3.8, this socket option could be set. -%% Maximum size of buffer for name: IFNAMSZIZ +%% Before linux 3.8, this socket option could be set but not get. +%% Maximum size of buffer for name: IFNAMSIZ %% So, we let the implementation decide. enc_sockopt_key(socket = _L, bindtodevice = _Opt, _Dir, _D, _T, _P) -> ?SOCKET_OPT_SOCK_BINDTODEVICE; -- cgit v1.2.3 From e9cc689af5c576316ae6fde106b2be260361d71c Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Thu, 11 Jul 2019 14:57:19 +0200 Subject: [esock|test] Post rebase corrections OTP-15904 --- erts/emulator/test/socket_SUITE.erl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'erts') diff --git a/erts/emulator/test/socket_SUITE.erl b/erts/emulator/test/socket_SUITE.erl index 83dc396a4d..6c2900a31b 100644 --- a/erts/emulator/test/socket_SUITE.erl +++ b/erts/emulator/test/socket_SUITE.erl @@ -8376,7 +8376,7 @@ api_opt_sock_acceptconn(_Config) when is_list(_Config) -> ?TT(?SECS(30)), tc_try(api_opt_sock_acceptconn, fun() -> - has_sock_acceptconn_support() + has_support_sock_acceptconn() end, fun() -> api_opt_sock_acceptconn() end). @@ -8829,7 +8829,7 @@ 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_sock_bindtodevice_support() end, + fun() -> has_support_sock_bindtodevice() end, fun() -> api_opt_sock_bindtodevice() end). @@ -8846,7 +8846,7 @@ api_opt_sock_bindtodevice() -> [ #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> - case which_local_host_info(Domain) of + case ?LIB:which_local_host_info(Domain) of {ok, {Name, _, Addr}} -> ?SEV_IPRINT("local host info (~p): " "~n Name: ~p" @@ -27829,8 +27829,8 @@ has_support_ip_drop_membership() -> has_support_socket_option_ip(Opt) -> has_support_socket_option(ip, Opt). -has_socket_option_sock_support(Opt) -> - has_socket_option_support(socket, 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 -- cgit v1.2.3 From 596d0fd5863ffffb4246814c6f74d75ce68b7791 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Thu, 11 Jul 2019 18:23:45 +0200 Subject: [esock] Handle wildcard address 'broadcast' when binding Its now possible to bind a socket to the (limited) broadcast address by specifying 'broadcast' as address: socket:bind(Socket, broadcast) This is *only* valid for family 'inet'. Add testing of sending (broadcasting) to both "limited" broadcast address and "subnet-directed" broadcast address. OTP-15904 --- erts/emulator/nifs/common/socket_util.c | 18 +- erts/emulator/test/socket_SUITE.erl | 361 ++++++++++++++++++++++++++++++-- erts/emulator/test/socket_test_lib.erl | 135 +++++++----- erts/preloaded/ebin/socket.beam | Bin 76408 -> 76476 bytes erts/preloaded/src/socket.erl | 20 +- 5 files changed, 454 insertions(+), 80 deletions(-) (limited to 'erts') diff --git a/erts/emulator/nifs/common/socket_util.c b/erts/emulator/nifs/common/socket_util.c index 2740cb51ef..54c310ecc7 100644 --- a/erts/emulator/nifs/common/socket_util.c +++ b/erts/emulator/nifs/common/socket_util.c @@ -741,16 +741,24 @@ char* esock_decode_ip4_address(ErlNifEnv* env, "\r\n", eAddr) ); if (IS_ATOM(env, eAddr)) { - /* This is either 'any' or 'loopback' */ + + /* This is either 'any' | 'broadcast' | 'loopback' */ if (COMPARE(esock_atom_loopback, eAddr) == 0) { - UDBG( ("SUTIL", "esock_decode_ip4_address -> address: lookback\r\n") ); + UDBG( ("SUTIL", + "esock_decode_ip4_address -> address: lookback\r\n") ); addr.s_addr = htonl(INADDR_LOOPBACK); } else if (COMPARE(esock_atom_any, eAddr) == 0) { - UDBG( ("SUTIL", "esock_decode_ip4_address -> address: any\r\n") ); - addr.s_addr = htonl(INADDR_ANY); + UDBG( ("SUTIL", + "esock_decode_ip4_address -> address: any\r\n") ); + addr.s_addr = htonl(INADDR_ANY); + } else if (COMPARE(esock_atom_broadcast, eAddr) == 0) { + UDBG( ("SUTIL", + "esock_decode_ip4_address -> address: broadcast\r\n") ); + addr.s_addr = htonl(INADDR_BROADCAST); } else { - UDBG( ("SUTIL", "esock_decode_ip4_address -> address: unknown\r\n") ); + UDBG( ("SUTIL", + "esock_decode_ip4_address -> address: unknown\r\n") ); return ESOCK_STR_EINVAL; } diff --git a/erts/emulator/test/socket_SUITE.erl b/erts/emulator/test/socket_SUITE.erl index 6c2900a31b..cbf612948b 100644 --- a/erts/emulator/test/socket_SUITE.erl +++ b/erts/emulator/test/socket_SUITE.erl @@ -124,6 +124,7 @@ api_opt_sock_acceptconn/1, api_opt_sock_acceptfilter/1, api_opt_sock_bindtodevice/1, + api_opt_sock_broadcast/1, api_opt_ip_add_drop_membership/1, %% *** API Operation Timeout *** @@ -785,7 +786,8 @@ api_options_socket_cases() -> [ api_opt_sock_acceptconn, api_opt_sock_acceptfilter, - api_opt_sock_bindtodevice + api_opt_sock_bindtodevice, + api_opt_sock_broadcast ]. api_options_ip_cases() -> @@ -8847,7 +8849,7 @@ api_opt_sock_bindtodevice() -> #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> case ?LIB:which_local_host_info(Domain) of - {ok, {Name, _, Addr}} -> + {ok, #{name := Name, addr := Addr}} -> ?SEV_IPRINT("local host info (~p): " "~n Name: ~p" "~n Addr: ~p", @@ -8903,8 +8905,13 @@ api_opt_sock_bindtodevice() -> {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]), + ?SEV_EPRINT("Unexpected Failure: ~p", + [Reason]), ERROR end end}, @@ -9076,6 +9083,326 @@ api_opt_sock_bindtodevice() -> +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% 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, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", + [Reason]), + ERROR + end + end}, + #{desc => "[socket 1] UDP socket sockname", + cmd => fun(#{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 bind and before 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}, + + ?SEV_SLEEP(?SECS(1)), + + #{desc => "[socket 3] try send to limited broadcast address", + cmd => fun(#{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(#{sock1 := Sock} = _State) -> + case socket:recvfrom(Sock, 0, 5000) of + {ok, _} -> + ?SEV_IPRINT("Expected Success: " + "received message"), + ok; + {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} = _State) -> + case socket:recvfrom(Sock, 0, 5000) of + {ok, _} -> + ?SEV_IPRINT("Expected Success: " + "received message"), + ok; + {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 that the add_mambership and drop_membership ip options work. @@ -9400,7 +9727,7 @@ which_multicast_address3(Domain, [MAddrStr|MAddrs]) -> which_local_host_ifname(Domain) -> case ?LIB:which_local_host_info(Domain) of - {ok, {Name, _Addr, _Flags}} -> + {ok, #{name := Name}} -> Name; {error, Reason} -> not_supported({multicast, Reason}) @@ -27760,7 +28087,7 @@ which_local_socket_addr(local = Domain) -> %% but until that gets the necessary functionality... which_local_socket_addr(Domain) -> case ?LIB:which_local_host_info(Domain) of - {ok, {_Name, _Flags, Addr}} -> + {ok, #{addr := Addr}} -> #{family => Domain, addr => Addr}; {error, Reason} -> @@ -27776,12 +28103,7 @@ which_local_addr(local = _Domain) -> %% We should really implement this using the (new) net module, %% but until that gets the necessary functionality... which_local_addr(Domain) -> - case ?LIB:which_local_host_info(Domain) of - {ok, {_Name, _Flags, Addr}} -> - Addr; - {error, Reason} -> - ?FAIL(Reason) - end. + ?LIB:which_local_addr(Domain). @@ -27799,7 +28121,7 @@ has_support_ip_multicast() -> {unix, OsName} when (OsName =:= linux) orelse (OsName =:= sunos) -> case ?LIB:which_local_host_info(inet) of - {ok, {_Name, Flags, _Addr}} -> + {ok, #{flags := Flags}} -> case lists:member(multicast, Flags) of true -> ok; @@ -27819,6 +28141,21 @@ has_support_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_ip_add_membership() -> has_support_socket_option_ip(add_membership). diff --git a/erts/emulator/test/socket_test_lib.erl b/erts/emulator/test/socket_test_lib.erl index 2ded82ae13..39cbf0c79f 100644 --- a/erts/emulator/test/socket_test_lib.erl +++ b/erts/emulator/test/socket_test_lib.erl @@ -36,6 +36,7 @@ has_support_ipv6/0, which_local_host_info/1, + which_local_addr/1, %% Skipping not_yet_implemented/0, @@ -174,46 +175,12 @@ has_support_ipv6() -> %% but until that gets the necessary functionality... which_local_addr(Domain) -> case which_local_host_info(Domain) of - {ok, {_Name, _Flags, Addr}} -> + {ok, #{addr := Addr}} -> {ok, Addr}; {error, _Reason} = ERROR -> ERROR end. -%% case inet:getifaddrs() of -%% {ok, IFL} -> -%% which_addr(Domain, IFL); -%% {error, Reason} -> -%% ?FAIL({inet, getifaddrs, Reason}) -%% end. - -%% which_addr(_Domain, []) -> -%% ?FAIL(no_address); -%% which_addr(Domain, [{"lo" ++ _, _}|IFL]) -> -%% which_addr(Domain, IFL); -%% which_addr(Domain, [{_Name, IFO}|IFL]) -> -%% case which_addr2(Domain, IFO) of -%% {ok, Addr} -> -%% Addr; -%% {error, no_address} -> -%% which_addr(Domain, IFL) -%% end; -%% which_addr(Domain, [_|IFL]) -> -%% which_addr(Domain, IFL). - -%% which_addr2(_Domain, []) -> -%% {error, no_address}; -%% which_addr2(inet = _Domain, [{addr, Addr}|_IFO]) -%% when (size(Addr) =:= 4) andalso (element(1, Addr) =/= 127) -> -%% {ok, Addr}; -%% which_addr2(inet6 = _Domain, [{addr, Addr}|_IFO]) -%% when (size(Addr) =:= 8) andalso -%% (element(1, Addr) =/= 0) andalso -%% (element(1, Addr) =/= 16#fe80) -> -%% {ok, Addr}; -%% which_addr2(Domain, [_|IFO]) -> -%% which_addr2(Domain, IFO). - %% Returns the interface (name), flags and address (not 127...) %% of the local host. @@ -234,35 +201,89 @@ which_local_host_info(Domain, [{"docker" ++ _, _}|IFL]) -> which_local_host_info(Domain, [{"br-" ++ _, _}|IFL]) -> which_local_host_info(Domain, IFL); which_local_host_info(Domain, [{Name, IFO}|IFL]) -> - case which_local_host_info2(Domain, IFO) of - {ok, {Flags, Addr}} -> - {ok, {Name, Flags, Addr}}; - {error, _} -> + try which_local_host_info2(Domain, IFO) of + Info -> + {ok, Info#{name => Name}} + catch + throw:_:_ -> which_local_host_info(Domain, IFL) end; which_local_host_info(Domain, [_|IFL]) -> which_local_host_info(Domain, IFL). -which_local_host_info2(Domain, IFO) -> - case lists:keysearch(flags, 1, IFO) of - {value, {flags, Flags}} -> - which_local_host_info2(Domain, IFO, Flags); +%% which_local_host_info2(Domain, IFO) -> +%% case lists:keysearch(flags, 1, IFO) of +%% {value, {flags, Flags}} -> +%% which_local_host_info2(Domain, IFO, Flags); +%% false -> +%% {error, no_flags} +%% end. + + +%% which_local_host_info2(_Domain, [], _Flags) -> +%% {error, no_address}; +%% which_local_host_info2(inet = _Domain, [{addr, Addr}|_IFO], Flags) +%% when (size(Addr) =:= 4) andalso (element(1, Addr) =/= 127) -> +%% {ok, {Flags, Addr}}; +%% which_local_host_info2(inet6 = _Domain, [{addr, Addr}|_IFO], Flags) +%% when (size(Addr) =:= 8) andalso +%% (element(1, Addr) =/= 0) andalso +%% (element(1, Addr) =/= 16#fe80) -> +%% {ok, {Flags, Addr}}; +%% which_local_host_info2(Domain, [_|IFO], Flags) -> +%% which_local_host_info2(Domain, IFO, Flags). + +%% foo(Info, inet = Domain, IFO) -> +%% foo(Info, Domain, IFO, [flags, addr, netmask, broadaddr, hwaddr]); +%% foo(Info, inet6 = Domain, IFO) -> +%% foo(Info, Domain, IFO, [flags, addr, netmask, hwaddr]). + +which_local_host_info2(inet = _Domain, IFO) -> + Addr = which_local_host_info3(addr, IFO, + fun({A, _, _, _}) when (A =/= 127) -> true; + (_) -> false + end), + NetMask = which_local_host_info3(netmask, IFO, + fun({_, _, _, _}) -> true; + (_) -> false + end), + BroadAddr = which_local_host_info3(broadaddr, IFO, + fun({_, _, _, _}) -> true; + (_) -> false + end), + Flags = which_local_host_info3(flags, IFO, fun(_) -> true end), + #{flags => Flags, + addr => Addr, + broadaddr => BroadAddr, + netmask => NetMask}; +which_local_host_info2(inet6 = _Domain, IFO) -> + Addr = which_local_host_info3(addr, IFO, + fun({A, _, _, _, _, _, _, _}) + when (A =/= 0) andalso + (A =/= 16#fe80) -> true; + (_) -> false + end), + NetMask = which_local_host_info3(netmask, IFO, + fun({_, _, _, _, _, _, _, _}) -> true; + (_) -> false + end), + Flags = which_local_host_info3(flags, IFO, fun(_) -> true end), + #{flags => Flags, + addr => Addr, + netmask => NetMask}. + +which_local_host_info3(_Key, [], _) -> + throw({error, no_address}); +which_local_host_info3(Key, [{Key, Val}|IFO], Check) -> + case Check(Val) of + true -> + Val; false -> - {error, no_flags} - end. + which_local_host_info3(Key, IFO, Check) + end; +which_local_host_info3(Key, [_|IFO], Check) -> + which_local_host_info3(Key, IFO, Check). -which_local_host_info2(_Domain, [], _Flags) -> - {error, no_address}; -which_local_host_info2(inet = _Domain, [{addr, Addr}|_IFO], Flags) - when (size(Addr) =:= 4) andalso (element(1, Addr) =/= 127) -> - {ok, {Flags, Addr}}; -which_local_host_info2(inet6 = _Domain, [{addr, Addr}|_IFO], Flags) - when (size(Addr) =:= 8) andalso - (element(1, Addr) =/= 0) andalso - (element(1, Addr) =/= 16#fe80) -> - {ok, {Flags, Addr}}; -which_local_host_info2(Domain, [_|IFO], Flags) -> - which_local_host_info2(Domain, IFO, Flags). diff --git a/erts/preloaded/ebin/socket.beam b/erts/preloaded/ebin/socket.beam index 7f7ba46e04..408c51b57a 100644 Binary files a/erts/preloaded/ebin/socket.beam and b/erts/preloaded/ebin/socket.beam differ diff --git a/erts/preloaded/src/socket.erl b/erts/preloaded/src/socket.erl index 016b479c4d..b9b67f25b4 100644 --- a/erts/preloaded/src/socket.erl +++ b/erts/preloaded/src/socket.erl @@ -313,7 +313,8 @@ path := binary() | string()}. -type sockaddr_in4() :: #{family := inet, port := port_number(), - addr := any | loopback | ip4_address()}. + %% The 'broadcast' here is the "limited broadcast" + addr := any | broadcast | loopback | ip4_address()}. -type sockaddr_in6() :: #{family := inet6, port := port_number(), addr := any | loopback | ip6_address(), @@ -334,7 +335,7 @@ -define(SOCKADDR_IN6_DEFAULTS, ?SOCKADDR_IN6_DEFAULTS(any)). -define(SOCKADDR_IN6_DEFAULT(A), (?SOCKADDR_IN6_DEFAULTS(A))#{family => inet6}). -%% otp - The option is internal to our (OTP) imeplementation. +%% otp - This option is internal to our (OTP) implementation. %% socket - The socket layer (SOL_SOCKET). %% ip - The IP layer (SOL_IP or is it IPPROTO_IP?). %% ipv6 - The IPv6 layer (SOL_IPV6). @@ -342,6 +343,7 @@ %% udp - The UDP (User Datagram Protocol) layer (IPPROTO_UDP). %% sctp - The SCTP (Stream Control Transmission Protocol) layer (IPPROTO_SCTP). %% Int - Raw level, sent down and used "as is". +%% Its up to the caller to make sure this is correct! -type sockopt_level() :: otp | socket | ip | ipv6 | tcp | udp | sctp | @@ -1146,19 +1148,25 @@ open(Domain, Type, Protocol, Extra) when is_map(Extra) -> %% %% bind - bind a name to a socket %% +%% Note that Addr can only have the value of broadcast *if* Domain =:= inet! +%% -spec bind(Socket, Addr) -> ok | {error, Reason} when Socket :: socket(), - Addr :: any | loopback | sockaddr(), + Addr :: any | broadcast | loopback | sockaddr(), Reason :: term(). bind(#socket{ref = SockRef}, Addr) - when ((Addr =:= any) orelse (Addr =:= loopback)) -> + when ((Addr =:= any) orelse + (Addr =:= broadcast) orelse + (Addr =:= loopback)) -> try which_domain(SockRef) of inet -> nif_bind(SockRef, ?SOCKADDR_IN4_DEFAULT(Addr)); - inet6 -> - nif_bind(SockRef, ?SOCKADDR_IN6_DEFAULT(Addr)) + inet6 when (Addr =:= any) orelse (Addr =:= loopback) -> + nif_bind(SockRef, ?SOCKADDR_IN6_DEFAULT(Addr)); + _ -> + einval() catch %% error:notsup:S -> -- cgit v1.2.3 From 96ef9b4a7e97b906a08350e8a7805856b0307cdb Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Tue, 16 Jul 2019 17:19:12 +0200 Subject: [esock|test] Fix broadcast test on FreeBSD On FreeBSD (for instance) the address "broadcast" (limited broadcast address = INADDR_BROADCAST) is not available (=> eaddrnotavail), so that part of the test is skipped. OTP-15904 --- erts/emulator/test/socket_SUITE.erl | 72 ++++++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 28 deletions(-) (limited to 'erts') diff --git a/erts/emulator/test/socket_SUITE.erl b/erts/emulator/test/socket_SUITE.erl index cbf612948b..ff12ef66a3 100644 --- a/erts/emulator/test/socket_SUITE.erl +++ b/erts/emulator/test/socket_SUITE.erl @@ -9153,6 +9153,11 @@ api_opt_sock_broadcast() -> ?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]), @@ -9160,14 +9165,17 @@ api_opt_sock_broadcast() -> end end}, #{desc => "[socket 1] UDP socket sockname", - cmd => fun(#{sock1 := Sock} = _State) -> - case socket:sockname(Sock) of - {ok, SA} -> + cmd => fun(#{sock1 := Sock, 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 + ok; + {error, _} = ERROR -> + ERROR + end end}, ?SEV_SLEEP(?SECS(1)), @@ -9281,17 +9289,17 @@ api_opt_sock_broadcast() -> ERROR end end}, - #{desc => "[socket 3] verify UDP socket (after bind and before set)", + #{desc => "[socket 3] verify UDP socket (after set)", cmd => fun(#{sock3 := Sock} = _State) -> case Get(Sock) of - {ok, false} -> + {ok, true} -> ?SEV_IPRINT("Expected Success: " - "broadcast not allowed"), + "broadcast allowed"), ok; - {ok, true} -> + {ok, false} -> ?SEV_IPRINT("Unexpected Success result: " - "broadcast already allowed"), - ok; + "broadcast not allowed"), + {error, not_allowed}; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), @@ -9303,23 +9311,31 @@ api_opt_sock_broadcast() -> #{desc => "[socket 3] try send to limited broadcast address", cmd => fun(#{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", + 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}, + ERROR + end + end}, #{desc => "[socket 1] try recv", - cmd => fun(#{sock1 := Sock} = _State) -> + cmd => fun(#{sock1 := Sock, + 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: " -- cgit v1.2.3 From c1faea0e9e663d2d69a75f519d8f671419e6e226 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Wed, 17 Jul 2019 14:06:25 +0200 Subject: [esock|test] Add test case for socket option 'debug' The test case must either be run with a user that has CAP_NET_ADMIN capability or by root. Otherwise the test case will be skipped (eacces). OTP-15904 --- erts/emulator/test/socket_SUITE.erl | 128 ++++++++++++++++++++++++++++++++++-- 1 file changed, 122 insertions(+), 6 deletions(-) (limited to 'erts') diff --git a/erts/emulator/test/socket_SUITE.erl b/erts/emulator/test/socket_SUITE.erl index ff12ef66a3..8921cdde04 100644 --- a/erts/emulator/test/socket_SUITE.erl +++ b/erts/emulator/test/socket_SUITE.erl @@ -125,6 +125,7 @@ api_opt_sock_acceptfilter/1, api_opt_sock_bindtodevice/1, api_opt_sock_broadcast/1, + api_opt_sock_debug/1, api_opt_ip_add_drop_membership/1, %% *** API Operation Timeout *** @@ -787,7 +788,8 @@ api_options_socket_cases() -> api_opt_sock_acceptconn, api_opt_sock_acceptfilter, api_opt_sock_bindtodevice, - api_opt_sock_broadcast + api_opt_sock_broadcast, + api_opt_sock_debug ]. api_options_ip_cases() -> @@ -9165,7 +9167,7 @@ api_opt_sock_broadcast() -> end end}, #{desc => "[socket 1] UDP socket sockname", - cmd => fun(#{sock1 := Sock, sa1 := skip} = _State) -> + cmd => fun(#{sa1 := skip} = _State) -> ?SEV_IPRINT("SKIP limited broadcast test"), ok; (#{sock1 := Sock} = _State) -> @@ -9310,8 +9312,7 @@ api_opt_sock_broadcast() -> ?SEV_SLEEP(?SECS(1)), #{desc => "[socket 3] try send to limited broadcast address", - cmd => fun(#{sock3 := Sock, - sa1 := skip} = _State) -> + cmd => fun(#{sa1 := skip} = _State) -> ?SEV_IPRINT("SKIP limited broadcast test"), ok; (#{sock3 := Sock, @@ -9331,8 +9332,7 @@ api_opt_sock_broadcast() -> end end}, #{desc => "[socket 1] try recv", - cmd => fun(#{sock1 := Sock, - sa1 := skip} = _State) -> + cmd => fun(#{sa1 := skip} = _State) -> ?SEV_IPRINT("SKIP limited broadcast test"), ok; (#{sock1 := Sock} = _State) -> @@ -9419,6 +9419,119 @@ api_opt_sock_broadcast() -> +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Tests the socket option debug. +%% Only allowed for processes with the CAP_NET_ADMIN capability or an +%% effective user ID of 0. +%% Since we never run the test as root (I hope), this test will +%% most likely be skipped (unless we give the test user CAP_NET_ADMIN +%% capability). + +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) -> + case Set(Sock, Debug + 1) of + ok -> + ?SEV_IPRINT("Expected Success"), + ok; + {error, eacces = Reason} -> + ?SEV_EPRINT("NO ACCESS => SKIP"), + {skip, Reason}; + {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 that the add_mambership and drop_membership ip options work. @@ -28171,6 +28284,9 @@ has_support_sock_broadcast() -> not_supported({broadcast, Reason}) end. +has_support_sock_debug() -> + has_support_socket_option_sock(debug). + has_support_ip_add_membership() -> has_support_socket_option_ip(add_membership). -- cgit v1.2.3 From 58217e460bd121a05f006413adecc3feb3895a06 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Wed, 17 Jul 2019 16:03:04 +0200 Subject: [esock|test] Add an attempt to read out the new debug value After a successful set of debug, also attempt to read it back to check that it actually took. OTP-15904 --- erts/emulator/test/socket_SUITE.erl | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) (limited to 'erts') diff --git a/erts/emulator/test/socket_SUITE.erl b/erts/emulator/test/socket_SUITE.erl index 8921cdde04..fd3206f2ef 100644 --- a/erts/emulator/test/socket_SUITE.erl +++ b/erts/emulator/test/socket_SUITE.erl @@ -9423,10 +9423,11 @@ api_opt_sock_broadcast() -> %% Tests the socket option debug. %% Only allowed for processes with the CAP_NET_ADMIN capability or an -%% effective user ID of 0. -%% Since we never run the test as root (I hope), this test will -%% most likely be skipped (unless we give the test user CAP_NET_ADMIN -%% capability). +%% . +%% 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) -> []; @@ -9494,11 +9495,12 @@ api_opt_sock_debug() -> end end}, #{desc => "Try enable socket debug", - cmd => fun(#{sock := Sock, debug := Debug} = _State) -> - case Set(Sock, Debug + 1) of + cmd => fun(#{sock := Sock, debug := Debug} = State) -> + NewDebug = Debug + 1, + case Set(Sock, NewDebug) of ok -> ?SEV_IPRINT("Expected Success"), - ok; + {ok, State#{debug => NewDebug}}; {error, eacces = Reason} -> ?SEV_EPRINT("NO ACCESS => SKIP"), {skip, Reason}; @@ -9508,6 +9510,18 @@ api_opt_sock_debug() -> 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", -- cgit v1.2.3 From f3733fff52ad0d91e8561f5bb8d77b4d7bf0e3ca Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Wed, 17 Jul 2019 18:18:55 +0200 Subject: [esock|test] Add test case for the domain socket option OTP-15904 --- erts/emulator/test/socket_SUITE.erl | 129 ++++++++++++++++++++++++++++++++++-- 1 file changed, 125 insertions(+), 4 deletions(-) (limited to 'erts') diff --git a/erts/emulator/test/socket_SUITE.erl b/erts/emulator/test/socket_SUITE.erl index fd3206f2ef..efafbb7c8d 100644 --- a/erts/emulator/test/socket_SUITE.erl +++ b/erts/emulator/test/socket_SUITE.erl @@ -126,6 +126,7 @@ api_opt_sock_bindtodevice/1, api_opt_sock_broadcast/1, api_opt_sock_debug/1, + api_opt_sock_domain/1, api_opt_ip_add_drop_membership/1, %% *** API Operation Timeout *** @@ -789,7 +790,8 @@ api_options_socket_cases() -> api_opt_sock_acceptfilter, api_opt_sock_bindtodevice, api_opt_sock_broadcast, - api_opt_sock_debug + api_opt_sock_debug, + api_opt_sock_domain ]. api_options_ip_cases() -> @@ -9422,8 +9424,6 @@ api_opt_sock_broadcast() -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Tests the socket option debug. -%% Only allowed for processes with the CAP_NET_ADMIN capability or an -%% . %% 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 @@ -9511,7 +9511,7 @@ api_opt_sock_debug() -> end end}, #{desc => "Get current (new) debug value", - cmd => fun(#{sock := Sock, debug := Debug} = State) -> + cmd => fun(#{sock := Sock, debug := Debug} = _State) -> case Get(Sock) of {ok, Debug} when is_integer(Debug) -> ?SEV_IPRINT("Success: ~p", [Debug]), @@ -9546,6 +9546,124 @@ api_opt_sock_debug() -> +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Tests the socket option domain. +%% This is a read only option. Also not available on oll 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 that the add_mambership and drop_membership ip options work. @@ -28301,6 +28419,9 @@ has_support_sock_broadcast() -> has_support_sock_debug() -> has_support_socket_option_sock(debug). +has_support_sock_domain() -> + has_support_socket_option_sock(domain). + has_support_ip_add_membership() -> has_support_socket_option_ip(add_membership). -- cgit v1.2.3 From 319465f1b4b7a518a27a9f5170de528b8566b3f9 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Thu, 18 Jul 2019 12:34:34 +0200 Subject: [esock|test] Add test case for socket option 'dontroute' OTP-15905 --- erts/emulator/test/socket_SUITE.erl | 135 +++++++++++++++++++++++++++++++++++- 1 file changed, 133 insertions(+), 2 deletions(-) (limited to 'erts') diff --git a/erts/emulator/test/socket_SUITE.erl b/erts/emulator/test/socket_SUITE.erl index fd3206f2ef..759d3ba58f 100644 --- a/erts/emulator/test/socket_SUITE.erl +++ b/erts/emulator/test/socket_SUITE.erl @@ -126,6 +126,7 @@ api_opt_sock_bindtodevice/1, api_opt_sock_broadcast/1, api_opt_sock_debug/1, + api_opt_sock_dontroute/1, api_opt_ip_add_drop_membership/1, %% *** API Operation Timeout *** @@ -789,7 +790,8 @@ api_options_socket_cases() -> api_opt_sock_acceptfilter, api_opt_sock_bindtodevice, api_opt_sock_broadcast, - api_opt_sock_debug + api_opt_sock_debug, + api_opt_sock_dontroute ]. api_options_ip_cases() -> @@ -9511,7 +9513,7 @@ api_opt_sock_debug() -> end end}, #{desc => "Get current (new) debug value", - cmd => fun(#{sock := Sock, debug := Debug} = State) -> + cmd => fun(#{sock := Sock, debug := Debug} = _State) -> case Get(Sock) of {ok, Debug} when is_integer(Debug) -> ?SEV_IPRINT("Success: ~p", [Debug]), @@ -9546,6 +9548,132 @@ api_opt_sock_debug() -> +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% 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), 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, 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 that the add_mambership and drop_membership ip options work. @@ -28301,6 +28429,9 @@ has_support_sock_broadcast() -> has_support_sock_debug() -> has_support_socket_option_sock(debug). +has_support_sock_dontroute() -> + has_support_socket_option_sock(dontroute). + has_support_ip_add_membership() -> has_support_socket_option_ip(add_membership). -- cgit v1.2.3 From 16d4820c063c0b88c8114dc8958905765ab82fc8 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Thu, 18 Jul 2019 14:06:57 +0200 Subject: [esock|test] Add test case for socket option 'keepalive' OTP-15904 --- erts/emulator/test/socket_SUITE.erl | 137 +++++++++++++++++++++++++++++++++++- 1 file changed, 135 insertions(+), 2 deletions(-) (limited to 'erts') diff --git a/erts/emulator/test/socket_SUITE.erl b/erts/emulator/test/socket_SUITE.erl index fd3206f2ef..7a54c5b883 100644 --- a/erts/emulator/test/socket_SUITE.erl +++ b/erts/emulator/test/socket_SUITE.erl @@ -126,6 +126,7 @@ api_opt_sock_bindtodevice/1, api_opt_sock_broadcast/1, api_opt_sock_debug/1, + api_opt_sock_keepalive/1, api_opt_ip_add_drop_membership/1, %% *** API Operation Timeout *** @@ -789,7 +790,8 @@ api_options_socket_cases() -> api_opt_sock_acceptfilter, api_opt_sock_bindtodevice, api_opt_sock_broadcast, - api_opt_sock_debug + api_opt_sock_debug, + api_opt_sock_keepalive ]. api_options_ip_cases() -> @@ -9511,7 +9513,7 @@ api_opt_sock_debug() -> end end}, #{desc => "Get current (new) debug value", - cmd => fun(#{sock := Sock, debug := Debug} = State) -> + cmd => fun(#{sock := Sock, debug := Debug} = _State) -> case Get(Sock) of {ok, Debug} when is_integer(Debug) -> ?SEV_IPRINT("Success: ~p", [Debug]), @@ -9546,6 +9548,134 @@ api_opt_sock_debug() -> +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% 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 that the add_mambership and drop_membership ip options work. @@ -28301,6 +28431,9 @@ has_support_sock_broadcast() -> has_support_sock_debug() -> has_support_socket_option_sock(debug). +has_support_sock_keepalive() -> + has_support_socket_option_sock(keepalive). + has_support_ip_add_membership() -> has_support_socket_option_ip(add_membership). -- cgit v1.2.3 From a0181ae41ba32af16501c8a674ab74a7354f11db Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Thu, 18 Jul 2019 14:48:25 +0200 Subject: [esock|test] Some platforms does not accept acceptconn for UDP Some platforms (for example darwin and OpenBSD) does not accept this option for UDP. Will result in 'enoprotoopt'. So, skip that part of the test case (UDP) if this error occurs. OTP-15904 --- erts/emulator/test/socket_SUITE.erl | 49 ++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 11 deletions(-) (limited to 'erts') diff --git a/erts/emulator/test/socket_SUITE.erl b/erts/emulator/test/socket_SUITE.erl index babf3a0c45..0a2d3dec4c 100644 --- a/erts/emulator/test/socket_SUITE.erl +++ b/erts/emulator/test/socket_SUITE.erl @@ -8419,7 +8419,7 @@ api_opt_sock_acceptconn() -> end}, #{desc => "[get] verify UDP socket (before bind)", - cmd => fun(#{sock := Sock} = _State) -> + cmd => fun(#{sock := Sock} = State) -> case Get(Sock) of {ok, false} -> ?SEV_IPRINT("Expected Success: " @@ -8429,16 +8429,28 @@ api_opt_sock_acceptconn() -> ?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 UDP", [Reason]), + (catch socket:close(Sock)), + {ok, State#{sock => skip}}; {error, Reason} = ERROR -> - ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), + ?SEV_EPRINT("Unexpected Failure: ~p", + [Reason]), ERROR end end}, #{desc => "[set] verify UDP socket (before bind)", - cmd => fun(#{sock := Sock} = _State) -> + cmd => fun(#{sock := skip} = _State) -> + ?SEV_IPRINT("SKIP'ed"), + ok; + (#{sock := Sock} = _State) -> case Set(Sock, true) of {error, Reason} -> - ?SEV_IPRINT("Expected Failure: ~p", [Reason]), + ?SEV_IPRINT("Expected Failure: ~p", + [Reason]), ok; ok -> ?SEV_EPRINT("Unexpected Success: " @@ -8448,7 +8460,10 @@ api_opt_sock_acceptconn() -> end}, #{desc => "bind UDP socket to local address", - cmd => fun(#{sock := Sock, local_sa := LSA} = _State) -> + cmd => fun(#{sock := skip} = _State) -> + ?SEV_IPRINT("SKIP'ed"), + ok; + (#{sock := Sock, local_sa := LSA} = _State) -> case socket:bind(Sock, LSA) of {ok, _} -> ok; @@ -8460,7 +8475,10 @@ api_opt_sock_acceptconn() -> ?SEV_SLEEP(?SECS(1)), #{desc => "[get] verify UDP socket (after bind)", - cmd => fun(#{sock := Sock} = _State) -> + cmd => fun(#{sock := skip} = _State) -> + ?SEV_IPRINT("SKIP'ed"), + ok; + (#{sock := Sock} = _State) -> case Get(Sock) of {ok, false} -> ?SEV_IPRINT("Expected Success: " @@ -8471,15 +8489,20 @@ api_opt_sock_acceptconn() -> "Accepting connections"), {error, {unexpected_success, {Opt, true}}}; {error, Reason} = ERROR -> - ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), + ?SEV_EPRINT("Unexpected Failure: ~p", + [Reason]), ERROR end end}, #{desc => "[set] verify UDP socket (after bind)", - cmd => fun(#{sock := Sock} = _State) -> + cmd => fun(#{sock := skip} = _State) -> + ?SEV_IPRINT("SKIP'ed"), + ok; + (#{sock := Sock} = _State) -> case Set(Sock, true) of {error, Reason} -> - ?SEV_IPRINT("Expected Failure: ~p", [Reason]), + ?SEV_IPRINT("Expected Failure: ~p", + [Reason]), ok; ok -> ?SEV_EPRINT("Unexpected Success: " @@ -8489,7 +8512,10 @@ api_opt_sock_acceptconn() -> end}, #{desc => "close UDP socket", - cmd => fun(#{sock := Sock} = State) -> + cmd => fun(#{sock := skip} = State) -> + ?SEV_IPRINT("SKIP'ed (already closed)"), + {ok, maps:remove(sock, State)}; + (#{sock := Sock} = State) -> socket:close(Sock), {ok, maps:remove(sock, State)} end}, @@ -8518,7 +8544,8 @@ api_opt_sock_acceptconn() -> "Accepting connections"), {error, {unexpected_success, {Opt, true}}}; {error, Reason} = ERROR -> - ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), + ?SEV_EPRINT("Unexpected Failure: ~p", + [Reason]), ERROR end end}, -- cgit v1.2.3 From 6c846678a1dbd705c63d0d3bd573db3daaacb5ec Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Thu, 18 Jul 2019 15:03:32 +0200 Subject: [esock|test] Make the broadcast test case more forgiving OTP-15904 --- erts/emulator/test/socket_SUITE.erl | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'erts') diff --git a/erts/emulator/test/socket_SUITE.erl b/erts/emulator/test/socket_SUITE.erl index 0a2d3dec4c..8ef27b1d04 100644 --- a/erts/emulator/test/socket_SUITE.erl +++ b/erts/emulator/test/socket_SUITE.erl @@ -9368,12 +9368,22 @@ api_opt_sock_broadcast() -> cmd => fun(#{sa1 := skip} = _State) -> ?SEV_IPRINT("SKIP limited broadcast test"), ok; - (#{sock1 := Sock} = _State) -> + (#{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]), @@ -9401,12 +9411,16 @@ api_opt_sock_broadcast() -> end end}, #{desc => "[socket 2] try recv", - cmd => fun(#{sock2 := Sock} = _State) -> + 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]), -- cgit v1.2.3 From 645be105b93b33d6568d5fe6a781a51914fe7313 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Thu, 18 Jul 2019 16:42:24 +0200 Subject: [esock] Fixed a copy-and-paste error for bindtodevice Fixed a copy-and-paste error for socket option bindtodevice. Incorrectly used SO_BROADCAST option instead. OTP-15904 --- erts/emulator/nifs/common/socket_nif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'erts') diff --git a/erts/emulator/nifs/common/socket_nif.c b/erts/emulator/nifs/common/socket_nif.c index 362e584bd3..485aa282c2 100644 --- a/erts/emulator/nifs/common/socket_nif.c +++ b/erts/emulator/nifs/common/socket_nif.c @@ -8212,7 +8212,7 @@ ERL_NIF_TERM nsetopt_lvl_sock_bindtodevice(ErlNifEnv* env, ERL_NIF_TERM eVal) { return nsetopt_str_opt(env, descP, - SOL_SOCKET, SO_BROADCAST, + SOL_SOCKET, SO_BINDTODEVICE, IFNAMSIZ, eVal); } #endif -- cgit v1.2.3 From 76b8f794ce7192bde3a8e112cd6534320a7d6a2b Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Thu, 18 Jul 2019 16:43:39 +0200 Subject: [esock|test] Update the bindtodevice test case Handle the eperm error reason that can be returned when attempting to use 'bindtodevice'. OTP-15904 --- erts/emulator/test/socket_SUITE.erl | 40 ++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) (limited to 'erts') diff --git a/erts/emulator/test/socket_SUITE.erl b/erts/emulator/test/socket_SUITE.erl index 8ef27b1d04..91ce723afa 100644 --- a/erts/emulator/test/socket_SUITE.erl +++ b/erts/emulator/test/socket_SUITE.erl @@ -8825,7 +8825,6 @@ api_opt_sock_acceptconn() -> ], - i("get multicast address"), Domain = inet, i("start tester evaluator"), @@ -8987,11 +8986,15 @@ api_opt_sock_bindtodevice() -> ?SEV_SLEEP(?SECS(1)), #{desc => "Bind UDP socket 1 to device", - cmd => fun(#{usock1 := Sock, dev := Dev} = _State) -> + 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 @@ -9009,11 +9012,19 @@ api_opt_sock_bindtodevice() -> end end}, #{desc => "Bind TCP socket 1 to device", - cmd => fun(#{tsock1 := Sock, dev := Dev} = _State) -> + 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 @@ -9034,7 +9045,10 @@ api_opt_sock_bindtodevice() -> ?SEV_SLEEP(?SECS(1)), #{desc => "[get] verify UDP socket 1 (after bindtodevice)", - cmd => fun(#{usock1 := Sock} = _State) -> + 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]), @@ -9056,7 +9070,10 @@ api_opt_sock_bindtodevice() -> end end}, #{desc => "[get] verify TCP socket 1 (after bindtodevice)", - cmd => fun(#{tsock1 := Sock} = _State) -> + 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]), @@ -9082,7 +9099,10 @@ api_opt_sock_bindtodevice() -> %% *** Termination *** #{desc => "close UDP socket 1", - cmd => fun(#{usock1 := Sock} = State) -> + 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}, @@ -9092,7 +9112,10 @@ api_opt_sock_bindtodevice() -> {ok, maps:remove(usock2, State)} end}, #{desc => "close TCP socket 1", - cmd => fun(#{tsock1 := Sock} = State) -> + 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}, @@ -9106,7 +9129,6 @@ api_opt_sock_bindtodevice() -> ?SEV_FINISH_NORMAL ], - i("get multicast address"), Domain = inet, i("start tester evaluator"), @@ -10203,8 +10225,8 @@ api_opt_ip_add_drop_membership() -> ], - i("get multicast address"), Domain = inet, + i("get multicast address"), MAddr = which_ip_multicast_address(), MSA = #{family => Domain, addr => MAddr}, -- cgit v1.2.3 From 9f577b0e6255240a32ec0debb28cb7638e4cd31a Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Thu, 18 Jul 2019 16:54:39 +0200 Subject: [esock|test] Add two placeholder test cases: error and linger Added two place holder test cases for the socket options error and linger. OTP-15904 --- erts/emulator/test/socket_SUITE.erl | 38 ++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) (limited to 'erts') diff --git a/erts/emulator/test/socket_SUITE.erl b/erts/emulator/test/socket_SUITE.erl index 91ce723afa..ed674eb335 100644 --- a/erts/emulator/test/socket_SUITE.erl +++ b/erts/emulator/test/socket_SUITE.erl @@ -128,7 +128,9 @@ 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 *** @@ -795,7 +797,9 @@ api_options_socket_cases() -> api_opt_sock_debug, api_opt_sock_domain, api_opt_sock_dontroute, - api_opt_sock_keepalive + api_opt_sock_error, + api_opt_sock_keepalive, + api_opt_sock_linger ]. api_options_ip_cases() -> @@ -9857,6 +9861,22 @@ api_opt_sock_dontroute() -> +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% 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. @@ -9985,6 +10005,22 @@ api_opt_sock_keepalive() -> +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% 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. -- cgit v1.2.3 From 47f5bd6f2b65668588383021f80f51984dfee63d Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Mon, 22 Jul 2019 13:46:30 +0200 Subject: [esock|test] Split the acceptconn test case into two The socket acceptconn test case has been split into two, one for UDP and one for TCP. OTP-15904 --- erts/emulator/test/socket_SUITE.erl | 326 +++++++++++++++++++++--------------- 1 file changed, 188 insertions(+), 138 deletions(-) (limited to 'erts') diff --git a/erts/emulator/test/socket_SUITE.erl b/erts/emulator/test/socket_SUITE.erl index ed674eb335..9bf7084e95 100644 --- a/erts/emulator/test/socket_SUITE.erl +++ b/erts/emulator/test/socket_SUITE.erl @@ -121,7 +121,8 @@ api_opt_simple_otp_options/1, api_opt_simple_otp_rcvbuf_option/1, api_opt_simple_otp_controlling_process/1, - api_opt_sock_acceptconn/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, @@ -623,85 +624,86 @@ use_group(Group, Env, Default) -> 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_options_ip, [], api_options_ip_cases()}, + [{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()} + {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()} ]. @@ -774,7 +776,7 @@ api_options_cases() -> [ {group, api_options_otp}, {group, api_options_socket}, - {group, api_options_ip}%% , + {group, api_options_ip}% , %% {group, api_options_ipv6}, %% {group, api_options_tcp}, %% {group, api_options_udp}, @@ -790,7 +792,9 @@ api_options_otp_cases() -> api_options_socket_cases() -> [ - api_opt_sock_acceptconn, + {group, api_option_sock_acceptconn}, + %% api_opt_sock_acceptconn_udp, + %% api_opt_sock_acceptconn_tcp, api_opt_sock_acceptfilter, api_opt_sock_bindtodevice, api_opt_sock_broadcast, @@ -802,6 +806,12 @@ api_options_socket_cases() -> 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 @@ -8379,24 +8389,24 @@ api_opt_simple_otp_controlling_process() -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% Tests the socket option acceptcon. This should be possible to get -%% but not set. +%% Tests the socket option acceptconn for UDP. +%% This should be possible to get but not set. -api_opt_sock_acceptconn(suite) -> +api_opt_sock_acceptconn_udp(suite) -> []; -api_opt_sock_acceptconn(doc) -> +api_opt_sock_acceptconn_udp(doc) -> []; -api_opt_sock_acceptconn(_Config) when is_list(_Config) -> +api_opt_sock_acceptconn_udp(_Config) when is_list(_Config) -> ?TT(?SECS(30)), - tc_try(api_opt_sock_acceptconn, + tc_try(api_opt_sock_acceptconn_udp, fun() -> has_support_sock_acceptconn() end, - fun() -> api_opt_sock_acceptconn() end). + fun() -> api_opt_sock_acceptconn_udp() end). -api_opt_sock_acceptconn() -> +api_opt_sock_acceptconn_udp() -> Opt = acceptconn, Set = fun(S, Val) -> socket:setopt(S, socket, Opt, Val) @@ -8412,7 +8422,7 @@ api_opt_sock_acceptconn() -> LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, - #{desc => "create UDP socket", + #{desc => "create socket", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, dgram, udp) of {ok, Sock} -> @@ -8422,8 +8432,8 @@ api_opt_sock_acceptconn() -> end end}, - #{desc => "[get] verify UDP socket (before bind)", - cmd => fun(#{sock := Sock} = State) -> + #{desc => "[get] verify socket (before bind)", + cmd => fun(#{sock := Sock} = _State) -> case Get(Sock) of {ok, false} -> ?SEV_IPRINT("Expected Success: " @@ -8437,20 +8447,17 @@ api_opt_sock_acceptconn() -> %% On some platforms this is not accepted %% for UDP, so skip this part (UDP). ?SEV_EPRINT("Expected Failure: " - "~p => SKIP UDP", [Reason]), + "~p => SKIP", [Reason]), (catch socket:close(Sock)), - {ok, State#{sock => skip}}; + {skip, Reason}; {error, Reason} = ERROR -> ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), ERROR end end}, - #{desc => "[set] verify UDP socket (before bind)", - cmd => fun(#{sock := skip} = _State) -> - ?SEV_IPRINT("SKIP'ed"), - ok; - (#{sock := Sock} = _State) -> + #{desc => "[set] verify socket (before bind)", + cmd => fun(#{sock := Sock} = _State) -> case Set(Sock, true) of {error, Reason} -> ?SEV_IPRINT("Expected Failure: ~p", @@ -8463,11 +8470,8 @@ api_opt_sock_acceptconn() -> end end}, - #{desc => "bind UDP socket to local address", - cmd => fun(#{sock := skip} = _State) -> - ?SEV_IPRINT("SKIP'ed"), - ok; - (#{sock := Sock, local_sa := LSA} = _State) -> + #{desc => "bind socket to local address", + cmd => fun(#{sock := Sock, local_sa := LSA} = _State) -> case socket:bind(Sock, LSA) of {ok, _} -> ok; @@ -8478,11 +8482,8 @@ api_opt_sock_acceptconn() -> ?SEV_SLEEP(?SECS(1)), - #{desc => "[get] verify UDP socket (after bind)", - cmd => fun(#{sock := skip} = _State) -> - ?SEV_IPRINT("SKIP'ed"), - ok; - (#{sock := Sock} = _State) -> + #{desc => "[get] verify socket (after bind)", + cmd => fun(#{sock := Sock} = _State) -> case Get(Sock) of {ok, false} -> ?SEV_IPRINT("Expected Success: " @@ -8498,11 +8499,8 @@ api_opt_sock_acceptconn() -> ERROR end end}, - #{desc => "[set] verify UDP socket (after bind)", - cmd => fun(#{sock := skip} = _State) -> - ?SEV_IPRINT("SKIP'ed"), - ok; - (#{sock := Sock} = _State) -> + #{desc => "[set] verify socket (after bind)", + cmd => fun(#{sock := Sock} = _State) -> case Set(Sock, true) of {error, Reason} -> ?SEV_IPRINT("Expected Failure: ~p", @@ -8515,18 +8513,65 @@ api_opt_sock_acceptconn() -> end end}, - #{desc => "close UDP socket", - cmd => fun(#{sock := skip} = State) -> - ?SEV_IPRINT("SKIP'ed (already closed)"), - {ok, maps:remove(sock, State)}; - (#{sock := Sock} = State) -> + %% *** Termination *** + #{desc => "close socket", + cmd => fun(#{sock := Sock} = State) -> socket:close(Sock), {ok, maps:remove(sock, State)} end}, - ?SEV_SLEEP(?SECS(1)), + %% *** 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]). - #{desc => "create TCP listen socket", + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% 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} -> @@ -8536,7 +8581,7 @@ api_opt_sock_acceptconn() -> end end}, - #{desc => "[get] verify TCP listen socket (before bind)", + #{desc => "[get] verify listen socket (before bind)", cmd => fun(#{lsock := Sock} = _State) -> case Get(Sock) of {ok, false} -> @@ -8547,13 +8592,18 @@ api_opt_sock_acceptconn() -> ?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 TCP listen socket (before bind)", + #{desc => "[set] verify listen socket (before bind)", cmd => fun(#{lsock := Sock} = _State) -> case Set(Sock, true) of {error, Reason} -> @@ -8568,7 +8618,7 @@ api_opt_sock_acceptconn() -> ?SEV_SLEEP(?SECS(1)), - #{desc => "bind TCP listen socket to local address", + #{desc => "bind listen socket to local address", cmd => fun(#{lsock := Sock, local_sa := LSA} = State) -> case socket:bind(Sock, LSA) of {ok, Port} -> @@ -8578,7 +8628,7 @@ api_opt_sock_acceptconn() -> end end}, - #{desc => "[get] verify TCP listen socket (after bind)", + #{desc => "[get] verify listen socket (after bind)", cmd => fun(#{lsock := Sock} = _State) -> case Get(Sock) of {ok, false} -> @@ -8594,7 +8644,7 @@ api_opt_sock_acceptconn() -> ERROR end end}, - #{desc => "[set] verify TCP listen socket (after bind)", + #{desc => "[set] verify listen socket (after bind)", cmd => fun(#{lsock := Sock} = _State) -> case Set(Sock, true) of {error, Reason} -> @@ -8609,7 +8659,7 @@ api_opt_sock_acceptconn() -> ?SEV_SLEEP(?SECS(1)), - #{desc => "make TCP listen socket accept connections", + #{desc => "make listen socket accept connections", cmd => fun(#{lsock := Sock} = _State) -> case socket:listen(Sock) of ok -> @@ -8619,7 +8669,7 @@ api_opt_sock_acceptconn() -> end end}, - #{desc => "[get] verify TCP listen socket (after listen)", + #{desc => "[get] verify listen socket (after listen)", cmd => fun(#{lsock := Sock} = _State) -> case Get(Sock) of {ok, true} -> @@ -8635,7 +8685,7 @@ api_opt_sock_acceptconn() -> ERROR end end}, - #{desc => "[set] verify TCP listen socket (after listen)", + #{desc => "[set] verify listen socket (after listen)", cmd => fun(#{lsock := Sock} = _State) -> case Set(Sock, false) of {error, Reason} -> @@ -8650,7 +8700,7 @@ api_opt_sock_acceptconn() -> ?SEV_SLEEP(?SECS(1)), - #{desc => "create TCP (connecting) socket", + #{desc => "create (connecting) socket", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, stream, tcp) of {ok, Sock} -> @@ -8660,7 +8710,7 @@ api_opt_sock_acceptconn() -> end end}, - #{desc => "bind TCP connecting socket to local address", + #{desc => "bind connecting socket to local address", cmd => fun(#{csockc := Sock, local_sa := LSA} = _State) -> case socket:bind(Sock, LSA) of {ok, _Port} -> @@ -8672,7 +8722,7 @@ api_opt_sock_acceptconn() -> ?SEV_SLEEP(?SECS(1)), - #{desc => "[get] verify TCP connecting socket (before connect)", + #{desc => "[get] verify connecting socket (before connect)", cmd => fun(#{csockc := Sock} = _State) -> case Get(Sock) of {ok, false} -> @@ -8688,7 +8738,7 @@ api_opt_sock_acceptconn() -> ERROR end end}, - #{desc => "[set] verify TCP connecting socket (before connect)", + #{desc => "[set] verify connecting socket (before connect)", cmd => fun(#{csockc := Sock} = _State) -> case Set(Sock, true) of {error, Reason} -> @@ -8723,7 +8773,7 @@ api_opt_sock_acceptconn() -> end end}, - #{desc => "[get] verify TCP connecting socket (after connect)", + #{desc => "[get] verify connecting socket (after connect)", cmd => fun(#{csockc := Sock} = _State) -> case Get(Sock) of {ok, false} -> @@ -8739,7 +8789,7 @@ api_opt_sock_acceptconn() -> ERROR end end}, - #{desc => "[set] verify TCP connecting socket (after connect)", + #{desc => "[set] verify connecting socket (after connect)", cmd => fun(#{csockc := Sock} = _State) -> case Set(Sock, true) of {error, Reason} -> @@ -8752,7 +8802,7 @@ api_opt_sock_acceptconn() -> end end}, - #{desc => "[get] verify TCP connected socket", + #{desc => "[get] verify connected socket", cmd => fun(#{csocks := Sock} = _State) -> case Get(Sock) of {ok, false} -> @@ -8768,7 +8818,7 @@ api_opt_sock_acceptconn() -> ERROR end end}, - #{desc => "[set] verify TCP connected socket", + #{desc => "[set] verify connected socket", cmd => fun(#{csocks := Sock} = _State) -> case Set(Sock, true) of {error, Reason} -> @@ -8781,7 +8831,7 @@ api_opt_sock_acceptconn() -> end end}, - #{desc => "[get] verify TCP listen socket (after connect)", + #{desc => "[get] verify listen socket (after connect)", cmd => fun(#{lsock := Sock} = _State) -> case Get(Sock) of {ok, true} -> @@ -8797,7 +8847,7 @@ api_opt_sock_acceptconn() -> ERROR end end}, - #{desc => "[set] verify TCP listen socket (after connect)", + #{desc => "[set] verify listen socket (after connect)", cmd => fun(#{lsock := Sock} = _State) -> case Set(Sock, false) of {error, Reason} -> @@ -8811,14 +8861,14 @@ api_opt_sock_acceptconn() -> end}, %% *** Termination *** - #{desc => "close TCP connecting socket(s)", + #{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 TCP listen socket", + #{desc => "close listen socket", cmd => fun(#{lsock := Sock} = State) -> socket:close(Sock), {ok, maps:remove(lsock, State)} -- cgit v1.2.3 From d8260be31109f3b9989c4987cea23de83de4e159 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Tue, 23 Jul 2019 16:35:47 +0200 Subject: [esock|test] Changing 'dontroute' may not be allowed If we are not allowe to change ('eopnotsupp') the socket option 'dontroute' then we skip the test case. OTP-15904 --- erts/emulator/test/socket_SUITE.erl | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'erts') diff --git a/erts/emulator/test/socket_SUITE.erl b/erts/emulator/test/socket_SUITE.erl index 9bf7084e95..4e3db11bbe 100644 --- a/erts/emulator/test/socket_SUITE.erl +++ b/erts/emulator/test/socket_SUITE.erl @@ -9790,11 +9790,12 @@ api_opt_sock_domain() -> %% 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 +%% 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), we only test if we -%% can set and get the value. Better then nothing. +%% 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) -> []; @@ -9869,6 +9870,10 @@ api_opt_sock_dontroute() -> 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]), -- cgit v1.2.3 From cc40b9c9a0135837ce12eb3eade8beedf6c58713 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Wed, 24 Jul 2019 13:10:01 +0200 Subject: [esock|test] Make some skip reasons more readable OTP-15904 --- erts/emulator/test/socket_SUITE.erl | 49 +++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 21 deletions(-) (limited to 'erts') diff --git a/erts/emulator/test/socket_SUITE.erl b/erts/emulator/test/socket_SUITE.erl index 4e3db11bbe..f2dc4869f4 100644 --- a/erts/emulator/test/socket_SUITE.erl +++ b/erts/emulator/test/socket_SUITE.erl @@ -564,22 +564,25 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --define(BASIC_REQ, <<"hejsan">>). --define(BASIC_REP, <<"hoppsan">>). +-define(LIB, socket_test_lib). +-define(TTEST_LIB, socket_test_ttest_lib). +-define(LOGGER, socket_test_logger). --define(DATA, <<"HOPPSAN">>). % Temporary --define(FAIL(R), exit(R)). +-define(BASIC_REQ, <<"hejsan">>). +-define(BASIC_REP, <<"hoppsan">>). --define(SLEEP(T), receive after T -> ok end). +-define(DATA, <<"HOPPSAN">>). % Temporary +-define(FAIL(R), exit(R)). --define(MINS(M), timer:minutes(M)). --define(SECS(S), timer:seconds(S)). +-define(SLEEP(T), receive after T -> ok end). --define(TT(T), ct:timetrap(T)). +-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(LIB, socket_test_lib). --define(TTEST_LIB, socket_test_ttest_lib). --define(LOGGER, socket_test_logger). -define(TPP_SMALL, lists:seq(1, 8)). -define(TPP_MEDIUM, lists:flatten(lists:duplicate(1024, ?TPP_SMALL))). @@ -793,8 +796,6 @@ api_options_otp_cases() -> api_options_socket_cases() -> [ {group, api_option_sock_acceptconn}, - %% api_opt_sock_acceptconn_udp, - %% api_opt_sock_acceptconn_tcp, api_opt_sock_acceptfilter, api_opt_sock_bindtodevice, api_opt_sock_broadcast, @@ -20199,12 +20200,14 @@ traffic_ping_pong_send_and_receive_tcp(#{msg := Msg} = InitState) -> ?SEV_IPRINT("RcvBuf is ~p (needs atleast ~p)", [RcvSz, 16+size(Msg)]), if (RcvSz < size(Msg)) -> - case socket:setopt(Sock, - socket, rcvbuf, 1024+size(Msg)) of + NewRcvSz = 1024+size(Msg), + case socket:setopt(Sock, socket, rcvbuf, NewRcvSz) of ok -> ok; {error, enobufs} -> - skip({failed_change, rcvbuf}); + skip(?F("Change ~w buffer size (to ~w) " + "not allowed", + [rcvbuf, NewRcvSz])); {error, Reason1} -> ?FAIL({rcvbuf, Reason1}) end; @@ -20215,12 +20218,14 @@ traffic_ping_pong_send_and_receive_tcp(#{msg := Msg} = InitState) -> ?SEV_IPRINT("SndBuf is ~p (needs atleast ~p)", [SndSz, 16+size(Msg)]), if (SndSz < size(Msg)) -> - case socket:setopt(Sock, - socket, sndbuf, 1024+size(Msg)) of + NewSndSz = 1024+size(Msg), + case socket:setopt(Sock, socket, sndbuf, NewSndSz) of ok -> ok; {error, enobufs} -> - skip({failed_change, sndbuf}); + skip(?F("Change ~w buffer size (to ~w) " + "not allowed", + [sndbuf, NewSndSz])); {error, Reason2} -> ?FAIL({sndbuf, Reason2}) end; @@ -28804,8 +28809,10 @@ has_support_ip_multicast() -> {error, Reason} -> not_supported({multicast, Reason}) end; + {unix, OsName} -> + skip(?F("Not Supported: platform ~w", [OsName])); Type -> - not_supported({multicast, Type}) + skip(?F("Not Supported: platform ~p", [Type])) end. has_support_sock_acceptconn() -> @@ -28859,7 +28866,7 @@ has_support_socket_option(Level, Option) -> true -> ok; false -> - not_supported({options, Level, Option}) + skip(?F("Not Supported: ~w option ~w", [Level, Option])) end. -- cgit v1.2.3 From 7f89eba6a8f61868f8e515c763c2cae5ef16664e Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Wed, 24 Jul 2019 16:02:02 +0200 Subject: [esock|test] Moved include file (to its proper place) OTP-15904 --- erts/emulator/test/socket_SUITE.erl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'erts') diff --git a/erts/emulator/test/socket_SUITE.erl b/erts/emulator/test/socket_SUITE.erl index f2dc4869f4..62e770b339 100644 --- a/erts/emulator/test/socket_SUITE.erl +++ b/erts/emulator/test/socket_SUITE.erl @@ -58,6 +58,7 @@ -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]). @@ -556,8 +557,6 @@ ]). --include("socket_test_evaluator.hrl"). - %% Internal exports %% -export([]). -- cgit v1.2.3 From d48d2e6b914582df5fb589113fc4201c64806591 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Mon, 29 Jul 2019 14:55:53 +0200 Subject: [esock|test] Race during socket close Add a sleep to reduce the chance that process exit has not been "processed" by the nif code. Also increased the test case timetrap for the sc_ctrl_proc_exit group of test cases. OTP-15904 --- erts/emulator/test/socket_SUITE.erl | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'erts') diff --git a/erts/emulator/test/socket_SUITE.erl b/erts/emulator/test/socket_SUITE.erl index 62e770b339..ff5a4e7e2e 100644 --- a/erts/emulator/test/socket_SUITE.erl +++ b/erts/emulator/test/socket_SUITE.erl @@ -12156,7 +12156,7 @@ sc_cpe_socket_cleanup_tcp4(suite) -> sc_cpe_socket_cleanup_tcp4(doc) -> []; sc_cpe_socket_cleanup_tcp4(_Config) when is_list(_Config) -> - ?TT(?SECS(5)), + ?TT(?SECS(30)), tc_try(sc_cpe_socket_cleanup_tcp4, fun() -> InitState = #{domain => inet, @@ -12176,7 +12176,7 @@ sc_cpe_socket_cleanup_tcp6(suite) -> sc_cpe_socket_cleanup_tcp6(doc) -> []; sc_cpe_socket_cleanup_tcp6(_Config) when is_list(_Config) -> - ?TT(?SECS(5)), + ?TT(?SECS(30)), tc_try(sc_cpe_socket_cleanup_tcp6, fun() -> has_support_ipv6() end, fun() -> @@ -12197,7 +12197,7 @@ sc_cpe_socket_cleanup_tcpL(suite) -> sc_cpe_socket_cleanup_tcpL(doc) -> []; sc_cpe_socket_cleanup_tcpL(_Config) when is_list(_Config) -> - ?TT(?SECS(5)), + ?TT(?SECS(30)), tc_try(sc_cpe_socket_cleanup_tcpL, fun() -> has_support_unix_domain_socket() end, fun() -> @@ -12218,7 +12218,7 @@ sc_cpe_socket_cleanup_udp4(suite) -> sc_cpe_socket_cleanup_udp4(doc) -> []; sc_cpe_socket_cleanup_udp4(_Config) when is_list(_Config) -> - ?TT(?SECS(5)), + ?TT(?SECS(30)), tc_try(sc_cpe_socket_cleanup_udp4, fun() -> InitState = #{domain => inet, @@ -12239,7 +12239,7 @@ sc_cpe_socket_cleanup_udp6(suite) -> sc_cpe_socket_cleanup_udp6(doc) -> []; sc_cpe_socket_cleanup_udp6(_Config) when is_list(_Config) -> - ?TT(?SECS(5)), + ?TT(?SECS(30)), tc_try(sc_cpe_socket_cleanup_udp6, fun() -> has_support_ipv6() end, fun() -> @@ -12260,7 +12260,7 @@ sc_cpe_socket_cleanup_udpL(suite) -> sc_cpe_socket_cleanup_udpL(doc) -> []; sc_cpe_socket_cleanup_udpL(_Config) when is_list(_Config) -> - ?TT(?SECS(5)), + ?TT(?SECS(30)), tc_try(sc_cpe_socket_cleanup_udpL, fun() -> has_support_unix_domain_socket() end, fun() -> @@ -12366,8 +12366,15 @@ sc_cpe_socket_cleanup(InitState) -> 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 -- cgit v1.2.3