From 6781913e975e93a4a29d14e14794aae4526de9f7 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Fri, 14 Dec 2018 19:14:43 +0100 Subject: [socket-nif|test] Add test case based on the ttest modules Added a (first) test case based on the ttest modules. OTP-14831 --- erts/emulator/test/socket_SUITE.erl | 574 ++++++++++++++++++++- erts/emulator/test/socket_test_evaluator.erl | 19 + erts/emulator/test/socket_test_lib.erl | 18 + erts/emulator/test/socket_test_logger.erl | 16 +- .../emulator/test/socket_test_ttest_tcp_client.erl | 182 +++++-- .../test/socket_test_ttest_tcp_client_gen.erl | 21 +- .../test/socket_test_ttest_tcp_client_socket.erl | 22 +- .../emulator/test/socket_test_ttest_tcp_server.erl | 80 ++- .../test/socket_test_ttest_tcp_server_gen.erl | 11 +- .../test/socket_test_ttest_tcp_server_socket.erl | 10 +- .../emulator/test/socket_test_ttest_tcp_socket.erl | 5 +- 11 files changed, 844 insertions(+), 114 deletions(-) (limited to 'erts/emulator') diff --git a/erts/emulator/test/socket_SUITE.erl b/erts/emulator/test/socket_SUITE.erl index 57f562f24d..72fea0a40a 100644 --- a/erts/emulator/test/socket_SUITE.erl +++ b/erts/emulator/test/socket_SUITE.erl @@ -121,7 +121,17 @@ traffic_ping_pong_small_sendmsg_and_recvmsg_udp4/1, traffic_ping_pong_small_sendmsg_and_recvmsg_udp6/1, traffic_ping_pong_medium_sendmsg_and_recvmsg_udp4/1, - traffic_ping_pong_medium_sendmsg_and_recvmsg_udp6/1 + traffic_ping_pong_medium_sendmsg_and_recvmsg_udp6/1, + + %% Time Test + ttest_sgenf_cgenf_small_tcp4/1, + ttest_sgenf_cgenf_small_tcp6/1%% , + + %% ttest_sgenf_cgenf_medium_tcp4/1, + %% ttest_sgenf_cgenf_medium_tcp6/1, + + %% ttest_sgenf_cgenf_large_tcp4/1, + %% ttest_sgenf_cgenf_large_tcp6/1 %% Tickets ]). @@ -148,8 +158,9 @@ -define(TT(T), ct:timetrap(T)). --define(LIB, socket_test_lib). --define(LOGGER, socket_test_logger). +-define(LIB, socket_test_lib). +-define(TTEST_LIB, socket_test_ttest_lib). +-define(LOGGER, socket_test_logger). -define(TPP_SMALL, lists:seq(1, 8)). -define(TPP_MEDIUM, lists:flatten(lists:duplicate(1024, ?TPP_SMALL))). @@ -170,7 +181,8 @@ all() -> [ {group, api}, {group, socket_closure}, - {group, traffic} + {group, traffic}, + {group, ttest} %% {group, tickets} ]. @@ -184,7 +196,8 @@ groups() -> {sc_local_close, [], sc_lc_cases()}, {sc_remote_close, [], sc_rc_cases()}, {sc_remote_shutdown, [], sc_rs_cases()}, - {traffic, [], traffic_cases()} + {traffic, [], traffic_cases()}, + {ttest, [], ttest_cases()} %% {tickets, [], ticket_cases()} ]. @@ -328,6 +341,19 @@ traffic_cases() -> ]. +ttest_cases() -> + [ + ttest_sgenf_cgenf_small_tcp4, + ttest_sgenf_cgenf_small_tcp6%% , + + %% ttest_sgenf_cgenf_medium_tcp4, + %% ttest_sgenf_cgenf_medium_tcp6, + + %% ttest_sgenf_cgenf_large_tcp4, + %% ttest_sgenf_cgenf_large_tcp6 + ]. + + %% ticket_cases() -> %% []. @@ -8482,9 +8508,6 @@ traffic_ping_pong_send_and_receive_tcp(#{msg := Msg} = InitState) -> true -> ok end, - - - ok = socket:setopt(Sock, otp, rcvbuf, 8*1024) end, traffic_ping_pong_send_and_receive_tcp2(InitState#{buf_init => Fun}). @@ -10134,6 +10157,539 @@ tpp_udp_sock_close(Sock) -> end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case uses the time test (ttest) utility to implement a +%% ping-pong like test case. + +ttest_sgenf_cgenf_small_tcp4(suite) -> + []; +ttest_sgenf_cgenf_small_tcp4(doc) -> + []; +ttest_sgenf_cgenf_small_tcp4(_Config) when is_list(_Config) -> + ttest_tcp(ttest_sgenf_cgenf_small_tcp4, + inet, + gen, false, + gen, false, + 1, 200). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% + +ttest_sgenf_cgenf_small_tcp6(suite) -> + []; +ttest_sgenf_cgenf_small_tcp6(doc) -> + []; +ttest_sgenf_cgenf_small_tcp6(_Config) when is_list(_Config) -> + ttest_tcp(ttest_sgenf_cgenf_small_tcp6, + inet6, + gen, false, + gen, false, + 1, 200). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +ttest_tcp(TC, + Domain, + ServerMod, ServerActive, + ClientMod, ClientActive, + MsgID, MaxOutstanding) -> + Runtime = ?SECS(60), + tc_try(TC, + fun() -> + if (Domain =/= inet) -> not_yet_implemented(); true -> ok end, + ?TT(Runtime + ?SECS(60)), + InitState = #{domain => Domain, + msg_id => MsgID, + max_outstanding => MaxOutstanding, + runtime => Runtime, + server_mod => ServerMod, + server_active => ServerActive, + client_mod => ClientMod, + client_active => ClientActive}, + ok = ttest_tcp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% This test is run with the following combinations: +%% (this does not take the message size into consideration) +%% server(gen, false) - client(gen, false) +%% server(gen, false) - client(gen, once) +%% server(gen, false) - client(gen, true) +%% server(gen, false) - client(sock, false) +%% server(gen, false) - client(sock, once) +%% server(gen, false) - client(sock, true) +%% server(gen, once) - client(gen, false) +%% server(gen, once) - client(gen, once) +%% server(gen, once) - client(gen, true) +%% server(gen, once) - client(sock, false) +%% server(gen, once) - client(sock, once) +%% server(gen, once) - client(sock, true) +%% server(gen, true) - client(gen, false) +%% server(gen, true) - client(gen, once) +%% server(gen, true) - client(gen, true) +%% server(gen, true) - client(sock, false) +%% server(gen, true) - client(sock, once) +%% server(gen, true) - client(sock, true) +%% server(sock, false) - client(gen, false) +%% server(sock, false) - client(gen, once) +%% server(sock, false) - client(gen, true) +%% server(sock, false) - client(sock, false) +%% server(sock, false) - client(sock, once) +%% server(sock, false) - client(sock, true) +%% server(sock, once) - client(gen, false) +%% server(sock, once) - client(gen, once) +%% server(sock, once) - client(gen, true) +%% server(sock, once) - client(sock, false) +%% server(sock, once) - client(sock, once) +%% server(sock, once) - client(sock, true) +%% server(sock, true) - client(gen, false) +%% server(sock, true) - client(gen, once) +%% server(sock, true) - client(gen, true) +%% server(sock, true) - client(sock, false) +%% server(sock, true) - client(sock, once) +%% server(sock, true) - client(sock, true) + +ttest_tcp(InitState) -> + ServerSeq = + [ + %% *** Wait for start order part *** + #{desc => "await start", + cmd => fun(State) -> + Tester = ?SEV_AWAIT_START(), + {ok, State#{tester => Tester}} + end}, + #{desc => "monitor tester", + cmd => fun(#{tester := Tester} = _State) -> + _MRef = erlang:monitor(process, Tester), + ok + end}, + + + %% *** Init part *** + #{desc => "create node", + cmd => fun(#{host := Host} = State) -> + case start_node(Host, server) of + {ok, Node} -> + {ok, State#{node => Node}}; + {error, Reason, _} -> + {error, Reason} + end + end}, + #{desc => "monitor server node", + cmd => fun(#{node := Node} = _State) -> + true = erlang:monitor_node(Node, true), + ok + end}, + #{desc => "start ttest (remote) server", + cmd => fun(#{mod := Mod, + active := Active, + node := Node} = State) -> + case ttest_tcp_server_start(Node, Mod, Active) of + {ok, {{Pid, _MRef}, {Addr, Port}}} -> + {ok, State#{rserver => Pid, + addr => Addr, + port => Port}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "announce ready (init)", + cmd => fun(#{tester := Tester, + addr := Addr, + port := Port}) -> + ?SEV_ANNOUNCE_READY(Tester, init, {Addr, Port}), + ok + end}, + + + %% *** Termination *** + #{desc => "await terminate (from tester)", + cmd => fun(#{tester := Tester, + rserver := RServer} = State) -> + case ?SEV_AWAIT_TERMINATE(Tester, tester, + [{rserver, RServer}]) of + ok -> + {ok, maps:remove(tester, State)}; + {error, _} = ERROR -> + ERROR + end + end}, + %% The remote server is in a accept, with a timeout of 5 seconds, + %% so may have to wait a bit... + #{desc => "order (remote) ttest server terminate", + cmd => fun(#{node := _Node, + rserver := RServer}) -> + ttest_tcp_server_stop(RServer), + ok + end}, + #{desc => "await ttest (remote) server termination", + cmd => fun(#{rserver := RServer} = State) -> + ?SEV_AWAIT_TERMINATION(RServer), + State1 = maps:remove(rserver, State), + {ok, State1} + end}, + #{desc => "stop (server) node", + cmd => fun(#{node := Node} = _State) -> + stop_node(Node) + end}, + #{desc => "await (server) node termination", + cmd => fun(#{node := Node} = State) -> + receive + {nodedown, Node} -> + {ok, maps:remove(node, State)} + end + end}, + + + %% *** We are done *** + ?SEV_FINISH_NORMAL + ], + + ClientSeq = + [ + %% *** Wait for start order part *** + #{desc => "await start", + cmd => fun(State) -> + {Tester, {ServerAddr, ServerPort}} = ?SEV_AWAIT_START(), + {ok, State#{tester => Tester, + server_addr => ServerAddr, + server_port => ServerPort}} + end}, + #{desc => "monitor tester", + cmd => fun(#{tester := Tester} = _State) -> + _MRef = erlang:monitor(process, Tester), + ok + end}, + + + %% *** Init part *** + #{desc => "create node", + cmd => fun(#{host := Host} = State) -> + case start_node(Host, client) of + {ok, Node} -> + {ok, State#{node => Node}}; + {error, Reason, _} -> + {error, Reason} + end + end}, + #{desc => "monitor client node", + cmd => fun(#{node := Node} = _State) -> + true = erlang:monitor_node(Node, true), + ok + end}, + #{desc => "announce ready (init)", + cmd => fun(#{tester := Tester}) -> + ?SEV_ANNOUNCE_READY(Tester, init), + ok + end}, + + + %% The actual test + #{desc => "await continue (ttest)", + cmd => fun(#{tester := Tester} = _State) -> + ?SEV_AWAIT_CONTINUE(Tester, tester, ttest), + ok + end}, + #{desc => "start ttest (remote) client", + cmd => fun(#{node := Node, + mod := Mod, + active := Active, + msg_id := MsgID, + max_outstanding := MaxOutstanding, + runtime := RunTime, + server_addr := Addr, + server_port := Port} = State) -> + Self = self(), + Notify = + fun(Result) -> + ?SEV_ANNOUNCE_READY(Self, ttest, Result) + end, + case ttest_tcp_client_start(Node, Notify, + Mod, Active, + Addr, Port, + MsgID, MaxOutstanding, + RunTime) of + {ok, {Pid, _MRef}} -> + {ok, State#{rclient => Pid}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "await ttest ready", + cmd => fun(#{tester := Tester, + rclient := RClient} = State) -> + %% TTestResult = ?SEV_AWAIT_READY(RClient, rclient, ttest, + %% [{tester, Tester}]), + case ?SEV_AWAIT_READY(RClient, rclient, ttest, + [{tester, Tester}]) of + {ok, Result} -> + {ok, State#{result => Result}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "await ttest (remote) client termination", + cmd => fun(#{rclient := RClient} = State) -> + ?SEV_AWAIT_TERMINATION(RClient), + State1 = maps:remove(rclient, State), + {ok, State1} + end}, + #{desc => "announce ready (ttest)", + cmd => fun(#{tester := Tester, + result := Result} = State) -> + ?SEV_ANNOUNCE_READY(Tester, ttest, Result), + {ok, maps:remove(result, State)} + end}, + + + %% *** Termination *** + #{desc => "await terminate (from tester)", + cmd => fun(#{tester := Tester} = State) -> + case ?SEV_AWAIT_TERMINATE(Tester, tester) of + ok -> + {ok, maps:remove(tester, State)}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "stop (client) node", + cmd => fun(#{node := Node} = _State) -> + stop_node(Node) + end}, + #{desc => "await (client) node termination", + cmd => fun(#{node := Node} = State) -> + receive + {nodedown, Node} -> + {ok, maps:remove(node, State)} + end + end}, + + + %% *** We are done *** + ?SEV_FINISH_NORMAL + ], + + TesterSeq = + [ + %% *** Init part *** + #{desc => "monitor server", + cmd => fun(#{server := Pid} = _State) -> + _MRef = erlang:monitor(process, Pid), + ok + end}, + #{desc => "monitor client", + cmd => fun(#{client := Pid} = _State) -> + _MRef = erlang:monitor(process, Pid), + ok + end}, + + %% Start the server + #{desc => "order server start", + cmd => fun(#{server := Pid} = _State) -> + ?SEV_ANNOUNCE_START(Pid), + ok + end}, + #{desc => "await server ready (init)", + cmd => fun(#{server := Pid} = State) -> + {ok, {Addr, Port}} = ?SEV_AWAIT_READY(Pid, server, init), + {ok, State#{server_addr => Addr, + server_port => Port}} + end}, + + + %% Start the client + #{desc => "order client start", + cmd => fun(#{client := Pid, + server_addr := Addr, + server_port := Port} = _State) -> + ?SEV_ANNOUNCE_START(Pid, {Addr, Port}), + ok + end}, + #{desc => "await client ready (init)", + cmd => fun(#{client := Client} = _State) -> + ok = ?SEV_AWAIT_READY(Client, client, init) + end}, + + %% The actual test + #{desc => "order client continue (ttest)", + cmd => fun(#{client := Client} = _State) -> + ?SEV_ANNOUNCE_CONTINUE(Client, ttest), + ok + end}, + #{desc => "await client ready (ttest)", + cmd => fun(#{server := Server, + client := Client} = State) -> + case ?SEV_AWAIT_READY(Client, client, ttest, + [{server, Server}]) of + {ok, Result} -> + {ok, State#{result => Result}}; + {error, _} = ERROR -> + ERROR + end + end}, + + + %% *** Terminate server *** + #{desc => "order client terminate", + cmd => fun(#{client := Client} = _State) -> + ?SEV_ANNOUNCE_TERMINATE(Client), + ok + end}, + #{desc => "await client down", + cmd => fun(#{client := Client} = State) -> + ?SEV_AWAIT_TERMINATION(Client), + State1 = maps:remove(client, State), + {ok, State1} + end}, + #{desc => "order server terminate", + cmd => fun(#{server := Server} = _State) -> + ?SEV_ANNOUNCE_TERMINATE(Server), + ok + end}, + #{desc => "await server down", + cmd => fun(#{server := Server} = _State) -> + ?SEV_AWAIT_TERMINATION(Server), + ok + end}, + + + %% Present the results + #{desc => "present the results", + cmd => fun(#{result := Result} = State) -> + case Result of + #{status := ok, + runtime := RunTime, + cnt := Cnt, + bcnt := BCnt} -> + ?SEV_IPRINT( + "TTest results: " + "~n Run Time: ~s" + "~n Byte Count: ~s" + "~n Number of message exchanges: ~s" + "~n~n", + [ + ?TTEST_LIB:format_time(RunTime), + if ((BCnt =:= 0) orelse (RunTime =:= 0)) -> + ?TTEST_LIB:format("~w, ~w", + [BCnt, RunTime]); + true -> + ?TTEST_LIB:format("~p => ~p byte / ms", + [BCnt, BCnt div RunTime]) + end, + if (RunTime =:= 0) -> + "-"; + true -> + ?TTEST_LIB:format("~p => ~p iterations / ms", + [Cnt, Cnt div RunTime]) + end + ]), + {ok, maps:remove(result, State)}; + + #{status := Failure, + runtime := RunTime, + sid := SID, + rid := RID, + scnt := SCnt, + rcnt := RCnt, + bcnt := BCnt, + num := Num} -> + ?SEV_EPRINT("Time Test failed: " + "~n ~p" + "~n" + "~nwhen" + "~n" + "~n Run Time: ~s" + "~n Send ID: ~p" + "~n Recv ID: ~p" + "~n Send Count: ~p" + "~n Recv Count: ~p" + "~n Byte Count: ~p" + "~n Num Iterations: ~p", + [Failure, + ?TTEST_LIB:format_time(RunTime), + SID, RID, SCnt, RCnt, BCnt, Num]), + {error, Failure} + end + end}, + + %% This is just so that the printout above shall have time to come + %% out before then end of the test case. + ?SEV_SLEEP(?SECS(1)), + + %% *** We are done *** + ?SEV_FINISH_NORMAL + ], + + i("start server evaluator"), + ServerInitState = #{host => local_host(), + domain => maps:get(domain, InitState), + mod => maps:get(server_mod, InitState), + active => maps:get(server_active, InitState)}, + Server = ?SEV_START("server", ServerSeq, ServerInitState), + + i("start client evaluator"), + ClientInitState = #{host => local_host(), + domain => maps:get(domain, InitState), + mod => maps:get(client_mod, InitState), + active => maps:get(client_active, InitState), + msg_id => maps:get(msg_id, InitState), + max_outstanding => maps:get(max_outstanding, InitState), + runtime => maps:get(runtime, InitState)}, + Client = ?SEV_START("client", ClientSeq, ClientInitState), + + i("start 'tester' evaluator"), + TesterInitState = #{server => Server#ev.pid, + client => Client#ev.pid}, + Tester = ?SEV_START("tester", TesterSeq, TesterInitState), + + i("await evaluator(s)"), + ok = ?SEV_AWAIT_FINISH([Server, Client, Tester]). + + + +ttest_tcp_server_start(Node, gen, Active) -> + Transport = socket_test_ttest_tcp_gen, + socket_test_ttest_tcp_server:start_monitor(Node, Transport, Active); +ttest_tcp_server_start(Node, sock, Active) -> + TransportMod = socket_test_ttest_tcp_socket, + Transport = {TransportMod, #{method => plain}}, + socket_test_ttest_tcp_server:start_monitor(Node, Transport, Active). + +ttest_tcp_server_stop(Pid) -> + socket_test_ttest_tcp_server:stop(Pid). + +ttest_tcp_client_start(Node, + Notify, + gen, + Active, Addr, Port, MsgID, MaxOutstanding, RunTime) -> + Transport = socket_test_ttest_tcp_gen, + socket_test_ttest_tcp_client:start_monitor(Node, + Notify, + Transport, + Active, + Addr, Port, + MsgID, MaxOutstanding, RunTime); +ttest_tcp_client_start(Node, + Notify, + sock, + Active, Addr, Port, MsgID, MaxOutstanding, RunTime) -> + TransportMod = socket_test_ttest_tcp_socket, + Transport = {TransportMod, #{method => plain}}, + socket_test_ttest_tcp_client:start_monitor(Node, + Notify, + Transport, + Active, + Addr, Port, + MsgID, MaxOutstanding, RunTime). + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% start_node(Host, NodeName) -> @@ -10406,7 +10962,7 @@ tc_which_name() -> Name end. - + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% l2a(S) when is_list(S) -> diff --git a/erts/emulator/test/socket_test_evaluator.erl b/erts/emulator/test/socket_test_evaluator.erl index 48fb6a027e..deea7e5d36 100644 --- a/erts/emulator/test/socket_test_evaluator.erl +++ b/erts/emulator/test/socket_test_evaluator.erl @@ -153,6 +153,7 @@ await_finish([], Fails) -> Fails; await_finish(Evs, Fails) -> receive + %% Successfull termination of evaluator {'DOWN', _MRef, process, Pid, normal} -> case lists:keysearch(Pid, #ev.pid, Evs) of {value, #ev{name = Name}} -> @@ -163,8 +164,20 @@ await_finish(Evs, Fails) -> iprint("unknown process ~p died (normal)", [Pid]), await_finish(Evs, Fails) end; + + %% The evaluator can skip the teat case: {'DOWN', _MRef, process, Pid, {skip, Reason}} -> + case lists:keysearch(Pid, #ev.pid, Evs) of + {value, #ev{name = Name}} -> + iprint("evaluator '~s' (~p) issued SKIP: " + "~n ~p", [Name, Pid, Reason]); + false -> + iprint("unknown process ~p issued SKIP: " + "~n ~p", [Pid, Reason]) + end, ?LIB:skip(Reason); + + %% Evaluator failed {'DOWN', _MRef, process, Pid, Reason} -> case lists:keysearch(Pid, #ev.pid, Evs) of {value, #ev{name = Name}} -> @@ -260,6 +273,12 @@ announce(To, Announcement, Slogan, Extra) when is_pid(To) andalso is_atom(Announcement) andalso is_atom(Slogan) -> + %% iprint("announce -> entry with: " + %% "~n To: ~p" + %% "~n Announcement: ~p" + %% "~n Slogan: ~p" + %% "~n Extra: ~p", + %% [To, Announcement, Slogan, Extra]), To ! {Announcement, self(), Slogan, Extra}, ok. diff --git a/erts/emulator/test/socket_test_lib.erl b/erts/emulator/test/socket_test_lib.erl index f55f338ef9..4e65c4f3c0 100644 --- a/erts/emulator/test/socket_test_lib.erl +++ b/erts/emulator/test/socket_test_lib.erl @@ -21,6 +21,8 @@ -module(socket_test_lib). -export([ + pi/1, pi/2, pi/3, + %% Time stuff timestamp/0, tdiff/2, @@ -36,6 +38,22 @@ ]). +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +pi(Item) when is_atom(Item) -> + pi(self(), Item). + +pi(Pid, Item) when is_pid(Pid) andalso is_atom(Item) -> + {Item, Info} = process_info(Pid, Item), + Info; +pi(Node, Pid) when is_pid(Pid) -> + rpc:call(Node, erlang, process_info, [Pid]). + +pi(Node, Pid, Item) when is_pid(Pid) andalso is_atom(Item) -> + rpc:call(Node, erlang, process_info, [Pid, Item]). + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% timestamp() -> diff --git a/erts/emulator/test/socket_test_logger.erl b/erts/emulator/test/socket_test_logger.erl index 5996bbe855..e42251158f 100644 --- a/erts/emulator/test/socket_test_logger.erl +++ b/erts/emulator/test/socket_test_logger.erl @@ -95,5 +95,17 @@ print(F, A) -> print(?LIB:f(F, A)). print(Str) -> - io:format(user, Str ++ "~n", []), - io:format(Str, []). + try + begin + io:format(user, Str ++ "~n", []), + io:format(Str, []) + end + catch + _:_:_ -> + io:format(user, + "~nFailed Format message:" + "~n~p~n", [Str]), + io:format("~nFailed Format message:" + "~n~p~n", [Str]) + end. + diff --git a/erts/emulator/test/socket_test_ttest_tcp_client.erl b/erts/emulator/test/socket_test_ttest_tcp_client.erl index 9c43c41841..180c280fb0 100644 --- a/erts/emulator/test/socket_test_ttest_tcp_client.erl +++ b/erts/emulator/test/socket_test_ttest_tcp_client.erl @@ -41,10 +41,19 @@ -module(socket_test_ttest_tcp_client). -export([ - start_monitor/4, start_monitor/5, start_monitor/7, + %% These are for the test suite + start_monitor/6, start_monitor/7, start_monitor/9, + + %% These are for starting in a shell when run "manually" + start/4, start/5, start/7, stop/1 ]). +%% Internal exports +-export([ + do_start/9 + ]). + -include_lib("kernel/include/inet.hrl"). -include("socket_test_ttest.hrl"). -include("socket_test_ttest_client.hrl"). @@ -71,66 +80,135 @@ %% ========================================================================== -start_monitor(Transport, Active, Addr, Port) -> - start_monitor(Transport, Active, Addr, Port, ?MSG_ID_DEFAULT). - -%% RunTime is in number of ms. -start_monitor(Transport, Active, Addr, Port, 1 = MsgID) -> - start_monitor(Transport, Active, Addr, Port, MsgID, - ?MAX_OUTSTANDING_DEFAULT_1, ?RUNTIME_DEFAULT); -start_monitor(Transport, Active, Addr, Port, 2 = MsgID) -> - start_monitor(Transport, Active, Addr, Port, MsgID, - ?MAX_OUTSTANDING_DEFAULT_2, ?RUNTIME_DEFAULT); -start_monitor(Transport, Active, Addr, Port, 3 = MsgID) -> - start_monitor(Transport, Active, Addr, Port, MsgID, - ?MAX_OUTSTANDING_DEFAULT_3, ?RUNTIME_DEFAULT). - --spec start_monitor(Transport, - Active, - Addr, - Port, - MsgID, - MaxOutstanding, - RunTime) -> term() when +start_monitor(Node, Notify, Transport, Active, Addr, Port) -> + start_monitor(Node, Notify, Transport, Active, Addr, Port, ?MSG_ID_DEFAULT). + +start_monitor(Node, Notify, Transport, Active, Addr, Port, 1 = MsgID) -> + start_monitor(Node, Notify, Transport, Active, Addr, Port, MsgID, + ?MAX_OUTSTANDING_DEFAULT_1, ?RUNTIME_DEFAULT); +start_monitor(Node, Notify, Transport, Active, Addr, Port, 2 = MsgID) -> + start_monitor(Node, Notify, Transport, Active, Addr, Port, MsgID, + ?MAX_OUTSTANDING_DEFAULT_2, ?RUNTIME_DEFAULT); +start_monitor(Node, Notify, Transport, Active, Addr, Port, 3 = MsgID) -> + start_monitor(Node, Notify, Transport, Active, Addr, Port, MsgID, + ?MAX_OUTSTANDING_DEFAULT_3, ?RUNTIME_DEFAULT). + +start_monitor(Node, Notify, Transport, Active, Addr, Port, + MsgID, MaxOutstanding, RunTime) + when (Node =/= node()) -> + ?I("start_monitor -> entry with" + "~n Node: ~p" + "~n Transport: ~p" + "~n Active: ~p" + "~n Addr: ~p" + "~n Port: ~p" + "~n MsgID: ~p" + "~n MaxOutstanding: ~p" + "~n RunTime: ~p", + [Node, Transport, Active, Addr, Port, MsgID, MaxOutstanding, RunTime]), + Args = [self(), Notify, + Transport, Active, Addr, Port, MsgID, MaxOutstanding, RunTime], + case rpc:call(Node, ?MODULE, do_start, Args) of + {badrpc, _} = Reason -> + {error, Reason}; + {ok, Pid} when is_pid(Pid) -> + MRef = erlang:monitor(process, Pid), + {ok, {Pid, MRef}}; + {error, _} = ERROR -> + ERROR + end; +start_monitor(_, Notify, Transport, Active, Addr, Port, + MsgID, MaxOutstanding, RunTime) -> + case do_start(self(), Notify, + Transport, Active, Addr, Port, + MsgID, MaxOutstanding, RunTime) of + {ok, Pid} -> + MRef = erlang:monitor(process, Pid), + {ok, {Pid, MRef}}; + {error, _} = ERROR -> + ERROR + end. + + +start(Transport, Active, Addr, Port) -> + start(Transport, Active, Addr, Port, ?MSG_ID_DEFAULT). + +start(Transport, Active, Addr, Port, 1 = MsgID) -> + start(Transport, Active, Addr, Port, MsgID, + ?MAX_OUTSTANDING_DEFAULT_1, ?RUNTIME_DEFAULT); +start(Transport, Active, Addr, Port, 2 = MsgID) -> + start(Transport, Active, Addr, Port, MsgID, + ?MAX_OUTSTANDING_DEFAULT_2, ?RUNTIME_DEFAULT); +start(Transport, Active, Addr, Port, 3 = MsgID) -> + start(Transport, Active, Addr, Port, MsgID, + ?MAX_OUTSTANDING_DEFAULT_3, ?RUNTIME_DEFAULT). + +start(Transport, Active, Addr, Port, MsgID, MaxOutstanding, RunTime) -> + Notify = fun(R) -> present_results(R) end, + do_start(self(), Notify, + Transport, Active, Addr, Port, MsgID, MaxOutstanding, RunTime). + + +-spec do_start(Parent, + Notify, + Transport, + Active, + Addr, + Port, + MsgID, + MaxOutstanding, + RunTime) -> {ok, Pid} | {error, Reason} when + Parent :: pid(), + Notify :: function(), Transport :: atom() | tuple(), Active :: active(), Addr :: inet:ip_address(), Port :: inet:port_number(), MsgID :: msg_id(), MaxOutstanding :: max_outstanding(), - RunTime :: runtime(). - -%% RunTime is in number of ms. -start_monitor(Transport, Active, Addr, Port, - MsgID, MaxOutstanding, RunTime) - when (is_atom(Transport) orelse is_tuple(Transport)) andalso + RunTime :: runtime(), + Pid :: pid(), + Reason :: term(). + +do_start(Parent, Notify, + Transport, Active, Addr, Port, MsgID, MaxOutstanding, RunTime) + when is_pid(Parent) andalso + is_function(Notify) andalso + (is_atom(Transport) orelse is_tuple(Transport)) andalso (is_boolean(Active) orelse (Active =:= once)) andalso is_tuple(Addr) andalso (is_integer(Port) andalso (Port > 0)) andalso (is_integer(MsgID) andalso (MsgID >= 1) andalso (MsgID =< 3)) andalso (is_integer(MaxOutstanding) andalso (MaxOutstanding > 0)) andalso (is_integer(RunTime) andalso (RunTime > 0)) -> - Self = self(), - ClientInit = fun() -> put(sname, "client"), - init(Self, - Transport, Active, Addr, Port, - MsgID, MaxOutstanding, RunTime) - end, - {Pid, MRef} = spawn_monitor(ClientInit), + ?I("do_start -> entry with" + "~n Parent: ~p" + "~n Transport: ~p" + "~n Active: ~p" + "~n Addr: ~p" + "~n Port: ~p" + "~n MsgID: ~p" + "~n MaxOutstanding: ~p" + "~n RunTime: ~p", + [Parent, Transport, Active, Addr, Port, MsgID, MaxOutstanding, RunTime]), + Starter = self(), + Init = fun() -> put(sname, "client"), + init(Starter, + Parent, + Notify, + Transport, Active, Addr, Port, + MsgID, MaxOutstanding, RunTime) + end, + {Pid, MRef} = spawn_monitor(Init), receive + {'DOWN', MRef, process, Pid, Reason} -> + {error, Reason}; {?MODULE, Pid, ok} -> - erlang:demonitor(MRef, [flush]), - {ok, {Pid, MRef}}; - + erlang:demonitor(MRef), + {ok, Pid}; {?MODULE, Pid, {error, _} = ERROR} -> - erlang:demonitor(MRef, [flush]), - ERROR; - - {'DOWN', MRef, process, Pid, normal} -> - ok; - {'DOWN', MRef, process, Pid, Reason} -> - {error, {exit, Reason}} - + erlang:demonitor(MRef, [flush]), + ERROR end. @@ -141,9 +219,12 @@ stop(Pid) when is_pid(Pid) -> %% ========================================================================== -init(Parent, Transport, Active, Addr, Port, +init(Starter, + Parent, Notify, + Transport, Active, Addr, Port, MsgID, MaxOutstanding, RunTime) -> ?I("init with" + "~n Starter: ~p" "~n Parent: ~p" "~n Transport: ~p" "~n Active: ~p" @@ -152,14 +233,15 @@ init(Parent, Transport, Active, Addr, Port, "~n Msg ID: ~p (=> 16 + ~w bytes)" "~n Max Outstanding: ~p" "~n (Suggested) Run Time: ~p ms", - [Parent, + [Starter, + Parent, Transport, Active, inet:ntoa(Addr), Port, MsgID, size(which_msg_data(MsgID)), MaxOutstanding, RunTime]), {Mod, Connect} = process_transport(Transport), case Connect(Addr, Port) of {ok, Sock} -> ?I("connected"), - Parent ! {?MODULE, self(), ok}, + Starter ! {?MODULE, self(), ok}, initial_activation(Mod, Sock, Active), Results = loop(#{slogan => run, runtime => RunTime, @@ -178,7 +260,7 @@ init(Parent, Transport, Active, Addr, Port, bcnt => 0, num => undefined, acc => <<>>}), - present_results(Results), + Notify(Results), (catch Mod:close(Sock)), exit(normal); {error, Reason} -> diff --git a/erts/emulator/test/socket_test_ttest_tcp_client_gen.erl b/erts/emulator/test/socket_test_ttest_tcp_client_gen.erl index 4f6152a4b1..33eebfb10f 100644 --- a/erts/emulator/test/socket_test_ttest_tcp_client_gen.erl +++ b/erts/emulator/test/socket_test_ttest_tcp_client_gen.erl @@ -21,25 +21,22 @@ -module(socket_test_ttest_tcp_client_gen). -export([ - start_monitor/3, start_monitor/4, start_monitor/6, + start/3, start/4, start/6, stop/1 ]). -define(TRANSPORT_MOD, socket_test_ttest_tcp_gen). -start_monitor(Active, Addr, Port) -> - socket_test_ttest_tcp_client:start_monitor(?TRANSPORT_MOD, - Active, Addr, Port). +start(Active, Addr, Port) -> + socket_test_ttest_tcp_client:start(?TRANSPORT_MOD, Active, Addr, Port). -start_monitor(Active, Addr, Port, MsgID) -> - socket_test_ttest_tcp_client:start_monitor(?TRANSPORT_MOD, - Active, Addr, Port, - MsgID). +start(Active, Addr, Port, MsgID) -> + socket_test_ttest_tcp_client:start(?TRANSPORT_MOD, Active, Addr, Port, MsgID). -start_monitor(Active, Addr, Port, MsgID, MaxOutstanding, RunTime) -> - socket_test_ttest_tcp_client:start_monitor(?TRANSPORT_MOD, - Active, Addr, Port, - MsgID, MaxOutstanding, RunTime). +start(Active, Addr, Port, MsgID, MaxOutstanding, RunTime) -> + socket_test_ttest_tcp_client:start(?TRANSPORT_MOD, + Active, Addr, Port, + MsgID, MaxOutstanding, RunTime). stop(Pid) -> socket_test_ttest_tcp_client:stop(Pid). diff --git a/erts/emulator/test/socket_test_ttest_tcp_client_socket.erl b/erts/emulator/test/socket_test_ttest_tcp_client_socket.erl index ef980e8d32..c0a3302ecd 100644 --- a/erts/emulator/test/socket_test_ttest_tcp_client_socket.erl +++ b/erts/emulator/test/socket_test_ttest_tcp_client_socket.erl @@ -21,26 +21,24 @@ -module(socket_test_ttest_tcp_client_socket). -export([ - start_monitor/4, start_monitor/5, start_monitor/7, + start/4, start/5, start/7, stop/1 ]). -define(TRANSPORT_MOD, socket_test_ttest_tcp_socket). -define(MOD(M), {?TRANSPORT_MOD, #{method => Method}}). -start_monitor(Method, Active, Addr, Port) -> - socket_test_ttest_tcp_client:start_monitor(?MOD(Method), - Active, Addr, Port). +start(Method, Active, Addr, Port) -> + socket_test_ttest_tcp_client:start_monitor(?MOD(Method), Active, Addr, Port). -start_monitor(Method, Active, Addr, Port, MsgID) -> - socket_test_ttest_tcp_client:start_monitor(?MOD(Method), - Active, Addr, Port, - MsgID). +start(Method, Active, Addr, Port, MsgID) -> + socket_test_ttest_tcp_client:start(?MOD(Method), + Active, Addr, Port, MsgID). -start_monitor(Method, Active, Addr, Port, MsgID, MaxOutstanding, RunTime) -> - socket_test_ttest_tcp_client:start_monitor(?MOD(Method), - Active, Addr, Port, - MsgID, MaxOutstanding, RunTime). +start(Method, Active, Addr, Port, MsgID, MaxOutstanding, RunTime) -> + socket_test_ttest_tcp_client:start(?MOD(Method), + Active, Addr, Port, + MsgID, MaxOutstanding, RunTime). stop(Pid) -> socket_test_ttest_client:stop(Pid). diff --git a/erts/emulator/test/socket_test_ttest_tcp_server.erl b/erts/emulator/test/socket_test_ttest_tcp_server.erl index b248b063a3..257bb18592 100644 --- a/erts/emulator/test/socket_test_ttest_tcp_server.erl +++ b/erts/emulator/test/socket_test_ttest_tcp_server.erl @@ -34,15 +34,25 @@ -module(socket_test_ttest_tcp_server). -export([ - start_monitor/2, + %% This are for the test suite + start_monitor/3, + + %% This are for starting in a shell when run "manually" + start/2, + stop/1 ]). +%% Internal exports +-export([ + do_start/3 + ]). + -include_lib("kernel/include/inet.hrl"). -include("socket_test_ttest.hrl"). --define(ACC_TIMEOUT, 10000). --define(RECV_TIMEOUT, 10000). +-define(ACC_TIMEOUT, 5000). +-define(RECV_TIMEOUT, 5000). -define(LIB, socket_test_ttest_lib). -define(I(F), ?LIB:info(F)). @@ -56,28 +66,51 @@ %% ========================================================================== -start_monitor(Transport, Active) - when (is_atom(Transport) orelse is_tuple(Transport)) andalso +start_monitor(Node, Transport, Active) when (Node =/= node()) -> + case rpc:call(Node, ?MODULE, do_start, [self(), Transport, Active]) of + {badrpc, _} = Reason -> + {error, Reason}; + {ok, {Pid, AddrPort}} -> + MRef = erlang:monitor(process, Pid), + {ok, {{Pid, MRef}, AddrPort}}; + {error, _} = ERROR -> + ERROR + end; +start_monitor(_, Transport, Active) -> + case do_start(self(), Transport, Active) of + {ok, {Pid, AddrPort}} -> + MRef = erlang:monitor(process, Pid), + {ok, {{Pid, MRef}, AddrPort}}; + {error, _} = ERROR -> + ERROR + end. + + + +start(Transport, Active) -> + do_start(self(), Transport, Active). + + +do_start(Parent, Transport, Active) + when is_pid(Parent) andalso + (is_atom(Transport) orelse is_tuple(Transport)) andalso (is_boolean(Active) orelse (Active =:= once)) -> - Self = self(), - ServerInit = fun() -> put(sname, "server"), - server_init(Self, Transport, Active) - end, + Starter = self(), + ServerInit = fun() -> put(sname, "server"), + server_init(Starter, Parent, Transport, Active) + end, {Pid, MRef} = spawn_monitor(ServerInit), receive - {'DOWN', MRef, process, Pid, normal} -> - ok; {'DOWN', MRef, process, Pid, Reason} -> - {error, {exit, Reason}}; - - {?MODULE, Pid, {ok, Port}} -> - erlang:demonitor(MRef, [flush]), - {ok, {Pid, MRef, Port}}; + {error, Reason}; + {?MODULE, Pid, {ok, AddrPort}} -> + erlang:demonitor(MRef), + {ok, {Pid, AddrPort}}; {?MODULE, Pid, {error, _} = ERROR} -> - erlang:demonitor(MRef, [flush]), + erlang:demonitor(MRef, [flush]), ERROR end. - + stop(Pid) when is_pid(Pid) -> req(Pid, stop). @@ -85,22 +118,23 @@ stop(Pid) when is_pid(Pid) -> %% ========================================================================== -server_init(Parent, Transport, Active) -> +server_init(Starter, Parent, Transport, Active) -> ?I("init -> entry with" - "~n Parent: ~p" + "~n Starter: ~p" + "~n Parent: ~p" "~n Transport: ~p" - "~n Active: ~p", [Parent, Transport, Active]), + "~n Active: ~p", [Starter, Parent, Transport, Active]), {Mod, Listen, StatsInterval} = process_transport(Transport, Active), case Listen(0) of {ok, LSock} -> case Mod:port(LSock) of - {ok, Port} = OK -> + {ok, Port} -> Addr = which_addr(), % This is just for convenience ?I("init -> listening on:" "~n Addr: ~p (~s)" "~n Port: ~w" "~n", [Addr, inet:ntoa(Addr), Port]), - Parent ! {?MODULE, self(), OK}, + Starter ! {?MODULE, self(), {ok, {Addr, Port}}}, server_loop(#{parent => Parent, mod => Mod, active => Active, diff --git a/erts/emulator/test/socket_test_ttest_tcp_server_gen.erl b/erts/emulator/test/socket_test_ttest_tcp_server_gen.erl index 53a9dc7d2a..425e3d74af 100644 --- a/erts/emulator/test/socket_test_ttest_tcp_server_gen.erl +++ b/erts/emulator/test/socket_test_ttest_tcp_server_gen.erl @@ -28,7 +28,16 @@ -define(TRANSPORT_MOD, socket_test_ttest_tcp_gen). start_monitor(Active) -> - socket_test_ttest_tcp_server:start_monitor(?TRANSPORT_MOD, Active). + case socket_test_ttest_tcp_server:start_monitor(node(), + ?TRANSPORT_MOD, + Active) of + {ok, {Pid, AddrPort}} -> + MRef = erlang:monitor(process, Pid), + {ok, {Pid, MRef, AddrPort}}; + {error, _} = ERROR -> + ERROR + end. + stop(Pid) -> socket_test_ttest_tcp_server:stop(Pid). diff --git a/erts/emulator/test/socket_test_ttest_tcp_server_socket.erl b/erts/emulator/test/socket_test_ttest_tcp_server_socket.erl index d62f4d86a6..c78c7111ce 100644 --- a/erts/emulator/test/socket_test_ttest_tcp_server_socket.erl +++ b/erts/emulator/test/socket_test_ttest_tcp_server_socket.erl @@ -31,7 +31,15 @@ -define(MOD(M), {?TRANSPORT_MOD, #{method => M}}). start_monitor(Method, Active) -> - socket_test_ttest_tcp_server:start_monitor(?MOD(Method), Active). + case socket_test_ttest_tcp_server:start_monitor(node(), + ?MOD(Method), + Active) of + {ok, {Pid, AddrPort}} -> + MRef = erlang:monitor(process, Pid), + {ok, {Pid, MRef, AddrPort}}; + {error, _} = ERROR -> + ERROR + end. stop(Pid) -> socket_test_ttest_tcp_server:stop(Pid). diff --git a/erts/emulator/test/socket_test_ttest_tcp_socket.erl b/erts/emulator/test/socket_test_ttest_tcp_socket.erl index f314d01a63..9af25c5f50 100644 --- a/erts/emulator/test/socket_test_ttest_tcp_socket.erl +++ b/erts/emulator/test/socket_test_ttest_tcp_socket.erl @@ -134,10 +134,7 @@ maybe_start_stats_timer(#{stats_to := Pid, stats_interval := T}, Reader) when is_pid(Pid) -> erlang:start_timer(T, Pid, {stats, T, "reader", Reader}); -maybe_start_stats_timer(O, _) -> - io:format("NO STATS: " - "~n ~p" - "~n", [O]), +maybe_start_stats_timer(_O, _) -> ok. controlling_process(#{sock := Sock, reader := Pid}, NewPid) -> -- cgit v1.2.3