From b98a1e312db1393aa5dd9cdd2e1a5f3daaf954bf Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Thu, 4 Oct 2018 18:16:38 +0200 Subject: [socket-nif|test] begin rework socket suite Begin rework socket test suite using a command evaluator. OTP-14831 --- lib/kernel/test/socket_SUITE.erl | 222 ++++++++++++++++++++++++++++++++++----- 1 file changed, 198 insertions(+), 24 deletions(-) (limited to 'lib') diff --git a/lib/kernel/test/socket_SUITE.erl b/lib/kernel/test/socket_SUITE.erl index 1fff17cf8c..70810f5f3d 100644 --- a/lib/kernel/test/socket_SUITE.erl +++ b/lib/kernel/test/socket_SUITE.erl @@ -71,6 +71,17 @@ %% -export([]). +-type evaluator_state() :: term(). +-type command_fun() :: + fun((State :: evaluator_state()) -> ok) | + fun((State :: evaluator_state()) -> {ok, evaluator_state()}) | + fun((State :: evaluator_state()) -> {error, term()}). + +-type command() :: #{desc := string(), + cmd := command_fun() + }. + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -define(BASIC_REQ, <<"hejsan">>). @@ -178,7 +189,10 @@ api_b_open_and_close_udp4(doc) -> []; api_b_open_and_close_udp4(_Config) when is_list(_Config) -> tc_begin(api_b_open_and_close_udp4), - ok = api_b_open_and_close(inet, dgram, udp), + State = #{domain => inet, + type => dgram, + protocol => udp}, + ok = api_b_open_and_close(State), tc_end(). @@ -192,34 +206,103 @@ api_b_open_and_close_tcp4(doc) -> []; api_b_open_and_close_tcp4(_Config) when is_list(_Config) -> tc_begin(api_b_open_and_close_tcp4), - ok = api_b_open_and_close(inet, stream, tcp), + State = #{domain => inet, + type => stream, + protocol => tcp}, + ok = api_b_open_and_close(State), tc_end(). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -api_b_open_and_close(Domain, Type, Proto) -> - Socket = case socket:open(Domain, Type, Proto) of - {ok, S} -> - S; - {error, Reason} -> - ?FAIL({open, Reason}) - end, - %% Domain is not available on all platforms: - case socket:getopt(Socket, socket, domain) of - {ok, Domain} -> - ok; - {error, einval} -> - ok; - Else -> - ?FAIL({getopt, domain, Else}) - end, - {ok, Type} = socket:getopt(Socket, socket, type), - {ok, Proto} = socket:getopt(Socket, socket, protocol), - Self = self(), - {ok, Self} = socket:getopt(Socket, otp, controlling_process), - ok = socket:close(Socket), - ok. +api_b_open_and_close(InitState) -> + Seq = + [ + #{desc => "open", + cmd => fun(#{domain := Domain, + type := Type, + protocol := Protocol} = S) -> + Res = socket:open(Domain, Type, Protocol), + {ok, {S, Res}} + end}, + #{desc => "validate open", + cmd => fun({S, {ok, Sock}}) -> + NewS = S#{socket => Sock}, + {ok, NewS}; + ({_, {error, _} = ERROR}) -> + ERROR + end}, + #{desc => "get domain (maybe)", + cmd => fun(#{socket := Sock} = S) -> + Res = socket:getopt(Sock, socket, domain), + {ok, {S, Res}} + end}, + #{desc => "validate domain (maybe)", + cmd => fun({#{domain := Domain} = S, {ok, Domain}}) -> + {ok, S}; + ({#{domain := ExpDomain}, {ok, Domain}}) -> + {error, {unexpected_domain, ExpDomain, Domain}}; + %% Some platforms do not support this option + ({S, {error, einval}}) -> + {ok, S}; + ({_, {error, _} = ERROR}) -> + ERROR + end}, + #{desc => "get type", + cmd => fun(#{socket := Sock} = State) -> + Res = socket:getopt(Sock, socket, type), + {ok, {State, Res}} + end}, + #{desc => "validate type", + cmd => fun({#{type := Type} = State, {ok, Type}}) -> + {ok, State}; + ({#{type := ExpType}, {ok, Type}}) -> + {error, {unexpected_type, ExpType, Type}}; + ({_, {error, _} = ERROR}) -> + ERROR + end}, + #{desc => "get protocol", + cmd => fun(#{socket := Sock} = State) -> + Res = socket:getopt(Sock, socket, protocol), + {ok, {State, Res}} + end}, + #{desc => "validate protocol", + cmd => fun({#{protocol := Protocol} = State, {ok, Protocol}}) -> + {ok, State}; + ({#{protocol := ExpProtocol}, {ok, Protocol}}) -> + {error, {unexpected_type, ExpProtocol, Protocol}}; + ({_, {error, _} = ERROR}) -> + ERROR + end}, + #{desc => "get controlling-process", + cmd => fun(#{socket := Sock} = State) -> + Res = socket:getopt(Sock, otp, controlling_process), + {ok, {State, Res}} + end}, + #{desc => "validate controlling-process", + cmd => fun({State, {ok, Pid}}) -> + case self() of + Pid -> + {ok, State}; + _ -> + {error, {unexpected_owner, Pid}} + end; + ({_, {error, _} = ERROR}) -> + ERROR + end}, + #{desc => "close socket", + cmd => fun(#{socket := Sock} = State) -> + Res = socket:close(Sock), + {ok, {State, Res}} + end}, + #{desc => "validate socket close", + cmd => fun({_, ok}) -> + {ok, normal}; + ({_, {error, _} = ERROR}) -> + ERROR + end}], + Evaluator = evaluator_start("tester", Seq, InitState), + ok = await_evaluator_finish([Evaluator]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1230,6 +1313,97 @@ which_addr2(Domain, [_|IFO]) -> +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% An evaluator is a process that executes a command sequence. +%% A test case will consist of atleast one evaluator (one for +%% each actor). +%% The evaluator process *always* run locally. Which means that +%% it will act as a "proxy" for remote nodes in necessary. +%% When the command sequence has been processed, the final state +%% will be used as exit reason. +%% A successful command shall evaluate to ok | {ok, NewState} + +-spec evaluator_start(Name, Seq, Init) -> {Pid, MRef} when + Name :: string(), + Seq :: [command()], + Init :: evaluator_state(), + Pid :: pid(), + MRef :: reference(). + +evaluator_start(Name, Seq, Init) + when is_list(Name) andalso is_list(Seq) andalso (Seq =/= []) -> + erlang:spawn_monitor(fun() -> evaluator_init(Name, Seq, Init) end). + +evaluator_init(Name, Seq, Init) -> + put(sname, Name), + evaluator_loop(1, Seq, Init). + +evaluator_loop(_ID, [], FinalState) -> + exit(FinalState); +evaluator_loop(ID, [#{desc := Desc, + cmd := Cmd}|Cmds], State) when is_function(Cmd, 1) -> + ei("evaluate command ~2w: ~s", [ID, Desc]), + try Cmd(State) of + ok -> + evaluator_loop(ID + 1, Cmds, State); + {ok, NewState} -> + evaluator_loop(ID + 1, Cmds, NewState); + {error, Reason} -> + ee("command ~w failed: " + "~n Reason: ~p", [ID, Reason]), + exit({command_failed, ID, Reason, State}) + catch + C:E:S -> + ee("command ~w crashed: " + "~n Class: ~p" + "~n Error: ~p" + "~n Call Stack: ~p", [ID, C, E, S]), + exit({command_crashed, ID, {C,E,S}, State}) + end. + +await_evaluator_finish(Evs) -> + await_evaluator_finish(Evs, []). + +await_evaluator_finish([], []) -> + ok; +await_evaluator_finish([], Fails) -> + Fails; +await_evaluator_finish(Evs, Fails) -> + receive + {'DOWN', _MRef, process, Pid, normal} -> + case lists:keydelete(Pid, 1, Evs) of + Evs -> + p("unknown process ~p died (normal)", [Pid]), + await_evaluator_finish(Evs, Fails); + NewEvs -> + p("evaluator ~p success", [Pid]), + await_evaluator_finish(NewEvs, Fails) + end; + {'DOWN', _MRef, process, Pid, Reason} -> + case lists:keydelete(Pid, 1, Evs) of + Evs -> + p("unknown process ~p died: " + "~n ~p", [Pid, Reason]), + await_evaluator_finish(Evs, Fails); + NewEvs -> + p("Evaluator ~p failed", [Pid]), + await_evaluator_finish(NewEvs, [{Pid, Reason}|Fails]) + end + end. + + +ei(F, A) -> + eprint("", F, A). + +ee(F, A) -> + eprint(" ", F, A). + +eprint(Prefix, F, A) -> + io:format(user, "[~s][~p] ~s" ++ F ++ "~n", [get(sname), self(), Prefix | A]). + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% sock_open(Domain, Type, Proto) -> -- cgit v1.2.3 From 8210ffc460a0bfab8b3007afe3e1141c1bb9dec6 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Fri, 5 Oct 2018 11:07:55 +0200 Subject: [socket-nif|test] Two more test cases (udp) reworked Two test cases where reworked using the command evaluator. OTP-14831 --- lib/kernel/test/socket_SUITE.erl | 111 +++++++++++++++++++++++++++++++++------ 1 file changed, 94 insertions(+), 17 deletions(-) (limited to 'lib') diff --git a/lib/kernel/test/socket_SUITE.erl b/lib/kernel/test/socket_SUITE.erl index 70810f5f3d..ed5722f008 100644 --- a/lib/kernel/test/socket_SUITE.erl +++ b/lib/kernel/test/socket_SUITE.erl @@ -305,6 +305,7 @@ api_b_open_and_close(InitState) -> ok = await_evaluator_finish([Evaluator]). + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically send and receive on an IPv4 UDP (dgram) socket using @@ -321,7 +322,10 @@ api_b_sendto_and_recvfrom_udp4(_Config) when is_list(_Config) -> Recv = fun(Sock) -> socket:recvfrom(Sock) end, - ok = api_b_send_and_recv_udp(inet, Send, Recv), + InitState = #{domain => inet, + send => Send, + recv => Recv}, + ok = api_b_send_and_recv_udp(InitState), tc_end(). @@ -352,27 +356,100 @@ api_b_sendmsg_and_recvmsg_udp4(_Config) when is_list(_Config) -> ERROR end end, - ok = api_b_send_and_recv_udp(inet, Send, Recv), + InitState = #{domain => inet, + send => Send, + recv => Recv}, + ok = api_b_send_and_recv_udp(InitState), tc_end(). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -api_b_send_and_recv_udp(Domain, Send, Recv) -> - SockSrc = sock_open(Domain, dgram, udp), - LAddr = which_local_addr(Domain), - LSA = #{family => Domain, addr => LAddr}, - sock_bind(SockSrc, LSA), - SockDst = sock_open(Domain, dgram, udp), - sock_bind(SockDst, LSA), - Dst = sock_sockname(SockDst), - ok = Send(SockSrc, ?BASIC_REQ, Dst), - {ok, {Src, ?BASIC_REQ}} = Recv(SockDst), - ok = Send(SockDst, ?BASIC_REP, Src), - {ok, {Dst, ?BASIC_REP}} = Recv(SockSrc), - socket:close(SockSrc), - socket:close(SockDst), - ok. +api_b_send_and_recv_udp(InitState) -> + %% SockSrc = sock_open(Domain, dgram, udp), + %% LAddr = which_local_addr(Domain), + %% LSA = #{family => Domain, addr => LAddr}, + %% sock_bind(SockSrc, LSA), + %% SockDst = sock_open(Domain, dgram, udp), + %% sock_bind(SockDst, LSA), + %% Dst = sock_sockname(SockDst), + %% ok = Send(SockSrc, ?BASIC_REQ, Dst), + %% {ok, {Src, ?BASIC_REQ}} = Recv(SockDst), + %% ok = Send(SockDst, ?BASIC_REP, Src), + %% {ok, {Dst, ?BASIC_REP}} = Recv(SockSrc), + %% socket:close(SockSrc), + %% socket:close(SockDst), + Seq = + [ + #{desc => "local address", + cmd => fun(#{domain := Domain} = State) -> + LAddr = which_local_addr(Domain), + LSA = #{family => Domain, addr => LAddr}, + {ok, State#{lsa => LSA}} + end}, + #{desc => "open src socket", + cmd => fun(#{domain := Domain} = State) -> + Sock = sock_open(Domain, dgram, udp), + SASrc = sock_sockname(Sock), + {ok, State#{sock_src => Sock, sa_src => SASrc}} + end}, + #{desc => "bind src", + cmd => fun(#{sock_src := Sock, lsa := LSA}) -> + sock_bind(Sock, LSA), + ok + end}, + #{desc => "sockname src socket", + cmd => fun(#{sock_src := Sock} = State) -> + SASrc = sock_sockname(Sock), + %% ei("src sockaddr: ~p", [SASrc]), + {ok, State#{sa_src => SASrc}} + end}, + #{desc => "open dst socket", + cmd => fun(#{domain := Domain} = State) -> + Sock = sock_open(Domain, dgram, udp), + {ok, State#{sock_dst => Sock}} + end}, + #{desc => "bind dst", + cmd => fun(#{sock_dst := Sock, lsa := LSA}) -> + sock_bind(Sock, LSA), + ok + end}, + #{desc => "sockname dst socket", + cmd => fun(#{sock_dst := Sock} = State) -> + SADst = sock_sockname(Sock), + %% ei("dst sockaddr: ~p", [SADst]), + {ok, State#{sa_dst => SADst}} + end}, + #{desc => "send req (to dst)", + cmd => fun(#{sock_src := Sock, sa_dst := Dst, send := Send}) -> + ok = Send(Sock, ?BASIC_REQ, Dst) + end}, + #{desc => "recv req (from src)", + cmd => fun(#{sock_dst := Sock, sa_src := Src, recv := Recv} = State) -> + {ok, {Src, ?BASIC_REQ}} = Recv(Sock), + ok + end}, + #{desc => "send rep (to src)", + cmd => fun(#{sock_dst := Sock, sa_src := Src, send := Send}) -> + ok = Send(Sock, ?BASIC_REP, Src) + end}, + #{desc => "recv rep (from dst)", + cmd => fun(#{sock_src := Sock, sa_dst := Dst, recv := Recv}) -> + {ok, {Dst, ?BASIC_REP}} = Recv(Sock), + ok + end}, + #{desc => "close src socket", + cmd => fun(#{sock_src := Sock}) -> + ok = socket:close(Sock) + end}, + #{desc => "close dst socket", + cmd => fun(#{sock_dst := Sock}) -> + ok = socket:close(Sock), + {ok, normal} + end} + ], + Evaluator = evaluator_start("tester", Seq, InitState), + ok = await_evaluator_finish([Evaluator]). -- cgit v1.2.3 From d4cedb9fa86db720cc247b9201d5c7e1e8aab461 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Fri, 5 Oct 2018 14:23:47 +0200 Subject: [socket-nif|test] Two more test cases (tcp) reworked Two (tcp) test cases where reworked using the command evaluator. OTP-14831 --- lib/kernel/test/socket_SUITE.erl | 288 ++++++++++++++++++++++----------------- 1 file changed, 160 insertions(+), 128 deletions(-) (limited to 'lib') diff --git a/lib/kernel/test/socket_SUITE.erl b/lib/kernel/test/socket_SUITE.erl index ed5722f008..e50daaf367 100644 --- a/lib/kernel/test/socket_SUITE.erl +++ b/lib/kernel/test/socket_SUITE.erl @@ -71,6 +71,7 @@ %% -export([]). +-type initial_evaluator_state() :: map(). -type evaluator_state() :: term(). -type command_fun() :: fun((State :: evaluator_state()) -> ok) | @@ -78,8 +79,7 @@ fun((State :: evaluator_state()) -> {error, term()}). -type command() :: #{desc := string(), - cmd := command_fun() - }. + cmd := command_fun()}. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -89,6 +89,8 @@ -define(FAIL(R), exit(R)). +-define(SLEEP(T), receive after T -> ok end). + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -366,19 +368,6 @@ api_b_sendmsg_and_recvmsg_udp4(_Config) when is_list(_Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% api_b_send_and_recv_udp(InitState) -> - %% SockSrc = sock_open(Domain, dgram, udp), - %% LAddr = which_local_addr(Domain), - %% LSA = #{family => Domain, addr => LAddr}, - %% sock_bind(SockSrc, LSA), - %% SockDst = sock_open(Domain, dgram, udp), - %% sock_bind(SockDst, LSA), - %% Dst = sock_sockname(SockDst), - %% ok = Send(SockSrc, ?BASIC_REQ, Dst), - %% {ok, {Src, ?BASIC_REQ}} = Recv(SockDst), - %% ok = Send(SockDst, ?BASIC_REP, Src), - %% {ok, {Dst, ?BASIC_REP}} = Recv(SockSrc), - %% socket:close(SockSrc), - %% socket:close(SockDst), Seq = [ #{desc => "local address", @@ -425,7 +414,7 @@ api_b_send_and_recv_udp(InitState) -> ok = Send(Sock, ?BASIC_REQ, Dst) end}, #{desc => "recv req (from src)", - cmd => fun(#{sock_dst := Sock, sa_src := Src, recv := Recv} = State) -> + cmd => fun(#{sock_dst := Sock, sa_src := Src, recv := Recv}) -> {ok, {Src, ?BASIC_REQ}} = Recv(Sock), ok end}, @@ -469,7 +458,10 @@ api_b_send_and_recv_tcp4(_Config) when is_list(_Config) -> Recv = fun(Sock) -> socket:recv(Sock) end, - ok = api_b_send_and_recv_tcp(inet, Send, Recv), + InitState = #{domain => inet, + send => Send, + recv => Recv}, + ok = api_b_send_and_recv_tcp(InitState), tc_end(). @@ -496,119 +488,157 @@ api_b_sendmsg_and_recvmsg_tcp4(_Config) when is_list(_Config) -> ERROR end end, - ok = api_b_send_and_recv_tcp(inet, Send, Recv), + InitState = #{domain => inet, + send => Send, + recv => Recv}, + ok = api_b_send_and_recv_tcp(InitState), tc_end(). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -api_b_send_and_recv_tcp(Domain, Send, Recv) -> +api_b_send_and_recv_tcp(InitState) -> process_flag(trap_exit, true), - LAddr = which_local_addr(Domain), - LSA = #{family => Domain, addr => LAddr}, - Starter = self(), - ServerFun = fun() -> - put(sname, "server"), - %% Create the listen socket - ServerLSock = - case socket:open(Domain, stream, tcp) of - {ok, S1} -> - S1; - {error, ServerOR} -> - ?FAIL({server, open, ServerOR}) - end, - %% And bind it to the local address - SP = - case socket:bind(ServerLSock, LSA) of - {ok, P} -> - P; - {error, ServerBR} -> - ?FAIL({server, bind, ServerBR}) - end, - %% Listen for connecting clients - case socket:listen(ServerLSock) of - ok -> - ok; - {error, ServerLR} -> - ?FAIL({server, listen, ServerLR}) - end, - %% We are ready - Starter ! {self(), {ok, SP}}, - %% Accept connections - ServerSock = - case socket:accept(ServerLSock) of - {ok, Sock} -> - Sock; - {error, ServerAR} -> - ?FAIL({server, accept, ServerAR}) - end, - %% Wait for a message - case Recv(ServerSock) of - {ok, ?BASIC_REQ} -> - ok; - {error, ServerRR} -> - ?FAIL({server, recv, ServerRR}) - end, - %% Send the reply - case Send(ServerSock, ?BASIC_REP) of - ok -> - ok; - {error, ServerSR} -> - ?FAIL({server, send, ServerSR}) - end, - %% Close the sockets - socket:close(ServerSock), - socket:close(ServerLSock), - %% We are done - exit(normal) - end, - Server = spawn_link(ServerFun), - ServerPort = - receive - {Server, {ok, P}} -> - P; - {'EXIT', Server, ServerStartReason} -> - ?FAIL({server, start, ServerStartReason}) - end, - ClientSock = - case socket:open(Domain, stream, tcp) of - {ok, S2} -> - S2; - {error, ClientOR} -> - ?FAIL({client, open, ClientOR}) - end, - case socket:bind(ClientSock, LSA) of - {ok, _} -> - ok; - {error, ClientBR} -> - ?FAIL({client, bind, ClientBR}) - end, - case socket:connect(ClientSock, LSA#{port => ServerPort}) of - ok -> - ok; - {error, ClientCR} -> - ?FAIL({client, connect, ClientCR}) - end, - case Send(ClientSock, ?BASIC_REQ) of - ok -> - ok; - {error, ClientSR} -> - ?FAIL({client, send, ClientSR}) - end, - case Recv(ClientSock) of - {ok, ?BASIC_REP} -> - ok; - {ok, Msg} -> - ?FAIL({client, recv, {unexpected, Msg}}) - end, - receive - {'EXIT', Server, normal} -> - ok; - {'EXIT', Server, ServerStopReason} -> - ?FAIL({server, stop, ServerStopReason}) - end, - socket:close(ClientSock), - ok. + ServerSeq = + [ + #{desc => "which local address", + cmd => fun(#{domain := Domain} = State) -> + LAddr = which_local_addr(Domain), + LSA = #{family => Domain, addr => LAddr}, + {ok, State#{lsa => LSA}} + end}, + #{desc => "create listen socket", + cmd => fun(#{domain := Domain} = State) -> + case socket:open(Domain, stream, tcp) of + {ok, Sock} -> + {ok, State#{lsock => Sock}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "bind to local address", + cmd => fun(#{lsock := LSock, lsa := LSA} = State) -> + case socket:bind(LSock, LSA) of + {ok, Port} -> + {ok, State#{lport => Port}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "make listen socket", + cmd => fun(#{lsock := LSock}) -> + socket:listen(LSock) + end}, + #{desc => "announce server port", + cmd => fun(#{parent := Parent, lport := Port}) -> + ei("announcing port to parent (~p)", [Parent]), + Parent ! {server_port, self(), Port}, + ok + end}, + #{desc => "await connection", + cmd => fun(#{lsock := LSock} = State) -> + case socket:accept(LSock) of + {ok, Sock} -> + ei("accepted: ~p", [Sock]), + {ok, State#{tsock => Sock}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "await request", + cmd => fun(#{tsock := Sock, recv := Recv}) -> + case Recv(Sock) of + {ok, ?BASIC_REQ} -> + ok; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "send reply", + cmd => fun(#{tsock := Sock, send := Send}) -> + Send(Sock, ?BASIC_REP) + end}, + #{desc => "sleep some", + cmd => fun(_) -> + ?SLEEP(1000), + ok + end}, + #{desc => "close traffic socket", + cmd => fun(#{tsock := Sock}) -> + socket:close(Sock) + end}, + #{desc => "close listen socket", + cmd => fun(#{lsock := Sock}) -> + socket:close(Sock) + end}, + #{desc => "finish", + cmd => fun(_) -> + {ok, normal} + end} + ], + + ClientSeq = + [ + #{desc => "which server (local) address", + cmd => fun(#{domain := Domain, server_port := Port} = State) -> + LAddr = which_local_addr(Domain), + LSA = #{family => Domain, + addr => LAddr}, + SSA = LSA#{port => Port}, + {ok, State#{lsa => LSA, ssa => SSA}} + end}, + #{desc => "create socket", + cmd => fun(#{domain := Domain} = State) -> + case socket:open(Domain, stream, tcp) of + {ok, Sock} -> + {ok, State#{sock => Sock}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "bind to local address", + cmd => fun(#{sock := Sock, lsa := LSA} = State) -> + case socket:bind(Sock, LSA) of + {ok, Port} -> + {ok, State#{port => Port}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "connect to server", + cmd => fun(#{sock := Sock, ssa := SSA}) -> + socket:connect(Sock, SSA) + end}, + #{desc => "send request (to server)", + cmd => fun(#{sock := Sock, send := Send}) -> + Send(Sock, ?BASIC_REQ) + end}, + #{desc => "recv reply (from server)", + cmd => fun(#{sock := Sock, recv := Recv}) -> + {ok, ?BASIC_REP} = Recv(Sock), + ok + end}, + #{desc => "close socket", + cmd => fun(#{sock := Sock}) -> + socket:close(Sock) + end}, + #{desc => "finish", + cmd => fun(_) -> + {ok, normal} + end} + ], + + p("start server evaluator"), + Server = evaluator_start("server", ServerSeq, InitState), + p("await server (~p) port", [Server]), + SPort = receive + {server_port, Server, Port} -> + Port + end, + p("start client evaluator"), + Client = evaluator_start("client", ClientSeq, InitState#{server_port => SPort}), + p("await evaluator(s)"), + ok = await_evaluator_finish([Server, Client]). @@ -1404,13 +1434,15 @@ which_addr2(Domain, [_|IFO]) -> -spec evaluator_start(Name, Seq, Init) -> {Pid, MRef} when Name :: string(), Seq :: [command()], - Init :: evaluator_state(), + Init :: initial_evaluator_state(), Pid :: pid(), MRef :: reference(). evaluator_start(Name, Seq, Init) when is_list(Name) andalso is_list(Seq) andalso (Seq =/= []) -> - erlang:spawn_monitor(fun() -> evaluator_init(Name, Seq, Init) end). + Init2 = Init#{parent => self()}, + {Pid, _} = erlang:spawn_monitor(fun() -> evaluator_init(Name, Seq, Init2) end), + Pid. evaluator_init(Name, Seq, Init) -> put(sname, Name), @@ -1449,7 +1481,7 @@ await_evaluator_finish([], Fails) -> await_evaluator_finish(Evs, Fails) -> receive {'DOWN', _MRef, process, Pid, normal} -> - case lists:keydelete(Pid, 1, Evs) of + case lists:delete(Pid, Evs) of Evs -> p("unknown process ~p died (normal)", [Pid]), await_evaluator_finish(Evs, Fails); @@ -1458,7 +1490,7 @@ await_evaluator_finish(Evs, Fails) -> await_evaluator_finish(NewEvs, Fails) end; {'DOWN', _MRef, process, Pid, Reason} -> - case lists:keydelete(Pid, 1, Evs) of + case lists:delete(Pid, Evs) of Evs -> p("unknown process ~p died: " "~n ~p", [Pid, Reason]), -- cgit v1.2.3 From 2a10a95dc380b41deffa060e30c0c461dfc3df8d Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Wed, 10 Oct 2018 17:59:55 +0200 Subject: [socket-nif|test] Reworked simple otp options test case --- lib/kernel/test/socket_SUITE.erl | 295 +++++++++++++++++++++++++++++++-------- 1 file changed, 234 insertions(+), 61 deletions(-) (limited to 'lib') diff --git a/lib/kernel/test/socket_SUITE.erl b/lib/kernel/test/socket_SUITE.erl index e50daaf367..a9f51cd11f 100644 --- a/lib/kernel/test/socket_SUITE.erl +++ b/lib/kernel/test/socket_SUITE.erl @@ -652,10 +652,6 @@ api_opt_simple_otp_options(doc) -> api_opt_simple_otp_options(_Config) when is_list(_Config) -> tc_begin(api_opt_simple_otp_options), - p("Create sockets"), - S1 = sock_open(inet, stream, tcp), - S2 = sock_open(inet, dgram, udp), - Get = fun(S, Key) -> socket:getopt(S, otp, Key) end, @@ -663,68 +659,245 @@ api_opt_simple_otp_options(_Config) when is_list(_Config) -> socket:setopt(S, otp, Key, Val) end, - p("Create dummy process"), - Pid = spawn_link(fun() -> - put(sname, "dummy"), - receive - die -> - exit(normal) - end - end), - - F = fun(Sock) -> - p("Test IOW"), - {ok, IOW} = Get(Sock, iow), - NotIOW = not IOW, - ok = Set(Sock, iow, NotIOW), - {ok, NotIOW} = Get(Sock, iow), - - p("Test rcvbuf"), - {ok, RcvBuf} = Get(Sock, rcvbuf), - RcvBuf2 = RcvBuf*2, - ok = Set(Sock, rcvbuf, RcvBuf2), - {ok, RcvBuf2} = Get(Sock, rcvbuf), - ok = Set(Sock, rcvbuf, default), - {ok, RcvBuf} = Get(Sock, rcvbuf), - - p("Test rcvctrlbuf"), - {ok, RcvCtrlBuf} = Get(Sock, rcvctrlbuf), - RcvCtrlBuf2 = RcvCtrlBuf*2, - ok = Set(Sock, rcvctrlbuf, RcvCtrlBuf2), - {ok, RcvCtrlBuf2} = Get(Sock, rcvctrlbuf), - ok = Set(Sock, rcvctrlbuf, default), - {ok, RcvCtrlBuf} = Get(Sock, rcvctrlbuf), - - p("Test sndctrlbuf"), - {ok, SndCtrlBuf} = Get(Sock, sndctrlbuf), - SndCtrlBuf2 = SndCtrlBuf*2, - ok = Set(Sock, sndctrlbuf, SndCtrlBuf2), - {ok, SndCtrlBuf2} = Get(Sock, sndctrlbuf), - ok = Set(Sock, sndctrlbuf, default), - {ok, RcvCtrlBuf} = Get(Sock, sndctrlbuf), - - p("Test controlling-process"), - Self = self(), - {ok, Self} = Get(Sock, controlling_process), - ok = Set(Sock, controlling_process, Pid), - {ok, Pid} = Get(Sock, controlling_process) + Seq = + [ + %% *** Init part *** + #{desc => "create socket", + cmd => fun(#{domain := Domain, + type := Type, + protocol := Protocol} = State) -> + Sock = sock_open(Domain, Type, Protocol), + {ok, State#{sock => Sock}} + end}, + #{desc => "create dummy process", + cmd => fun(State) -> + Pid = spawn_link(fun() -> + put(sname, "dummy"), + receive + die -> + exit(normal) + end + end), + {ok, State#{dummy => Pid}} + end}, - end, + %% *** Check iow part *** + #{desc => "get iow", + cmd => fun(#{sock := Sock} = State) -> + case Get(Sock, iow) of + {ok, IOW} when is_boolean(IOW) -> + {ok, State#{iow => IOW}}; + {ok, InvalidIOW} -> + {error, {invalid, InvalidIOW}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "set (new) iow", + cmd => fun(#{sock := Sock, iow := OldIOW} = State) -> + NewIOW = not OldIOW, + case Set(Sock, iow, NewIOW) of + ok -> + {ok, State#{iow => NewIOW}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "get (new) iow", + cmd => fun(#{sock := Sock, iow := IOW}) -> + case Get(Sock, iow) of + {ok, IOW} -> + ok; + {ok, InvalidIOW} -> + {error, {invalid, InvalidIOW}}; + {error, _} = ERROR -> + ERROR + end + end}, - p("Test stream/tcp "), - F(S1), + %% *** Check rcvbuf part *** + #{desc => "get rcvbuf", + cmd => fun(#{sock := Sock} = State) -> + case Get(Sock, rcvbuf) of + {ok, RcvBuf} when is_integer(RcvBuf) -> + {ok, State#{rcvbuf => RcvBuf}}; + {ok, InvalidRcvBuf} -> + {error, {invalid, InvalidRcvBuf}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "set (new) rcvbuf", + cmd => fun(#{sock := Sock, rcvbuf := OldRcvBuf} = State) -> + NewRcvBuf = 2 * OldRcvBuf, + case Set(Sock, rcvbuf, NewRcvBuf) of + ok -> + {ok, State#{rcvbuf => NewRcvBuf}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "get (new) rcvbuf", + cmd => fun(#{sock := Sock, rcvbuf := RcvBuf}) -> + case Get(Sock, rcvbuf) of + {ok, RcvBuf} -> + ok; + {ok, InvalidRcvBuf} -> + {error, {invalid, InvalidRcvBuf}}; + {error, _} = ERROR -> + ERROR + end + end}, - p("Test dgram/udp "), - F(S2), + %% *** Check rcvctrlbuf part *** + #{desc => "get rcvctrlbuf", + cmd => fun(#{sock := Sock} = State) -> + case Get(Sock, rcvctrlbuf) of + {ok, RcvCtrlBuf} when is_integer(RcvCtrlBuf) -> + {ok, State#{rcvctrlbuf => RcvCtrlBuf}}; + {ok, InvalidRcvCtrlBuf} -> + {error, {invalid, InvalidRcvCtrlBuf}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "set (new) rcvctrlbuf", + cmd => fun(#{sock := Sock, rcvctrlbuf := OldRcvCtrlBuf} = State) -> + NewRcvCtrlBuf = 2 * OldRcvCtrlBuf, + case Set(Sock, rcvctrlbuf, NewRcvCtrlBuf) of + ok -> + {ok, State#{rcvctrlbuf => NewRcvCtrlBuf}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "get (new) rcvctrlbuf", + cmd => fun(#{sock := Sock, rcvctrlbuf := RcvCtrlBuf}) -> + case Get(Sock, rcvctrlbuf) of + {ok, RcvCtrlBuf} -> + ok; + {ok, InvalidRcvCtrlBuf} -> + {error, {invalid, InvalidRcvCtrlBuf}}; + {error, _} = ERROR -> + ERROR + end + end}, + %% *** Check rcvctrlbuf part *** + #{desc => "get rcvctrlbuf", + cmd => fun(#{sock := Sock} = State) -> + case Get(Sock, rcvctrlbuf) of + {ok, RcvCtrlBuf} when is_integer(RcvCtrlBuf) -> + {ok, State#{rcvctrlbuf => RcvCtrlBuf}}; + {ok, InvalidRcvCtrlBuf} -> + {error, {invalid, InvalidRcvCtrlBuf}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "set (new) rcvctrlbuf", + cmd => fun(#{sock := Sock, rcvctrlbuf := OldRcvCtrlBuf} = State) -> + NewRcvCtrlBuf = 2 * OldRcvCtrlBuf, + case Set(Sock, rcvctrlbuf, NewRcvCtrlBuf) of + ok -> + {ok, State#{rcvctrlbuf => NewRcvCtrlBuf}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "get (new) rcvctrlbuf", + cmd => fun(#{sock := Sock, rcvctrlbuf := RcvCtrlBuf}) -> + case Get(Sock, rcvctrlbuf) of + {ok, RcvCtrlBuf} -> + ok; + {ok, InvalidRcvCtrlBuf} -> + {error, {invalid, InvalidRcvCtrlBuf}}; + {error, _} = ERROR -> + ERROR + end + end}, - p("kill dummy process"), - %% This will also close its sockets (S1 and S2), - %% This should really be tested explicitly... - Pid ! die, - %% p("close sockets"), - %% sock_close(S1), - %% sock_close(S2), + %% *** Check sndctrlbuf part *** + #{desc => "get sndctrlbuf", + cmd => fun(#{sock := Sock} = State) -> + case Get(Sock, sndctrlbuf) of + {ok, SndCtrlBuf} when is_integer(SndCtrlBuf) -> + {ok, State#{sndctrlbuf => SndCtrlBuf}}; + {ok, InvalidSndCtrlBuf} -> + {error, {invalid, InvalidSndCtrlBuf}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "set (new) sndctrlbuf", + cmd => fun(#{sock := Sock, sndctrlbuf := OldSndCtrlBuf} = State) -> + NewSndCtrlBuf = 2 * OldSndCtrlBuf, + case Set(Sock, sndctrlbuf, NewSndCtrlBuf) of + ok -> + {ok, State#{sndctrlbuf => NewSndCtrlBuf}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "get (new) sndctrlbuf", + cmd => fun(#{sock := Sock, sndctrlbuf := SndCtrlBuf}) -> + case Get(Sock, sndctrlbuf) of + {ok, SndCtrlBuf} -> + ok; + {ok, InvalidSndCtrlBuf} -> + {error, {invalid, InvalidSndCtrlBuf}}; + {error, _} = ERROR -> + ERROR + end + end}, + + %% *** Check controlling-process part *** + #{desc => "verify self as controlling-process", + cmd => fun(#{sock := Sock}) -> + Self = self(), + case Get(Sock, controlling_process) of + {ok, Self} -> + ok; + {ok, InvalidPid} -> + {error, {invalid, InvalidPid}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "set dummy as controlling-process", + cmd => fun(#{sock := Sock, dummy := Dummy}) -> + Set(Sock, controlling_process, Dummy) + end}, + #{desc => "verify dummy as controlling-process", + cmd => fun(#{sock := Sock, dummy := Dummy}) -> + case Get(Sock, controlling_process) of + {ok, Dummy} -> + ok; + {ok, InvalidPid} -> + {error, {invalid, InvalidPid}}; + {error, _} = ERROR -> + ERROR + end + end}, + + %% *** We are done *** + #{desc => "finish", + cmd => fun(_) -> + {ok, normal} + end} + ], + + p("Run test for stream/tcp socket"), + InitState1 = #{domain => inet, type => stream, protocol => tcp}, + Tester1 = evaluator_start("tcp-tester", Seq, InitState1), + p("await evaluator 1"), + ok = await_evaluator_finish([Tester1]), + + p("Run test for dgram/udp socket"), + InitState2 = #{domain => inet, type => dgram, protocol => udp}, + Tester2 = evaluator_start("udp-tester", Seq, InitState2), + p("await evaluator 2"), + ok = await_evaluator_finish([Tester2]), tc_end(). -- cgit v1.2.3 From 8092cb3bb4e3a90be52df03fff211a2e29dc8784 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Wed, 10 Oct 2018 18:55:33 +0200 Subject: [socket-nif|test] Reworked otp controlling process option test case --- lib/kernel/test/socket_SUITE.erl | 327 +++++++++++++++++++++++++++------------ 1 file changed, 224 insertions(+), 103 deletions(-) (limited to 'lib') diff --git a/lib/kernel/test/socket_SUITE.erl b/lib/kernel/test/socket_SUITE.erl index a9f51cd11f..23a77f428c 100644 --- a/lib/kernel/test/socket_SUITE.erl +++ b/lib/kernel/test/socket_SUITE.erl @@ -912,10 +912,6 @@ api_opt_simple_otp_controlling_process(doc) -> api_opt_simple_otp_controlling_process(_Config) when is_list(_Config) -> tc_begin(api_opt_simple_otp_controlling_process), - p("Create sockets"), - S1 = sock_open(inet, stream, tcp), - S2 = sock_open(inet, dgram, udp), - Get = fun(S, Key) -> socket:getopt(S, otp, Key) end, @@ -923,110 +919,235 @@ api_opt_simple_otp_controlling_process(_Config) when is_list(_Config) -> socket:setopt(S, otp, Key, Val) end, - AwaitStart = - fun() -> - p("await start command"), - receive - {start, P, S} -> - {P, S} - end - end, - AwaitContinue = - fun(Pid) -> - p("await continue command"), - receive - {continue, Pid} -> - ok - end - end, - AwaitReady = - fun(Pid) -> - p("await ready confirmation from ~p", [Pid]), - receive - {ready, Pid} -> - ok - end - end, - AwaitDie = - fun(Pid) -> - p("await die command"), - receive - {die, Pid} -> - ok - end - end, - ClientStarter = - fun() -> - put(sname, "client"), - Self = self(), - {Parent, Sock} = AwaitStart(), - p("verify parent ~p controlling", [Parent]), - {ok, Parent} = Get(Sock, controlling_process), - p("attempt invalid control transfer (to self)"), - {error, not_owner} = Set(Sock, controlling_process, self()), - p("verify parent ~p (still) controlling", [Parent]), - {ok, Parent} = Get(Sock, controlling_process), - p("announce ready"), - Parent ! {ready, self()}, - - AwaitContinue(Parent), - p("verify self controlling"), - {ok, Self} = Get(Sock, controlling_process), - p("transfer control to parent ~p", [Parent]), - ok = Set(Sock, controlling_process, Parent), - p("attempt invalid control transfer (to self)"), - {error, not_owner} = Set(Sock, controlling_process, self()), - p("verify parent ~p controlling", [Parent]), - {ok, Parent} = Get(Sock, controlling_process), - p("announce ready"), - Parent ! {ready, self()}, - - AwaitDie(Parent), - p("done"), - exit(normal) - end, + ClientSeq = + [ + %% *** Init part *** + #{desc => "await start", + cmd => fun(State) -> + receive + {start, Tester, Socket} -> + {ok, State#{tester => Tester, + sock => Socket}} + end + end}, + #{desc => "verify tester as controlling-process", + cmd => fun(#{tester := Tester, sock := Sock} = _State) -> + case Get(Sock, controlling_process) of + {ok, Tester} -> + ok; + {ok, InvalidPid} -> + {error, {invalid, InvalidPid}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "attempt invalid controlling-process transfer (to self)", + cmd => fun(#{sock := Sock} = _State) -> + case Set(Sock, controlling_process, self()) of + {error, not_owner} -> + ok; + ok -> + {error, unexpected_success}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "announce ready (1)", + cmd => fun(#{tester := Tester} = _State) -> + Tester ! {ready, self()}, + ok + end}, + #{desc => "await continue", + cmd => fun(#{tester := Tester} = _State) -> + receive + {continue, Tester} -> + ok + end + end}, + #{desc => "verify self as controlling-process", + cmd => fun(#{sock := Sock} = _State) -> + Self = self(), + case Get(Sock, controlling_process) of + {ok, Self} -> + ok; + {ok, InvalidPid} -> + {error, {invalid, InvalidPid}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "attempt controlling-process transfer to tester", + cmd => fun(#{tester := Tester, sock := Sock} = _State) -> + Set(Sock, controlling_process, Tester) + end}, + #{desc => "attempt invalid controlling-process transfer (to self)", + cmd => fun(#{sock := Sock} = _State) -> + case Set(Sock, controlling_process, self()) of + {error, not_owner} -> + ok; + ok -> + {error, unexpected_success}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "announce ready (2)", + cmd => fun(#{tester := Tester} = _State) -> + Tester ! {ready, self()}, + ok + end}, + #{desc => "await termination", + cmd => fun(#{tester := Tester} = State) -> + receive + {terminate, Tester} -> + State1 = maps:remove(tester, State), + State2 = maps:remove(sock, State1), + {ok, State2} + end + end}, - Tester = - fun(Sock, Client) -> - p("start"), - Self = self(), - p("verify self controlling"), - {ok, Self} = Get(Sock, controlling_process), - p("announce start"), - Client ! {start, Self, Sock}, - AwaitReady(Client), - - p("transfer control to client ~p", [Client]), - ok = Set(Sock, controlling_process, Client), - p("verify client ~p controlling", [Client]), - {ok, Client} = Get(Sock, controlling_process), - p("attempt invalid control transfer (to self)"), - {error, not_owner} = Set(Sock, controlling_process, self()), - p("announce continue"), - Client ! {continue, Self}, - AwaitReady(Client), - - p("verify self controlling"), - {ok, Self} = Get(Sock, controlling_process), - p("announce die"), - Client ! {die, Self}, - p("done"), - ok - end, + %% *** We are done *** + #{desc => "finish", + cmd => fun(_) -> + {ok, normal} + end} + ], - p("Create Worker Process(s)"), - Pid1 = spawn_link(ClientStarter), - Pid2 = spawn_link(ClientStarter), + TesterSeq = + [ + %% *** Init part *** + #{desc => "create socket", + cmd => fun(#{domain := Domain, + type := Type, + protocol := Protocol} = State) -> + Sock = sock_open(Domain, Type, Protocol), + {ok, State#{sock => Sock}} + end}, + #{desc => "verify self as controlling-process", + cmd => fun(#{sock := Sock} = _State) -> + Self = self(), + case Get(Sock, controlling_process) of + {ok, Self} -> + ok; + {ok, InvalidPid} -> + {error, {invalid, InvalidPid}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "order (client) start", + cmd => fun(#{client := Client, sock := Sock} = _State) -> + Client ! {start, self(), Sock}, + ok + end}, + #{desc => "await (client) ready (1)", + cmd => fun(#{client := Client} = _State) -> + receive + {ready, Client} -> + ok + end + end}, + #{desc => "attempt controlling-process transfer to client", + cmd => fun(#{client := Client, sock := Sock} = _State) -> + Set(Sock, controlling_process, Client) + end}, + #{desc => "verify client as controlling-process", + cmd => fun(#{client := Client, sock := Sock} = _State) -> + case Get(Sock, controlling_process) of + {ok, Client} -> + ok; + {ok, InvalidPid} -> + {error, {invalid, InvalidPid}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "attempt invalid controlling-process transfer (to self)", + cmd => fun(#{sock := Sock} = _State) -> + case Set(Sock, controlling_process, self()) of + {error, not_owner} -> + ok; + ok -> + {error, unexpected_success}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "order (client) continue", + cmd => fun(#{client := Client} = _State) -> + Client ! {continue, self()}, + ok + end}, + #{desc => "await (client) ready (2)", + cmd => fun(#{client := Client} = _State) -> + receive + {ready, Client} -> + ok + end + end}, + #{desc => "verify self as controlling-process", + cmd => fun(#{sock := Sock} = _State) -> + Self = self(), + case Get(Sock, controlling_process) of + {ok, Self} -> + ok; + {ok, InvalidPid} -> + {error, {invalid, InvalidPid}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "monitor client", + cmd => fun(#{client := Client} = State) -> + MRef = erlang:monitor(process, Client), + {ok, State#{client_mref => MRef}} + end}, + #{desc => "order (client) terminate", + cmd => fun(#{client := Client} = _State) -> + Client ! {terminate, self()}, + ok + end}, + #{desc => "await (client) down", + cmd => fun(#{client := Client} = State) -> + receive + {'DOWN', _, process, Client, _} -> + {ok, maps:remove(client, State)} + end + end}, + #{desc => "close socket", + cmd => fun(#{sock := Sock} = State) -> + sock_close(Sock), + {ok, maps:remove(sock, State)} + end}, - p("Test stream/tcp "), - Tester(S1, Pid1), + %% *** We are done *** + #{desc => "finish", + cmd => fun(_) -> + {ok, normal} + end} + ], - p("Test dgram/udp "), - Tester(S2, Pid2), + p("Run test for stream/tcp socket"), + ClientInitState1 = #{}, + Client1 = evaluator_start("tcp-client", ClientSeq, ClientInitState1), + TesterInitState1 = #{domain => inet, + type => stream, + protocol => tcp, + client => Client1}, + Tester1 = evaluator_start("tcp-tester", TesterSeq, TesterInitState1), + p("await stream/tcp evaluator"), + ok = await_evaluator_finish([Tester1, Client1]), - p("close sockets"), - sock_close(S1), - sock_close(S2), + p("Run test for dgram/udp socket"), + ClientInitState2 = #{}, + Client2 = evaluator_start("udp-client", ClientSeq, ClientInitState2), + TesterInitState2 = #{domain => inet, + type => dgram, + protocol => udp, + client => Client2}, + Tester2 = evaluator_start("udp-tester", TesterSeq, TesterInitState2), + p("await dgram/udp evaluator"), + ok = await_evaluator_finish([Tester2, Client2]), tc_end(). -- cgit v1.2.3 From 3ccba221981a6ae61cb2b7222fe7ea56aa56a923 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Thu, 11 Oct 2018 12:06:41 +0200 Subject: [socket-nif|test] Reworked the connect timeout test case --- lib/kernel/test/socket_SUITE.erl | 281 +++++++++++++++++++++++++++++++-------- 1 file changed, 226 insertions(+), 55 deletions(-) (limited to 'lib') diff --git a/lib/kernel/test/socket_SUITE.erl b/lib/kernel/test/socket_SUITE.erl index 23a77f428c..2d406458f0 100644 --- a/lib/kernel/test/socket_SUITE.erl +++ b/lib/kernel/test/socket_SUITE.erl @@ -1162,7 +1162,8 @@ api_to_connect_tcp4(doc) -> []; api_to_connect_tcp4(_Config) when is_list(_Config) -> tc_begin(api_to_connect_tcp4), - ok = api_to_connect_tcp(inet), + InitState = #{domain => inet}, + ok = api_to_connect_tcp(InitState), tc_end(). %% not_yet_implemented(). @@ -1177,7 +1178,8 @@ api_to_connect_tcp6(doc) -> []; api_to_connect_tcp6(_Config) when is_list(_Config) -> %% tc_begin(api_to_connect_tcp6), - %% ok = api_to_connect_tcp(inet6), + %% InitState = #{domain => inet6}, + %% ok = api_to_connect_tcp(InitState), %% tc_end(). not_yet_implemented(). @@ -1189,54 +1191,223 @@ api_to_connect_tcp6(_Config) when is_list(_Config) -> %% For instance, on FreeBSD (11.2) the reponse when the backlog is full %% is a econreset. -api_to_connect_tcp(Domain) -> +api_to_connect_tcp(InitState) -> process_flag(trap_exit, true), - p("init"), - Client = self(), - LocalAddr = which_local_addr(Domain), - LocalSA = #{family => Domain, addr => LocalAddr}, - ServerName = f("~s:server", [get_tc_name()]), - Server = spawn_link(fun() -> - put(sname, ServerName), - p("open"), - LSock = sock_open(Domain, stream, tcp), - p("bind"), - ServerLPort = sock_bind(LSock, LocalSA), - p("listen on ~w", [ServerLPort]), - sock_listen(LSock, 1), - p("inform client"), - Client ! {self(), ServerLPort}, - p("await termination command"), - receive - die -> - p("terminating"), - exit(normal) - end - end), - - p("await server port"), - ServerLPort = - receive - {Server, Port} -> - Port - end, - p("open(s)"), - CSock1 = sock_open(Domain, stream, tcp), - CSock2 = sock_open(Domain, stream, tcp), - CSock3 = sock_open(Domain, stream, tcp), - p("bind(s)"), - _ClientPort1 = sock_bind(CSock1, LocalSA), - _ClientPort2 = sock_bind(CSock2, LocalSA), - _ClientPort3 = sock_bind(CSock3, LocalSA), - ServerSA = LocalSA#{port => ServerLPort}, - api_to_connect_tcp_await_timeout([CSock1, CSock2, CSock3], ServerSA), - p("terminate server"), - Server ! die, - receive - {'EXIT', Server, _} -> - p("server terminated"), - ok - end, + + ServerSeq = + [ + %% *** Wait for start order part *** + #{desc => "await start (from tester)", + cmd => fun(State) -> + receive + {start, Tester} when is_pid(Tester) -> + {ok, State#{tester => Tester}} + end + end}, + + %% *** Init part *** + #{desc => "which local address", + cmd => fun(#{domain := Domain} = State) -> + LAddr = which_local_addr(Domain), + LSA = #{family => Domain, addr => LAddr}, + {ok, State#{lsa => LSA}} + end}, + #{desc => "create listen socket", + cmd => fun(#{domain := Domain} = State) -> + case socket:open(Domain, stream, tcp) of + {ok, Sock} -> + {ok, State#{lsock => Sock}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "bind to local address", + cmd => fun(#{lsock := LSock, lsa := LSA} = State) -> + case socket:bind(LSock, LSA) of + {ok, Port} -> + {ok, State#{lport => Port}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "make listen socket (with backlog = 1)", + cmd => fun(#{lsock := LSock}) -> + socket:listen(LSock, 1) + end}, + #{desc => "monitor server", + cmd => fun(#{tester := Tester} = State) -> + MRef = erlang:monitor(process, Tester), + {ok, State#{tester_mref => MRef}} + end}, + #{desc => "announce ready", + cmd => fun(#{tester := Tester, lport := Port}) -> + ei("announcing ready to tester (~p)", [Tester]), + Tester ! {ready, self(), Port}, + ok + end}, + #{desc => "await terminate (from tester)", + cmd => fun(#{tester := Tester}) -> + receive + {'DOWN', _, process, Tester, Reason} -> + {error, {unexpected_tester_exit, Reason}}; + {terminate, Tester} -> + ok + end + end}, + + %% *** We are done *** + #{desc => "finish", + cmd => fun(_) -> + {ok, normal} + end} + ], + + TesterSeq = + [ + %% *** Init part *** + #{desc => "which local address", + cmd => fun(#{domain := Domain} = State) -> + LAddr = which_local_addr(Domain), + LSA = #{family => Domain, addr => LAddr}, + {ok, State#{lsa => LSA}} + end}, + #{desc => "create socket 1", + cmd => fun(#{domain := Domain} = State) -> + case socket:open(Domain, stream, tcp) of + {ok, Sock} -> + {ok, State#{sock1 => Sock}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "create socket 2", + cmd => fun(#{domain := Domain} = State) -> + case socket:open(Domain, stream, tcp) of + {ok, Sock} -> + {ok, State#{sock2 => Sock}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "create socket 3", + cmd => fun(#{domain := Domain} = State) -> + case socket:open(Domain, stream, tcp) of + {ok, Sock} -> + {ok, State#{sock3 => Sock}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "bind socket 1 to local address", + cmd => fun(#{sock1 := Sock, lsa := LSA} = _State) -> + case socket:bind(Sock, LSA) of + {ok, _} -> + ok; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "bind socket 2 to local address", + cmd => fun(#{sock2 := Sock, lsa := LSA} = _State) -> + case socket:bind(Sock, LSA) of + {ok, _} -> + ok; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "bind socket 3 to local address", + cmd => fun(#{sock3 := Sock, lsa := LSA} = _State) -> + case socket:bind(Sock, LSA) of + {ok, _} -> + ok; + {error, _} = ERROR -> + ERROR + end + end}, + + %% *** Synchronize with the server *** + #{desc => "order (server) start", + cmd => fun(#{server := Server}) -> + Server ! {start, self()}, + ok + end}, + #{desc => "await ready (from server)", + cmd => fun(#{server := Server, lsa := LSA} = State) -> + receive + {ready, Server, Port} -> + {ok, State#{ssa => LSA#{port => Port}}} + end + end}, + + %% *** Connect sequence *** + #{desc => "order (server) start", + cmd => fun(#{sock1 := Sock1, + sock2 := Sock2, + sock3 := Sock3, + ssa := SSA}) -> + Socks = [Sock1, Sock2, Sock3], + api_to_connect_tcp_await_timeout(Socks, SSA) + end}, + + %% *** Terminate server *** + #{desc => "monitor server", + cmd => fun(#{server := Server} = State) -> + MRef = erlang:monitor(process, Server), + {ok, State#{server_mref => MRef}} + end}, + #{desc => "order (server) terminate", + cmd => fun(#{server := Server} = _State) -> + Server ! {terminate, self()}, + ok + end}, + #{desc => "await (server) down", + cmd => fun(#{server := Server} = State) -> + receive + {'DOWN', _, process, Server, _} -> + State1 = maps:remove(server, State), + State2 = maps:remove(ssa, State1), + {ok, State2} + end + end}, + + %% *** Close our sockets *** + #{desc => "close socket 3", + cmd => fun(#{sock3 := Sock} = State) -> + sock_close(Sock), + {ok, maps:remove(sock3, State)} + + end}, + #{desc => "close socket 2", + cmd => fun(#{sock2 := Sock} = State) -> + sock_close(Sock), + {ok, maps:remove(sock2, State)} + + end}, + #{desc => "close socket 1", + cmd => fun(#{sock1 := Sock} = State) -> + sock_close(Sock), + {ok, maps:remove(sock1, State)} + + end}, + + %% *** We are done *** + #{desc => "finish", + cmd => fun(_) -> + {ok, normal} + end} + ], + + p("create server evaluator"), + ServerInitState = InitState, + Server = evaluator_start("server", ServerSeq, ServerInitState), + + p("create tester evaluator"), + TesterInitState = InitState#{server => Server}, + Tester = evaluator_start("tester", TesterSeq, TesterInitState), + + p("await evaluator(s)"), + ok = await_evaluator_finish([Server, Tester]), ok. @@ -1246,19 +1417,19 @@ api_to_connect_tcp_await_timeout(Socks, ServerSA) -> api_to_connect_tcp_await_timeout([], _ServerSA, _ID) -> ?FAIL(unexpected_success); api_to_connect_tcp_await_timeout([Sock|Socks], ServerSA, ID) -> - p("~w: try connect", [ID]), + ei("~w: try connect", [ID]), case socket:connect(Sock, ServerSA, 5000) of {error, timeout} -> - p("expected timeout (~w)", [ID]), + ei("expected timeout (~w)", [ID]), ok; {error, econnreset = Reason} -> - p("failed connecting: ~p - giving up", [Reason]), + ei("failed connecting: ~p - giving up", [Reason]), ok; {error, Reason} -> - p("failed connecting: ~p", [Reason]), - ?FAIL({recv, Reason}); + ee("failed connecting: ~p", [Reason]), + ?FAIL({connect, Reason}); ok -> - p("unexpected success (~w) - try next", [ID]), + ei("unexpected success (~w) - try next", [ID]), api_to_connect_tcp_await_timeout(Socks, ServerSA, ID+1) end. -- cgit v1.2.3 From 51d0d80c96d29445713a026870e3e0124f3380a4 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Thu, 11 Oct 2018 15:06:54 +0200 Subject: [socket-nif|test] Reworked tcp (IPv4) recv timeout test case --- lib/kernel/test/socket_SUITE.erl | 384 ++++++++++++++++++++++++++++++++++----- 1 file changed, 334 insertions(+), 50 deletions(-) (limited to 'lib') diff --git a/lib/kernel/test/socket_SUITE.erl b/lib/kernel/test/socket_SUITE.erl index 2d406458f0..9a4b263ea0 100644 --- a/lib/kernel/test/socket_SUITE.erl +++ b/lib/kernel/test/socket_SUITE.erl @@ -1246,12 +1246,12 @@ api_to_connect_tcp(InitState) -> ok end}, #{desc => "await terminate (from tester)", - cmd => fun(#{tester := Tester}) -> + cmd => fun(#{tester := Tester} = State) -> receive {'DOWN', _, process, Tester, Reason} -> - {error, {unexpected_tester_exit, Reason}}; + {error, {unexpected_exit, tester, Reason}}; {terminate, Tester} -> - ok + {ok, maps:remove(tester, State)} end end}, @@ -1597,7 +1597,8 @@ api_to_recv_tcp4(doc) -> []; api_to_recv_tcp4(_Config) when is_list(_Config) -> tc_begin(api_to_recv_tcp4), - ok = api_to_recv_tcp(inet), + InitState = #{domain => inet}, + ok = api_to_recv_tcp(InitState), tc_end(). @@ -1611,59 +1612,342 @@ api_to_recv_tcp6(doc) -> []; api_to_recv_tcp6(_Config) when is_list(_Config) -> %% tc_begin(api_to_recv_tcp6), - %% ok = api_to_recv_tcp(inet6), + %% InitState = #{domain => inet6}, + %% ok = api_to_recv_tcp(InitState), %% tc_end(). not_yet_implemented(). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -api_to_recv_tcp(Domain) -> +api_to_recv_tcp(InitState) -> process_flag(trap_exit, true), - p("server -> open"), - LSock = sock_open(Domain, stream, tcp), - LocalAddr = which_local_addr(Domain), - LocalSA = #{family => Domain, addr => LocalAddr}, - p("server -> bind"), - ServerLPort = sock_bind(LSock, LocalSA), - p("server(~w) -> listen", [ServerLPort]), - sock_listen(LSock), - ClientName = f("~s:client", [get_tc_name()]), - Client = spawn_link(fun() -> - put(sname, ClientName), - p("open"), - CSock = sock_open(Domain, stream, tcp), - p("bind"), - ClientPort = sock_bind(CSock, LocalSA), - p("[~w] connect to ~w", - [ClientPort, ServerLPort]), - sock_connect(CSock, LocalSA#{port => ServerLPort}), - p("await termination command"), - receive - die -> - p("terminating"), - exit(normal) - end - end), - p("server -> accept on ~w", [ServerLPort]), - Sock = sock_accept(LSock), - p("server -> recv"), - %% The zero (0) represents "give me everything you have" - case socket:recv(Sock, 0, 5000) of - {error, timeout} -> - p("server -> expected timeout"), - ok; - {ok, _Data} -> - ?FAIL(unexpected_success); - {error, Reason} -> - ?FAIL({recv, Reason}) - end, - Client ! die, - receive - {'EXIT', Client, _} -> - ok - end, - ok. + + ServerSeq = + [ + %% *** Wait for start order *** + #{desc => "await start (from tester)", + cmd => fun(State) -> + receive + {start, Tester} when is_pid(Tester) -> + {ok, State#{tester => Tester}} + end + end}, + + %% *** Init part *** + #{desc => "which local address", + cmd => fun(#{domain := Domain} = State) -> + LAddr = which_local_addr(Domain), + LSA = #{family => Domain, addr => LAddr}, + {ok, State#{lsa => LSA}} + end}, + #{desc => "create listen socket", + cmd => fun(#{domain := Domain} = State) -> + case socket:open(Domain, stream, tcp) of + {ok, Sock} -> + {ok, State#{lsock => Sock}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "bind to local address", + cmd => fun(#{lsock := LSock, lsa := LSA} = State) -> + case socket:bind(LSock, LSA) of + {ok, Port} -> + {ok, State#{lport => Port}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "make listen socket (with backlog = 1)", + cmd => fun(#{lsock := LSock}) -> + socket:listen(LSock, 1) + end}, + #{desc => "monitor tester", + cmd => fun(#{tester := Tester} = State) -> + MRef = erlang:monitor(process, Tester), + {ok, State#{tester_mref => MRef}} + end}, + #{desc => "announce ready", + cmd => fun(#{tester := Tester, lport := Port}) -> + Tester ! {ready, self(), Port}, + ok + end}, + #{desc => "await continue", + cmd => fun(#{tester := Tester}) -> + receive + {'DOWN', _, process, Tester, Reason} -> + {error, {unexpected_exit, tester, Reason}}; + {continue, Tester} -> + ok + end + end}, + + %% *** The actual test *** + #{desc => "await accept", + cmd => fun(#{lsock := LSock} = State) -> + case socket:accept(LSock) of + {ok, Sock} -> + {ok, State#{sock => Sock}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "attempt to recv (without success)", + cmd => fun(#{sock := Sock} = _State) -> + case socket:recv(Sock, 0, 5000) of + {error, timeout} -> + ok; + {ok, _Data} -> + {error, unexpected_success}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "announce ready (recv timeout success)", + cmd => fun(#{tester := Tester} = _State) -> + Tester ! {ready, self()}, + ok + end}, + + %% *** Termination *** + #{desc => "await terminate", + cmd => fun(#{tester := Tester} = State) -> + receive + {'DOWN', _, process, Tester, Reason} -> + {error, {unexpected_exit, tester, Reason}}; + {terminate, Tester} -> + {ok, maps:remove(tester, State)} + end + end}, + #{desc => "close (traffic) socket", + cmd => fun(#{sock := Sock} = State) -> + sock_close(Sock), + {ok, maps:remove(sock, State)} + end}, + #{desc => "close (listen) socket", + cmd => fun(#{lsock := LSock} = State) -> + sock_close(LSock), + {ok, maps:remove(lsock, State)} + end}, + + %% *** We are done *** + #{desc => "finish", + cmd => fun(_) -> + {ok, normal} + end} + ], + + ClientSeq = + [ + %% *** Wait for start order part *** + #{desc => "await start (from tester)", + cmd => fun(State) -> + receive + {start, Tester, Port} when is_pid(Tester) -> + {ok, State#{tester => Tester, + server_port => Port}} + end + end}, + + %% *** Init part *** + #{desc => "which local address", + cmd => fun(#{domain := Domain, server_port := Port} = State) -> + LAddr = which_local_addr(Domain), + LSA = #{family => Domain, + addr => LAddr}, + SSA = LSA#{port => Port}, + {ok, State#{lsa => LSA, ssa => SSA}} + end}, + #{desc => "create socket", + cmd => fun(#{domain := Domain} = State) -> + case socket:open(Domain, stream, tcp) of + {ok, Sock} -> + {ok, State#{sock => Sock}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "bind to local address", + cmd => fun(#{sock := Sock, lsa := LSA} = _State) -> + case socket:bind(Sock, LSA) of + {ok, _} -> + ok; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "monitor tester", + cmd => fun(#{tester := Tester} = State) -> + MRef = erlang:monitor(process, Tester), + {ok, State#{tester_mref => MRef}} + end}, + #{desc => "announce ready", + cmd => fun(#{tester := Tester} = _State) -> + Tester ! {ready, self()}, + ok + end}, + + %% *** The actual test *** + #{desc => "await continue (with connect)", + cmd => fun(#{tester := Tester} = _State) -> + receive + {'DOWN', _, process, Tester, Reason} -> + {error, {unexpected_exit, tester, Reason}}; + {continue, Tester} -> + ok + end + end}, + #{desc => "connect", + cmd => fun(#{sock := Sock, ssa := SSA}) -> + sock_connect(Sock, SSA), + ok + end}, + + %% *** Termination *** + #{desc => "await terminate", + cmd => fun(#{tester := Tester} = State) -> + receive + {'DOWN', _, process, Tester, Reason} -> + {error, {unexpected_exit, tester, Reason}}; + {terminate, Tester} -> + {ok, maps:remove(tester, State)} + end + end}, + #{desc => "close socket", + cmd => fun(#{sock := Sock} = State) -> + sock_close(Sock), + {ok, maps:remove(sock, State)} + end}, + + %% *** We are done *** + #{desc => "finish", + cmd => fun(_) -> + {ok, normal} + end} + ], + + TesterSeq = + [ + %% *** Init part *** + #{desc => "monitor server", + cmd => fun(#{server := Server} = State) -> + MRef = erlang:monitor(process, Server), + {ok, State#{server_mref => MRef}} + end}, + #{desc => "monitor client", + cmd => fun(#{client := Client} = State) -> + MRef = erlang:monitor(process, Client), + {ok, State#{client_mref => MRef}} + end}, + + %% *** Activate server *** + #{desc => "start server", + cmd => fun(#{server := Server} = _State) -> + Server ! {start, self()}, + ok + end}, + #{desc => "await server ready (init)", + cmd => fun(#{server := Server} = State) -> + receive + {'DOWN', _, process, Server, Reason} -> + {error, {unexpected_exit, server, Reason}}; + {ready, Server, Port} -> + {ok, State#{server_port => Port}} + end + end}, + #{desc => "order server to continue (with accept)", + cmd => fun(#{server := Server} = _State) -> + Server ! {continue, self()}, + ok + end}, + + %% *** Activate client *** + #{desc => "start client", + cmd => fun(#{client := Client, server_port := Port} = _State) -> + Client ! {start, self(), Port}, + ok + end}, + #{desc => "await client ready", + cmd => fun(#{client := Client} = _State) -> + receive + {'DOWN', _, process, Client, Reason} -> + {error, {unexpected_exit, client, Reason}}; + {ready, Client} -> + ok + end + end}, + + %% *** The actual test *** + #{desc => "order client to continue (with connect)", + cmd => fun(#{client := Client} = _State) -> + Client ! {continue, self()}, + ok + end}, + #{desc => "await server ready (accept/recv)", + cmd => fun(#{server := Server} = _State) -> + receive + {'DOWN', _, process, Server, Reason} -> + {error, {unexpected_exit, server, Reason}}; + {ready, Server} -> + ok + end + end}, + + %% *** Termination *** + #{desc => "order client to terminate", + cmd => fun(#{client := Client} = _State) -> + Client ! {terminate, self()}, + ok + end}, + #{desc => "await client termination", + cmd => fun(#{client := Client} = State) -> + receive + {'DOWN', _, process, Client, _Reason} -> + State1 = maps:remove(client, State), + State2 = maps:remove(client_mref, State1), + {ok, State2} + end + end}, + #{desc => "order server to terminate", + cmd => fun(#{server := Server} = State) -> + Server ! {terminate, self()}, + ok + end}, + #{desc => "await server termination", + cmd => fun(#{server := Server} = State) -> + receive + {'DOWN', _, process, Server, _Reason} -> + State1 = maps:remove(server, State), + State2 = maps:remove(server_mref, State1), + State3 = maps:remove(server_port, State2), + {ok, State3} + end + end}, + + %% *** We are done *** + #{desc => "finish", + cmd => fun(_) -> + {ok, normal} + end} + ], + + + p("start server evaluator"), + ServerInitState = InitState, + Server = evaluator_start("server", ServerSeq, ServerInitState), + + p("start client evaluator"), + ClientInitState = InitState, + Client = evaluator_start("client", ClientSeq, ClientInitState), + + p("start tester evaluator"), + TesterInitState = #{server => Server, client => Client}, + Tester = evaluator_start("tester", TesterSeq, TesterInitState), + + p("await evaluator(s)"), + ok = await_evaluator_finish([Server, Client, Tester]). + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -- cgit v1.2.3 From d66f69c98404b8c299e98237839a35b351d454ca Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Thu, 11 Oct 2018 15:27:31 +0200 Subject: [socket-nif|test] Reworked (IPv4) tcp recvmsg timeout test case --- lib/kernel/test/socket_SUITE.erl | 152 +++++++++++++++------------------------ 1 file changed, 57 insertions(+), 95 deletions(-) (limited to 'lib') diff --git a/lib/kernel/test/socket_SUITE.erl b/lib/kernel/test/socket_SUITE.erl index 9a4b263ea0..a432473f01 100644 --- a/lib/kernel/test/socket_SUITE.erl +++ b/lib/kernel/test/socket_SUITE.erl @@ -1597,8 +1597,9 @@ api_to_recv_tcp4(doc) -> []; api_to_recv_tcp4(_Config) when is_list(_Config) -> tc_begin(api_to_recv_tcp4), - InitState = #{domain => inet}, - ok = api_to_recv_tcp(InitState), + Recv = fun(Sock) -> socket:recv(Sock, 0, 5000) end, + InitState = #{domain => inet, recv => Recv}, + ok = api_to_receive_tcp(InitState), tc_end(). @@ -1612,15 +1613,22 @@ api_to_recv_tcp6(doc) -> []; api_to_recv_tcp6(_Config) when is_list(_Config) -> %% tc_begin(api_to_recv_tcp6), - %% InitState = #{domain => inet6}, - %% ok = api_to_recv_tcp(InitState), - %% tc_end(). + %% Res = case socket:supports(ipv6) of + %% true -> + %% Recv = fun(Sock) -> socket:recv(Sock, 0, 5000) end, + %% InitState = #{domain => inet6, recv => Recv}, + %% ok = api_to_receive_tcp(InitState); + %% false -> + %% {skip, ipv6_not_supported} + %% end, + %% tc_end(), + %% Res. not_yet_implemented(). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -api_to_recv_tcp(InitState) -> +api_to_receive_tcp(InitState) -> process_flag(trap_exit, true), ServerSeq = @@ -1694,8 +1702,8 @@ api_to_recv_tcp(InitState) -> end end}, #{desc => "attempt to recv (without success)", - cmd => fun(#{sock := Sock} = _State) -> - case socket:recv(Sock, 0, 5000) of + cmd => fun(#{sock := Sock, recv := Recv} = _State) -> + case Recv(Sock) of {error, timeout} -> ok; {ok, _Data} -> @@ -1910,7 +1918,7 @@ api_to_recv_tcp(InitState) -> end end}, #{desc => "order server to terminate", - cmd => fun(#{server := Server} = State) -> + cmd => fun(#{server := Server} = _State) -> Server ! {terminate, self()}, ok end}, @@ -2067,9 +2075,10 @@ api_to_recvmsg_tcp4(doc) -> []; api_to_recvmsg_tcp4(_Config) when is_list(_Config) -> tc_begin(api_to_recvmsg_tcp4), - ok = api_to_recvmsg_tcp(inet), + Recv = fun(Sock) -> socket:recvmsg(Sock, 5000) end, + InitState = #{domain => inet, recv => Recv}, + ok = api_to_receive_tcp(InitState), tc_end(). - %% not_yet_implemented(). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -2082,60 +2091,13 @@ api_to_recvmsg_tcp6(doc) -> []; api_to_recvmsg_tcp6(_Config) when is_list(_Config) -> %% tc_begin(api_to_recvmsg_tcp6), - %% ok = api_to_recvmsg_tcp(inet6), + %% Recv = fun(Sock) -> socket:recvmsg(Sock, 5000) end, + %% InitState = #{domain => inet6, recv => Recv}, + %% ok = api_to_receive_tcp(InitState), %% tc_end(). not_yet_implemented(). -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -api_to_recvmsg_tcp(Domain) -> - process_flag(trap_exit, true), - p("server -> open"), - LSock = sock_open(Domain, stream, tcp), - LocalAddr = which_local_addr(Domain), - LocalSA = #{family => Domain, addr => LocalAddr}, - p("server -> bind"), - ServerLPort = sock_bind(LSock, LocalSA), - p("server(~w) -> listen", [ServerLPort]), - sock_listen(LSock), - ClientName = f("~s:client", [get_tc_name()]), - Client = spawn_link(fun() -> - put(sname, ClientName), - p("open"), - CSock = sock_open(Domain, stream, tcp), - p("bind"), - ClientPort = sock_bind(CSock, LocalSA), - p("[~w] connect to ~w", - [ClientPort, ServerLPort]), - sock_connect(CSock, LocalSA#{port => ServerLPort}), - p("await termination command"), - receive - die -> - p("terminating"), - exit(normal) - end - end), - p("server -> accept on ~w", [ServerLPort]), - Sock = sock_accept(LSock), - p("server -> recv"), - %% The zero (0) represents "give me everything you have" - case socket:recvmsg(Sock, 5000) of - {error, timeout} -> - p("server -> expected timeout"), - ok; - {ok, _Data} -> - ?FAIL(unexpected_success); - {error, Reason} -> - ?FAIL({recv, Reason}) - end, - Client ! die, - receive - {'EXIT', Client, _} -> - ok - end, - ok. - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -2312,36 +2274,36 @@ sock_sockname(Sock) -> end. -sock_listen(Sock) -> - sock_listen2(fun() -> socket:listen(Sock) end). - -sock_listen(Sock, BackLog) -> - sock_listen2(fun() -> socket:listen(Sock, BackLog) end). - -sock_listen2(Listen) -> - try Listen() of - ok -> - ok; - {error, Reason} -> - ?FAIL({listen, Reason}) - catch - C:E:S -> - ?FAIL({listen, C, E, S}) - end. - - -sock_accept(LSock) -> - try socket:accept(LSock) of - {ok, Sock} -> - Sock; - {error, Reason} -> - p("sock_accept -> error: ~p", [Reason]), - ?FAIL({accept, Reason}) - catch - C:E:S -> - p("sock_accept -> failed: ~p, ~p, ~p", [C, E, S]), - ?FAIL({accept, C, E, S}) - end. +%% sock_listen(Sock) -> +%% sock_listen2(fun() -> socket:listen(Sock) end). + +%% sock_listen(Sock, BackLog) -> +%% sock_listen2(fun() -> socket:listen(Sock, BackLog) end). + +%% sock_listen2(Listen) -> +%% try Listen() of +%% ok -> +%% ok; +%% {error, Reason} -> +%% ?FAIL({listen, Reason}) +%% catch +%% C:E:S -> +%% ?FAIL({listen, C, E, S}) +%% end. + + +%% sock_accept(LSock) -> +%% try socket:accept(LSock) of +%% {ok, Sock} -> +%% Sock; +%% {error, Reason} -> +%% p("sock_accept -> error: ~p", [Reason]), +%% ?FAIL({accept, Reason}) +%% catch +%% C:E:S -> +%% p("sock_accept -> failed: ~p, ~p, ~p", [C, E, S]), +%% ?FAIL({accept, C, E, S}) +%% end. sock_close(Sock) -> @@ -2372,8 +2334,8 @@ set_tc_name(N) when is_atom(N) -> set_tc_name(N) when is_list(N) -> put(tc_name, N). -get_tc_name() -> - get(tc_name). +%% get_tc_name() -> +%% get(tc_name). tc_begin(TC) -> set_tc_name(TC), @@ -2386,8 +2348,8 @@ tc_end() -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -f(F, A) -> - lists:flatten(io_lib:format(F, A)). +%% f(F, A) -> +%% lists:flatten(io_lib:format(F, A)). p(F) -> p(F, []). -- cgit v1.2.3 From c4c1f1d2bd307a88c5668a489d131dc6b74bf3af Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Thu, 11 Oct 2018 19:13:31 +0200 Subject: [socket-nif|test] Wrapped each test case in try Each test case is wrapped in a try catch in the ttc_try function. It handles entry, exit and skip. --- lib/kernel/test/socket_SUITE.erl | 428 ++++++++++++++++++++++----------------- 1 file changed, 238 insertions(+), 190 deletions(-) (limited to 'lib') diff --git a/lib/kernel/test/socket_SUITE.erl b/lib/kernel/test/socket_SUITE.erl index a432473f01..dc9d5240ca 100644 --- a/lib/kernel/test/socket_SUITE.erl +++ b/lib/kernel/test/socket_SUITE.erl @@ -49,8 +49,8 @@ api_to_accept_tcp6/1, api_to_send_tcp4/1, api_to_send_tcp6/1, - api_to_sendapi_to_udp4/1, - api_to_sendapi_to_udp6/1, + api_to_sendto_udp4/1, + api_to_sendto_udp6/1, api_to_sendmsg_tcp4/1, api_to_sendmsg_tcp6/1, api_to_recv_udp4/1, @@ -143,8 +143,8 @@ api_op_with_timeout_cases() -> api_to_accept_tcp6, api_to_send_tcp4, api_to_send_tcp6, - api_to_sendapi_to_udp4, - api_to_sendapi_to_udp6, + api_to_sendto_udp4, + api_to_sendto_udp6, api_to_sendmsg_tcp4, api_to_sendmsg_tcp6, api_to_recv_udp4, @@ -190,12 +190,13 @@ api_b_open_and_close_udp4(suite) -> api_b_open_and_close_udp4(doc) -> []; api_b_open_and_close_udp4(_Config) when is_list(_Config) -> - tc_begin(api_b_open_and_close_udp4), - State = #{domain => inet, - type => dgram, - protocol => udp}, - ok = api_b_open_and_close(State), - tc_end(). + tc_try(api_b_open_and_close_udp4, + fun() -> + InitState = #{domain => inet, + type => dgram, + protocol => udp}, + ok = api_b_open_and_close(InitState) + end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -207,12 +208,13 @@ api_b_open_and_close_tcp4(suite) -> api_b_open_and_close_tcp4(doc) -> []; api_b_open_and_close_tcp4(_Config) when is_list(_Config) -> - tc_begin(api_b_open_and_close_tcp4), - State = #{domain => inet, - type => stream, - protocol => tcp}, - ok = api_b_open_and_close(State), - tc_end(). + tc_try(api_b_open_and_close_tcp4, + fun() -> + InitState = #{domain => inet, + type => stream, + protocol => tcp}, + ok = api_b_open_and_close(InitState) + end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -317,18 +319,19 @@ api_b_sendto_and_recvfrom_udp4(suite) -> api_b_sendto_and_recvfrom_udp4(doc) -> []; api_b_sendto_and_recvfrom_udp4(_Config) when is_list(_Config) -> - tc_begin(api_b_sendto_and_recvfrom_udp4), - Send = fun(Sock, Data, Dest) -> - socket:sendto(Sock, Data, Dest) - end, - Recv = fun(Sock) -> - socket:recvfrom(Sock) - end, - InitState = #{domain => inet, - send => Send, - recv => Recv}, - ok = api_b_send_and_recv_udp(InitState), - tc_end(). + tc_try(api_b_sendto_and_recvfrom_udp4, + fun() -> + Send = fun(Sock, Data, Dest) -> + socket:sendto(Sock, Data, Dest) + end, + Recv = fun(Sock) -> + socket:recvfrom(Sock) + end, + InitState = #{domain => inet, + send => Send, + recv => Recv}, + ok = api_b_send_and_recv_udp(InitState) + end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -340,29 +343,32 @@ api_b_sendmsg_and_recvmsg_udp4(suite) -> api_b_sendmsg_and_recvmsg_udp4(doc) -> []; api_b_sendmsg_and_recvmsg_udp4(_Config) when is_list(_Config) -> - tc_begin(api_b_sendmsg_and_recvmsg_udp4), - Send = fun(Sock, Data, Dest) -> - %% CMsgHdr = #{level => ip, type => tos, data => reliability}, - %% CMsgHdrs = [CMsgHdr], + tc_try(api_b_sendmsg_and_recvmsg_udp4, + fun() -> + Send = fun(Sock, Data, Dest) -> + %% CMsgHdr = #{level => ip, + %% type => tos, + %% data => reliability}, + %% CMsgHdrs = [CMsgHdr], MsgHdr = #{addr => Dest, %% ctrl => CMsgHdrs, iov => [Data]}, - socket:sendmsg(Sock, MsgHdr) - end, - Recv = fun(Sock) -> - case socket:recvmsg(Sock) of - {ok, #{addr := Source, - iov := [Data]}} -> - {ok, {Source, Data}}; - {error, _} = ERROR -> - ERROR - end - end, - InitState = #{domain => inet, - send => Send, - recv => Recv}, - ok = api_b_send_and_recv_udp(InitState), - tc_end(). + socket:sendmsg(Sock, MsgHdr) + end, + Recv = fun(Sock) -> + case socket:recvmsg(Sock) of + {ok, #{addr := Source, + iov := [Data]}} -> + {ok, {Source, Data}}; + {error, _} = ERROR -> + ERROR + end + end, + InitState = #{domain => inet, + send => Send, + recv => Recv}, + ok = api_b_send_and_recv_udp(InitState) + end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -451,18 +457,19 @@ api_b_send_and_recv_tcp4(suite) -> api_b_send_and_recv_tcp4(doc) -> []; api_b_send_and_recv_tcp4(_Config) when is_list(_Config) -> - tc_begin(api_b_send_and_recv_tcp4), - Send = fun(Sock, Data) -> - socket:send(Sock, Data) - end, - Recv = fun(Sock) -> - socket:recv(Sock) - end, - InitState = #{domain => inet, - send => Send, - recv => Recv}, - ok = api_b_send_and_recv_tcp(InitState), - tc_end(). + tc_try(api_b_send_and_recv_tcp4, + fun() -> + Send = fun(Sock, Data) -> + socket:send(Sock, Data) + end, + Recv = fun(Sock) -> + socket:recv(Sock) + end, + InitState = #{domain => inet, + send => Send, + recv => Recv}, + ok = api_b_send_and_recv_tcp(InitState) + end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -474,25 +481,26 @@ api_b_sendmsg_and_recvmsg_tcp4(suite) -> api_b_sendmsg_and_recvmsg_tcp4(doc) -> []; api_b_sendmsg_and_recvmsg_tcp4(_Config) when is_list(_Config) -> - tc_begin(api_b_sendmsg_and_recvmsg_tcp4), - Send = fun(Sock, Data) -> - MsgHdr = #{iov => [Data]}, - socket:sendmsg(Sock, MsgHdr) - end, - Recv = fun(Sock) -> - case socket:recvmsg(Sock) of - {ok, #{addr := undefined, - iov := [Data]}} -> - {ok, Data}; - {error, _} = ERROR -> - ERROR - end - end, - InitState = #{domain => inet, - send => Send, - recv => Recv}, - ok = api_b_send_and_recv_tcp(InitState), - tc_end(). + tc_try(api_b_sendmsg_and_recvmsg_tcp4, + fun() -> + Send = fun(Sock, Data) -> + MsgHdr = #{iov => [Data]}, + socket:sendmsg(Sock, MsgHdr) + end, + Recv = fun(Sock) -> + case socket:recvmsg(Sock) of + {ok, #{addr := undefined, + iov := [Data]}} -> + {ok, Data}; + {error, _} = ERROR -> + ERROR + end + end, + InitState = #{domain => inet, + send => Send, + recv => Recv}, + ok = api_b_send_and_recv_tcp(InitState) + end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -650,8 +658,10 @@ api_opt_simple_otp_options(suite) -> api_opt_simple_otp_options(doc) -> []; api_opt_simple_otp_options(_Config) when is_list(_Config) -> - tc_begin(api_opt_simple_otp_options), + tc_try(api_opt_simple_otp_options, + fun() -> api_opt_simple_otp_options() end). +api_opt_simple_otp_options() -> Get = fun(S, Key) -> socket:getopt(S, otp, Key) end, @@ -897,9 +907,7 @@ api_opt_simple_otp_options(_Config) when is_list(_Config) -> InitState2 = #{domain => inet, type => dgram, protocol => udp}, Tester2 = evaluator_start("udp-tester", Seq, InitState2), p("await evaluator 2"), - ok = await_evaluator_finish([Tester2]), - - tc_end(). + ok = await_evaluator_finish([Tester2]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -910,8 +918,10 @@ api_opt_simple_otp_controlling_process(suite) -> api_opt_simple_otp_controlling_process(doc) -> []; api_opt_simple_otp_controlling_process(_Config) when is_list(_Config) -> - tc_begin(api_opt_simple_otp_controlling_process), + tc_try(api_opt_simple_otp_controlling_process, + fun() -> api_opt_simple_otp_controlling_process() end). +api_opt_simple_otp_controlling_process() -> Get = fun(S, Key) -> socket:getopt(S, otp, Key) end, @@ -1147,9 +1157,8 @@ api_opt_simple_otp_controlling_process(_Config) when is_list(_Config) -> client => Client2}, Tester2 = evaluator_start("udp-tester", TesterSeq, TesterInitState2), p("await dgram/udp evaluator"), - ok = await_evaluator_finish([Tester2, Client2]), + ok = await_evaluator_finish([Tester2, Client2]). - tc_end(). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1161,11 +1170,11 @@ api_to_connect_tcp4(suite) -> api_to_connect_tcp4(doc) -> []; api_to_connect_tcp4(_Config) when is_list(_Config) -> - tc_begin(api_to_connect_tcp4), - InitState = #{domain => inet}, - ok = api_to_connect_tcp(InitState), - tc_end(). - %% not_yet_implemented(). + tc_try(api_to_connect_tcp4, + fun() -> + InitState = #{domain => inet}, + ok = api_to_connect_tcp(InitState) + end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1177,11 +1186,12 @@ api_to_connect_tcp6(suite) -> api_to_connect_tcp6(doc) -> []; api_to_connect_tcp6(_Config) when is_list(_Config) -> - %% tc_begin(api_to_connect_tcp6), - %% InitState = #{domain => inet6}, - %% ok = api_to_connect_tcp(InitState), - %% tc_end(). - not_yet_implemented(). + tc_try(api_to_connect_tcp6, + fun() -> + not_yet_implemented(), + InitState = #{domain => inet6}, + ok = api_to_connect_tcp(InitState) + end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1429,7 +1439,7 @@ api_to_connect_tcp_await_timeout([Sock|Socks], ServerSA, ID) -> ee("failed connecting: ~p", [Reason]), ?FAIL({connect, Reason}); ok -> - ei("unexpected success (~w) - try next", [ID]), + ei("unexpected success (~w) - try next", [ID]), api_to_connect_tcp_await_timeout(Socks, ServerSA, ID+1) end. @@ -1444,10 +1454,11 @@ api_to_accept_tcp4(suite) -> api_to_accept_tcp4(doc) -> []; api_to_accept_tcp4(_Config) when is_list(_Config) -> - %% tc_begin(api_to_accept_tcp4), - %% ok = api_to_accept_tcp(inet), - %% tc_end(). - not_yet_implemented(). + tc_try(api_to_accept_tcp4, + fun() -> + not_yet_implemented()%% , + %% ok = api_to_accept_tcp(inet) + end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1459,10 +1470,11 @@ api_to_accept_tcp6(suite) -> api_to_accept_tcp6(doc) -> []; api_to_accept_tcp6(_Config) when is_list(_Config) -> - %% tc_begin(api_to_accept_tcp6), - %% ok = api_to_accept_tcp(inet6), - %% tc_end(). - not_yet_implemented(). + tc_try(api_to_accept_tcp4, + fun() -> + not_yet_implemented()%% , + %% ok = api_to_accept_tcp(inet6) + end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1474,10 +1486,11 @@ api_to_send_tcp4(suite) -> api_to_send_tcp4(doc) -> []; api_to_send_tcp4(_Config) when is_list(_Config) -> - %% tc_begin(api_to_send_tcp4), - %% ok = api_to_send_tcp(inet), - %% tc_end(). - not_yet_implemented(). + tc_try(api_to_send_tcp4, + fun() -> + not_yet_implemented()%% , + %% ok = api_to_send_tcp(inet) + end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1489,40 +1502,43 @@ api_to_send_tcp6(suite) -> api_to_send_tcp6(doc) -> []; api_to_send_tcp6(_Config) when is_list(_Config) -> - %% tc_begin(api_to_send_tcp6), - %% ok = api_to_send_tcp(inet6), - %% tc_end(). - not_yet_implemented(). + tc_try(api_to_send_tcp6, + fun() -> + not_yet_implemented()%% , + %% ok = api_to_send_tcp(inet6) + end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test the sendto timeout option %% on an IPv4 UDP (dgram) socket. -api_to_sendapi_to_udp4(suite) -> +api_to_sendto_udp4(suite) -> []; -api_to_sendapi_to_udp4(doc) -> +api_to_sendto_udp4(doc) -> []; -api_to_sendapi_to_udp4(_Config) when is_list(_Config) -> - %% tc_begin(api_to_sendapi_to_udp4), - %% ok = api_to_sendapi_to_udp(inet), - %% tc_end(). - not_yet_implemented(). +api_to_sendto_udp4(_Config) when is_list(_Config) -> + tc_try(api_to_sendto_udp4, + fun() -> + not_yet_implemented()%% , + %% ok = api_to_sendto_to_udp(inet) + end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test the sendto timeout option %% on an IPv6 UDP (dgram) socket. -api_to_sendapi_to_udp6(suite) -> +api_to_sendto_udp6(suite) -> []; -api_to_sendapi_to_udp6(doc) -> +api_to_sendto_udp6(doc) -> []; -api_to_sendapi_to_udp6(_Config) when is_list(_Config) -> - %% tc_begin(api_to_sendapi_to_udp6), - %% ok = api_to_sendapi_to_udp(inet6), - %% tc_end(). - not_yet_implemented(). +api_to_sendto_udp6(_Config) when is_list(_Config) -> + tc_try(api_to_sendto_udp6, + fun() -> + not_yet_implemented()%% , + %% ok = api_to_sendto_to_udp(inet6) + end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1534,10 +1550,11 @@ api_to_sendmsg_tcp4(suite) -> api_to_sendmsg_tcp4(doc) -> []; api_to_sendmsg_tcp4(_Config) when is_list(_Config) -> - %% tc_begin(api_to_sendmsg_tcp4), - %% ok = api_to_sendmsg_tcp(inet), - %% tc_end(). - not_yet_implemented(). + tc_try(api_to_sendmsg_tcp4, + fun() -> + not_yet_implemented()%% , + %% ok = api_to_sendmsg_tcp(inet) + end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1549,10 +1566,11 @@ api_to_sendmsg_tcp6(suite) -> api_to_sendmsg_tcp6(doc) -> []; api_to_sendmsg_tcp6(_Config) when is_list(_Config) -> - %% tc_begin(api_to_sendmsg_tcp6), - %% ok = api_to_sendmsg_tcp(inet6), - %% tc_end(). - not_yet_implemented(). + tc_try(api_to_sendmsg_tcp6, + fun() -> + not_yet_implemented()%% , + %% ok = api_to_sendmsg_tcp(inet6) + end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1565,10 +1583,11 @@ api_to_recv_udp4(suite) -> api_to_recv_udp4(doc) -> []; api_to_recv_udp4(_Config) when is_list(_Config) -> - %% tc_begin(api_to_recv_udp4), - %% ok = api_to_recv_udp(inet), - %% tc_end(). - not_yet_implemented(). + tc_try(api_to_recv_udp4, + fun() -> + not_yet_implemented()%%, + %%ok = api_to_recv_udp(inet) + end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1581,10 +1600,11 @@ api_to_recv_udp6(suite) -> api_to_recv_udp6(doc) -> []; api_to_recv_udp6(_Config) when is_list(_Config) -> - %% tc_begin(api_to_recv_udp6), - %% ok = api_to_recv_udp(inet6), - %% tc_end(). - not_yet_implemented(). + tc_try(api_to_recv_udp6, + fun() -> + not_yet_implemented()%% , + %% ok = api_to_recv_udp(inet6) + end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1596,11 +1616,12 @@ api_to_recv_tcp4(suite) -> api_to_recv_tcp4(doc) -> []; api_to_recv_tcp4(_Config) when is_list(_Config) -> - tc_begin(api_to_recv_tcp4), - Recv = fun(Sock) -> socket:recv(Sock, 0, 5000) end, - InitState = #{domain => inet, recv => Recv}, - ok = api_to_receive_tcp(InitState), - tc_end(). + tc_try(api_to_recv_tcp4, + fun() -> + Recv = fun(Sock) -> socket:recv(Sock, 0, 5000) end, + InitState = #{domain => inet, recv => Recv}, + ok = api_to_receive_tcp(InitState) + end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1612,18 +1633,20 @@ api_to_recv_tcp6(suite) -> api_to_recv_tcp6(doc) -> []; api_to_recv_tcp6(_Config) when is_list(_Config) -> - %% tc_begin(api_to_recv_tcp6), - %% Res = case socket:supports(ipv6) of - %% true -> - %% Recv = fun(Sock) -> socket:recv(Sock, 0, 5000) end, - %% InitState = #{domain => inet6, recv => Recv}, - %% ok = api_to_receive_tcp(InitState); - %% false -> - %% {skip, ipv6_not_supported} - %% end, - %% tc_end(), - %% Res. - not_yet_implemented(). + tc_try(api_to_recv_tcp6, + fun() -> + not_yet_implemented(), + case socket:supports(ipv6) of + true -> + Recv = fun(Sock) -> + socket:recv(Sock, 0, 5000) + end, + InitState = #{domain => inet6, recv => Recv}, + ok = api_to_receive_tcp(InitState); + false -> + skip("ipv6 not supported") + end + end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1967,9 +1990,10 @@ api_to_recvfrom_udp4(suite) -> api_to_recvfrom_udp4(doc) -> []; api_to_recvfrom_udp4(_Config) when is_list(_Config) -> - tc_begin(api_to_recvfrom_udp4), - ok = api_to_recvfrom_udp(inet), - tc_end(). + tc_try(api_to_recvfrom_udp4, + fun() -> + ok = api_to_recvfrom_udp(inet) + end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1981,10 +2005,11 @@ api_to_recvfrom_udp6(suite) -> api_to_recvfrom_udp6(doc) -> []; api_to_recvfrom_udp6(_Config) when is_list(_Config) -> - %% tc_begin(api_to_recvfrom_udp6), - %% ok = api_to_recvfrom_udp(inet6), - %% tc_end(). - not_yet_implemented(). + tc_try(api_to_recvfrom_udp6, + fun() -> + not_yet_implemented(), + ok = api_to_recvfrom_udp(inet6) + end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -2020,10 +2045,10 @@ api_to_recvmsg_udp4(suite) -> api_to_recvmsg_udp4(doc) -> []; api_to_recvmsg_udp4(_Config) when is_list(_Config) -> - %% not_yet_implemented(). - tc_begin(api_to_recvmsg_udp4), - ok = api_to_recvmsg_udp(inet), - tc_end(). + tc_try(api_to_recvmsg_udp4, + fun() -> + ok = api_to_recvmsg_udp(inet) + end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -2035,10 +2060,11 @@ api_to_recvmsg_udp6(suite) -> api_to_recvmsg_udp6(doc) -> []; api_to_recvmsg_udp6(_Config) when is_list(_Config) -> - %% tc_begin(api_to_recvmsg_udp6), - %% ok = api_to_recvmsg_udp(inet6), - %% tc_end(). - not_yet_implemented(). + tc_try(api_to_recvmsg_udp6, + fun() -> + not_yet_implemented(), + ok = api_to_recvmsg_udp(inet6) + end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -2074,11 +2100,12 @@ api_to_recvmsg_tcp4(suite) -> api_to_recvmsg_tcp4(doc) -> []; api_to_recvmsg_tcp4(_Config) when is_list(_Config) -> - tc_begin(api_to_recvmsg_tcp4), - Recv = fun(Sock) -> socket:recvmsg(Sock, 5000) end, - InitState = #{domain => inet, recv => Recv}, - ok = api_to_receive_tcp(InitState), - tc_end(). + tc_try(api_to_recvmsg_tcp4, + fun() -> + Recv = fun(Sock) -> socket:recvmsg(Sock, 5000) end, + InitState = #{domain => inet, recv => Recv}, + ok = api_to_receive_tcp(InitState) + end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -2090,13 +2117,13 @@ api_to_recvmsg_tcp6(suite) -> api_to_recvmsg_tcp6(doc) -> []; api_to_recvmsg_tcp6(_Config) when is_list(_Config) -> - %% tc_begin(api_to_recvmsg_tcp6), - %% Recv = fun(Sock) -> socket:recvmsg(Sock, 5000) end, - %% InitState = #{domain => inet6, recv => Recv}, - %% ok = api_to_receive_tcp(InitState), - %% tc_end(). - not_yet_implemented(). - + tc_try(api_to_recvmsg_tcp6, + fun() -> + not_yet_implemented(), + Recv = fun(Sock) -> socket:recvmsg(Sock, 5000) end, + InitState = #{domain => inet6, recv => Recv}, + ok = api_to_receive_tcp(InitState) + end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -2324,7 +2351,10 @@ sock_close(Sock) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% not_yet_implemented() -> - {skip, "not yet implemented"}. + skip("not yet implemented"). + +skip(Reason) -> + throw({skip, Reason}). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -2341,11 +2371,29 @@ tc_begin(TC) -> set_tc_name(TC), p("begin ***"). -tc_end() -> - p("done ***"), +tc_end(Result) when is_list(Result) -> + p("done: ~s", [Result]), ok. +tc_try(Case, Fun) when is_atom(Case) andalso is_function(Fun, 0) -> + tc_begin(Case), + try + begin + Fun(), + tc_end("ok") + end + catch + throw:{skip, _} = SKIP -> + tc_end("skipping"), + SKIP; + Class:Error:Stack -> + tc_end("failed"), + erlang:raise(Class, Error, Stack) + end. + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% f(F, A) -> -- cgit v1.2.3 From cb2d61a99ff3613f9b47598844a0274049859b7e Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Fri, 12 Oct 2018 10:48:00 +0200 Subject: [socket-nif|test] Reworked (IPv4) udp recvfrom timeout test case --- lib/kernel/test/socket_SUITE.erl | 88 ++++++++++++++++++++++++++++++---------- 1 file changed, 66 insertions(+), 22 deletions(-) (limited to 'lib') diff --git a/lib/kernel/test/socket_SUITE.erl b/lib/kernel/test/socket_SUITE.erl index dc9d5240ca..724bbc9539 100644 --- a/lib/kernel/test/socket_SUITE.erl +++ b/lib/kernel/test/socket_SUITE.erl @@ -1992,7 +1992,8 @@ api_to_recvfrom_udp4(doc) -> api_to_recvfrom_udp4(_Config) when is_list(_Config) -> tc_try(api_to_recvfrom_udp4, fun() -> - ok = api_to_recvfrom_udp(inet) + InitState = #{domain => inet}, + ok = api_to_recvfrom_udp(InitState) end). @@ -2008,32 +2009,75 @@ api_to_recvfrom_udp6(_Config) when is_list(_Config) -> tc_try(api_to_recvfrom_udp6, fun() -> not_yet_implemented(), - ok = api_to_recvfrom_udp(inet6) + InitState = #{domain => inet6}, + ok = api_to_recvfrom_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -api_to_recvfrom_udp(Domain) -> - process_flag(trap_exit, true), - p("init"), - LocalAddr = which_local_addr(Domain), - LocalSA = #{family => Domain, addr => LocalAddr}, - p("open"), - Sock = sock_open(Domain, dgram, udp), - p("bind"), - _Port = sock_bind(Sock, LocalSA), - p("recv"), - case socket:recvfrom(Sock, 0, 5000) of - {error, timeout} -> - p("expected timeout"), - ok; - {ok, _SrcData} -> - ?FAIL(unexpected_success); - {error, Reason} -> - ?FAIL({recv, Reason}) - end, - ok. +api_to_recvfrom_udp(InitState) -> + TesterSeq = + [ + %% *** Init part *** + #{desc => "which local address", + cmd => fun(#{domain := Domain} = State) -> + LAddr = which_local_addr(Domain), + LSA = #{family => Domain, addr => LAddr}, + {ok, State#{lsa => LSA}} + end}, + #{desc => "create socket", + cmd => fun(#{domain := Domain} = State) -> + case socket:open(Domain, dgram, udp) of + {ok, Sock} -> + {ok, State#{sock => Sock}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "bind to local address", + cmd => fun(#{sock := Sock, lsa := LSA} = _State) -> + case socket:bind(Sock, LSA) of + {ok, _Port} -> + ok; + {error, _} = ERROR -> + ERROR + end + end}, + + %% *** The actual test *** + #{desc => "attempt to read (without success)", + cmd => fun(#{sock := Sock} = _State) -> + case socket:recvfrom(Sock, 0, 5000) of + {error, timeout} -> + ok; + {ok, _SrcData} -> + {error, unexpected_sucsess}; + {error, _} = ERROR -> + ERROR + end + end}, + + %% *** Termination *** + #{desc => "close socket", + cmd => fun(#{sock := Sock} = _State) -> + sock_close(Sock), + ok + end}, + + %% *** We are done *** + #{desc => "finish", + cmd => fun(_) -> + {ok, normal} + end} + ], + + p("start tester evaluator"), + Tester = evaluator_start("tester", TesterSeq, InitState), + + p("await evaluator"), + ok = await_evaluator_finish([Tester]). + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -- cgit v1.2.3 From 227eb3efe1cd42324c315dc14d9945ffcd935069 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Fri, 12 Oct 2018 11:05:26 +0200 Subject: [socket-nif|test] Reworked (IPv4) udp recvmsg timeout test case --- lib/kernel/test/socket_SUITE.erl | 63 ++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 34 deletions(-) (limited to 'lib') diff --git a/lib/kernel/test/socket_SUITE.erl b/lib/kernel/test/socket_SUITE.erl index 724bbc9539..82d79ef32b 100644 --- a/lib/kernel/test/socket_SUITE.erl +++ b/lib/kernel/test/socket_SUITE.erl @@ -1992,8 +1992,9 @@ api_to_recvfrom_udp4(doc) -> api_to_recvfrom_udp4(_Config) when is_list(_Config) -> tc_try(api_to_recvfrom_udp4, fun() -> - InitState = #{domain => inet}, - ok = api_to_recvfrom_udp(InitState) + Recv = fun(Sock) -> socket:recvfrom(Sock, 0, 5000) end, + InitState = #{domain => inet, recv => Recv}, + ok = api_to_receive_udp(InitState) end). @@ -2009,14 +2010,15 @@ api_to_recvfrom_udp6(_Config) when is_list(_Config) -> tc_try(api_to_recvfrom_udp6, fun() -> not_yet_implemented(), - InitState = #{domain => inet6}, - ok = api_to_recvfrom_udp(InitState) + Recv = fun(Sock) -> socket:recvfrom(Sock, 0, 5000) end, + InitState = #{domain => inet6, recv => Recv}, + ok = api_to_receive_udp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -api_to_recvfrom_udp(InitState) -> +api_to_receive_udp(InitState) -> TesterSeq = [ %% *** Init part *** @@ -2047,11 +2049,11 @@ api_to_recvfrom_udp(InitState) -> %% *** The actual test *** #{desc => "attempt to read (without success)", - cmd => fun(#{sock := Sock} = _State) -> - case socket:recvfrom(Sock, 0, 5000) of + cmd => fun(#{sock := Sock, recv := Recv} = _State) -> + case Recv(Sock) of {error, timeout} -> ok; - {ok, _SrcData} -> + {ok, _} -> {error, unexpected_sucsess}; {error, _} = ERROR -> ERROR @@ -2091,7 +2093,9 @@ api_to_recvmsg_udp4(doc) -> api_to_recvmsg_udp4(_Config) when is_list(_Config) -> tc_try(api_to_recvmsg_udp4, fun() -> - ok = api_to_recvmsg_udp(inet) + Recv = fun(Sock) -> socket:recvmsg(Sock, 5000) end, + InitState = #{domain => inet, recv => Recv}, + ok = api_to_receive_udp(InitState) end). @@ -2107,34 +2111,12 @@ api_to_recvmsg_udp6(_Config) when is_list(_Config) -> tc_try(api_to_recvmsg_udp6, fun() -> not_yet_implemented(), - ok = api_to_recvmsg_udp(inet6) + Recv = fun(Sock) -> socket:recvmsg(Sock, 5000) end, + InitState = #{domain => inet6, recv => Recv}, + ok = api_to_receive_udp(InitState) end). -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -api_to_recvmsg_udp(Domain) -> - process_flag(trap_exit, true), - p("init"), - LocalAddr = which_local_addr(Domain), - LocalSA = #{family => Domain, addr => LocalAddr}, - p("open"), - Sock = sock_open(Domain, dgram, udp), - p("bind"), - _Port = sock_bind(Sock, LocalSA), - p("recv"), - case socket:recvmsg(Sock, 5000) of - {error, timeout} -> - p("expected timeout"), - ok; - {ok, _MsgHdr} -> - ?FAIL(unexpected_success); - {error, Reason} -> - ?FAIL({recv, Reason}) - end, - ok. - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test the recvmsg timeout option @@ -2401,6 +2383,19 @@ skip(Reason) -> throw({skip, Reason}). +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% t() -> +%% os:timestamp(). + + +%% tdiff({A1, B1, C1} = _T1x, {A2, B2, C2} = _T2x) -> +%% T1 = A1*1000000000+B1*1000+(C1 div 1000), +%% T2 = A2*1000000000+B2*1000+(C2 div 1000), +%% T2 - T1. + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% set_tc_name(N) when is_atom(N) -> -- cgit v1.2.3 From 22336422d7a014db53dcba7ff1b6e71a1729d89a Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Fri, 12 Oct 2018 11:59:16 +0200 Subject: [socket-nif|test] Add accept timeout test case and update other timeout test cases(s) Added simple accept timeout testcase. Updated timeout test cases(s) with a timeout validation. OTP-14831 --- lib/kernel/test/socket_SUITE.erl | 249 ++++++++++++++++++++++++++++++--------- 1 file changed, 196 insertions(+), 53 deletions(-) (limited to 'lib') diff --git a/lib/kernel/test/socket_SUITE.erl b/lib/kernel/test/socket_SUITE.erl index 82d79ef32b..de6a20e60b 100644 --- a/lib/kernel/test/socket_SUITE.erl +++ b/lib/kernel/test/socket_SUITE.erl @@ -1172,7 +1172,7 @@ api_to_connect_tcp4(doc) -> api_to_connect_tcp4(_Config) when is_list(_Config) -> tc_try(api_to_connect_tcp4, fun() -> - InitState = #{domain => inet}, + InitState = #{domain => inet, timeout => 5000}, ok = api_to_connect_tcp(InitState) end). @@ -1189,7 +1189,7 @@ api_to_connect_tcp6(_Config) when is_list(_Config) -> tc_try(api_to_connect_tcp6, fun() -> not_yet_implemented(), - InitState = #{domain => inet6}, + InitState = #{domain => inet6, timeout => 5000}, ok = api_to_connect_tcp(InitState) end). @@ -1352,12 +1352,13 @@ api_to_connect_tcp(InitState) -> %% *** Connect sequence *** #{desc => "order (server) start", - cmd => fun(#{sock1 := Sock1, - sock2 := Sock2, - sock3 := Sock3, - ssa := SSA}) -> + cmd => fun(#{sock1 := Sock1, + sock2 := Sock2, + sock3 := Sock3, + ssa := SSA, + timeout := To}) -> Socks = [Sock1, Sock2, Sock3], - api_to_connect_tcp_await_timeout(Socks, SSA) + api_to_connect_tcp_await_timeout(Socks, To, SSA) end}, %% *** Terminate server *** @@ -1417,21 +1418,28 @@ api_to_connect_tcp(InitState) -> Tester = evaluator_start("tester", TesterSeq, TesterInitState), p("await evaluator(s)"), - ok = await_evaluator_finish([Server, Tester]), - ok. + ok = await_evaluator_finish([Server, Tester]). -api_to_connect_tcp_await_timeout(Socks, ServerSA) -> - api_to_connect_tcp_await_timeout(Socks, ServerSA, 1). +api_to_connect_tcp_await_timeout(Socks, To, ServerSA) -> + api_to_connect_tcp_await_timeout(Socks, To, ServerSA, 1). -api_to_connect_tcp_await_timeout([], _ServerSA, _ID) -> +api_to_connect_tcp_await_timeout([], _To, _ServerSA, _ID) -> ?FAIL(unexpected_success); -api_to_connect_tcp_await_timeout([Sock|Socks], ServerSA, ID) -> +api_to_connect_tcp_await_timeout([Sock|Socks], To, ServerSA, ID) -> ei("~w: try connect", [ID]), - case socket:connect(Sock, ServerSA, 5000) of + Start = t(), + case socket:connect(Sock, ServerSA, To) of {error, timeout} -> ei("expected timeout (~w)", [ID]), - ok; + Stop = t(), + TDiff = tdiff(Start, Stop), + if + (TDiff >= To) -> + ok; + true -> + {error, {unexpected_timeout, TDiff, To}} + end; {error, econnreset = Reason} -> ei("failed connecting: ~p - giving up", [Reason]), ok; @@ -1440,7 +1448,7 @@ api_to_connect_tcp_await_timeout([Sock|Socks], ServerSA, ID) -> ?FAIL({connect, Reason}); ok -> ei("unexpected success (~w) - try next", [ID]), - api_to_connect_tcp_await_timeout(Socks, ServerSA, ID+1) + api_to_connect_tcp_await_timeout(Socks, To, ServerSA, ID+1) end. @@ -1456,8 +1464,8 @@ api_to_accept_tcp4(doc) -> api_to_accept_tcp4(_Config) when is_list(_Config) -> tc_try(api_to_accept_tcp4, fun() -> - not_yet_implemented()%% , - %% ok = api_to_accept_tcp(inet) + InitState = #{domain => inet, timeout => 5000}, + ok = api_to_accept_tcp(InitState) end). @@ -1472,11 +1480,94 @@ api_to_accept_tcp6(doc) -> api_to_accept_tcp6(_Config) when is_list(_Config) -> tc_try(api_to_accept_tcp4, fun() -> - not_yet_implemented()%% , - %% ok = api_to_accept_tcp(inet6) + not_yet_implemented(), + InitState = #{domain => inet6, timeout => 5000}, + ok = api_to_accept_tcp(InitState) end). +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +api_to_accept_tcp(InitState) -> + TesterSeq = + [ + %% *** Init part *** + #{desc => "which local address", + cmd => fun(#{domain := Domain} = State) -> + LAddr = which_local_addr(Domain), + LSA = #{family => Domain, addr => LAddr}, + {ok, State#{lsa => LSA}} + end}, + #{desc => "create (listen) socket", + cmd => fun(#{domain := Domain} = State) -> + case socket:open(Domain, stream, tcp) of + {ok, Sock} -> + {ok, State#{lsock => Sock}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "bind to local address", + cmd => fun(#{lsock := LSock, lsa := LSA} = _State) -> + case socket:bind(LSock, LSA) of + {ok, _} -> + ok; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "make listen socket", + cmd => fun(#{lsock := LSock}) -> + socket:listen(LSock) + end}, + + %% *** The actual test part *** + #{desc => "attempt to accept (without success)", + cmd => fun(#{lsock := LSock, timeout := To} = State) -> + Start = t(), + case socket:accept(LSock, To) of + {error, timeout} -> + {ok, State#{start => Start, stop => t()}}; + {ok, Sock} -> + (catch socket:close(Sock)), + {error, unexpected_success}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "validate timeout time", + cmd => fun(#{start := Start, stop := Stop, timeout := To} = _State) -> + TDiff = tdiff(Start, Stop), + if + (TDiff >= To) -> + ok; + true -> + {error, {unexpected_timeout, TDiff, To}} + end + end}, + + %% *** Close (listen) socket *** + #{desc => "close (listen) socket", + cmd => fun(#{lsock := LSock} = State) -> + sock_close(LSock), + {ok, maps:remove(sock3, State)} + end}, + + %% *** We are done *** + #{desc => "finish", + cmd => fun(_) -> + {ok, normal} + end} + ], + + p("create tester evaluator"), + Tester = evaluator_start("tester", TesterSeq, InitState), + + p("await evaluator"), + ok = await_evaluator_finish([Tester]). + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test the send timeout option @@ -1618,8 +1709,10 @@ api_to_recv_tcp4(doc) -> api_to_recv_tcp4(_Config) when is_list(_Config) -> tc_try(api_to_recv_tcp4, fun() -> - Recv = fun(Sock) -> socket:recv(Sock, 0, 5000) end, - InitState = #{domain => inet, recv => Recv}, + Recv = fun(Sock, To) -> socket:recv(Sock, 0, To) end, + InitState = #{domain => inet, + recv => Recv, + timeout => 5000}, ok = api_to_receive_tcp(InitState) end). @@ -1638,10 +1731,12 @@ api_to_recv_tcp6(_Config) when is_list(_Config) -> not_yet_implemented(), case socket:supports(ipv6) of true -> - Recv = fun(Sock) -> - socket:recv(Sock, 0, 5000) + Recv = fun(Sock, To) -> + socket:recv(Sock, 0, To) end, - InitState = #{domain => inet6, recv => Recv}, + InitState = #{domain => inet6, + recv => Recv, + timeout => 5000}, ok = api_to_receive_tcp(InitState); false -> skip("ipv6 not supported") @@ -1725,16 +1820,27 @@ api_to_receive_tcp(InitState) -> end end}, #{desc => "attempt to recv (without success)", - cmd => fun(#{sock := Sock, recv := Recv} = _State) -> - case Recv(Sock) of + cmd => fun(#{sock := Sock, recv := Recv, timeout := To} = State) -> + Start = t(), + case Recv(Sock, To) of {error, timeout} -> - ok; + {ok, State#{start => Start, stop => t()}}; {ok, _Data} -> {error, unexpected_success}; {error, _} = ERROR -> ERROR end end}, + #{desc => "validate timeout time", + cmd => fun(#{start := Start, stop := Stop, timeout := To} = _State) -> + TDiff = tdiff(Start, Stop), + if + (TDiff >= To) -> + ok; + true -> + {error, {unexpected_timeout, TDiff, To}} + end + end}, #{desc => "announce ready (recv timeout success)", cmd => fun(#{tester := Tester} = _State) -> Tester ! {ready, self()}, @@ -1992,8 +2098,10 @@ api_to_recvfrom_udp4(doc) -> api_to_recvfrom_udp4(_Config) when is_list(_Config) -> tc_try(api_to_recvfrom_udp4, fun() -> - Recv = fun(Sock) -> socket:recvfrom(Sock, 0, 5000) end, - InitState = #{domain => inet, recv => Recv}, + Recv = fun(Sock, To) -> socket:recvfrom(Sock, 0, To) end, + InitState = #{domain => inet, + recv => Recv, + timeout => 5000}, ok = api_to_receive_udp(InitState) end). @@ -2010,8 +2118,10 @@ api_to_recvfrom_udp6(_Config) when is_list(_Config) -> tc_try(api_to_recvfrom_udp6, fun() -> not_yet_implemented(), - Recv = fun(Sock) -> socket:recvfrom(Sock, 0, 5000) end, - InitState = #{domain => inet6, recv => Recv}, + Recv = fun(Sock, To) -> socket:recvfrom(Sock, 0, To) end, + InitState = #{domain => inet6, + recv => Recv, + timeout => 5000}, ok = api_to_receive_udp(InitState) end). @@ -2049,17 +2159,28 @@ api_to_receive_udp(InitState) -> %% *** The actual test *** #{desc => "attempt to read (without success)", - cmd => fun(#{sock := Sock, recv := Recv} = _State) -> - case Recv(Sock) of + cmd => fun(#{sock := Sock, recv := Recv, timeout := To} = State) -> + Start = t(), + case Recv(Sock, To) of {error, timeout} -> - ok; + {ok, State#{start => Start, stop => t()}}; {ok, _} -> {error, unexpected_sucsess}; {error, _} = ERROR -> ERROR end end}, - + #{desc => "validate timeout time", + cmd => fun(#{start := Start, stop := Stop, timeout := To} = _State) -> + TDiff = tdiff(Start, Stop), + if + (TDiff >= To) -> + ok; + true -> + {error, {unexpected_timeout, TDiff, To}} + end + end}, + %% *** Termination *** #{desc => "close socket", cmd => fun(#{sock := Sock} = _State) -> @@ -2093,8 +2214,10 @@ api_to_recvmsg_udp4(doc) -> api_to_recvmsg_udp4(_Config) when is_list(_Config) -> tc_try(api_to_recvmsg_udp4, fun() -> - Recv = fun(Sock) -> socket:recvmsg(Sock, 5000) end, - InitState = #{domain => inet, recv => Recv}, + Recv = fun(Sock, To) -> socket:recvmsg(Sock, To) end, + InitState = #{domain => inet, + recv => Recv, + timeout => 5000}, ok = api_to_receive_udp(InitState) end). @@ -2111,8 +2234,10 @@ api_to_recvmsg_udp6(_Config) when is_list(_Config) -> tc_try(api_to_recvmsg_udp6, fun() -> not_yet_implemented(), - Recv = fun(Sock) -> socket:recvmsg(Sock, 5000) end, - InitState = #{domain => inet6, recv => Recv}, + Recv = fun(Sock, To) -> socket:recvmsg(Sock, To) end, + InitState = #{domain => inet6, + recv => Recv, + timeout => 5000}, ok = api_to_receive_udp(InitState) end). @@ -2128,8 +2253,10 @@ api_to_recvmsg_tcp4(doc) -> api_to_recvmsg_tcp4(_Config) when is_list(_Config) -> tc_try(api_to_recvmsg_tcp4, fun() -> - Recv = fun(Sock) -> socket:recvmsg(Sock, 5000) end, - InitState = #{domain => inet, recv => Recv}, + Recv = fun(Sock, To) -> socket:recvmsg(Sock, To) end, + InitState = #{domain => inet, + recv => Recv, + timeout => 5000}, ok = api_to_receive_tcp(InitState) end). @@ -2146,8 +2273,10 @@ api_to_recvmsg_tcp6(_Config) when is_list(_Config) -> tc_try(api_to_recvmsg_tcp6, fun() -> not_yet_implemented(), - Recv = fun(Sock) -> socket:recvmsg(Sock, 5000) end, - InitState = #{domain => inet6, recv => Recv}, + Recv = fun(Sock, To) -> socket:recvmsg(Sock, To) end, + InitState = #{domain => inet6, + recv => Recv, + timeout => 5000}, ok = api_to_receive_tcp(InitState) end). @@ -2273,7 +2402,8 @@ ee(F, A) -> eprint(" ", F, A). eprint(Prefix, F, A) -> - io:format(user, "[~s][~p] ~s" ++ F ++ "~n", [get(sname), self(), Prefix | A]). + io:format(user, "[~s][~s][~p] ~s" ++ F ++ "~n", + [formated_timestamp(), get(sname), self(), Prefix | A]). @@ -2385,17 +2515,30 @@ skip(Reason) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% t() -> -%% os:timestamp(). +t() -> + os:timestamp(). -%% tdiff({A1, B1, C1} = _T1x, {A2, B2, C2} = _T2x) -> -%% T1 = A1*1000000000+B1*1000+(C1 div 1000), -%% T2 = A2*1000000000+B2*1000+(C2 div 1000), -%% T2 - T1. +tdiff({A1, B1, C1} = _T1x, {A2, B2, C2} = _T2x) -> + T1 = A1*1000000000+B1*1000+(C1 div 1000), + T2 = A2*1000000000+B2*1000+(C2 div 1000), + T2 - T1. - +formated_timestamp() -> + format_timestamp(os:timestamp()). + +format_timestamp({_N1, _N2, _N3} = TS) -> + {_Date, Time} = calendar:now_to_local_time(TS), + %% {YYYY,MM,DD} = Date, + {Hour,Min,Sec} = Time, + %% FormatTS = + %% io_lib:format("~.4w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w.~w", + %% [YYYY, MM, DD, Hour, Min, Sec, N3]), + FormatTS = io_lib:format("~.2.0w:~.2.0w:~.2.0w", [Hour, Min, Sec]), + lists:flatten(FormatTS). + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% set_tc_name(N) when is_atom(N) -> @@ -2454,7 +2597,7 @@ p(F, A) -> Name when is_list(Name) -> Name end, - i("*** ~s[~p] " ++ F, [TcName,self()|A]). + i("*** [~s][~s][~p] " ++ F, [formated_timestamp(),TcName,self()|A]). %% i(F) -> -- cgit v1.2.3 From 09168a9d0a78319639d62254da717090e21c47ab Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Fri, 12 Oct 2018 15:54:46 +0200 Subject: [socket-nif|test] Add multi accept timeout test case Added simple multi-accept (multiple acceptors) timeout testcase. OTP-14831 --- lib/kernel/test/socket_SUITE.erl | 436 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 436 insertions(+) (limited to 'lib') diff --git a/lib/kernel/test/socket_SUITE.erl b/lib/kernel/test/socket_SUITE.erl index de6a20e60b..3f4347c52f 100644 --- a/lib/kernel/test/socket_SUITE.erl +++ b/lib/kernel/test/socket_SUITE.erl @@ -47,6 +47,8 @@ api_to_connect_tcp6/1, api_to_accept_tcp4/1, api_to_accept_tcp6/1, + api_to_maccept_tcp4/1, + api_to_maccept_tcp6/1, api_to_send_tcp4/1, api_to_send_tcp6/1, api_to_sendto_udp4/1, @@ -1568,6 +1570,440 @@ api_to_accept_tcp(InitState) -> +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% This test case is intended to test the multi accept timeout option +%% on an IPv4 TCP (stream) socket with multiple acceptor processes +%% (three in this case). +api_to_maccept_tcp4(suite) -> + []; +api_to_maccept_tcp4(doc) -> + []; +api_to_maccept_tcp4(_Config) when is_list(_Config) -> + tc_try(api_to_maccept_tcp4, + fun() -> + InitState = #{domain => inet, timeout => 5000}, + ok = api_to_maccept_tcp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% This test case is intended to test the accept timeout option +%% on an IPv6 TCP (stream) socket. +api_to_maccept_tcp6(suite) -> + []; +api_to_maccept_tcp6(doc) -> + []; +api_to_maccept_tcp6(_Config) when is_list(_Config) -> + tc_try(api_to_maccept_tcp4, + fun() -> + not_yet_implemented(), + InitState = #{domain => inet6, timeout => 5000}, + ok = api_to_maccept_tcp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +api_to_maccept_tcp(InitState) -> + PrimAcceptorSeq = + [ + %% *** Init part *** + #{desc => "await start", + cmd => fun(State) -> + receive + {start, Tester} -> + MRef = erlang:monitor(process, Tester), + {ok, State#{tester => Tester, + tester_mref => MRef}} + end + end}, + #{desc => "which local address", + cmd => fun(#{domain := Domain} = State) -> + LAddr = which_local_addr(Domain), + LSA = #{family => Domain, addr => LAddr}, + {ok, State#{lsa => LSA}} + end}, + #{desc => "create (listen) socket", + cmd => fun(#{domain := Domain} = State) -> + case socket:open(Domain, stream, tcp) of + {ok, Sock} -> + {ok, State#{lsock => Sock}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "bind to local address", + cmd => fun(#{lsock := LSock, lsa := LSA} = _State) -> + case socket:bind(LSock, LSA) of + {ok, _} -> + ok; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "make listen socket", + cmd => fun(#{lsock := LSock}) -> + socket:listen(LSock) + end}, + + #{desc => "announce ready", + cmd => fun(#{lsock := LSock, tester := Tester}) -> + ei("announcing port to tester (~p)", [Tester]), + Tester ! {ready, self(), LSock}, + ok + end}, + #{desc => "await continue", + cmd => fun(#{tester := Tester} = _State) -> + receive + {'DOWN', _, process, Tester, Reason} -> + {error, {unexpected_exit, tester, Reason}}; + {continue, Tester} -> + ok + end + end}, + + %% *** The actual test part *** + #{desc => "attempt to accept (without success)", + cmd => fun(#{lsock := LSock, timeout := To} = State) -> + Start = t(), + case socket:accept(LSock, To) of + {error, timeout} -> + {ok, State#{start => Start, stop => t()}}; + {ok, Sock} -> + (catch socket:close(Sock)), + {error, unexpected_success}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "validate timeout time", + cmd => fun(#{start := Start, stop := Stop, timeout := To} = _State) -> + TDiff = tdiff(Start, Stop), + if + (TDiff >= To) -> + ok; + true -> + {error, {unexpected_timeout, TDiff, To}} + end + end}, + #{desc => "announce ready", + cmd => fun(#{tester := Tester}) -> + ei("announcing port to tester (~p)", [Tester]), + Tester ! {ready, self()}, + ok + end}, + #{desc => "await terminate", + cmd => fun(#{tester := Tester} = _State) -> + receive + {'DOWN', _, process, Tester, Reason} -> + {error, {unexpected_exit, tester, Reason}}; + {terminate, Tester} -> + ok + end + end}, + + %% *** Close (listen) socket *** + #{desc => "close (listen) socket", + cmd => fun(#{lsock := LSock} = State) -> + sock_close(LSock), + {ok, maps:remove(sock3, State)} + end}, + + %% *** We are done *** + #{desc => "finish", + cmd => fun(_) -> + {ok, normal} + end} + ], + + + SecAcceptorSeq = + [ + %% *** Init part *** + #{desc => "await start", + cmd => fun(State) -> + receive + {start, Tester, LSock} -> + MRef = erlang:monitor(process, Tester), + {ok, State#{tester => Tester, + lsock => LSock, + tester_mref => MRef}} + end + end}, + #{desc => "announce ready (1)", + cmd => fun(#{tester := Tester} = _State) -> + Tester ! {ready, self()}, + ok + end}, + #{desc => "await continue", + cmd => fun(#{tester := Tester} = _State) -> + receive + {'DOWN', _, process, Tester, Reason} -> + ee("Unexpected DOWN regarding tester ~p: " + "~n ~p", [Reason]), + {error, {unexpected_exit, tester, Reason}}; + {continue, Tester} -> + ok + end + end}, + + %% *** The actual test part *** + #{desc => "attempt to accept (without success)", + cmd => fun(#{lsock := LSock, timeout := To} = State) -> + Start = t(), + case socket:accept(LSock, To) of + {error, timeout} -> + {ok, State#{start => Start, stop => t()}}; + {ok, Sock} -> + (catch socket:close(Sock)), + {error, unexpected_success}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "validate timeout time", + cmd => fun(#{start := Start, stop := Stop, timeout := To} = _State) -> + TDiff = tdiff(Start, Stop), + if + (TDiff >= To) -> + ok; + true -> + {error, {unexpected_timeout, TDiff, To}} + end + end}, + #{desc => "announce ready (2)", + cmd => fun(#{tester := Tester} = _State) -> + Tester ! {ready, self()}, + ok + end}, + #{desc => "await terminate", + cmd => fun(#{tester := Tester} = _State) -> + receive + {'DOWN', _, process, Tester, Reason} -> + ee("Unexpected DOWN regarding tester ~p: " + "~n ~p", [Reason]), + {error, {unexpected_exit, tester, Reason}}; + {terminate, Tester} -> + ok + end + end}, + + %% *** We are done *** + #{desc => "finish", + cmd => fun(_) -> + {ok, normal} + end} + ], + + + TesterSeq = + [ + %% Init part + #{desc => "monitor prim-acceptor", + cmd => fun(#{prim_acceptor := Pid} = _State) -> + _MRef = erlang:monitor(process, Pid), + ok + end}, + #{desc => "monitor sec-acceptor 1", + cmd => fun(#{sec_acceptor1 := Pid} = _State) -> + _MRef = erlang:monitor(process, Pid), + ok + end}, + #{desc => "monitor sec-acceptor 2", + cmd => fun(#{sec_acceptor2 := Pid} = _State) -> + _MRef = erlang:monitor(process, Pid), + ok + end}, + + + %% Start the prim-acceptor + #{desc => "start prim-acceptor", + cmd => fun(#{prim_acceptor := Pid} = _State) -> + Pid ! {start, self()}, + ok + end}, + #{desc => "await prim-acceptor ready (1)", + cmd => fun(#{prim_acceptor := Pid} = State) -> + receive + {'DOWN', _, process, Pid, Reason} -> + ee("Unexpected DOWN regarding prim-acceptor ~p:" + "~n ~p", [Reason]), + {error, {unexpected_exit, prim_acceptor}}; + {ready, Pid, LSock} -> + {ok, State#{lsock => LSock}} + end + end}, + + %% Start sec-acceptor-1 + #{desc => "start sec-acceptor 1", + cmd => fun(#{sec_acceptor1 := Pid, lsock := LSock} = _State) -> + Pid ! {start, self(), LSock}, + ok + end}, + #{desc => "await sec-acceptor 1 ready (1)", + cmd => fun(#{sec_acceptor1 := Pid} = _State) -> + receive + {'DOWN', _, process, Pid, Reason} -> + ee("Unexpected DOWN regarding sec-acceptor 1 ~p:" + "~n ~p", [Reason]), + {error, {unexpected_exit, sec_acceptor_1}}; + {ready, Pid} -> + ok + end + end}, + + %% Start sec-acceptor-2 + #{desc => "start sec-acceptor 2", + cmd => fun(#{sec_acceptor2 := Pid, lsock := LSock} = _State) -> + Pid ! {start, self(), LSock}, + ok + end}, + #{desc => "await sec-acceptor 2 ready (1)", + cmd => fun(#{sec_acceptor2 := Pid} = _State) -> + receive + {'DOWN', _, process, Pid, Reason} -> + ee("Unexpected DOWN regarding sec-acceptor 2 ~p:" + "~n ~p", [Reason]), + {error, {unexpected_exit, sec_acceptor_2}}; + {ready, Pid} -> + ok + end + end}, + + %% Activate the acceptor(s) + #{desc => "active prim-acceptor", + cmd => fun(#{prim_acceptor := Pid} = _State) -> + Pid ! {continue, self()}, + ok + end}, + #{desc => "active sec-acceptor 1", + cmd => fun(#{sec_acceptor1 := Pid} = _State) -> + Pid ! {continue, self()}, + ok + end}, + #{desc => "active sec-acceptor 2", + cmd => fun(#{sec_acceptor2 := Pid} = _State) -> + Pid ! {continue, self()}, + ok + end}, + + %% Await acceptor(s) completions + #{desc => "await prim-acceptor ready (2)", + cmd => fun(#{prim_acceptor := Pid} = _State) -> + receive + {'DOWN', _, process, Pid, Reason} -> + ee("Unexpected DOWN regarding prim-acceptor ~p:" + "~n ~p", [Reason]), + {error, {unexpected_exit, prim_acceptor}}; + {ready, Pid} -> + ok + end + end}, + #{desc => "await sec-acceptor 1 ready (2)", + cmd => fun(#{sec_acceptor1 := Pid} = _State) -> + receive + {'DOWN', _, process, Pid, Reason} -> + ee("Unexpected DOWN regarding sec-acceptor 1 ~p:" + "~n ~p", [Reason]), + {error, {unexpected_exit, sec_acceptor_1}}; + {ready, Pid} -> + ok + end + end}, + #{desc => "await sec-acceptor 2 ready (2)", + cmd => fun(#{sec_acceptor2 := Pid} = _State) -> + receive + {'DOWN', _, process, Pid, Reason} -> + ee("Unexpected DOWN regarding sec-acceptor 2 ~p:" + "~n ~p", [Reason]), + {error, {unexpected_exit, sec_acceptor_2}}; + {ready, Pid} -> + ok + end + end}, + + + %% Terminate the acceptor(s) + #{desc => "order prim-acceptor to terminate", + cmd => fun(#{prim_acceptor := Pid} = _State) -> + ei("send terminate command to prim-acceptor (~p)", [Pid]), + Pid ! {terminate, self()}, + ok + end}, + #{desc => "order sec-acceptor 1 to terminate", + cmd => fun(#{sec_acceptor1 := Pid} = _State) -> + ei("send terminate command to sec-acceptor-1 (~p)", [Pid]), + Pid ! {terminate, self()}, + ok + end}, + #{desc => "order sec-acceptor 2 to terminate", + cmd => fun(#{sec_acceptor2 := Pid} = _State) -> + ei("send terminate command to sec-acceptor-2 (~p)", [Pid]), + Pid ! {terminate, self()}, + ok + end}, + + %% Await acceptor(s) termination + #{desc => "await prim-acceptor termination", + cmd => fun(#{prim_acceptor := Pid} = State) -> + receive + {'DOWN', _, process, Pid, _} -> + State1 = maps:remove(prim_acceptor, State), + {ok, State1} + end + end}, + #{desc => "await sec-acceptor 1 termination", + cmd => fun(#{sec_acceptor1 := Pid} = State) -> + receive + {'DOWN', _, process, Pid, _} -> + State1 = maps:remove(sec_acceptor1, State), + {ok, State1} + end + end}, + #{desc => "await sec-acceptor 2 termination", + cmd => fun(#{sec_acceptor2 := Pid} = State) -> + receive + {'DOWN', _, process, Pid, _} -> + State1 = maps:remove(sec_acceptor2, State), + {ok, State1} + end + end}, + + %% *** We are done *** + #{desc => "finish", + cmd => fun(_) -> + {ok, normal} + end} + ], + + p("create prim-acceptor evaluator"), + PrimAInitState = InitState, + PrimAcceptor = evaluator_start("prim-acceptor", + PrimAcceptorSeq, PrimAInitState), + + p("create prim-acceptor 1 evaluator"), + SecAInitState1 = maps:remove(domain, InitState), + SecAcceptor1 = evaluator_start("sec-acceptor-1", + SecAcceptorSeq, SecAInitState1), + + p("create prim-acceptor 2 evaluator"), + SecAInitState2 = SecAInitState1, + SecAcceptor2 = evaluator_start("sec-acceptor-2", + SecAcceptorSeq, SecAInitState2), + + p("create tester evaluator"), + TesterInitState = #{prim_acceptor => PrimAcceptor, + sec_acceptor1 => SecAcceptor1, + sec_acceptor2 => SecAcceptor2}, + Tester = evaluator_start("tester", TesterSeq, TesterInitState), + + p("await evaluator(s)"), + ok = await_evaluator_finish([PrimAcceptor, SecAcceptor1, SecAcceptor2, Tester]). + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test the send timeout option -- cgit v1.2.3 From ac1e27ce82fde99519a9cf271144179e4a2ef373 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Fri, 12 Oct 2018 16:59:28 +0200 Subject: [socket-nif|test] Add skeletons for controlling-process test cases --- lib/kernel/test/socket_SUITE.erl | 560 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 556 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/kernel/test/socket_SUITE.erl b/lib/kernel/test/socket_SUITE.erl index 3f4347c52f..71e6dff174 100644 --- a/lib/kernel/test/socket_SUITE.erl +++ b/lib/kernel/test/socket_SUITE.erl @@ -64,7 +64,29 @@ api_to_recvmsg_udp4/1, api_to_recvmsg_udp6/1, api_to_recvmsg_tcp4/1, - api_to_recvmsg_tcp6/1 + api_to_recvmsg_tcp6/1, + + %% Controlling Process + socket_cleanup_tcp4/1, + socket_cleanup_tcp6/1, + socket_cleanup_udp4/1, + socket_cleanup_udp6/1, + socket_close_tcp4/1, + socket_close_tcp6/1, + socket_close_udp4/1, + socket_close_udp6/1, + recv_response_local_close_tcp4/1, + recv_response_local_close_tcp6/1, + recv_response_remote_close_tcp4/1, + recv_response_remote_close_tcp6/1, + recvmsg_response_local_close_tcp4/1, + recvmsg_response_local_close_tcp6/1, + recvmsg_response_remote_close_tcp4/1, + recvmsg_response_remote_close_tcp6/1, + acceptor_response_local_close_tcp4/1, + acceptor_response_local_close_tcp6/1, + acceptor_response_remote_close_tcp4/1, + acceptor_response_remote_close_tcp6/1 %% Tickets ]). @@ -102,15 +124,17 @@ suite() -> all() -> [ - {group, api} + {group, api}, + {group, controlling_process} %% {group, tickets} ]. groups() -> [{api, [], api_cases()}, {api_basic, [], api_basic_cases()}, + {api_options, [], api_options_cases()}, {api_op_with_timeout, [], api_op_with_timeout_cases()}, - {api_options, [], api_options_cases()} + {controlling_process, [], controlling_process_cases()} %% {tickets, [], ticket_cases()} ]. @@ -161,6 +185,34 @@ api_op_with_timeout_cases() -> api_to_recvmsg_tcp6 ]. +%% These cases tests what happens when the controlling process dies +controlling_process_cases() -> + [ + socket_cleanup_tcp4, + socket_cleanup_tcp6, + socket_cleanup_udp4, + socket_cleanup_udp6, + + socket_close_tcp4, + socket_close_tcp6, + socket_close_udp4, + socket_close_udp6, + + recv_response_local_close_tcp4, + recv_response_local_close_tcp6, + recv_response_remote_close_tcp4, + recv_response_remote_close_tcp6, + + recvmsg_response_local_close_tcp4, + recvmsg_response_local_close_tcp6, + recvmsg_response_remote_close_tcp4, + recvmsg_response_remote_close_tcp6, + + acceptor_response_local_close_tcp4, + acceptor_response_local_close_tcp6, + acceptor_response_remote_close_tcp4, + acceptor_response_remote_close_tcp6 + ]. %% ticket_cases() -> %% []. @@ -183,6 +235,14 @@ end_per_testcase(_TC, Config) -> +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% %% +%% API BASIC %% +%% %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically open (create) and close an IPv4 UDP (dgram) socket. @@ -549,7 +609,7 @@ api_b_send_and_recv_tcp(InitState) -> cmd => fun(#{lsock := LSock} = State) -> case socket:accept(LSock) of {ok, Sock} -> - ei("accepted: ~p", [Sock]), + ei("accepted: ~n ~p", [Sock]), {ok, State#{tsock => Sock}}; {error, _} = ERROR -> ERROR @@ -652,6 +712,14 @@ api_b_send_and_recv_tcp(InitState) -> +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% %% +%% API OPTIONS %% +%% %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Perform some simple getopt and setopt with the level = otp options @@ -1163,6 +1231,14 @@ api_opt_simple_otp_controlling_process() -> +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% %% +%% API OPERATIONS WITH TIMEOUT %% +%% %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test the connect timeout option @@ -2717,6 +2793,482 @@ api_to_recvmsg_tcp6(_Config) when is_list(_Config) -> end). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% %% +%% CONTROLLING PROCESS %% +%% %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test that the sockets are cleaned up +%% (removed) when the controlling process terminates (without explicitly +%% calling the close function). For a IPv4 TCP (stream) socket. + +socket_cleanup_tcp4(suite) -> + []; +socket_cleanup_tcp4(doc) -> + []; +socket_cleanup_tcp4(_Config) when is_list(_Config) -> + tc_try(socket_cleanup_tcp4, + fun() -> + not_yet_implemented(), + InitState = #{domain => inet, + type => stream, + protocol => tcp}, + ok = socket_cleanup(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test that the sockets are cleaned up +%% (removed) when the controlling process terminates (without explicitly +%% calling the close function). For a IPv6 TCP (stream) socket. + +socket_cleanup_tcp6(suite) -> + []; +socket_cleanup_tcp6(doc) -> + []; +socket_cleanup_tcp6(_Config) when is_list(_Config) -> + tc_try(socket_cleanup_tcp6, + fun() -> + not_yet_implemented(), + InitState = #{domain => inet6, + type => stream, + protocol => tcp}, + ok = socket_cleanup(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test that the sockets are cleaned up +%% (removed) when the controlling process terminates (without explicitly +%% calling the close function). For a IPv4 UDP (dgram) socket. + +socket_cleanup_udp4(suite) -> + []; +socket_cleanup_udp4(doc) -> + []; +socket_cleanup_udp4(_Config) when is_list(_Config) -> + tc_try(socket_cleanup_udp4, + fun() -> + not_yet_implemented(), + InitState = #{domain => inet, + type => dgram, + protocol => udp}, + ok = socket_cleanup(InitState) + end). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test that the sockets are cleaned up +%% (removed) when the controlling process terminates (without explicitly +%% calling the close function). For a IPv6 UDP (dgram) socket. + +socket_cleanup_udp6(suite) -> + []; +socket_cleanup_udp6(doc) -> + []; +socket_cleanup_udp6(_Config) when is_list(_Config) -> + tc_try(socket_cleanup_udp6, + fun() -> + not_yet_implemented(), + InitState = #{domain => inet6, + type => dgram, + protocol => udp}, + ok = socket_cleanup(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +socket_cleanup(_InitState) -> + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test what happens when a process other +%% than the controlling process closes a socket. +%% For a IPv4 TCP (stream) socket. + +socket_close_tcp4(suite) -> + []; +socket_close_tcp4(doc) -> + []; +socket_close_tcp4(_Config) when is_list(_Config) -> + tc_try(socket_close_tcp4, + fun() -> + not_yet_implemented(), + InitState = #{domain => inet, + type => stream, + protocol => tcp}, + ok = socket_close(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test what happens when a process other +%% than the controlling process closes a socket. +%% For a IPv6 TCP (stream) socket. + +socket_close_tcp6(suite) -> + []; +socket_close_tcp6(doc) -> + []; +socket_close_tcp6(_Config) when is_list(_Config) -> + tc_try(socket_close_tcp6, + fun() -> + not_yet_implemented(), + InitState = #{domain => inet6, + type => stream, + protocol => tcp}, + ok = socket_close(InitState) + end). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test what happens when a process other +%% than the controlling process closes a socket. +%% For a IPv4 UDP (dgram) socket. + +socket_close_udp4(suite) -> + []; +socket_close_udp4(doc) -> + []; +socket_close_udp4(_Config) when is_list(_Config) -> + tc_try(socket_close_udp4, + fun() -> + not_yet_implemented(), + InitState = #{domain => inet, + type => dgram, + protocol => udp}, + ok = socket_close(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test what happens when a process other +%% than the controlling process closes a socket. +%% For a IPv6 UDP (dgram) socket. + +socket_close_udp6(suite) -> + []; +socket_close_udp6(doc) -> + []; +socket_close_udp6(_Config) when is_list(_Config) -> + tc_try(socket_close_udp6, + fun() -> + not_yet_implemented(), + InitState = #{domain => inet6, + type => dgram, + protocol => udp}, + ok = socket_close(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +socket_close(_InitState) -> + ok. + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test what happens when a socket is +%% locally closed while the process is calling the recv function. +%% Socket is IPv4. + +recv_response_local_close_tcp4(suite) -> + []; +recv_response_local_close_tcp4(doc) -> + []; +recv_response_local_close_tcp4(_Config) when is_list(_Config) -> + tc_try(recv_response_local_close_tcp4, + fun() -> + not_yet_implemented(), + Recv = fun(Sock) -> socket:recv(Sock) end, + InitState = #{domain => inet, + type => stream, + protocol => tcp, + recv => Recv}, + ok = receive_response_local_close_tcp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test what happens when a socket is +%% locally closed while the process is calling the recv function. +%% Socket is IPv6. + +recv_response_local_close_tcp6(suite) -> + []; +recv_response_local_close_tcp6(doc) -> + []; +recv_response_local_close_tcp6(_Config) when is_list(_Config) -> + tc_try(recv_response_local_close_tcp6, + fun() -> + not_yet_implemented(), + Recv = fun(Sock) -> socket:recv(Sock) end, + InitState = #{domain => inet6, + type => stream, + protocol => tcp, + recv => Recv}, + ok = receive_response_local_close_tcp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +receive_response_local_close_tcp(_InitState) -> + ok. + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test what happens when a socket is +%% remotely closed while the process is calling the recv function. +%% Socket is IPv4. + +recv_response_remote_close_tcp4(suite) -> + []; +recv_response_remote_close_tcp4(doc) -> + []; +recv_response_remote_close_tcp4(_Config) when is_list(_Config) -> + tc_try(recv_response_remote_close_tcp4, + fun() -> + not_yet_implemented(), + Recv = fun(Sock) -> socket:recv(Sock) end, + InitState = #{domain => inet, + type => stream, + protocol => tcp, + recv => Recv}, + ok = receive_response_remote_close_tcp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test what happens when a socket is +%% remotely closed while the process is calling the recv function. +%% Socket is IPv6. + +recv_response_remote_close_tcp6(suite) -> + []; +recv_response_remote_close_tcp6(doc) -> + []; +recv_response_remote_close_tcp6(_Config) when is_list(_Config) -> + tc_try(recv_response_remote_close_tcp6, + fun() -> + not_yet_implemented(), + Recv = fun(Sock) -> socket:recv(Sock) end, + InitState = #{domain => inet6, + type => stream, + protocol => tcp, + recv => Recv}, + ok = receive_response_remote_close_tcp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +receive_response_remote_close_tcp(_InitState) -> + ok. + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test what happens when a socket is +%% locally closed while the process is calling the recvmsg function. +%% Socket is IPv4. + +recvmsg_response_local_close_tcp4(suite) -> + []; +recvmsg_response_local_close_tcp4(doc) -> + []; +recvmsg_response_local_close_tcp4(_Config) when is_list(_Config) -> + tc_try(recvmsg_response_local_close_tcp4, + fun() -> + not_yet_implemented(), + Recv = fun(Sock) -> socket:recvmsg(Sock) end, + InitState = #{domain => inet, + type => stream, + protocol => tcp, + recv => Recv}, + ok = receive_response_local_close_tcp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test what happens when a socket is +%% locally closed while the process is calling the recvmsg function. +%% Socket is IPv6. + +recvmsg_response_local_close_tcp6(suite) -> + []; +recvmsg_response_local_close_tcp6(doc) -> + []; +recvmsg_response_local_close_tcp6(_Config) when is_list(_Config) -> + tc_try(recvmsg_response_local_close_tcp6, + fun() -> + not_yet_implemented(), + Recv = fun(Sock) -> socket:recvmsg(Sock) end, + InitState = #{domain => inet6, + type => stream, + protocol => tcp, + recv => Recv}, + ok = receive_response_local_close_tcp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test what happens when a socket is +%% remotely closed while the process is calling the recvmsg function. +%% Socket is IPv4. + +recvmsg_response_remote_close_tcp4(suite) -> + []; +recvmsg_response_remote_close_tcp4(doc) -> + []; +recvmsg_response_remote_close_tcp4(_Config) when is_list(_Config) -> + tc_try(recvmsg_response_remote_close_tcp4, + fun() -> + not_yet_implemented(), + Recv = fun(Sock) -> socket:recvmsg(Sock) end, + InitState = #{domain => inet, + type => stream, + protocol => tcp, + recv => Recv}, + ok = receive_response_remote_close_tcp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test what happens when a socket is +%% remotely closed while the process is calling the recvmsg function. +%% Socket is IPv6. + +recvmsg_response_remote_close_tcp6(suite) -> + []; +recvmsg_response_remote_close_tcp6(doc) -> + []; +recvmsg_response_remote_close_tcp6(_Config) when is_list(_Config) -> + tc_try(recvmsg_response_remote_close_tcp6, + fun() -> + not_yet_implemented(), + Recv = fun(Sock) -> socket:recvmsg(Sock) end, + InitState = #{domain => inet6, + type => stream, + protocol => tcp, + recv => Recv}, + ok = receive_response_remote_close_tcp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test what happens when a socket is +%% locally closed while the process is calling the accept function. +%% We test what happens with a non-controlling_process also, since we +%% git the setup anyway. +%% Socket is IPv4. + +acceptor_response_local_close_tcp4(suite) -> + []; +acceptor_response_local_close_tcp4(doc) -> + []; +acceptor_response_local_close_tcp4(_Config) when is_list(_Config) -> + tc_try(acceptor_response_local_close_tcp4, + fun() -> + not_yet_implemented(), + InitState = #{domain => inet, + type => stream, + protocol => tcp}, + ok = acceptor_response_local_close_tcp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test what happens when a socket is +%% locally closed while the process is calling the accept function. +%% We test what happens with a non-controlling_process also, since we +%% git the setup anyway. +%% Socket is IPv6. + +acceptor_response_local_close_tcp6(suite) -> + []; +acceptor_response_local_close_tcp6(doc) -> + []; +acceptor_response_local_close_tcp6(_Config) when is_list(_Config) -> + tc_try(acceptor_response_local_close_tcp6, + fun() -> + not_yet_implemented(), + InitState = #{domain => inet, + type => stream, + protocol => tcp}, + ok = acceptor_response_local_close_tcp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +acceptor_response_local_close_tcp(_InitState) -> + ok. + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test what happens when a socket is +%% remotely closed while the process is calling the accept function. +%% We test what happens with a non-controlling_process also, since we +%% git the setup anyway. +%% Socket is IPv4. + +acceptor_response_remote_close_tcp4(suite) -> + []; +acceptor_response_remote_close_tcp4(doc) -> + []; +acceptor_response_remote_close_tcp4(_Config) when is_list(_Config) -> + tc_try(acceptor_response_remote_close_tcp4, + fun() -> + not_yet_implemented(), + InitState = #{domain => inet, + type => stream, + protocol => tcp}, + ok = acceptor_response_remote_close_tcp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test what happens when a socket is +%% remotely closed while the process is calling the accept function. +%% We test what happens with a non-controlling_process also, since we +%% git the setup anyway. +%% Socket is IPv6. + +acceptor_response_remote_close_tcp6(suite) -> + []; +acceptor_response_remote_close_tcp6(doc) -> + []; +acceptor_response_remote_close_tcp6(_Config) when is_list(_Config) -> + tc_try(acceptor_response_remote_close_tcp6, + fun() -> + not_yet_implemented(), + InitState = #{domain => inet, + type => stream, + protocol => tcp}, + ok = acceptor_response_remote_close_tcp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +acceptor_response_remote_close_tcp(_InitState) -> + ok. + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -- cgit v1.2.3 From f2481d58a2fb64b8f3c7cbb26e09cb17c04726e0 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Mon, 15 Oct 2018 18:31:43 +0200 Subject: [socket-nif|test] Added two test cases regarding exiting owner Added two (working) test cases for testing "socket cleanup" when the controlling-process exits. OTP-14831 --- lib/kernel/test/socket_SUITE.erl | 487 +++++++++++++++++++++------------------ 1 file changed, 265 insertions(+), 222 deletions(-) (limited to 'lib') diff --git a/lib/kernel/test/socket_SUITE.erl b/lib/kernel/test/socket_SUITE.erl index 71e6dff174..42420a37dc 100644 --- a/lib/kernel/test/socket_SUITE.erl +++ b/lib/kernel/test/socket_SUITE.erl @@ -67,26 +67,22 @@ api_to_recvmsg_tcp6/1, %% Controlling Process - socket_cleanup_tcp4/1, - socket_cleanup_tcp6/1, - socket_cleanup_udp4/1, - socket_cleanup_udp6/1, - socket_close_tcp4/1, - socket_close_tcp6/1, - socket_close_udp4/1, - socket_close_udp6/1, - recv_response_local_close_tcp4/1, - recv_response_local_close_tcp6/1, - recv_response_remote_close_tcp4/1, - recv_response_remote_close_tcp6/1, - recvmsg_response_local_close_tcp4/1, - recvmsg_response_local_close_tcp6/1, - recvmsg_response_remote_close_tcp4/1, - recvmsg_response_remote_close_tcp6/1, - acceptor_response_local_close_tcp4/1, - acceptor_response_local_close_tcp6/1, - acceptor_response_remote_close_tcp4/1, - acceptor_response_remote_close_tcp6/1 + sc_socket_cleanup_tcp4/1, + sc_socket_cleanup_tcp6/1, + sc_socket_cleanup_udp4/1, + sc_socket_cleanup_udp6/1, + sc_recv_response_local_close_tcp4/1, + sc_recv_response_local_close_tcp6/1, + sc_recv_response_remote_close_tcp4/1, + sc_recv_response_remote_close_tcp6/1, + sc_recvmsg_response_local_close_tcp4/1, + sc_recvmsg_response_local_close_tcp6/1, + sc_recvmsg_response_remote_close_tcp4/1, + sc_recvmsg_response_remote_close_tcp6/1, + sc_acceptor_response_local_close_tcp4/1, + sc_acceptor_response_local_close_tcp6/1, + sc_acceptor_response_remote_close_tcp4/1, + sc_acceptor_response_remote_close_tcp6/1 %% Tickets ]). @@ -125,7 +121,7 @@ suite() -> all() -> [ {group, api}, - {group, controlling_process} + {group, socket_closure} %% {group, tickets} ]. @@ -134,7 +130,7 @@ groups() -> {api_basic, [], api_basic_cases()}, {api_options, [], api_options_cases()}, {api_op_with_timeout, [], api_op_with_timeout_cases()}, - {controlling_process, [], controlling_process_cases()} + {socket_closure, [], socket_closure_cases()} %% {tickets, [], ticket_cases()} ]. @@ -185,33 +181,29 @@ api_op_with_timeout_cases() -> api_to_recvmsg_tcp6 ]. -%% These cases tests what happens when the controlling process dies -controlling_process_cases() -> +%% These cases tests what happens when the socket is closed, locally or +%% remotely. +socket_closure_cases() -> [ - socket_cleanup_tcp4, - socket_cleanup_tcp6, - socket_cleanup_udp4, - socket_cleanup_udp6, - - socket_close_tcp4, - socket_close_tcp6, - socket_close_udp4, - socket_close_udp6, - - recv_response_local_close_tcp4, - recv_response_local_close_tcp6, - recv_response_remote_close_tcp4, - recv_response_remote_close_tcp6, - - recvmsg_response_local_close_tcp4, - recvmsg_response_local_close_tcp6, - recvmsg_response_remote_close_tcp4, - recvmsg_response_remote_close_tcp6, - - acceptor_response_local_close_tcp4, - acceptor_response_local_close_tcp6, - acceptor_response_remote_close_tcp4, - acceptor_response_remote_close_tcp6 + sc_socket_cleanup_tcp4, + sc_socket_cleanup_tcp6, + sc_socket_cleanup_udp4, + sc_socket_cleanup_udp6, + + sc_recv_response_local_close_tcp4, + sc_recv_response_local_close_tcp6, + sc_recv_response_remote_close_tcp4, + sc_recv_response_remote_close_tcp6, + + sc_recvmsg_response_local_close_tcp4, + sc_recvmsg_response_local_close_tcp6, + sc_recvmsg_response_remote_close_tcp4, + sc_recvmsg_response_remote_close_tcp6, + + sc_acceptor_response_local_close_tcp4, + sc_acceptor_response_local_close_tcp6, + sc_acceptor_response_remote_close_tcp4, + sc_acceptor_response_remote_close_tcp6 ]. %% ticket_cases() -> @@ -1337,7 +1329,9 @@ api_to_connect_tcp(InitState) -> cmd => fun(#{tester := Tester} = State) -> receive {'DOWN', _, process, Tester, Reason} -> - {error, {unexpected_exit, tester, Reason}}; + ee("Unexpected DOWN regarding tester ~p: " + "~n ~p", [Reason]), + {error, {unexpected_exit, tester}}; {terminate, Tester} -> {ok, maps:remove(tester, State)} end @@ -1734,7 +1728,9 @@ api_to_maccept_tcp(InitState) -> cmd => fun(#{tester := Tester} = _State) -> receive {'DOWN', _, process, Tester, Reason} -> - {error, {unexpected_exit, tester, Reason}}; + ee("Unexpected DOWN regarding tester ~p: " + "~n ~p", [Reason]), + {error, {unexpected_exit, tester}}; {continue, Tester} -> ok end @@ -1774,7 +1770,9 @@ api_to_maccept_tcp(InitState) -> cmd => fun(#{tester := Tester} = _State) -> receive {'DOWN', _, process, Tester, Reason} -> - {error, {unexpected_exit, tester, Reason}}; + ee("Unexpected DOWN regarding tester ~p: " + "~n ~p", [Reason]), + {error, {unexpected_exit, tester}}; {terminate, Tester} -> ok end @@ -2797,68 +2795,67 @@ api_to_recvmsg_tcp6(_Config) when is_list(_Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %% -%% CONTROLLING PROCESS %% +%% SOCKET CLOSURE %% %% %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the sockets are cleaned up -%% (removed) when the controlling process terminates (without explicitly +%% ("removed") when the controlling process terminates (without explicitly %% calling the close function). For a IPv4 TCP (stream) socket. -socket_cleanup_tcp4(suite) -> +sc_socket_cleanup_tcp4(suite) -> []; -socket_cleanup_tcp4(doc) -> +sc_socket_cleanup_tcp4(doc) -> []; -socket_cleanup_tcp4(_Config) when is_list(_Config) -> - tc_try(socket_cleanup_tcp4, +sc_socket_cleanup_tcp4(_Config) when is_list(_Config) -> + tc_try(sc_socket_cleanup_tcp4, fun() -> - not_yet_implemented(), + %% not_yet_implemented(), InitState = #{domain => inet, type => stream, protocol => tcp}, - ok = socket_cleanup(InitState) + ok = sc_socket_cleanup(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the sockets are cleaned up -%% (removed) when the controlling process terminates (without explicitly +%% ("removed") when the controlling process terminates (without explicitly %% calling the close function). For a IPv6 TCP (stream) socket. -socket_cleanup_tcp6(suite) -> +sc_socket_cleanup_tcp6(suite) -> []; -socket_cleanup_tcp6(doc) -> +sc_socket_cleanup_tcp6(doc) -> []; -socket_cleanup_tcp6(_Config) when is_list(_Config) -> - tc_try(socket_cleanup_tcp6, +sc_socket_cleanup_tcp6(_Config) when is_list(_Config) -> + tc_try(sc_socket_cleanup_tcp6, fun() -> not_yet_implemented(), InitState = #{domain => inet6, type => stream, protocol => tcp}, - ok = socket_cleanup(InitState) + ok = sc_socket_cleanup(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the sockets are cleaned up -%% (removed) when the controlling process terminates (without explicitly +%% ("removed") when the controlling process terminates (without explicitly %% calling the close function). For a IPv4 UDP (dgram) socket. -socket_cleanup_udp4(suite) -> +sc_socket_cleanup_udp4(suite) -> []; -socket_cleanup_udp4(doc) -> +sc_socket_cleanup_udp4(doc) -> []; -socket_cleanup_udp4(_Config) when is_list(_Config) -> - tc_try(socket_cleanup_udp4, +sc_socket_cleanup_udp4(_Config) when is_list(_Config) -> + tc_try(sc_socket_cleanup_udp4, fun() -> - not_yet_implemented(), InitState = #{domain => inet, type => dgram, protocol => udp}, - ok = socket_cleanup(InitState) + ok = sc_socket_cleanup(InitState) end). @@ -2868,113 +2865,159 @@ socket_cleanup_udp4(_Config) when is_list(_Config) -> %% (removed) when the controlling process terminates (without explicitly %% calling the close function). For a IPv6 UDP (dgram) socket. -socket_cleanup_udp6(suite) -> +sc_socket_cleanup_udp6(suite) -> []; -socket_cleanup_udp6(doc) -> +sc_socket_cleanup_udp6(doc) -> []; -socket_cleanup_udp6(_Config) when is_list(_Config) -> - tc_try(socket_cleanup_udp6, +sc_socket_cleanup_udp6(_Config) when is_list(_Config) -> + tc_try(sc_socket_cleanup_udp6, fun() -> not_yet_implemented(), InitState = #{domain => inet6, type => dgram, protocol => udp}, - ok = socket_cleanup(InitState) - end). - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -socket_cleanup(_InitState) -> - ok. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% This test case is intended to test what happens when a process other -%% than the controlling process closes a socket. -%% For a IPv4 TCP (stream) socket. - -socket_close_tcp4(suite) -> - []; -socket_close_tcp4(doc) -> - []; -socket_close_tcp4(_Config) when is_list(_Config) -> - tc_try(socket_close_tcp4, - fun() -> - not_yet_implemented(), - InitState = #{domain => inet, - type => stream, - protocol => tcp}, - ok = socket_close(InitState) + ok = sc_socket_cleanup(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% This test case is intended to test what happens when a process other -%% than the controlling process closes a socket. -%% For a IPv6 TCP (stream) socket. - -socket_close_tcp6(suite) -> - []; -socket_close_tcp6(doc) -> - []; -socket_close_tcp6(_Config) when is_list(_Config) -> - tc_try(socket_close_tcp6, - fun() -> - not_yet_implemented(), - InitState = #{domain => inet6, - type => stream, - protocol => tcp}, - ok = socket_close(InitState) - end). +sc_socket_cleanup(InitState) -> + OwnerSeq = + [ + %% *** Wait for start order part *** + #{desc => "await start (from tester)", + cmd => fun(State) -> + receive + {start, Tester} when is_pid(Tester) -> + {ok, State#{tester => Tester}} + end + end}, + %% *** Init part *** + #{desc => "monitor tester", + cmd => fun(#{tester := Tester} = _State) -> + _MRef = erlang:monitor(process, Tester), + ok + end}, + #{desc => "create socket", + cmd => fun(#{domain := Domain, + type := Type, + protocol := Proto} = State) -> + case socket:open(Domain, Type, Proto) of + {ok, Sock} -> + {ok, State#{sock => Sock}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "announce ready", + cmd => fun(#{tester := Tester, sock := Sock} = _State) -> + Tester ! {ready, self(), Sock}, + ok + end}, -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% This test case is intended to test what happens when a process other -%% than the controlling process closes a socket. -%% For a IPv4 UDP (dgram) socket. - -socket_close_udp4(suite) -> - []; -socket_close_udp4(doc) -> - []; -socket_close_udp4(_Config) when is_list(_Config) -> - tc_try(socket_close_udp4, - fun() -> - not_yet_implemented(), - InitState = #{domain => inet, - type => dgram, - protocol => udp}, - ok = socket_close(InitState) - end). - + %% *** The actual test *** + %% We intentially leave the socket "as is", no explicit close + #{desc => "await terminate (from tester)", + cmd => fun(#{tester := Tester} = State) -> + receive + {'DOWN', _, process, Tester, Reason} -> + ee("Unexpected DOWN regarding tester ~p: " + "~n ~p", [Reason]), + {error, {unexpected_exit, tester}}; + {terminate, Tester} -> + {ok, maps:remove(tester, State)} + end + end}, + #{desc => "enable (otp) debug", + cmd => fun(#{sock := Sock} = _State) -> + ok = socket:setopt(Sock, otp, debug, true) + end}, -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% This test case is intended to test what happens when a process other -%% than the controlling process closes a socket. -%% For a IPv6 UDP (dgram) socket. + %% *** We are done *** + #{desc => "finish", + cmd => fun(_) -> + {ok, normal} + end} + ], -socket_close_udp6(suite) -> - []; -socket_close_udp6(doc) -> - []; -socket_close_udp6(_Config) when is_list(_Config) -> - tc_try(socket_close_udp6, - fun() -> - not_yet_implemented(), - InitState = #{domain => inet6, - type => dgram, - protocol => udp}, - ok = socket_close(InitState) - end). + TesterSeq = + [ + %% *** Init part *** + #{desc => "monitor owner", + cmd => fun(#{owner := Owner} = _State) -> + _MRef = erlang:monitor(process, Owner), + ok + end}, + #{desc => "order (owner) start", + cmd => fun(#{owner := Pid} = _State) -> + Pid ! {start, self()}, + ok + end}, + #{desc => "await (owner) ready", + cmd => fun(#{owner := Owner} = State) -> + receive + {'DOWN', _, process, Owner, Reason} -> + ee("Unexpected DOWN regarding owner ~p: " + "~n ~p", [Reason]), + {error, {unexpected_exit, owner}}; + {ready, Owner, Sock} -> + {ok, State#{sock => Sock}} + end + end}, + #{desc => "verify owner as controlling-process", + cmd => fun(#{owner := Owner, sock := Sock} = _State) -> + case socket:getopt(Sock, otp, controlling_process) of + {ok, Owner} -> + ok; + {ok, Other} -> + {error, {unexpected_owner, Other}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "order (owner) terminate", + cmd => fun(#{owner := Pid} = _State) -> + Pid ! {terminate, self()}, + ok + end}, + #{desc => "await (owner) termination", + cmd => fun(#{owner := Owner} = _State) -> + receive + {'DOWN', _, process, Owner, _} -> + ok + end + end}, + #{desc => "verify no socket (closed)", + cmd => fun(#{owner := Owner, sock := Sock} = _State) -> + case socket:getopt(Sock, otp, controlling_process) of + {ok, Pid} -> + {error, {unexpected_success, Owner, Pid}}; + {error, closed} -> + ok; + {error, Reason} -> + ei("expected failure: ~p", [Reason]), + {error, {unexpected_failure, Reason}} + end + end}, + %% *** We are done *** + #{desc => "finish", + cmd => fun(_) -> + {ok, normal} + end} + ], -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + p("start (socket) owner evaluator"), + Owner = evaluator_start("owner", OwnerSeq, InitState), -socket_close(_InitState) -> - ok. + p("start tester evaluator"), + TesterInitState = #{owner => Owner}, + Tester = evaluator_start("tester", TesterSeq, TesterInitState), + p("await evaluator"), + ok = await_evaluator_finish([Owner, Tester]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -2982,12 +3025,12 @@ socket_close(_InitState) -> %% locally closed while the process is calling the recv function. %% Socket is IPv4. -recv_response_local_close_tcp4(suite) -> +sc_recv_response_local_close_tcp4(suite) -> []; -recv_response_local_close_tcp4(doc) -> +sc_recv_response_local_close_tcp4(doc) -> []; -recv_response_local_close_tcp4(_Config) when is_list(_Config) -> - tc_try(recv_response_local_close_tcp4, +sc_recv_response_local_close_tcp4(_Config) when is_list(_Config) -> + tc_try(sc_recv_response_local_close_tcp4, fun() -> not_yet_implemented(), Recv = fun(Sock) -> socket:recv(Sock) end, @@ -2995,7 +3038,7 @@ recv_response_local_close_tcp4(_Config) when is_list(_Config) -> type => stream, protocol => tcp, recv => Recv}, - ok = receive_response_local_close_tcp(InitState) + ok = sc_receive_response_local_close_tcp(InitState) end). @@ -3004,12 +3047,12 @@ recv_response_local_close_tcp4(_Config) when is_list(_Config) -> %% locally closed while the process is calling the recv function. %% Socket is IPv6. -recv_response_local_close_tcp6(suite) -> +sc_recv_response_local_close_tcp6(suite) -> []; -recv_response_local_close_tcp6(doc) -> +sc_recv_response_local_close_tcp6(doc) -> []; -recv_response_local_close_tcp6(_Config) when is_list(_Config) -> - tc_try(recv_response_local_close_tcp6, +sc_recv_response_local_close_tcp6(_Config) when is_list(_Config) -> + tc_try(sc_recv_response_local_close_tcp6, fun() -> not_yet_implemented(), Recv = fun(Sock) -> socket:recv(Sock) end, @@ -3017,13 +3060,13 @@ recv_response_local_close_tcp6(_Config) when is_list(_Config) -> type => stream, protocol => tcp, recv => Recv}, - ok = receive_response_local_close_tcp(InitState) + ok = sc_receive_response_local_close_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -receive_response_local_close_tcp(_InitState) -> +sc_receive_response_local_close_tcp(_InitState) -> ok. @@ -3033,12 +3076,12 @@ receive_response_local_close_tcp(_InitState) -> %% remotely closed while the process is calling the recv function. %% Socket is IPv4. -recv_response_remote_close_tcp4(suite) -> +sc_recv_response_remote_close_tcp4(suite) -> []; -recv_response_remote_close_tcp4(doc) -> +sc_recv_response_remote_close_tcp4(doc) -> []; -recv_response_remote_close_tcp4(_Config) when is_list(_Config) -> - tc_try(recv_response_remote_close_tcp4, +sc_recv_response_remote_close_tcp4(_Config) when is_list(_Config) -> + tc_try(sc_recv_response_remote_close_tcp4, fun() -> not_yet_implemented(), Recv = fun(Sock) -> socket:recv(Sock) end, @@ -3046,7 +3089,7 @@ recv_response_remote_close_tcp4(_Config) when is_list(_Config) -> type => stream, protocol => tcp, recv => Recv}, - ok = receive_response_remote_close_tcp(InitState) + ok = sc_receive_response_remote_close_tcp(InitState) end). @@ -3055,12 +3098,12 @@ recv_response_remote_close_tcp4(_Config) when is_list(_Config) -> %% remotely closed while the process is calling the recv function. %% Socket is IPv6. -recv_response_remote_close_tcp6(suite) -> +sc_recv_response_remote_close_tcp6(suite) -> []; -recv_response_remote_close_tcp6(doc) -> +sc_recv_response_remote_close_tcp6(doc) -> []; -recv_response_remote_close_tcp6(_Config) when is_list(_Config) -> - tc_try(recv_response_remote_close_tcp6, +sc_recv_response_remote_close_tcp6(_Config) when is_list(_Config) -> + tc_try(sc_recv_response_remote_close_tcp6, fun() -> not_yet_implemented(), Recv = fun(Sock) -> socket:recv(Sock) end, @@ -3068,13 +3111,13 @@ recv_response_remote_close_tcp6(_Config) when is_list(_Config) -> type => stream, protocol => tcp, recv => Recv}, - ok = receive_response_remote_close_tcp(InitState) + ok = sc_receive_response_remote_close_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -receive_response_remote_close_tcp(_InitState) -> +sc_receive_response_remote_close_tcp(_InitState) -> ok. @@ -3084,12 +3127,12 @@ receive_response_remote_close_tcp(_InitState) -> %% locally closed while the process is calling the recvmsg function. %% Socket is IPv4. -recvmsg_response_local_close_tcp4(suite) -> +sc_recvmsg_response_local_close_tcp4(suite) -> []; -recvmsg_response_local_close_tcp4(doc) -> +sc_recvmsg_response_local_close_tcp4(doc) -> []; -recvmsg_response_local_close_tcp4(_Config) when is_list(_Config) -> - tc_try(recvmsg_response_local_close_tcp4, +sc_recvmsg_response_local_close_tcp4(_Config) when is_list(_Config) -> + tc_try(sc_recvmsg_response_local_close_tcp4, fun() -> not_yet_implemented(), Recv = fun(Sock) -> socket:recvmsg(Sock) end, @@ -3097,7 +3140,7 @@ recvmsg_response_local_close_tcp4(_Config) when is_list(_Config) -> type => stream, protocol => tcp, recv => Recv}, - ok = receive_response_local_close_tcp(InitState) + ok = sc_receive_response_local_close_tcp(InitState) end). @@ -3106,12 +3149,12 @@ recvmsg_response_local_close_tcp4(_Config) when is_list(_Config) -> %% locally closed while the process is calling the recvmsg function. %% Socket is IPv6. -recvmsg_response_local_close_tcp6(suite) -> +sc_recvmsg_response_local_close_tcp6(suite) -> []; -recvmsg_response_local_close_tcp6(doc) -> +sc_recvmsg_response_local_close_tcp6(doc) -> []; -recvmsg_response_local_close_tcp6(_Config) when is_list(_Config) -> - tc_try(recvmsg_response_local_close_tcp6, +sc_recvmsg_response_local_close_tcp6(_Config) when is_list(_Config) -> + tc_try(sc_recvmsg_response_local_close_tcp6, fun() -> not_yet_implemented(), Recv = fun(Sock) -> socket:recvmsg(Sock) end, @@ -3119,7 +3162,7 @@ recvmsg_response_local_close_tcp6(_Config) when is_list(_Config) -> type => stream, protocol => tcp, recv => Recv}, - ok = receive_response_local_close_tcp(InitState) + ok = sc_receive_response_local_close_tcp(InitState) end). @@ -3128,12 +3171,12 @@ recvmsg_response_local_close_tcp6(_Config) when is_list(_Config) -> %% remotely closed while the process is calling the recvmsg function. %% Socket is IPv4. -recvmsg_response_remote_close_tcp4(suite) -> +sc_recvmsg_response_remote_close_tcp4(suite) -> []; -recvmsg_response_remote_close_tcp4(doc) -> +sc_recvmsg_response_remote_close_tcp4(doc) -> []; -recvmsg_response_remote_close_tcp4(_Config) when is_list(_Config) -> - tc_try(recvmsg_response_remote_close_tcp4, +sc_recvmsg_response_remote_close_tcp4(_Config) when is_list(_Config) -> + tc_try(sc_recvmsg_response_remote_close_tcp4, fun() -> not_yet_implemented(), Recv = fun(Sock) -> socket:recvmsg(Sock) end, @@ -3141,7 +3184,7 @@ recvmsg_response_remote_close_tcp4(_Config) when is_list(_Config) -> type => stream, protocol => tcp, recv => Recv}, - ok = receive_response_remote_close_tcp(InitState) + ok = sc_receive_response_remote_close_tcp(InitState) end). @@ -3150,12 +3193,12 @@ recvmsg_response_remote_close_tcp4(_Config) when is_list(_Config) -> %% remotely closed while the process is calling the recvmsg function. %% Socket is IPv6. -recvmsg_response_remote_close_tcp6(suite) -> +sc_recvmsg_response_remote_close_tcp6(suite) -> []; -recvmsg_response_remote_close_tcp6(doc) -> +sc_recvmsg_response_remote_close_tcp6(doc) -> []; -recvmsg_response_remote_close_tcp6(_Config) when is_list(_Config) -> - tc_try(recvmsg_response_remote_close_tcp6, +sc_recvmsg_response_remote_close_tcp6(_Config) when is_list(_Config) -> + tc_try(sc_recvmsg_response_remote_close_tcp6, fun() -> not_yet_implemented(), Recv = fun(Sock) -> socket:recvmsg(Sock) end, @@ -3163,7 +3206,7 @@ recvmsg_response_remote_close_tcp6(_Config) when is_list(_Config) -> type => stream, protocol => tcp, recv => Recv}, - ok = receive_response_remote_close_tcp(InitState) + ok = sc_receive_response_remote_close_tcp(InitState) end). @@ -3174,18 +3217,18 @@ recvmsg_response_remote_close_tcp6(_Config) when is_list(_Config) -> %% git the setup anyway. %% Socket is IPv4. -acceptor_response_local_close_tcp4(suite) -> +sc_acceptor_response_local_close_tcp4(suite) -> []; -acceptor_response_local_close_tcp4(doc) -> +sc_acceptor_response_local_close_tcp4(doc) -> []; -acceptor_response_local_close_tcp4(_Config) when is_list(_Config) -> - tc_try(acceptor_response_local_close_tcp4, +sc_acceptor_response_local_close_tcp4(_Config) when is_list(_Config) -> + tc_try(sc_acceptor_response_local_close_tcp4, fun() -> not_yet_implemented(), InitState = #{domain => inet, type => stream, protocol => tcp}, - ok = acceptor_response_local_close_tcp(InitState) + ok = sc_acceptor_response_local_close_tcp(InitState) end). @@ -3196,24 +3239,24 @@ acceptor_response_local_close_tcp4(_Config) when is_list(_Config) -> %% git the setup anyway. %% Socket is IPv6. -acceptor_response_local_close_tcp6(suite) -> +sc_acceptor_response_local_close_tcp6(suite) -> []; -acceptor_response_local_close_tcp6(doc) -> +sc_acceptor_response_local_close_tcp6(doc) -> []; -acceptor_response_local_close_tcp6(_Config) when is_list(_Config) -> - tc_try(acceptor_response_local_close_tcp6, +sc_acceptor_response_local_close_tcp6(_Config) when is_list(_Config) -> + tc_try(sc_acceptor_response_local_close_tcp6, fun() -> not_yet_implemented(), InitState = #{domain => inet, type => stream, protocol => tcp}, - ok = acceptor_response_local_close_tcp(InitState) + ok = sc_acceptor_response_local_close_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -acceptor_response_local_close_tcp(_InitState) -> +sc_acceptor_response_local_close_tcp(_InitState) -> ok. @@ -3225,18 +3268,18 @@ acceptor_response_local_close_tcp(_InitState) -> %% git the setup anyway. %% Socket is IPv4. -acceptor_response_remote_close_tcp4(suite) -> +sc_acceptor_response_remote_close_tcp4(suite) -> []; -acceptor_response_remote_close_tcp4(doc) -> +sc_acceptor_response_remote_close_tcp4(doc) -> []; -acceptor_response_remote_close_tcp4(_Config) when is_list(_Config) -> - tc_try(acceptor_response_remote_close_tcp4, +sc_acceptor_response_remote_close_tcp4(_Config) when is_list(_Config) -> + tc_try(sc_acceptor_response_remote_close_tcp4, fun() -> not_yet_implemented(), InitState = #{domain => inet, type => stream, protocol => tcp}, - ok = acceptor_response_remote_close_tcp(InitState) + ok = sc_acceptor_response_remote_close_tcp(InitState) end). @@ -3247,24 +3290,24 @@ acceptor_response_remote_close_tcp4(_Config) when is_list(_Config) -> %% git the setup anyway. %% Socket is IPv6. -acceptor_response_remote_close_tcp6(suite) -> +sc_acceptor_response_remote_close_tcp6(suite) -> []; -acceptor_response_remote_close_tcp6(doc) -> +sc_acceptor_response_remote_close_tcp6(doc) -> []; -acceptor_response_remote_close_tcp6(_Config) when is_list(_Config) -> +sc_acceptor_response_remote_close_tcp6(_Config) when is_list(_Config) -> tc_try(acceptor_response_remote_close_tcp6, fun() -> not_yet_implemented(), InitState = #{domain => inet, type => stream, protocol => tcp}, - ok = acceptor_response_remote_close_tcp(InitState) + ok = sc_acceptor_response_remote_close_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -acceptor_response_remote_close_tcp(_InitState) -> +sc_acceptor_response_remote_close_tcp(_InitState) -> ok. -- cgit v1.2.3 From f945aa4a8067d745ee75fe695272104e220d7bc3 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Tue, 16 Oct 2018 15:57:17 +0200 Subject: [socket-nif|test] Added test case for closed socket while recv Added a test cases for testing "socket cleanup" while process is reading using recv. OTP-14831 --- lib/kernel/test/socket_SUITE.erl | 632 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 596 insertions(+), 36 deletions(-) (limited to 'lib') diff --git a/lib/kernel/test/socket_SUITE.erl b/lib/kernel/test/socket_SUITE.erl index 42420a37dc..8ab39f6ffe 100644 --- a/lib/kernel/test/socket_SUITE.erl +++ b/lib/kernel/test/socket_SUITE.erl @@ -66,11 +66,11 @@ api_to_recvmsg_tcp4/1, api_to_recvmsg_tcp6/1, - %% Controlling Process - sc_socket_cleanup_tcp4/1, - sc_socket_cleanup_tcp6/1, - sc_socket_cleanup_udp4/1, - sc_socket_cleanup_udp6/1, + %% Socket Closure + sc_cpe_socket_cleanup_tcp4/1, + sc_cpe_socket_cleanup_tcp6/1, + sc_cpe_socket_cleanup_udp4/1, + sc_cpe_socket_cleanup_udp6/1, sc_recv_response_local_close_tcp4/1, sc_recv_response_local_close_tcp6/1, sc_recv_response_remote_close_tcp4/1, @@ -130,7 +130,8 @@ groups() -> {api_basic, [], api_basic_cases()}, {api_options, [], api_options_cases()}, {api_op_with_timeout, [], api_op_with_timeout_cases()}, - {socket_closure, [], socket_closure_cases()} + {socket_closure, [], socket_closure_cases()}, + {sc_ctrl_proc_exit, [], sc_cp_exit_cases()} %% {tickets, [], ticket_cases()} ]. @@ -185,10 +186,7 @@ api_op_with_timeout_cases() -> %% remotely. socket_closure_cases() -> [ - sc_socket_cleanup_tcp4, - sc_socket_cleanup_tcp6, - sc_socket_cleanup_udp4, - sc_socket_cleanup_udp6, + {group, sc_ctrl_proc_exit}, sc_recv_response_local_close_tcp4, sc_recv_response_local_close_tcp6, @@ -206,6 +204,16 @@ socket_closure_cases() -> sc_acceptor_response_remote_close_tcp6 ]. +%% These cases are all about socket cleanup after the controlling process +%% exits *without* calling socket:close/1. +sc_cp_exit_cases() -> + [ + sc_cpe_socket_cleanup_tcp4, + sc_cpe_socket_cleanup_tcp6, + sc_cpe_socket_cleanup_udp4, + sc_cpe_socket_cleanup_udp6 + ]. + %% ticket_cases() -> %% []. @@ -1782,7 +1790,7 @@ api_to_maccept_tcp(InitState) -> #{desc => "close (listen) socket", cmd => fun(#{lsock := LSock} = State) -> sock_close(LSock), - {ok, maps:remove(sock3, State)} + {ok, maps:remove(lsock, State)} end}, %% *** We are done *** @@ -2805,18 +2813,18 @@ api_to_recvmsg_tcp6(_Config) when is_list(_Config) -> %% ("removed") when the controlling process terminates (without explicitly %% calling the close function). For a IPv4 TCP (stream) socket. -sc_socket_cleanup_tcp4(suite) -> +sc_cpe_socket_cleanup_tcp4(suite) -> []; -sc_socket_cleanup_tcp4(doc) -> +sc_cpe_socket_cleanup_tcp4(doc) -> []; -sc_socket_cleanup_tcp4(_Config) when is_list(_Config) -> - tc_try(sc_socket_cleanup_tcp4, +sc_cpe_socket_cleanup_tcp4(_Config) when is_list(_Config) -> + tc_try(sc_cpe_socket_cleanup_tcp4, fun() -> %% not_yet_implemented(), InitState = #{domain => inet, type => stream, protocol => tcp}, - ok = sc_socket_cleanup(InitState) + ok = sc_cpe_socket_cleanup(InitState) end). @@ -2825,18 +2833,18 @@ sc_socket_cleanup_tcp4(_Config) when is_list(_Config) -> %% ("removed") when the controlling process terminates (without explicitly %% calling the close function). For a IPv6 TCP (stream) socket. -sc_socket_cleanup_tcp6(suite) -> +sc_cpe_socket_cleanup_tcp6(suite) -> []; -sc_socket_cleanup_tcp6(doc) -> +sc_cpe_socket_cleanup_tcp6(doc) -> []; -sc_socket_cleanup_tcp6(_Config) when is_list(_Config) -> - tc_try(sc_socket_cleanup_tcp6, +sc_cpe_socket_cleanup_tcp6(_Config) when is_list(_Config) -> + tc_try(sc_cpe_socket_cleanup_tcp6, fun() -> not_yet_implemented(), InitState = #{domain => inet6, type => stream, protocol => tcp}, - ok = sc_socket_cleanup(InitState) + ok = sc_cpe_socket_cleanup(InitState) end). @@ -2845,17 +2853,17 @@ sc_socket_cleanup_tcp6(_Config) when is_list(_Config) -> %% ("removed") when the controlling process terminates (without explicitly %% calling the close function). For a IPv4 UDP (dgram) socket. -sc_socket_cleanup_udp4(suite) -> +sc_cpe_socket_cleanup_udp4(suite) -> []; -sc_socket_cleanup_udp4(doc) -> +sc_cpe_socket_cleanup_udp4(doc) -> []; -sc_socket_cleanup_udp4(_Config) when is_list(_Config) -> - tc_try(sc_socket_cleanup_udp4, +sc_cpe_socket_cleanup_udp4(_Config) when is_list(_Config) -> + tc_try(sc_cpe_socket_cleanup_udp4, fun() -> InitState = #{domain => inet, type => dgram, protocol => udp}, - ok = sc_socket_cleanup(InitState) + ok = sc_cpe_socket_cleanup(InitState) end). @@ -2865,24 +2873,24 @@ sc_socket_cleanup_udp4(_Config) when is_list(_Config) -> %% (removed) when the controlling process terminates (without explicitly %% calling the close function). For a IPv6 UDP (dgram) socket. -sc_socket_cleanup_udp6(suite) -> +sc_cpe_socket_cleanup_udp6(suite) -> []; -sc_socket_cleanup_udp6(doc) -> +sc_cpe_socket_cleanup_udp6(doc) -> []; -sc_socket_cleanup_udp6(_Config) when is_list(_Config) -> - tc_try(sc_socket_cleanup_udp6, +sc_cpe_socket_cleanup_udp6(_Config) when is_list(_Config) -> + tc_try(sc_cpe_socket_cleanup_udp6, fun() -> not_yet_implemented(), InitState = #{domain => inet6, type => dgram, protocol => udp}, - ok = sc_socket_cleanup(InitState) + ok = sc_cpe_socket_cleanup(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -sc_socket_cleanup(InitState) -> +sc_cpe_socket_cleanup(InitState) -> OwnerSeq = [ %% *** Wait for start order part *** @@ -3022,8 +3030,16 @@ sc_socket_cleanup(InitState) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test what happens when a socket is -%% locally closed while the process is calling the recv function. +%% locally closed while a process is calling the recv function. %% Socket is IPv4. +%% +%% +%% +%% We should really have a similar test cases for when the controlling +%% process exits and there are other processes in recv, accept, and +%% all the other functions. +%% +%% sc_recv_response_local_close_tcp4(suite) -> []; @@ -3032,7 +3048,7 @@ sc_recv_response_local_close_tcp4(doc) -> sc_recv_response_local_close_tcp4(_Config) when is_list(_Config) -> tc_try(sc_recv_response_local_close_tcp4, fun() -> - not_yet_implemented(), + %% not_yet_implemented(), Recv = fun(Sock) -> socket:recv(Sock) end, InitState = #{domain => inet, type => stream, @@ -3066,8 +3082,548 @@ sc_recv_response_local_close_tcp6(_Config) when is_list(_Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -sc_receive_response_local_close_tcp(_InitState) -> - ok. +sc_receive_response_local_close_tcp(InitState) -> + %% This is the server that accepts connections. + %% But it is also suppose to close the connection socket, + %% and trigger the read failure for the handler process. + AcceptorSeq = + [ + %% *** Wait for start order part *** + #{desc => "await start (from tester)", + cmd => fun(State) -> + receive + {start, Tester} when is_pid(Tester) -> + {ok, State#{tester => Tester}} + end + end}, + #{desc => "monitor tester", + cmd => fun(#{tester := Tester} = _State) -> + _MRef = erlang:monitor(process, Tester), + ok + end}, + + %% *** Init part *** + #{desc => "which local address", + cmd => fun(#{domain := Domain} = State) -> + LAddr = which_local_addr(Domain), + LSA = #{family => Domain, addr => LAddr}, + {ok, State#{lsa => LSA}} + end}, + #{desc => "create (listen) socket", + cmd => fun(#{domain := Domain, + type := Type, + protocol := Proto} = State) -> + case socket:open(Domain, Type, Proto) of + {ok, Sock} -> + {ok, State#{lsock => Sock}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "bind to local address", + cmd => fun(#{lsock := LSock, lsa := LSA} = State) -> + case socket:bind(LSock, LSA) of + {ok, Port} -> + {ok, State#{lport => Port}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "make listen socket", + cmd => fun(#{lsock := LSock}) -> + socket:listen(LSock) + end}, + #{desc => "announce ready (init)", + cmd => fun(#{tester := Tester, lport := Port}) -> + Tester ! {ready, self(), Port}, + ok + end}, + + %% The actual test + #{desc => "await continue (connection)", + cmd => fun(#{tester := Tester} = State) -> + receive + {'DOWN', _, process, Tester, Reason} -> + ee("Unexpected DOWN regarding tester ~p: " + "~n ~p", [Reason]), + {error, {unexpected_exit, tester}}; + {continue, Tester, Handler} -> + {ok, State#{handler => Handler}} + end + end}, + #{desc => "await connection", + cmd => fun(#{lsock := LSock} = State) -> + case socket:accept(LSock) of + {ok, Sock} -> + ei("connection accepted"), + {ok, State#{csock => Sock}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "transfer new connection to handler", + cmd => fun(#{handler := Handler, csock := Sock}) -> + ok = socket:setopt(Sock, + otp, controlling_process, + Handler), + Handler ! {connection, Sock}, + ok + end}, + #{desc => "announce ready (connection)", + cmd => fun(#{tester := Tester}) -> + Tester ! {ready, self()}, + ok + end}, + #{desc => "await continue (close)", + cmd => fun(#{tester := Tester} = _State) -> + receive + {'DOWN', _, process, Tester, Reason} -> + ee("Unexpected DOWN regarding tester ~p: " + "~n ~p", [Reason]), + {error, {unexpected_exit, tester}}; + {continue, Tester} -> + ok + end + end}, + %% #{desc => "enable debug", + %% cmd => fun(#{csock := Sock}) -> + %% socket:setopt(Sock, otp, debug, true) + %% end}, + #{desc => "close (the connection) socket", + cmd => fun(#{csock := Sock}) -> + socket:close(Sock) + end}, + + #{desc => "await terminate", + cmd => fun(#{tester := Tester} = State) -> + receive + {'DOWN', _, process, Tester, Reason} -> + ee("Unexpected DOWN regarding tester ~p: " + "~n ~p", [Reason]), + {error, {unexpected_exit, tester}}; + {terminate, Tester} -> + {ok, maps:remove(tester, State)} + end + end}, + #{desc => "socket cleanup", + cmd => fun(#{lsock := Sock} = State) -> + ok = socket:close(Sock), + State1 = maps:remove(csock, State), + State2 = maps:remove(lsock, State1), + State3 = maps:remove(lport, State2), + {ok, State3} + end}, + + %% *** We are done *** + #{desc => "finish", + cmd => fun(_) -> + {ok, normal} + end} + ], + + %% The point of this is to perform the recv for which we are testing the reponse + HandlerSeq = + [ + %% *** Wait for start order part *** + #{desc => "await start (from tester)", + cmd => fun(State) -> + receive + {start, Tester} when is_pid(Tester) -> + {ok, State#{tester => Tester}} + end + end}, + #{desc => "monitor server", + cmd => fun(#{tester := Tester} = _State) -> + _MRef = erlang:monitor(process, Tester), + ok + end}, + #{desc => "announce ready (init)", + cmd => fun(#{tester := Tester}) -> + Tester ! {ready, self()}, + ok + end}, + + %% The actual test + #{desc => "await connection socket", + cmd => fun(#{tester := Tester} = State) -> + receive + {'DOWN', _, process, Tester, Reason} -> + ee("Unexpected DOWN regarding tester ~p: " + "~n ~p", [Reason]), + {error, {unexpected_exit, tester}}; + {connection, Sock} -> + {ok, State#{sock => Sock}} + end + end}, + #{desc => "announce ready (connection)", + cmd => fun(#{tester := Tester}) -> + Tester ! {ready, self()}, + ok + end}, + %% #{desc => "enable debug", + %% cmd => fun(#{sock := Sock}) -> + %% socket:setopt(Sock, otp, debug, true) + %% end}, + %% #{desc => "monitored-by", + %% cmd => fun(_) -> + %% {_, Mons} = process_info(self(), monitored_by), + %% ei("Monitored By: ~p", [Mons]), + %% ok + %% end}, + #{desc => "attempt recv", + cmd => fun(#{sock := Sock} = State) -> + case socket:recv(Sock) of + {ok, _Data} -> + ee("Unexpected data received"), + {error, unexpected_data}; + {error, closed} -> + State1 = maps:remove(sock, State), + {ok, State1}; + {error, Reason} = ERROR -> + ee("Unexpected read faulure: " + "~n ~p", [Reason]), + ERROR + end + end}, + %% #{desc => "monitored-by", + %% cmd => fun(_) -> + %% {_, Mons} = process_info(self(), monitored_by), + %% ei("Monitored By: ~p", [Mons]), + %% ok + %% end}, + #{desc => "announce ready (close)", + cmd => fun(#{tester := Tester}) -> + Tester ! {ready, self()}, + ok + end}, + #{desc => "sleep some", + cmd => fun(_) -> + ?SLEEP(1000), + ok + end}, + %% #{desc => "monitored-by", + %% cmd => fun(_) -> + %% {_, Mons} = process_info(self(), monitored_by), + %% ei("Monitored By: ~p", [Mons]), + %% ok + %% end}, + #{desc => "await terminate", + cmd => fun(#{tester := Tester} = _State) -> + receive + {'DOWN', _, process, Tester, Reason} -> + ee("Unexpected DOWN regarding tester ~p: " + "~n ~p", [Reason]), + {error, {unexpected_exit, tester}}; + {terminate, Tester} -> + ok + end + end}, + + + %% *** We are done *** + #{desc => "finish", + cmd => fun(_) -> + {ok, normal} + end} + ], + + %% The point of this is basically just to create the connection. + ClientSeq = + [ + %% *** Wait for start order part *** + #{desc => "await start (from tester)", + cmd => fun(State) -> + receive + {start, Tester} when is_pid(Tester) -> + {ok, State#{tester => Tester}} + end + end}, + + %% Init + #{desc => "which local address", + cmd => fun(#{domain := Domain} = State) -> + LAddr = which_local_addr(Domain), + LSA = #{family => Domain, addr => LAddr}, + {ok, State#{lsa => LSA}} + end}, + #{desc => "create socket", + cmd => fun(#{domain := Domain, + type := Type, + protocol := Proto} = State) -> + case socket:open(Domain, Type, Proto) of + {ok, Sock} -> + {ok, State#{sock => Sock}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "bind socket to local address", + cmd => fun(#{sock := Sock, lsa := LSA} = _State) -> + case socket:bind(Sock, LSA) of + {ok, _} -> + ok; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "announce ready", + cmd => fun(#{tester := Tester} = _State) -> + Tester ! {ready, self()}, + ok + end}, + + %% The actual test + #{desc => "await continue", + cmd => fun(#{tester := Tester} = State) -> + receive + {'DOWN', _, process, Tester, Reason} -> + ee("Unexpected DOWN regarding tester ~p: " + "~n ~p", [Tester, Reason]), + {error, {unexpected_exit, tester, Reason}}; + {continue, Tester, Port} -> + {ok, State#{lport => Port}} + end + end}, + #{desc => "connect to server", + cmd => fun(#{sock := Sock, lsa := LSA, lport := LPort}) -> + socket:connect(Sock, LSA#{port => LPort}) + end}, + #{desc => "announce ready (connection)", + cmd => fun(#{tester := Tester} = _State) -> + Tester ! {ready, self()}, + ok + end}, + + %% Cleaning up + #{desc => "await terminate (from tester)", + cmd => fun(#{tester := Tester} = State) -> + receive + {'DOWN', _, process, Tester, Reason} -> + ee("Unexpected DOWN regarding tester ~p: " + "~n ~p", [Tester, Reason]), + {error, {unexpected_exit, tester}}; + {terminate, Tester} -> + {ok, maps:remove(tester, State)} + end + end}, + #{desc => "close socket", + cmd => fun(#{sock := Sock} = State) -> + sock_close(Sock), + {ok, maps:remove(sock, State)} + end}, + + %% *** We are done *** + #{desc => "finish", + cmd => fun(_) -> + {ok, normal} + end} + ], + + TesterSeq = + [ + %% *** Init part *** + #{desc => "monitor acceptor", + cmd => fun(#{acceptor := Pid} = _State) -> + _MRef = erlang:monitor(process, Pid), + ok + end}, + #{desc => "monitor handler", + cmd => fun(#{handler := Pid} = _State) -> + _MRef = erlang:monitor(process, Pid), + ok + end}, + #{desc => "monitor client", + cmd => fun(#{client := Pid} = _State) -> + _MRef = erlang:monitor(process, Pid), + ok + end}, + + %% Start the acceptor + #{desc => "order acceptor start", + cmd => fun(#{acceptor := Pid} = _State) -> + Pid ! {start, self()}, + ok + end}, + #{desc => "await acceptor ready (init)", + cmd => fun(#{acceptor := Pid} = State) -> + receive + {'DOWN', _, process, Pid, Reason} -> + ee("Unexpected DOWN regarding acceptor ~p: " + "~n ~p", [Pid, Reason]), + {error, {unexpected_exit, acceptor}}; + {ready, Pid, Port} -> + {ok, State#{lport => Port}} + end + end}, + + %% Start the handler + #{desc => "order handler start", + cmd => fun(#{handler := Pid} = _State) -> + Pid ! {start, self()}, + ok + end}, + #{desc => "await handler ready (init)", + cmd => fun(#{handler := Pid} = _State) -> + receive + {'DOWN', _, process, Pid, Reason} -> + ee("Unexpected DOWN regarding handler ~p: " + "~n ~p", [Pid, Reason]), + {error, {unexpected_exit, acceptor}}; + {ready, Pid} -> + ok + end + end}, + + %% Start the client + #{desc => "order client start", + cmd => fun(#{client := Pid} = _State) -> + Pid ! {start, self()}, + ok + end}, + #{desc => "await client ready (init)", + cmd => fun(#{client := Pid} = _State) -> + receive + {'DOWN', _, process, Pid, Reason} -> + ee("Unexpected DOWN regarding cient ~p: " + "~n ~p", [Pid, Reason]), + {error, {unexpected_exit, acceptor}}; + {ready, Pid} -> + ok + end + end}, + + %% The actual test + #{desc => "order acceptor to continue", + cmd => fun(#{acceptor := Pid, handler := Handler} = _State) -> + Pid ! {continue, self(), Handler}, + ok + end}, + #{desc => "order client to continue", + cmd => fun(#{client := Pid, lport := Port} = _State) -> + Pid ! {continue, self(), Port}, + ok + end}, + #{desc => "await acceptor ready (connection)", + cmd => fun(#{acceptor := Pid} = _State) -> + receive + {'DOWN', _, process, Pid, Reason} -> + ee("Unexpected DOWN regarding acceptor ~p: " + "~n ~p", [Pid, Reason]), + {error, {unexpected_exit, acceptor}}; + {ready, Pid} -> + ok + end + end}, + #{desc => "await client ready (connection)", + cmd => fun(#{client := Pid} = _State) -> + receive + {'DOWN', _, process, Pid, Reason} -> + ee("Unexpected DOWN regarding client ~p: " + "~n ~p", [Pid, Reason]), + {error, {unexpected_exit, acceptor}}; + {ready, Pid} -> + ok + end + end}, + #{desc => "await handler ready (connection)", + cmd => fun(#{handler := Pid} = _State) -> + receive + {'DOWN', _, process, Pid, Reason} -> + ee("Unexpected DOWN regarding handler ~p: " + "~n ~p", [Reason]), + {error, {unexpected_exit, acceptor}}; + {ready, Pid} -> + ok + end + end}, + #{desc => "sleep some", + cmd => fun(_State) -> + ?SLEEP(1000), + ok + end}, + #{desc => "order acceptor to continue (close)", + cmd => fun(#{acceptor := Pid} = _State) -> + Pid ! {continue, self()}, + ok + end}, + #{desc => "await handler ready (close)", + cmd => fun(#{handler := Pid} = _State) -> + receive + {'DOWN', _, process, Pid, Reason} -> + ee("Unexpected DOWN regarding handler ~p: " + "~n ~p", [Pid, Reason]), + {error, {unexpected_exit, acceptor}}; + {ready, Pid} -> + ok + end + end}, + + %% Terminations + #{desc => "order handler to terminate", + cmd => fun(#{handler := Pid} = _State) -> + Pid ! {terminate, self()}, + ok + end}, + #{desc => "await handler termination", + cmd => fun(#{handler := Pid} = State) -> + receive + {'DOWN', _, process, Pid, _} -> + {ok, maps:remove(handler, State)} + end + end}, + #{desc => "order client to terminate", + cmd => fun(#{client := Pid} = _State) -> + Pid ! {terminate, self()}, + ok + end}, + #{desc => "await client termination", + cmd => fun(#{client := Pid} = State) -> + receive + {'DOWN', _, process, Pid, _} -> + {ok, maps:remove(client, State)} + end + end}, + #{desc => "order acceptor to terminate", + cmd => fun(#{acceptor := Pid} = _State) -> + Pid ! {terminate, self()}, + ok + end}, + #{desc => "await acceptor termination", + cmd => fun(#{acceptor := Pid} = State) -> + receive + {'DOWN', _, process, Pid, _} -> + {ok, maps:remove(acceptor, State)} + end + end}, + + + %% *** We are done *** + #{desc => "finish", + cmd => fun(_) -> + {ok, normal} + end} + ], + + p("start acceptor evaluator"), + AccInitState = InitState, + Acceptor = evaluator_start("acceptor", AcceptorSeq, AccInitState), + + p("start handler evaluator"), + HandlerInitState = #{}, + Handler = evaluator_start("handler", HandlerSeq, HandlerInitState), + + p("start client evaluator"), + ClientInitState = InitState, + Client = evaluator_start("client", ClientSeq, ClientInitState), + + p("start tester evaluator"), + TesterInitState = #{acceptor => Acceptor, + handler => Handler, + client => Client}, + Tester = evaluator_start("tester", TesterSeq, TesterInitState), + + p("await evaluator"), + ok = await_evaluator_finish([Acceptor, Handler, Client, Tester]). @@ -3426,9 +3982,13 @@ await_evaluator_finish(Evs, Fails) -> end. +ei(F) -> + ei(F, []). ei(F, A) -> eprint("", F, A). +ee(F) -> + ee(F, []). ee(F, A) -> eprint(" ", F, A). -- cgit v1.2.3 From 598ecec8b59509f223807d36e9dd1244d7d80fa2 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Thu, 18 Oct 2018 16:25:47 +0200 Subject: [socket-nif|test] Some minor test case re-grouping --- lib/kernel/test/socket_SUITE.erl | 267 +++++++++++++++++++-------------------- 1 file changed, 128 insertions(+), 139 deletions(-) (limited to 'lib') diff --git a/lib/kernel/test/socket_SUITE.erl b/lib/kernel/test/socket_SUITE.erl index 8ab39f6ffe..4ee2eec39a 100644 --- a/lib/kernel/test/socket_SUITE.erl +++ b/lib/kernel/test/socket_SUITE.erl @@ -71,18 +71,16 @@ sc_cpe_socket_cleanup_tcp6/1, sc_cpe_socket_cleanup_udp4/1, sc_cpe_socket_cleanup_udp6/1, - sc_recv_response_local_close_tcp4/1, - sc_recv_response_local_close_tcp6/1, - sc_recv_response_remote_close_tcp4/1, - sc_recv_response_remote_close_tcp6/1, - sc_recvmsg_response_local_close_tcp4/1, - sc_recvmsg_response_local_close_tcp6/1, - sc_recvmsg_response_remote_close_tcp4/1, - sc_recvmsg_response_remote_close_tcp6/1, - sc_acceptor_response_local_close_tcp4/1, - sc_acceptor_response_local_close_tcp6/1, - sc_acceptor_response_remote_close_tcp4/1, - sc_acceptor_response_remote_close_tcp6/1 + sc_lc_recv_response_tcp4/1, + sc_lc_recv_response_tcp6/1, + sc_lc_recvmsg_response_tcp4/1, + sc_lc_recvmsg_response_tcp6/1, + sc_lc_acceptor_response_tcp4/1, + sc_lc_acceptor_response_tcp6/1, + sc_rc_recv_response_tcp4/1, + sc_rc_recv_response_tcp6/1, + sc_rc_recvmsg_response_tcp4/1, + sc_rc_recvmsg_response_tcp6/1 %% Tickets ]). @@ -131,7 +129,9 @@ groups() -> {api_options, [], api_options_cases()}, {api_op_with_timeout, [], api_op_with_timeout_cases()}, {socket_closure, [], socket_closure_cases()}, - {sc_ctrl_proc_exit, [], sc_cp_exit_cases()} + {sc_ctrl_proc_exit, [], sc_cp_exit_cases()}, + {sc_local_close, [], sc_lc_cases()}, + {sc_remote_close, [], sc_rc_cases()} %% {tickets, [], ticket_cases()} ]. @@ -187,21 +187,8 @@ api_op_with_timeout_cases() -> socket_closure_cases() -> [ {group, sc_ctrl_proc_exit}, - - sc_recv_response_local_close_tcp4, - sc_recv_response_local_close_tcp6, - sc_recv_response_remote_close_tcp4, - sc_recv_response_remote_close_tcp6, - - sc_recvmsg_response_local_close_tcp4, - sc_recvmsg_response_local_close_tcp6, - sc_recvmsg_response_remote_close_tcp4, - sc_recvmsg_response_remote_close_tcp6, - - sc_acceptor_response_local_close_tcp4, - sc_acceptor_response_local_close_tcp6, - sc_acceptor_response_remote_close_tcp4, - sc_acceptor_response_remote_close_tcp6 + {group, sc_local_close}, + {group, sc_remote_close} ]. %% These cases are all about socket cleanup after the controlling process @@ -214,6 +201,30 @@ sc_cp_exit_cases() -> sc_cpe_socket_cleanup_udp6 ]. +%% These cases tests what happens when the socket is closed locally. +sc_lc_cases() -> + [ + sc_lc_recv_response_tcp4, + sc_lc_recv_response_tcp6, + + sc_lc_recvmsg_response_tcp4, + sc_lc_recvmsg_response_tcp6, + + sc_lc_acceptor_response_tcp4, + sc_lc_acceptor_response_tcp6 + ]. + +%% These cases tests what happens when the socket is closed remotely. +sc_rc_cases() -> + [ + sc_rc_recv_response_tcp4, + sc_rc_recv_response_tcp6, + + sc_rc_recvmsg_response_tcp4, + sc_rc_recvmsg_response_tcp6 + ]. + + %% ticket_cases() -> %% []. @@ -2332,6 +2343,7 @@ api_to_receive_tcp(InitState) -> cmd => fun(#{lsock := LSock} = State) -> case socket:accept(LSock) of {ok, Sock} -> + %% ok = socket:setopt(Sock, otp, debug, true), {ok, State#{sock => Sock}}; {error, _} = ERROR -> ERROR @@ -2375,16 +2387,44 @@ api_to_receive_tcp(InitState) -> {ok, maps:remove(tester, State)} end end}, + %% #{desc => "sleep some (before traffic close)", + %% cmd => fun(_) -> + %% ?SLEEP(1000), + %% ok + %% end}, + %% #{desc => "monitored-by", + %% cmd => fun(_) -> + %% {_, Mons} = process_info(self(), monitored_by), + %% ei("Monitored By: ~p", [Mons]), + %% ok + %% end}, #{desc => "close (traffic) socket", cmd => fun(#{sock := Sock} = State) -> + %% ok = socket:setopt(Sock, otp, debug, true), sock_close(Sock), {ok, maps:remove(sock, State)} end}, + %% #{desc => "monitored-by", + %% cmd => fun(_) -> + %% {_, Mons} = process_info(self(), monitored_by), + %% ei("Monitored By: ~p", [Mons]), + %% ok + %% end}, + %% #{desc => "sleep some (before listen close)", + %% cmd => fun(_) -> + %% ?SLEEP(1000), + %% ok + %% end}, #{desc => "close (listen) socket", cmd => fun(#{lsock := LSock} = State) -> sock_close(LSock), {ok, maps:remove(lsock, State)} end}, + %% #{desc => "sleep some (after listen close)", + %% cmd => fun(_) -> + %% ?SLEEP(1000), + %% ok + %% end}, %% *** We are done *** #{desc => "finish", @@ -2938,10 +2978,10 @@ sc_cpe_socket_cleanup(InitState) -> {ok, maps:remove(tester, State)} end end}, - #{desc => "enable (otp) debug", - cmd => fun(#{sock := Sock} = _State) -> - ok = socket:setopt(Sock, otp, debug, true) - end}, + %% #{desc => "enable (otp) debug", + %% cmd => fun(#{sock := Sock} = _State) -> + %% ok = socket:setopt(Sock, otp, debug, true) + %% end}, %% *** We are done *** #{desc => "finish", @@ -3041,12 +3081,12 @@ sc_cpe_socket_cleanup(InitState) -> %% %% -sc_recv_response_local_close_tcp4(suite) -> +sc_lc_recv_response_tcp4(suite) -> []; -sc_recv_response_local_close_tcp4(doc) -> +sc_lc_recv_response_tcp4(doc) -> []; -sc_recv_response_local_close_tcp4(_Config) when is_list(_Config) -> - tc_try(sc_recv_response_local_close_tcp4, +sc_lc_recv_response_tcp4(_Config) when is_list(_Config) -> + tc_try(sc_lc_recv_response_tcp4, fun() -> %% not_yet_implemented(), Recv = fun(Sock) -> socket:recv(Sock) end, @@ -3054,7 +3094,7 @@ sc_recv_response_local_close_tcp4(_Config) when is_list(_Config) -> type => stream, protocol => tcp, recv => Recv}, - ok = sc_receive_response_local_close_tcp(InitState) + ok = sc_lc_receive_response_tcp(InitState) end). @@ -3063,12 +3103,12 @@ sc_recv_response_local_close_tcp4(_Config) when is_list(_Config) -> %% locally closed while the process is calling the recv function. %% Socket is IPv6. -sc_recv_response_local_close_tcp6(suite) -> +sc_lc_recv_response_tcp6(suite) -> []; -sc_recv_response_local_close_tcp6(doc) -> +sc_lc_recv_response_tcp6(doc) -> []; -sc_recv_response_local_close_tcp6(_Config) when is_list(_Config) -> - tc_try(sc_recv_response_local_close_tcp6, +sc_lc_recv_response_tcp6(_Config) when is_list(_Config) -> + tc_try(sc_lc_recv_response_tcp6, fun() -> not_yet_implemented(), Recv = fun(Sock) -> socket:recv(Sock) end, @@ -3076,13 +3116,13 @@ sc_recv_response_local_close_tcp6(_Config) when is_list(_Config) -> type => stream, protocol => tcp, recv => Recv}, - ok = sc_receive_response_local_close_tcp(InitState) + ok = sc_lc_receive_response_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -sc_receive_response_local_close_tcp(InitState) -> +sc_lc_receive_response_tcp(InitState) -> %% This is the server that accepts connections. %% But it is also suppose to close the connection socket, %% and trigger the read failure for the handler process. @@ -3271,8 +3311,8 @@ sc_receive_response_local_close_tcp(InitState) -> %% ok %% end}, #{desc => "attempt recv", - cmd => fun(#{sock := Sock} = State) -> - case socket:recv(Sock) of + cmd => fun(#{sock := Sock, recv := Recv} = State) -> + case Recv(Sock) of {ok, _Data} -> ee("Unexpected data received"), {error, unexpected_data}; @@ -3609,7 +3649,7 @@ sc_receive_response_local_close_tcp(InitState) -> Acceptor = evaluator_start("acceptor", AcceptorSeq, AccInitState), p("start handler evaluator"), - HandlerInitState = #{}, + HandlerInitState = #{recv => maps:get(recv, InitState)}, Handler = evaluator_start("handler", HandlerSeq, HandlerInitState), p("start client evaluator"), @@ -3632,12 +3672,12 @@ sc_receive_response_local_close_tcp(InitState) -> %% remotely closed while the process is calling the recv function. %% Socket is IPv4. -sc_recv_response_remote_close_tcp4(suite) -> +sc_rc_recv_response_tcp4(suite) -> []; -sc_recv_response_remote_close_tcp4(doc) -> +sc_rc_recv_response_tcp4(doc) -> []; -sc_recv_response_remote_close_tcp4(_Config) when is_list(_Config) -> - tc_try(sc_recv_response_remote_close_tcp4, +sc_rc_recv_response_tcp4(_Config) when is_list(_Config) -> + tc_try(sc_rc_recv_response_tcp4, fun() -> not_yet_implemented(), Recv = fun(Sock) -> socket:recv(Sock) end, @@ -3645,7 +3685,7 @@ sc_recv_response_remote_close_tcp4(_Config) when is_list(_Config) -> type => stream, protocol => tcp, recv => Recv}, - ok = sc_receive_response_remote_close_tcp(InitState) + ok = sc_rc_receive_response_tcp(InitState) end). @@ -3654,12 +3694,12 @@ sc_recv_response_remote_close_tcp4(_Config) when is_list(_Config) -> %% remotely closed while the process is calling the recv function. %% Socket is IPv6. -sc_recv_response_remote_close_tcp6(suite) -> +sc_rc_recv_response_tcp6(suite) -> []; -sc_recv_response_remote_close_tcp6(doc) -> +sc_rc_recv_response_tcp6(doc) -> []; -sc_recv_response_remote_close_tcp6(_Config) when is_list(_Config) -> - tc_try(sc_recv_response_remote_close_tcp6, +sc_rc_recv_response_tcp6(_Config) when is_list(_Config) -> + tc_try(sc_rc_recv_response_tcp6, fun() -> not_yet_implemented(), Recv = fun(Sock) -> socket:recv(Sock) end, @@ -3667,13 +3707,13 @@ sc_recv_response_remote_close_tcp6(_Config) when is_list(_Config) -> type => stream, protocol => tcp, recv => Recv}, - ok = sc_receive_response_remote_close_tcp(InitState) + ok = sc_rc_receive_response_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -sc_receive_response_remote_close_tcp(_InitState) -> +sc_rc_receive_response_tcp(_InitState) -> ok. @@ -3683,12 +3723,12 @@ sc_receive_response_remote_close_tcp(_InitState) -> %% locally closed while the process is calling the recvmsg function. %% Socket is IPv4. -sc_recvmsg_response_local_close_tcp4(suite) -> +sc_lc_recvmsg_response_tcp4(suite) -> []; -sc_recvmsg_response_local_close_tcp4(doc) -> +sc_lc_recvmsg_response_tcp4(doc) -> []; -sc_recvmsg_response_local_close_tcp4(_Config) when is_list(_Config) -> - tc_try(sc_recvmsg_response_local_close_tcp4, +sc_lc_recvmsg_response_tcp4(_Config) when is_list(_Config) -> + tc_try(sc_lc_recvmsg_response_tcp4, fun() -> not_yet_implemented(), Recv = fun(Sock) -> socket:recvmsg(Sock) end, @@ -3696,7 +3736,7 @@ sc_recvmsg_response_local_close_tcp4(_Config) when is_list(_Config) -> type => stream, protocol => tcp, recv => Recv}, - ok = sc_receive_response_local_close_tcp(InitState) + ok = sc_lc_receive_response_tcp(InitState) end). @@ -3705,12 +3745,12 @@ sc_recvmsg_response_local_close_tcp4(_Config) when is_list(_Config) -> %% locally closed while the process is calling the recvmsg function. %% Socket is IPv6. -sc_recvmsg_response_local_close_tcp6(suite) -> +sc_lc_recvmsg_response_tcp6(suite) -> []; -sc_recvmsg_response_local_close_tcp6(doc) -> +sc_lc_recvmsg_response_tcp6(doc) -> []; -sc_recvmsg_response_local_close_tcp6(_Config) when is_list(_Config) -> - tc_try(sc_recvmsg_response_local_close_tcp6, +sc_lc_recvmsg_response_tcp6(_Config) when is_list(_Config) -> + tc_try(sc_recvmsg_response_tcp6, fun() -> not_yet_implemented(), Recv = fun(Sock) -> socket:recvmsg(Sock) end, @@ -3718,7 +3758,7 @@ sc_recvmsg_response_local_close_tcp6(_Config) when is_list(_Config) -> type => stream, protocol => tcp, recv => Recv}, - ok = sc_receive_response_local_close_tcp(InitState) + ok = sc_lc_receive_response_tcp(InitState) end). @@ -3727,12 +3767,12 @@ sc_recvmsg_response_local_close_tcp6(_Config) when is_list(_Config) -> %% remotely closed while the process is calling the recvmsg function. %% Socket is IPv4. -sc_recvmsg_response_remote_close_tcp4(suite) -> +sc_rc_recvmsg_response_tcp4(suite) -> []; -sc_recvmsg_response_remote_close_tcp4(doc) -> +sc_rc_recvmsg_response_tcp4(doc) -> []; -sc_recvmsg_response_remote_close_tcp4(_Config) when is_list(_Config) -> - tc_try(sc_recvmsg_response_remote_close_tcp4, +sc_rc_recvmsg_response_tcp4(_Config) when is_list(_Config) -> + tc_try(sc_rc_recvmsg_response_tcp4, fun() -> not_yet_implemented(), Recv = fun(Sock) -> socket:recvmsg(Sock) end, @@ -3740,7 +3780,7 @@ sc_recvmsg_response_remote_close_tcp4(_Config) when is_list(_Config) -> type => stream, protocol => tcp, recv => Recv}, - ok = sc_receive_response_remote_close_tcp(InitState) + ok = sc_rc_receive_response_tcp(InitState) end). @@ -3749,12 +3789,12 @@ sc_recvmsg_response_remote_close_tcp4(_Config) when is_list(_Config) -> %% remotely closed while the process is calling the recvmsg function. %% Socket is IPv6. -sc_recvmsg_response_remote_close_tcp6(suite) -> +sc_rc_recvmsg_response_tcp6(suite) -> []; -sc_recvmsg_response_remote_close_tcp6(doc) -> +sc_rc_recvmsg_response_tcp6(doc) -> []; -sc_recvmsg_response_remote_close_tcp6(_Config) when is_list(_Config) -> - tc_try(sc_recvmsg_response_remote_close_tcp6, +sc_rc_recvmsg_response_tcp6(_Config) when is_list(_Config) -> + tc_try(sc_rc_recvmsg_response_tcp6, fun() -> not_yet_implemented(), Recv = fun(Sock) -> socket:recvmsg(Sock) end, @@ -3762,7 +3802,7 @@ sc_recvmsg_response_remote_close_tcp6(_Config) when is_list(_Config) -> type => stream, protocol => tcp, recv => Recv}, - ok = sc_receive_response_remote_close_tcp(InitState) + ok = sc_rc_receive_response_tcp(InitState) end). @@ -3773,18 +3813,18 @@ sc_recvmsg_response_remote_close_tcp6(_Config) when is_list(_Config) -> %% git the setup anyway. %% Socket is IPv4. -sc_acceptor_response_local_close_tcp4(suite) -> +sc_lc_acceptor_response_tcp4(suite) -> []; -sc_acceptor_response_local_close_tcp4(doc) -> +sc_lc_acceptor_response_tcp4(doc) -> []; -sc_acceptor_response_local_close_tcp4(_Config) when is_list(_Config) -> - tc_try(sc_acceptor_response_local_close_tcp4, +sc_lc_acceptor_response_tcp4(_Config) when is_list(_Config) -> + tc_try(sc_lc_acceptor_response_tcp4, fun() -> not_yet_implemented(), InitState = #{domain => inet, type => stream, protocol => tcp}, - ok = sc_acceptor_response_local_close_tcp(InitState) + ok = sc_lc_acceptor_response_tcp(InitState) end). @@ -3795,75 +3835,24 @@ sc_acceptor_response_local_close_tcp4(_Config) when is_list(_Config) -> %% git the setup anyway. %% Socket is IPv6. -sc_acceptor_response_local_close_tcp6(suite) -> - []; -sc_acceptor_response_local_close_tcp6(doc) -> - []; -sc_acceptor_response_local_close_tcp6(_Config) when is_list(_Config) -> - tc_try(sc_acceptor_response_local_close_tcp6, - fun() -> - not_yet_implemented(), - InitState = #{domain => inet, - type => stream, - protocol => tcp}, - ok = sc_acceptor_response_local_close_tcp(InitState) - end). - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -sc_acceptor_response_local_close_tcp(_InitState) -> - ok. - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% This test case is intended to test what happens when a socket is -%% remotely closed while the process is calling the accept function. -%% We test what happens with a non-controlling_process also, since we -%% git the setup anyway. -%% Socket is IPv4. - -sc_acceptor_response_remote_close_tcp4(suite) -> - []; -sc_acceptor_response_remote_close_tcp4(doc) -> - []; -sc_acceptor_response_remote_close_tcp4(_Config) when is_list(_Config) -> - tc_try(sc_acceptor_response_remote_close_tcp4, - fun() -> - not_yet_implemented(), - InitState = #{domain => inet, - type => stream, - protocol => tcp}, - ok = sc_acceptor_response_remote_close_tcp(InitState) - end). - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% This test case is intended to test what happens when a socket is -%% remotely closed while the process is calling the accept function. -%% We test what happens with a non-controlling_process also, since we -%% git the setup anyway. -%% Socket is IPv6. - -sc_acceptor_response_remote_close_tcp6(suite) -> +sc_lc_acceptor_response_tcp6(suite) -> []; -sc_acceptor_response_remote_close_tcp6(doc) -> +sc_lc_acceptor_response_tcp6(doc) -> []; -sc_acceptor_response_remote_close_tcp6(_Config) when is_list(_Config) -> - tc_try(acceptor_response_remote_close_tcp6, +sc_lc_acceptor_response_tcp6(_Config) when is_list(_Config) -> + tc_try(sc_lc_acceptor_response_tcp6, fun() -> not_yet_implemented(), InitState = #{domain => inet, type => stream, protocol => tcp}, - ok = sc_acceptor_response_remote_close_tcp(InitState) + ok = sc_lc_acceptor_response_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -sc_acceptor_response_remote_close_tcp(_InitState) -> +sc_lc_acceptor_response_tcp(_InitState) -> ok. -- cgit v1.2.3 From 3c4c36587df5a847dd6f03011a4ecb76d0b70b40 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Thu, 18 Oct 2018 17:21:11 +0200 Subject: [socket-nif|test] Enables test case sc_lc_recvmsg_response_tcp4 --- lib/kernel/test/socket_SUITE.erl | 1 - 1 file changed, 1 deletion(-) (limited to 'lib') diff --git a/lib/kernel/test/socket_SUITE.erl b/lib/kernel/test/socket_SUITE.erl index 4ee2eec39a..022e83a944 100644 --- a/lib/kernel/test/socket_SUITE.erl +++ b/lib/kernel/test/socket_SUITE.erl @@ -3730,7 +3730,6 @@ sc_lc_recvmsg_response_tcp4(doc) -> sc_lc_recvmsg_response_tcp4(_Config) when is_list(_Config) -> tc_try(sc_lc_recvmsg_response_tcp4, fun() -> - not_yet_implemented(), Recv = fun(Sock) -> socket:recvmsg(Sock) end, InitState = #{domain => inet, type => stream, -- cgit v1.2.3