diff options
Diffstat (limited to 'erts/emulator/test/port_SUITE.erl')
-rw-r--r-- | erts/emulator/test/port_SUITE.erl | 1633 |
1 files changed, 816 insertions, 817 deletions
diff --git a/erts/emulator/test/port_SUITE.erl b/erts/emulator/test/port_SUITE.erl index 7d881a483f..c3ea0fb5c9 100644 --- a/erts/emulator/test/port_SUITE.erl +++ b/erts/emulator/test/port_SUITE.erl @@ -75,25 +75,25 @@ -export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2, - init_per_testcase/2, end_per_testcase/2, - init_per_suite/1, end_per_suite/1, - stream_small/1, stream_big/1, - basic_ping/1, slow_writes/1, bad_packet/1, bad_port_messages/1, - mul_basic/1, mul_slow_writes/1, - dying_port/1, port_program_with_path/1, - open_input_file_port/1, open_output_file_port/1, + init_per_testcase/2, end_per_testcase/2, + init_per_suite/1, end_per_suite/1, + stream_small/1, stream_big/1, + basic_ping/1, slow_writes/1, bad_packet/1, bad_port_messages/1, + mul_basic/1, mul_slow_writes/1, + dying_port/1, port_program_with_path/1, + open_input_file_port/1, open_output_file_port/1, count_fds/1, - iter_max_ports/1, eof/1, input_only/1, output_only/1, - name1/1, - t_binary/1, parallell/1, t_exit/1, - env/1, huge_env/1, bad_env/1, cd/1, exit_status/1, - tps_16_bytes/1, tps_1K/1, line/1, stderr_to_stdout/1, - otp_3906/1, otp_4389/1, win_massive/1, win_massive_client/1, - mix_up_ports/1, otp_5112/1, otp_5119/1, otp_6224/1, - exit_status_multi_scheduling_block/1, ports/1, - spawn_driver/1, spawn_executable/1, close_deaf_port/1, - port_setget_data/1, - unregister_name/1, parallelism_option/1]). + iter_max_ports/1, eof/1, input_only/1, output_only/1, + name1/1, + t_binary/1, parallell/1, t_exit/1, + env/1, huge_env/1, bad_env/1, cd/1, exit_status/1, + tps_16_bytes/1, tps_1K/1, line/1, stderr_to_stdout/1, + otp_3906/1, otp_4389/1, win_massive/1, win_massive_client/1, + mix_up_ports/1, otp_5112/1, otp_5119/1, otp_6224/1, + exit_status_multi_scheduling_block/1, ports/1, + spawn_driver/1, spawn_executable/1, close_deaf_port/1, + port_setget_data/1, + unregister_name/1, parallelism_option/1]). -export([do_iter_max_ports/2]). @@ -154,10 +154,10 @@ end_per_suite(Config) when is_list(Config) -> %% on a Windows machine given the correct environment. win_massive(Config) when is_list(Config) -> case os:type() of - {win32,_} -> - do_win_massive(); - _ -> - {skip,"Only on Windows."} + {win32,_} -> + do_win_massive(); + _ -> + {skip,"Only on Windows."} end. do_win_massive() -> @@ -165,44 +165,44 @@ do_win_massive() -> SuiteDir = filename:dirname(code:which(?MODULE)), Ports = " +Q 8192", {ok, Node} = - test_server:start_node(win_massive, - slave, - [{args, " -pa " ++ SuiteDir ++ Ports}]), + test_server:start_node(win_massive, + slave, + [{args, " -pa " ++ SuiteDir ++ Ports}]), ok = rpc:call(Node,?MODULE,win_massive_client,[3000]), test_server:stop_node(Node), ok. - + win_massive_client(N) -> {ok,P}=gen_tcp:listen(?WIN_MASSIVE_PORT,[{reuseaddr,true}]), L = win_massive_loop(P,N), Len = length(L), lists:foreach(fun(E) -> - gen_tcp:close(E) - end, - L), + gen_tcp:close(E) + end, + L), case Len div 2 of - N -> - ok; - _Else -> - {too_few, Len} + N -> + ok; + _Else -> + {too_few, Len} end. win_massive_loop(_,0) -> []; win_massive_loop(P,N) -> case (catch gen_tcp:connect("localhost",?WIN_MASSIVE_PORT,[])) of - {ok,A} -> - case (catch gen_tcp:accept(P)) of - {ok,B} -> - %erlang:display(N), - [A,B|win_massive_loop(P,N-1)]; - _Else -> - [A] - end; - _Else0 -> - [] + {ok,A} -> + case (catch gen_tcp:accept(P)) of + {ok,B} -> + %erlang:display(N), + [A,B|win_massive_loop(P,N-1)]; + _Else -> + [A] + end; + _Else0 -> + [] end. - + %% Test that we can send a stream of bytes and get it back. %% We will send only a small amount of data, to avoid deadlock. @@ -259,8 +259,8 @@ bad_packet(PortTest, HeaderSize, PacketSize) -> P = open_port({spawn, PortTest}, [{packet, HeaderSize}]), P ! {self(), {command, make_zero_packet(PacketSize)}}, receive - {'EXIT', P, einval} -> ok; - Other -> ct:fail({unexpected_message, Other}) + {'EXIT', P, einval} -> ok; + Other -> ct:fail({unexpected_message, Other}) end. make_zero_packet(0) -> []; @@ -286,8 +286,8 @@ bad_message(PortTest, Message) -> P = open_port({spawn,PortTest}, []), P ! Message, receive - {'EXIT',P,badsig} -> ok; - Other -> ct:fail({unexpected_message, Other}) + {'EXIT',P,badsig} -> ok; + Other -> ct:fail({unexpected_message, Other}) end. %% Tests various options (stream and {packet, Number} are implicitly @@ -419,21 +419,21 @@ mul_slow_writes(Config) when is_list(Config) -> parallell(Config) when is_list(Config) -> ct:timetrap({minutes, 5}), Testers = [ - fun() -> stream_ping(Config, 1007, "-s100", []) end, - fun() -> stream_ping(Config, 10007, "-s1000", []) end, - fun() -> stream_ping(Config, 10007, "-s1000", []) end, + fun() -> stream_ping(Config, 1007, "-s100", []) end, + fun() -> stream_ping(Config, 10007, "-s1000", []) end, + fun() -> stream_ping(Config, 10007, "-s1000", []) end, - fun() -> expect_input(Config, [21, 22, 23, 24, 25], 1, - "-s10", [in]) end, + fun() -> expect_input(Config, [21, 22, 23, 24, 25], 1, + "-s10", [in]) end, - fun() -> ping(Config, [10], 1, "-d", []) end, - fun() -> ping(Config, [20000], 2, "-d", []) end, - fun() -> ping(Config, [101], 1, "-s10", []) end, - fun() -> ping(Config, [1001], 2, "-s100", []) end, - fun() -> ping(Config, [10001], 4, "-s1000", []) end, + fun() -> ping(Config, [10], 1, "-d", []) end, + fun() -> ping(Config, [20000], 2, "-d", []) end, + fun() -> ping(Config, [101], 1, "-s10", []) end, + fun() -> ping(Config, [1001], 2, "-s100", []) end, + fun() -> ping(Config, [10001], 4, "-s1000", []) end, - fun() -> ping(Config, [501, 501], 2, "-s100", []) end, - fun() -> ping(Config, [11, 12, 13, 14, 11], 1, "-s5", []) end], + fun() -> ping(Config, [501, 501], 2, "-s100", []) end, + fun() -> ping(Config, [11, 12, 13, 14, 11], 1, "-s5", []) end], process_flag(trap_exit, true), Pids = lists:map(fun fun_spawn/1, Testers), wait_for(Pids), @@ -444,10 +444,10 @@ wait_for([]) -> wait_for(Pids) -> io:format("Waiting for ~p", [Pids]), receive - {'EXIT', Pid, normal} -> - wait_for(lists:delete(Pid, Pids)); - Other -> - ct:fail({bad_exit, Other}) + {'EXIT', Pid, normal} -> + wait_for(lists:delete(Pid, Pids)); + Other -> + ct:fail({bad_exit, Other}) end. %% Tests starting port programs that terminate by themselves. @@ -479,8 +479,8 @@ dying_port(Config) when is_list(Config) -> wait_for_port_exit(Port) -> receive - {'EXIT', Port, _} -> - ok + {'EXIT', Port, _} -> + ok end. make_dying_port(Config) when is_list(Config) -> @@ -503,17 +503,17 @@ port_program_with_path(Config) when is_list(Config) -> ct:timetrap({minutes, 2}), DataDir = proplists:get_value(data_dir, Config), PrivDir = proplists:get_value(priv_dir, Config), - + %% Create a copy of the port test program in a directory not %% included in PATH (i.e. in priv_dir), with the name 'my_port_test.exe'. %% Also, place a file named 'my_port_test' in the same directory. %% This used to confuse the CreateProcess() call in spawn driver. %% (On Unix, there will be a single file created, which will be %% a copy of the port program.) - + PortTest = os:find_executable("port_test", DataDir), io:format("os:find_executable(~p, ~p) returned ~p", - ["port_test", DataDir, PortTest]), + ["port_test", DataDir, PortTest]), {ok, PortTestPgm} = file:read_file(PortTest), NewName = filename:join(PrivDir, filename:basename(PortTest)), RedHerring = filename:rootname(NewName), @@ -521,12 +521,12 @@ port_program_with_path(Config) when is_list(Config) -> ok = file:write_file(NewName, PortTestPgm), ok = file:write_file_info(NewName, #file_info{mode=8#111}), PgmWithPathAndNoExt = filename:rootname(NewName), - + %% Open the port using the path to the copied port test program, %% but without the .exe extension, and verified that it was started. %% %% If the bug is present the open_port call will fail with badarg. - + Command = lists:concat([PgmWithPathAndNoExt, " -h2"]), P = open_port({spawn, Command}, [{packet, 2}]), Message = "echo back to me", @@ -542,7 +542,7 @@ port_program_with_path(Config) when is_list(Config) -> %% This used to fail on Windows. open_input_file_port(Config) when is_list(Config) -> PrivDir = proplists:get_value(priv_dir, Config), - + %% Create a file with the file driver and read it back using %% open_port/2. @@ -550,11 +550,11 @@ open_input_file_port(Config) when is_list(Config) -> FileData1 = "An input file", ok = file:write_file(MyFile1, FileData1), case open_port(MyFile1, [in]) of - InputPort when is_port(InputPort) -> - receive - {InputPort, {data, FileData1}} -> - ok - end + InputPort when is_port(InputPort) -> + receive + {InputPort, {data, FileData1}} -> + ok + end end, ok. @@ -597,9 +597,9 @@ count_fds(Config) when is_list(Config) -> {ok, Written} = file:read_file(Filename), Written end, - <<4:32/native>> = RunTest([out, nouse_stdio]), - <<4:32/native>> = RunTest([in, nouse_stdio]), - <<5:32/native>> = RunTest([in, out, nouse_stdio]), + <<4:32/native>> = RunTest([out, nouse_stdio]), + <<4:32/native>> = RunTest([in, nouse_stdio]), + <<5:32/native>> = RunTest([in, out, nouse_stdio]), <<3:32/native>> = RunTest([out, use_stdio]), <<3:32/native>> = RunTest([in, use_stdio]), <<3:32/native>> = RunTest([in, out, use_stdio]), @@ -622,24 +622,24 @@ iter_max_ports(Config) when is_list(Config) -> %% Config2 = ignore_cores:setup(?MODULE, iter_max_ports, Config, true), try - iter_max_ports_test(Config2) + iter_max_ports_test(Config2) after - ignore_cores:restore(Config2) + ignore_cores:restore(Config2) end. - - + + iter_max_ports_test(Config) -> ct:timetrap({minutes, 30}), PortTest = port_test(Config), Command = lists:concat([PortTest, " -h0 -q"]), Iters = case os:type() of - {win32,_} -> 4; - _ -> 10 - end, + {win32,_} -> 4; + _ -> 10 + end, %% Run on a different node in order to limit the effect if this test fails. Dir = filename:dirname(code:which(?MODULE)), {ok,Node} = test_server:start_node(test_iter_max_socks,slave, - [{args,"+Q 2048 -pa " ++ Dir}]), + [{args,"+Q 2048 -pa " ++ Dir}]), L = rpc:call(Node,?MODULE,do_iter_max_ports,[Iters, Command]), test_server:stop_node(Node), @@ -669,8 +669,8 @@ max_ports(Command) -> close_ports([P|Ps]) -> P ! {self(), close}, receive - {P,closed} -> - ok + {P,closed} -> + ok end, close_ports(Ps); close_ports([]) -> @@ -688,23 +688,23 @@ open_ports(Name, Settings) -> test_server:sleep(5) end, case catch open_port(Name, Settings) of - P when is_port(P) -> - [P| open_ports(Name, Settings)]; - {'EXIT', {Code, _}} -> - case Code of - enfile -> - []; - emfile -> - []; - system_limit -> - []; - enomem -> - []; - Other -> - ct:fail({open_ports, Other}) - end; - Other -> - ct:fail({open_ports, Other}) + P when is_port(P) -> + [P| open_ports(Name, Settings)]; + {'EXIT', {Code, _}} -> + case Code of + enfile -> + []; + emfile -> + []; + system_limit -> + []; + enomem -> + []; + Other -> + ct:fail({open_ports, Other}) + end; + Other -> + ct:fail({open_ports, Other}) end. %% Tests that exit(Port, Term) works (has been known to crash the emulator). @@ -713,10 +713,10 @@ t_exit(Config) when is_list(Config) -> process_flag(trap_exit, true), Pid = fun_spawn(fun suicide_port/1, [Config]), receive - {'EXIT', Pid, die} -> - ok; - Other -> - ct:fail({bad_message, Other}) + {'EXIT', Pid, die} -> + ok; + Other -> + ct:fail({bad_message, Other}) end. suicide_port(Config) when is_list(Config) -> @@ -738,17 +738,17 @@ tps(Size, Config) -> Port = open_port({spawn, PortTest}, [binary, {packet, 2}]), Transactions = 10000, {Elapsed, ok} = test_server:timecall(?MODULE, tps, - [Port, Packet, Transactions]), + [Port, Packet, Transactions]), {comment, integer_to_list(trunc(Transactions/Elapsed+0.5)) ++ " transactions/s"}. tps(_Port, _Packet, 0) -> ok; tps(Port, Packet, N) -> port_command(Port, Packet), receive - {Port, {data, Packet}} -> - tps(Port, Packet, N-1); - Other -> - ct:fail({bad_message, Other}) + {Port, {data, Packet}} -> + tps(Port, Packet, N-1); + Other -> + ct:fail({bad_message, Other}) end. %% Line I/O test @@ -759,38 +759,38 @@ line(Config) when is_list(Config) -> Packet2 = random_packet(Siz div 2), %% Test that packets are split into lines port_expect(Config,[{lists:append([Packet1, io_lib:nl(), Packet2, - io_lib:nl()]), - [{eol, Packet1}, {eol, Packet2}]}], - 0, "", [{line,Siz}]), + io_lib:nl()]), + [{eol, Packet1}, {eol, Packet2}]}], + 0, "", [{line,Siz}]), %% Test the same for binaries port_expect(Config,[{lists:append([Packet1, io_lib:nl(), Packet2, - io_lib:nl()]), - [{eol, Packet1}, {eol, Packet2}]}], - 0, "", [{line,Siz},binary]), + io_lib:nl()]), + [{eol, Packet1}, {eol, Packet2}]}], + 0, "", [{line,Siz},binary]), %% Test that too long lines get split port_expect(Config,[{lists:append([Packet1, io_lib:nl(), Packet1, - Packet2, io_lib:nl()]), - [{eol, Packet1}, {noeol, Packet1}, - {eol, Packet2}]}], 0, "", [{line,Siz}]), + Packet2, io_lib:nl()]), + [{eol, Packet1}, {noeol, Packet1}, + {eol, Packet2}]}], 0, "", [{line,Siz}]), %% Test that last output from closing port program gets received. L1 = lists:append([Packet1, io_lib:nl(), Packet2]), S1 = lists:flatten(io_lib:format("-l~w", [length(L1)])), io:format("S1 = ~w, L1 = ~w~n", [S1,L1]), port_expect(Config,[{L1, - [{eol, Packet1}, {noeol, Packet2}, eof]}], 0, - S1, [{line,Siz},eof]), + [{eol, Packet1}, {noeol, Packet2}, eof]}], 0, + S1, [{line,Siz},eof]), %% Test that lonely <CR> Don't get treated as newlines port_expect(Config,[{lists:append([Packet1, [13], Packet2, - io_lib:nl()]), - [{noeol, Packet1}, {eol, [13 |Packet2]}]}], - 0, "", [{line,Siz}]), + io_lib:nl()]), + [{noeol, Packet1}, {eol, [13 |Packet2]}]}], + 0, "", [{line,Siz}]), %% Test that packets get built up to lines (delayed output from %% port program) port_expect(Config,[{Packet2,[]}, - {lists:append([Packet2, io_lib:nl(), - Packet1, io_lib:nl()]), - [{eol, lists:append(Packet2, Packet2)}, - {eol, Packet1}]}], 0, "-d", [{line,Siz}]), + {lists:append([Packet2, io_lib:nl(), + Packet1, io_lib:nl()]), + [{eol, lists:append(Packet2, Packet2)}, + {eol, Packet1}]}], 0, "-d", [{line,Siz}]), %% Test that we get badarg if trying both packet and line bad_argument(Config, [{packet, 5}, {line, 5}]), ok. @@ -801,7 +801,7 @@ stderr_to_stdout(Config) when is_list(Config) -> %% See that it works Packet = random_packet(10), port_expect(Config,[{Packet,[Packet]}], 0, "-e -l10", - [stderr_to_stdout]), + [stderr_to_stdout]), %% stream_ping(Config, 10, "-e", [stderr_to_stdout]), %% See that it doesn't always happen (will generate garbage on stderr) port_expect(Config,[{Packet,[eof]}], 0, "-e -l10", [line,eof]), @@ -811,10 +811,10 @@ stderr_to_stdout(Config) when is_list(Config) -> bad_argument(Config, ArgList) -> PortTest = port_test(Config), case catch open_port({spawn, PortTest}, ArgList) of - {'EXIT', {badarg, _}} -> - ok + {'EXIT', {badarg, _}} -> + ok end. - + %% 'env' option %% (Can perhaps be made smaller by calling the other utility functions @@ -833,34 +833,34 @@ env(Config) when is_list(Config) -> os:putenv(Long, "nisse"), env_slave(Temp, [{"plupp",PluppVal}, - {"DIR_PLUPP","###glurfrik"}], - fun() -> - PluppVal = os:getenv("plupp"), - "###glurfrik" = os:getenv("DIR_PLUPP"), - "nisse" = os:getenv(Long) - end), + {"DIR_PLUPP","###glurfrik"}], + fun() -> + PluppVal = os:getenv("plupp"), + "###glurfrik" = os:getenv("DIR_PLUPP"), + "nisse" = os:getenv(Long) + end), env_slave(Temp, [{"must_define_something","some_value"}, - {"certainly_not_existing",false}, - {"ends_with_equal", "value="}, - {Long,false}, - {"glurf","a glorfy string"}]), + {"certainly_not_existing",false}, + {"ends_with_equal", "value="}, + {Long,false}, + {"glurf","a glorfy string"}]), %% A lot of non existing variables (mingled with existing) NotExistingList = [{lists:flatten(io_lib:format("V~p_not_existing",[X])),false} - || X <- lists:seq(1,150)], + || X <- lists:seq(1,150)], ExistingList = [{lists:flatten(io_lib:format("V~p_existing",[X])),"a_value"} - || X <- lists:seq(1,150)], + || X <- lists:seq(1,150)], env_slave(Temp, lists:sort(ExistingList ++ NotExistingList)), ok. env_slave(File, Env) -> F = fun() -> - lists:foreach(fun({Name,Val}) -> - Val = os:getenv(Name) - end, Env) - end, + lists:foreach(fun({Name,Val}) -> + Val = os:getenv(Name) + end, Env) + end, env_slave(File, Env, F). env_slave(File, Env, Body) -> @@ -868,26 +868,26 @@ env_slave(File, Env, Body) -> Program = atom_to_list(lib:progname()), Dir = filename:dirname(code:which(?MODULE)), Cmd = Program ++ " -pz " ++ Dir ++ - " -noinput -run " ++ ?MODULE_STRING ++ " env_slave_main " ++ - File ++ " -run erlang halt", + " -noinput -run " ++ ?MODULE_STRING ++ " env_slave_main " ++ + File ++ " -run erlang halt", Port = open_port({spawn, Cmd}, [{env,Env},{line,256}]), receive - {Port,{data,{eol,"ok"}}} -> - ok; - {Port,{data,{eol,Error}}} -> - ct:fail("eol error ~p\n", [Error]); - Other -> - ct:fail(Other) + {Port,{data,{eol,"ok"}}} -> + ok; + {Port,{data,{eol,Error}}} -> + ct:fail("eol error ~p\n", [Error]); + Other -> + ct:fail(Other) end. env_slave_main([File]) -> {ok,Body0} = file:read_file(File), Body = binary_to_term(Body0), case Body() of - {'EXIT',Reason} -> - io:format("Error: ~p\n", [Reason]); - _ -> - io:format("ok\n") + {'EXIT',Reason} -> + io:format("Error: ~p\n", [Reason]); + _ -> + io:format("ok\n") end, init:stop(). @@ -909,23 +909,23 @@ bad_env(Config) when is_list(Config) -> try_bad_env(Env) -> try open_port({spawn,"ls"}, [{env,Env}]) catch - error:badarg -> ok + error:badarg -> ok end. %% Test that we can handle a very very large environment gracefully. huge_env(Config) when is_list(Config) -> Vars = case os:type() of - {win32,_} -> 500; - _ -> + {win32,_} -> 500; + _ -> %% We create a huge environment, %% 20000 variables is about 25MB %% which seems to be the limit on Linux. 20000 - end, + end, Env = [{[$a + I div (25*25*25*25) rem 25, - $a + I div (25*25*25) rem 25, - $a + I div (25*25) rem 25, - $a+I div 25 rem 25, $a+I rem 25], + $a + I div (25*25*25) rem 25, + $a + I div (25*25) rem 25, + $a+I div 25 rem 25, $a+I rem 25], lists:duplicate(100,$a+I rem 25)} || I <- lists:seq(1,Vars)], try erlang:open_port({spawn,"ls"},[exit_status, {env, Env}]) of @@ -939,9 +939,9 @@ huge_env(Config) when is_list(Config) -> true = is_integer(N) end catch E:R -> - %% Have to catch the error here, as printing the stackdump - %% in the ct log is way to heavy for some test machines. - ct:fail("Open port failed ~p:~p",[E,R]) + %% Have to catch the error here, as printing the stackdump + %% in the ct log is way to heavy for some test machines. + ct:fail("Open port failed ~p:~p",[E,R]) end. @@ -958,43 +958,43 @@ cd(Config) when is_list(Config) -> DataDir = proplists:get_value(data_dir, Config), TestDir = filename:join(DataDir, "dir"), Cmd = Program ++ " -pz " ++ DataDir ++ - " -noshell -s port_test pwd -s erlang halt", + " -noshell -s port_test pwd -s erlang halt", _ = open_port({spawn, Cmd}, - [{cd, TestDir}, - {line, 256}]), + [{cd, TestDir}, + {line, 256}]), receive - {_, {data, {eol, String}}} -> - case filename_equal(String, TestDir) of - true -> - ok; - false -> - ct:fail({cd, String}) - end; - Other2 -> - ct:fail({env, Other2}) + {_, {data, {eol, String}}} -> + case filename_equal(String, TestDir) of + true -> + ok; + false -> + ct:fail({cd, String}) + end; + Other2 -> + ct:fail({env, Other2}) end, _ = open_port({spawn, Cmd}, - [{cd, unicode:characters_to_binary(TestDir)}, - {line, 256}]), + [{cd, unicode:characters_to_binary(TestDir)}, + {line, 256}]), receive - {_, {data, {eol, String2}}} -> - case filename_equal(String2, TestDir) of - true -> - ok; - false -> - ct:fail({cd, String2}) - end; - Other3 -> - ct:fail({env, Other3}) + {_, {data, {eol, String2}}} -> + case filename_equal(String2, TestDir) of + true -> + ok; + false -> + ct:fail({cd, String2}) + end; + Other3 -> + ct:fail({env, Other3}) end, ok. filename_equal(A, B) -> case os:type() of - {win32, _} -> - win_filename_equal(A, B); - _ -> - A == B + {win32, _} -> + win_filename_equal(A, B); + _ -> + A == B end. win_filename_equal([], []) -> @@ -1005,10 +1005,10 @@ win_filename_equal(_, []) -> false; win_filename_equal([C1 | Rest1], [C2 | Rest2]) -> case tolower(C1) == tolower(C2) of - true -> - win_filename_equal(Rest1, Rest2); - false -> - false + true -> + win_filename_equal(Rest1, Rest2); + false -> + false end. tolower(C) when C >= $A, C =< $Z -> @@ -1020,10 +1020,10 @@ tolower(C) -> %% a large amount of concurrently dying children. See ticket OTP-3906. otp_3906(Config) when is_list(Config) -> case os:type() of - {unix, OSName} -> - otp_3906(Config, OSName); - _ -> - {skipped, "Only run on Unix systems"} + {unix, OSName} -> + otp_3906(Config, OSName); + _ -> + {skipped, "Only run on Unix systems"} end. -define(OTP_3906_CHILDREN, 1000). @@ -1036,54 +1036,54 @@ otp_3906(Config) when is_list(Config) -> otp_3906(Config, OSName) -> DataDir = filename:dirname(proplists:get_value(data_dir,Config)), {ok, Variables} = file:consult( - filename:join([DataDir,"..","..", - "test_server","variables"])), + filename:join([DataDir,"..","..", + "test_server","variables"])), case lists:keysearch('CC', 1, Variables) of - {value,{'CC', CC}} -> - SuiteDir = filename:dirname(code:which(?MODULE)), - PrivDir = proplists:get_value(priv_dir, Config), - Prog = otp_3906_make_prog(CC, PrivDir), - {ok, Node} = test_server:start_node(otp_3906, - slave, - [{args, " -pa " ++ SuiteDir}, - {linked, false}]), - OP = process_flag(priority, max), - OTE = process_flag(trap_exit, true), - FS = spawn_link(Node, - ?MODULE, - otp_3906_start_forker_starter, - [?OTP_3906_CHILDREN, [], self(), Prog]), - Result = receive - {'EXIT', _ForkerStarter, Reason} -> - {failed, Reason}; - {emulator_pid, EmPid} -> - case otp_3906_wait_result(FS, 0, 0) of - {succeded, - ?OTP_3906_CHILDREN, - ?OTP_3906_CHILDREN} -> - succeded; - {succeded, Forked, Exited} -> - otp_3906_list_defunct(EmPid, OSName), - {failed, - {mismatch, - {forked, Forked}, - {exited, Exited}}}; - Res -> - otp_3906_list_defunct(EmPid, OSName), - Res - end - end, - process_flag(trap_exit, OTE), - process_flag(priority, OP), - test_server:stop_node(Node), - case Result of - succeded -> - ok; - _ -> - ct:fail(Result) - end; - _ -> - {skipped, "No C compiler found"} + {value,{'CC', CC}} -> + SuiteDir = filename:dirname(code:which(?MODULE)), + PrivDir = proplists:get_value(priv_dir, Config), + Prog = otp_3906_make_prog(CC, PrivDir), + {ok, Node} = test_server:start_node(otp_3906, + slave, + [{args, " -pa " ++ SuiteDir}, + {linked, false}]), + OP = process_flag(priority, max), + OTE = process_flag(trap_exit, true), + FS = spawn_link(Node, + ?MODULE, + otp_3906_start_forker_starter, + [?OTP_3906_CHILDREN, [], self(), Prog]), + Result = receive + {'EXIT', _ForkerStarter, Reason} -> + {failed, Reason}; + {emulator_pid, EmPid} -> + case otp_3906_wait_result(FS, 0, 0) of + {succeded, + ?OTP_3906_CHILDREN, + ?OTP_3906_CHILDREN} -> + succeded; + {succeded, Forked, Exited} -> + otp_3906_list_defunct(EmPid, OSName), + {failed, + {mismatch, + {forked, Forked}, + {exited, Exited}}}; + Res -> + otp_3906_list_defunct(EmPid, OSName), + Res + end + end, + process_flag(trap_exit, OTE), + process_flag(priority, OP), + test_server:stop_node(Node), + case Result of + succeded -> + ok; + _ -> + ct:fail(Result) + end; + _ -> + {skipped, "No C compiler found"} end. otp_3906_list_defunct(EmPid, OSName) -> @@ -1110,9 +1110,9 @@ otp_3906_htmlize([]) -> []; otp_3906_htmlize([C | Cs]) -> case [C] of - "<" -> "<" ++ otp_3906_htmlize(Cs); - ">" -> ">" ++ otp_3906_htmlize(Cs); - _ -> [C | otp_3906_htmlize(Cs)] + "<" -> "<" ++ otp_3906_htmlize(Cs); + ">" -> ">" ++ otp_3906_htmlize(Cs); + _ -> [C | otp_3906_htmlize(Cs)] end. otp_3906_make_prog(CC, PrivDir) -> @@ -1120,12 +1120,12 @@ otp_3906_make_prog(CC, PrivDir) -> TrgtFileName = filename:join(PrivDir, ?OTP_3906_PROGNAME), {ok, SrcFile} = file:open(SrcFileName, write), io:format(SrcFile, - "int ~n" - "main(void) ~n" - "{ ~n" - " return ~p; ~n" - "} ~n", - [?OTP_3906_EXIT_STATUS]), + "int ~n" + "main(void) ~n" + "{ ~n" + " return ~p; ~n" + "} ~n", + [?OTP_3906_EXIT_STATUS]), file:close(SrcFile), os:cmd(CC ++ " " ++ SrcFileName ++ " -o " ++ TrgtFileName), TrgtFileName. @@ -1133,21 +1133,21 @@ otp_3906_make_prog(CC, PrivDir) -> otp_3906_wait_result(ForkerStarter, F, E) -> receive - {'EXIT', ForkerStarter, Reason} -> - {failed, {Reason, {forked, F}, {exited, E}}}; - forked -> - otp_3906_wait_result(ForkerStarter, F+1, E); - exited -> - otp_3906_wait_result(ForkerStarter, F, E+1); - tick -> - otp_3906_wait_result(ForkerStarter, F, E); - succeded -> - {succeded, F, E} + {'EXIT', ForkerStarter, Reason} -> + {failed, {Reason, {forked, F}, {exited, E}}}; + forked -> + otp_3906_wait_result(ForkerStarter, F+1, E); + exited -> + otp_3906_wait_result(ForkerStarter, F, E+1); + tick -> + otp_3906_wait_result(ForkerStarter, F, E); + succeded -> + {succeded, F, E} after - ?OTP_3906_TICK_TIMEOUT -> - unlink(ForkerStarter), - exit(ForkerStarter, timeout), - {failed, {timeout, {forked, F}, {exited, E}}} + ?OTP_3906_TICK_TIMEOUT -> + unlink(ForkerStarter), + exit(ForkerStarter, timeout), + {failed, {timeout, {forked, F}, {exited, E}}} end. otp_3906_collect([], _) -> @@ -1157,17 +1157,17 @@ otp_3906_collect(RefList, Sup) -> otp_3906_collect_one(RefList, Sup) -> receive - Ref when is_reference(Ref) -> - Sup ! tick, - lists:delete(Ref, RefList) + Ref when is_reference(Ref) -> + Sup ! tick, + lists:delete(Ref, RefList) end. - + otp_3906_start_forker(N, Sup, Prog) -> Ref = make_ref(), spawn_opt(?MODULE, - otp_3906_forker, - [N, self(), Ref, Sup, Prog], - [link, {priority, max}]), + otp_3906_forker, + [N, self(), Ref, Sup, Prog], + [link, {priority, max}]), Ref. otp_3906_start_forker_starter(N, RefList, Sup, Prog) -> @@ -1186,18 +1186,18 @@ otp_3906_forker_starter(N, RefList, Sup, Prog) otp_3906_forker_starter(N, RefList, Sup, Prog) when is_integer(N), N > ?OTP_3906_OSP_P_ERLP -> otp_3906_forker_starter(N-?OTP_3906_OSP_P_ERLP, - [otp_3906_start_forker(?OTP_3906_OSP_P_ERLP, - Sup, - Prog)|RefList], - Sup, - Prog); + [otp_3906_start_forker(?OTP_3906_OSP_P_ERLP, + Sup, + Prog)|RefList], + Sup, + Prog); otp_3906_forker_starter(N, RefList, Sup, Prog) when is_integer(N) -> otp_3906_forker_starter(0, - [otp_3906_start_forker(N, - Sup, - Prog)|RefList], - Sup, - Prog). + [otp_3906_start_forker(N, + Sup, + Prog)|RefList], + Sup, + Prog). otp_3906_forker(0, Parent, Ref, _, _) -> unlink(Parent), @@ -1206,87 +1206,87 @@ otp_3906_forker(N, Parent, Ref, Sup, Prog) -> Port = erlang:open_port({spawn, Prog}, [exit_status, in]), Sup ! forked, receive - {Port, {exit_status, ?OTP_3906_EXIT_STATUS}} -> - Sup ! exited, - otp_3906_forker(N-1, Parent, Ref, Sup, Prog); - {Port, Res} -> - exit(Res); - Other -> - exit(Other) + {Port, {exit_status, ?OTP_3906_EXIT_STATUS}} -> + Sup ! exited, + otp_3906_forker(N-1, Parent, Ref, Sup, Prog); + {Port, Res} -> + exit(Res); + Other -> + exit(Other) end. otp_4389(Config) when is_list(Config) -> case os:type() of - {unix, _} -> + {unix, _} -> ct:timetrap({minutes, 4}), - TCR = self(), - case get_true_cmd() of - True when is_list(True) -> - lists:foreach( - fun (P) -> - receive - {P, ok} -> ok; - {P, Err} -> ct:fail(Err) - end - end, - lists:map( - fun(_) -> - spawn_link( - fun() -> - process_flag(trap_exit, true), - case catch open_port({spawn, True}, - [stream,exit_status]) of - P when is_port(P) -> - receive - {P,{exit_status,_}} -> - TCR ! {self(),ok}; - {'EXIT',_,{R2,_}} when R2 == emfile; - R2 == eagain; - R2 == enomem -> - TCR ! {self(),ok}; - Err2 -> - TCR ! {self(),{msg,Err2}} - end; - {'EXIT',{R1,_}} when R1 == emfile; - R1 == eagain; - R1 == enomem -> - TCR ! {self(),ok}; - Err1 -> - TCR ! {self(), {open_port,Err1}} - end - end) - end, - lists:duplicate(1000,[]))), - {comment, - "This test case doesn't always fail when the bug that " - "it tests for is present (it is most likely to fail on" - " a multi processor machine). If the test case fails it" - " will fail by deadlocking the emulator."}; - _ -> - {skipped, "\"true\" command not found"} - end; - _ -> - {skip,"Only run on Unix"} + TCR = self(), + case get_true_cmd() of + True when is_list(True) -> + lists:foreach( + fun (P) -> + receive + {P, ok} -> ok; + {P, Err} -> ct:fail(Err) + end + end, + lists:map( + fun(_) -> + spawn_link( + fun() -> + process_flag(trap_exit, true), + case catch open_port({spawn, True}, + [stream,exit_status]) of + P when is_port(P) -> + receive + {P,{exit_status,_}} -> + TCR ! {self(),ok}; + {'EXIT',_,{R2,_}} when R2 == emfile; + R2 == eagain; + R2 == enomem -> + TCR ! {self(),ok}; + Err2 -> + TCR ! {self(),{msg,Err2}} + end; + {'EXIT',{R1,_}} when R1 == emfile; + R1 == eagain; + R1 == enomem -> + TCR ! {self(),ok}; + Err1 -> + TCR ! {self(), {open_port,Err1}} + end + end) + end, + lists:duplicate(1000,[]))), + {comment, + "This test case doesn't always fail when the bug that " + "it tests for is present (it is most likely to fail on" + " a multi processor machine). If the test case fails it" + " will fail by deadlocking the emulator."}; + _ -> + {skipped, "\"true\" command not found"} + end; + _ -> + {skip,"Only run on Unix"} end. get_true_cmd() -> DoFileExist = fun (FileName) -> - case file:read_file_info(FileName) of - {ok, _} -> throw(FileName); - _ -> not_found - end - end, + case file:read_file_info(FileName) of + {ok, _} -> throw(FileName); + _ -> not_found + end + end, catch begin - %% First check in /usr/bin and /bin - DoFileExist("/usr/bin/true"), - DoFileExist("/bin/true"), - %% Try which - case filename:dirname(os:cmd("which true")) of - "." -> not_found; - TrueDir -> filename:join(TrueDir, "true") - end - end. + %% First check in /usr/bin and /bin + DoFileExist("/usr/bin/true"), + DoFileExist("/bin/true"), + %% Try which + case filename:dirname(os:cmd("which true")) of + "." -> not_found; + TrueDir -> filename:join(TrueDir, "true") + end + end. %% 'exit_status' option %% @@ -1305,24 +1305,24 @@ spawn_driver(Config) when is_list(Config) -> Port = erlang:open_port({spawn_driver, "echo_drv"}, []), Port ! {self(), {command, "Hello port!"}}, receive - {Port, {data, "Hello port!"}} = Msg1 -> - io:format("~p~n", [Msg1]), - ok; - Other -> - ct:fail({unexpected, Other}) - end, + {Port, {data, "Hello port!"}} = Msg1 -> + io:format("~p~n", [Msg1]), + ok; + Other -> + ct:fail({unexpected, Other}) + end, Port ! {self(), close}, receive {Port, closed} -> ok end, Port2 = erlang:open_port({spawn_driver, "echo_drv -Hello port?"}, - []), + []), receive - {Port2, {data, "Hello port?"}} = Msg2 -> - io:format("~p~n", [Msg2]), - ok; - Other2 -> - ct:fail({unexpected2, Other2}) - end, + {Port2, {data, "Hello port?"}} = Msg2 -> + io:format("~p~n", [Msg2]), + ok; + Other2 -> + ct:fail({unexpected2, Other2}) + end, Port2 ! {self(), close}, receive {Port2, closed} -> ok end, {'EXIT',{badarg,_}} = (catch erlang:open_port({spawn_driver, "ls"}, [])), @@ -1332,34 +1332,34 @@ spawn_driver(Config) when is_list(Config) -> %% Test parallelism option of open_port parallelism_option(Config) when is_list(Config) -> - ?line Path = proplists:get_value(data_dir, Config), - ?line ok = load_driver(Path, "echo_drv"), - ?line Port = erlang:open_port({spawn_driver, "echo_drv"}, - [{parallelism, true}]), - ?line {parallelism, true} = erlang:port_info(Port, parallelism), - ?line Port ! {self(), {command, "Hello port!"}}, - ?line receive - {Port, {data, "Hello port!"}} = Msg1 -> - io:format("~p~n", [Msg1]), - ok; - Other -> - ct:fail({unexpected, Other}) - end, - ?line Port ! {self(), close}, - ?line receive {Port, closed} -> ok end, - - ?line Port2 = erlang:open_port({spawn_driver, "echo_drv -Hello port?"}, - [{parallelism, false}]), - ?line {parallelism, false} = erlang:port_info(Port2, parallelism), - ?line receive - {Port2, {data, "Hello port?"}} = Msg2 -> - io:format("~p~n", [Msg2]), - ok; - Other2 -> - ct:fail({unexpected2, Other2}) - end, - ?line Port2 ! {self(), close}, - ?line receive {Port2, closed} -> ok end, + Path = proplists:get_value(data_dir, Config), + ok = load_driver(Path, "echo_drv"), + Port = erlang:open_port({spawn_driver, "echo_drv"}, + [{parallelism, true}]), + {parallelism, true} = erlang:port_info(Port, parallelism), + Port ! {self(), {command, "Hello port!"}}, + receive + {Port, {data, "Hello port!"}} = Msg1 -> + io:format("~p~n", [Msg1]), + ok; + Other -> + ct:fail({unexpected, Other}) + end, + Port ! {self(), close}, + receive {Port, closed} -> ok end, + + Port2 = erlang:open_port({spawn_driver, "echo_drv -Hello port?"}, + [{parallelism, false}]), + {parallelism, false} = erlang:port_info(Port2, parallelism), + receive + {Port2, {data, "Hello port?"}} = Msg2 -> + io:format("~p~n", [Msg2]), + ok; + Other2 -> + ct:fail({unexpected2, Other2}) + end, + Port2 ! {self(), close}, + receive {Port2, closed} -> ok end, ok. %% Test spawning an executable specifically @@ -1374,22 +1374,22 @@ spawn_executable(Config) when is_list(Config) -> ["echo_arguments"] = run_echo_args(DataDir,["echo_arguments"]), ["echo_arguments"] = run_echo_args(DataDir,[binary, "echo_arguments"]), [ExactFile1,"hello world","dlrow olleh"] = - run_echo_args(DataDir,[ExactFile1,"hello world","dlrow olleh"]), + run_echo_args(DataDir,[ExactFile1,"hello world","dlrow olleh"]), [ExactFile1] = run_echo_args(DataDir,[default]), [ExactFile1] = run_echo_args(DataDir,[binary, default]), [ExactFile1,"hello world","dlrow olleh"] = - run_echo_args(DataDir,[switch_order,ExactFile1,"hello world", - "dlrow olleh"]), + run_echo_args(DataDir,[switch_order,ExactFile1,"hello world", + "dlrow olleh"]), [ExactFile1,"hello world","dlrow olleh"] = - run_echo_args(DataDir,[binary,switch_order,ExactFile1,"hello world", - "dlrow olleh"]), + run_echo_args(DataDir,[binary,switch_order,ExactFile1,"hello world", + "dlrow olleh"]), [ExactFile1,"hello world","dlrow olleh"] = - run_echo_args(DataDir,[default,"hello world","dlrow olleh"]), + run_echo_args(DataDir,[default,"hello world","dlrow olleh"]), [ExactFile1,"hello world","dlrow olleh"] = - run_echo_args_2("\""++ExactFile1++"\" "++"\"hello world\" \"dlrow olleh\""), + run_echo_args_2("\""++ExactFile1++"\" "++"\"hello world\" \"dlrow olleh\""), [ExactFile1,"hello world","dlrow olleh"] = - run_echo_args_2(unicode:characters_to_binary("\""++ExactFile1++"\" "++"\"hello world\" \"dlrow olleh\"")), + run_echo_args_2(unicode:characters_to_binary("\""++ExactFile1++"\" "++"\"hello world\" \"dlrow olleh\"")), PrivDir = proplists:get_value(priv_dir, Config), SpaceDir = filename:join([PrivDir,"With Spaces"]), @@ -1403,33 +1403,32 @@ spawn_executable(Config) when is_list(Config) -> ["echo_args"] = run_echo_args(SpaceDir,["echo_args"]), ["echo_arguments"] = run_echo_args(SpaceDir,["echo_arguments"]), [ExactFile2,"hello world","dlrow olleh"] = - run_echo_args(SpaceDir,[ExactFile2,"hello world","dlrow olleh"]), + run_echo_args(SpaceDir,[ExactFile2,"hello world","dlrow olleh"]), [ExactFile2,"hello world","dlrow olleh"] = - run_echo_args(SpaceDir,[binary, ExactFile2,"hello world","dlrow olleh"]), + run_echo_args(SpaceDir,[binary, ExactFile2,"hello world","dlrow olleh"]), [ExactFile2,"hello \"world\"","\"dlrow\" olleh"] = - run_echo_args(SpaceDir,[binary, ExactFile2,"hello \"world\"","\"dlrow\" olleh"]), + run_echo_args(SpaceDir,[binary, ExactFile2,"hello \"world\"","\"dlrow\" olleh"]), [ExactFile2,"hello \"world\"","\"dlrow\" olleh"] = - run_echo_args(SpaceDir,[binary, ExactFile2,"hello \"world\"","\"dlrow\" olleh"]), + run_echo_args(SpaceDir,[binary, ExactFile2,"hello \"world\"","\"dlrow\" olleh"]), [ExactFile2] = run_echo_args(SpaceDir,[default]), [ExactFile2,"hello world","dlrow olleh"] = - run_echo_args(SpaceDir,[switch_order,ExactFile2,"hello world", - "dlrow olleh"]), + run_echo_args(SpaceDir,[switch_order,ExactFile2,"hello world", "dlrow olleh"]), [ExactFile2,"hello world","dlrow olleh"] = - run_echo_args(SpaceDir,[default,"hello world","dlrow olleh"]), + run_echo_args(SpaceDir,[default,"hello world","dlrow olleh"]), [ExactFile2,"hello world","dlrow olleh"] = - run_echo_args_2("\""++ExactFile2++"\" "++"\"hello world\" \"dlrow olleh\""), + run_echo_args_2("\""++ExactFile2++"\" "++"\"hello world\" \"dlrow olleh\""), [ExactFile2,"hello world","dlrow olleh"] = - run_echo_args_2(unicode:characters_to_binary("\""++ExactFile2++"\" "++"\"hello world\" \"dlrow olleh\"")), + run_echo_args_2(unicode:characters_to_binary("\""++ExactFile2++"\" "++"\"hello world\" \"dlrow olleh\"")), ExeExt = - case string:to_lower(lists:last(string:tokens(ExactFile2,"."))) of - "exe" -> - ".exe"; - _ -> - "" - end, + case string:to_lower(lists:last(string:tokens(ExactFile2,"."))) of + "exe" -> + ".exe"; + _ -> + "" + end, Executable2 = "spoky name"++ExeExt, file:copy(ExactFile1,filename:join([SpaceDir,Executable2])), ExactFile3 = filename:nativename(filename:join([SpaceDir,Executable2])), @@ -1438,36 +1437,36 @@ spawn_executable(Config) when is_list(Config) -> ["echo_args"] = run_echo_args(SpaceDir,Executable2,["echo_args"]), ["echo_arguments"] = run_echo_args(SpaceDir,Executable2,["echo_arguments"]), [ExactFile3,"hello world","dlrow olleh"] = - run_echo_args(SpaceDir,Executable2,[ExactFile3,"hello world","dlrow olleh"]), + run_echo_args(SpaceDir,Executable2,[ExactFile3,"hello world","dlrow olleh"]), [ExactFile3] = run_echo_args(SpaceDir,Executable2,[default]), [ExactFile3,"hello world","dlrow olleh"] = - run_echo_args(SpaceDir,Executable2, - [switch_order,ExactFile3,"hello world", - "dlrow olleh"]), + run_echo_args(SpaceDir,Executable2, + [switch_order,ExactFile3,"hello world", + "dlrow olleh"]), [ExactFile3,"hello world","dlrow olleh"] = - run_echo_args(SpaceDir,Executable2, - [default,"hello world","dlrow olleh"]), + run_echo_args(SpaceDir,Executable2, + [default,"hello world","dlrow olleh"]), [ExactFile3,"hello world","dlrow olleh"] = - run_echo_args_2("\""++ExactFile3++"\" "++"\"hello world\" \"dlrow olleh\""), + run_echo_args_2("\""++ExactFile3++"\" "++"\"hello world\" \"dlrow olleh\""), [ExactFile3,"hello world","dlrow olleh"] = - run_echo_args_2(unicode:characters_to_binary("\""++ExactFile3++"\" "++"\"hello world\" \"dlrow olleh\"")), + run_echo_args_2(unicode:characters_to_binary("\""++ExactFile3++"\" "++"\"hello world\" \"dlrow olleh\"")), {'EXIT',{enoent,_}} = (catch run_echo_args(SpaceDir,"fnurflmonfi", - [default,"hello world", - "dlrow olleh"])), + [default,"hello world", + "dlrow olleh"])), NonExec = "kronxfrt"++ExeExt, file:write_file(filename:join([SpaceDir,NonExec]), - <<"Not an executable">>), + <<"Not an executable">>), {'EXIT',{eacces,_}} = (catch run_echo_args(SpaceDir,NonExec, - [default,"hello world", - "dlrow olleh"])), + [default,"hello world", + "dlrow olleh"])), {'EXIT',{enoent,_}} = (catch open_port({spawn_executable,"cmd"},[])), {'EXIT',{enoent,_}} = (catch open_port({spawn_executable,"sh"},[])), case os:type() of - {win32,_} -> - test_bat_file(SpaceDir); - {unix,_} -> - test_sh_file(SpaceDir) + {win32,_} -> + test_bat_file(SpaceDir); + {unix,_} -> + test_sh_file(SpaceDir) end, ok. @@ -1479,29 +1478,29 @@ test_bat_file(Dir) -> FN = "tf.bat", Full = filename:join([Dir,FN]), D = [<<"@echo off\r\n">>, - <<"echo argv[0]:^|%0^|\r\n">>, - <<"if \"%1\" == \"\" goto done\r\n">>, - <<"echo argv[1]:^|%1^|\r\n">>, - <<"if \"%2\" == \"\" goto done\r\n">>, - <<"echo argv[2]:^|%2^|\r\n">>, - <<"if \"%3\" == \"\" goto done\r\n">>, - <<"echo argv[3]:^|%3^|\r\n">>, - <<"if \"%4\" == \"\" goto done\r\n">>, - <<"echo argv[4]:^|%4^|\r\n">>, - <<"if \"%5\" == \"\" goto done\r\n">>, - <<"echo argv[5]:^|%5^|\r\n">>, - <<"\r\n">>, - <<":done\r\n">>, - <<"\r\n">>], + <<"echo argv[0]:^|%0^|\r\n">>, + <<"if \"%1\" == \"\" goto done\r\n">>, + <<"echo argv[1]:^|%1^|\r\n">>, + <<"if \"%2\" == \"\" goto done\r\n">>, + <<"echo argv[2]:^|%2^|\r\n">>, + <<"if \"%3\" == \"\" goto done\r\n">>, + <<"echo argv[3]:^|%3^|\r\n">>, + <<"if \"%4\" == \"\" goto done\r\n">>, + <<"echo argv[4]:^|%4^|\r\n">>, + <<"if \"%5\" == \"\" goto done\r\n">>, + <<"echo argv[5]:^|%5^|\r\n">>, + <<"\r\n">>, + <<":done\r\n">>, + <<"\r\n">>], file:write_file(Full,list_to_binary(D)), EF = filename:basename(FN), [DN,"hello","world"] = - run_echo_args(Dir,FN, - [default,"hello","world"]), + run_echo_args(Dir,FN, + [default,"hello","world"]), %% The arg0 argumant should be ignored when running batch files [DN,"hello","world"] = - run_echo_args(Dir,FN, - ["knaskurt","hello","world"]), + run_echo_args(Dir,FN, + ["knaskurt","hello","world"]), EF = filename:basename(DN), ok. @@ -1509,40 +1508,40 @@ test_sh_file(Dir) -> FN = "tf.sh", Full = filename:join([Dir,FN]), D = [<<"#! /bin/sh\n">>, - <<"echo 'argv[0]:|'$0'|'\n">>, - <<"i=1\n">>, - <<"while [ '!' -z \"$1\" ]; do\n">>, - <<" echo 'argv['$i']:|'\"$1\"'|'\n">>, - <<" shift\n">>, - <<" i=`expr $i + 1`\n">>, - <<"done\n">>], + <<"echo 'argv[0]:|'$0'|'\n">>, + <<"i=1\n">>, + <<"while [ '!' -z \"$1\" ]; do\n">>, + <<" echo 'argv['$i']:|'\"$1\"'|'\n">>, + <<" shift\n">>, + <<" i=`expr $i + 1`\n">>, + <<"done\n">>], file:write_file(Full,list_to_binary(D)), chmodplusx(Full), [Full,"hello","world"] = - run_echo_args(Dir,FN, - [default,"hello","world"]), + run_echo_args(Dir,FN, + [default,"hello","world"]), [Full,"hello","world of spaces"] = - run_echo_args(Dir,FN, - [default,"hello","world of spaces"]), + run_echo_args(Dir,FN, + [default,"hello","world of spaces"]), file:write_file(filename:join([Dir,"testfile1"]),<<"testdata1">>), file:write_file(filename:join([Dir,"testfile2"]),<<"testdata2">>), Pattern = filename:join([Dir,"testfile*"]), L = filelib:wildcard(Pattern), 2 = length(L), [Full,"hello",Pattern] = - run_echo_args(Dir,FN, - [default,"hello",Pattern]), - ok. + run_echo_args(Dir,FN, + [default,"hello",Pattern]), + ok. + - chmodplusx(Filename) -> case file:read_file_info(Filename) of - {ok,FI} -> - FI2 = FI#file_info{mode = ((FI#file_info.mode) bor 8#00100)}, - file:write_file_info(Filename,FI2); - _ -> - ok + {ok,FI} -> + FI2 = FI#file_info{mode = ((FI#file_info.mode) bor 8#00100)}, + file:write_file_info(Filename,FI2); + _ -> + ok end. run_echo_args_2(FullnameAndArgs) -> @@ -1551,7 +1550,7 @@ run_echo_args_2(FullnameAndArgs) -> Port ! {self(), close}, receive {Port, closed} -> ok end, parse_echo_args_output(Data). - + run_echo_args(Where,Args) -> run_echo_args(Where,"echo_args",Args). @@ -1559,9 +1558,9 @@ run_echo_args(Where,Prog,Args) -> {Binary, ArgvArg} = pack_argv(Args), Command0 = filename:join([Where,Prog]), Command = case Binary of - true -> unicode:characters_to_binary(Command0); - false -> Command0 - end, + true -> unicode:characters_to_binary(Command0); + false -> Command0 + end, Port = open_port({spawn_executable,Command},ArgvArg++[eof]), Data = collect_data(Port), Port ! {self(), close}, @@ -1575,14 +1574,14 @@ pack_argv(Args) -> pack_argv(Args, Binary) -> case Args of - [] -> - []; - [default|T] -> - [{args,[make_bin(Arg,Binary) || Arg <- T]}]; - [switch_order,H|T] -> - [{args,[make_bin(Arg,Binary) || Arg <- T]},{arg0,make_bin(H,Binary)}]; - [H|T] -> - [{arg0,make_bin(H,Binary)},{args,[make_bin(Arg,Binary) || Arg <- T]}] + [] -> + []; + [default|T] -> + [{args,[make_bin(Arg,Binary) || Arg <- T]}]; + [switch_order,H|T] -> + [{args,[make_bin(Arg,Binary) || Arg <- T]},{arg0,make_bin(H,Binary)}]; + [H|T] -> + [{arg0,make_bin(H,Binary)},{args,[make_bin(Arg,Binary) || Arg <- T]}] end. make_bin(Str, false) -> Str; @@ -1590,10 +1589,10 @@ make_bin(Str, true) -> unicode:characters_to_binary(Str). collect_data(Port) -> receive - {Port, {data, Data}} -> - Data ++ collect_data(Port); - {Port, eof} -> - [] + {Port, {data, Data}} -> + Data ++ collect_data(Port); + {Port, eof} -> + [] end. parse_echo_args_output(Data) -> @@ -1606,33 +1605,33 @@ mix_up_ports(Config) when is_list(Config) -> Port = erlang:open_port({spawn, "echo_drv"}, []), Port ! {self(), {command, "Hello port!"}}, receive - {Port, {data, "Hello port!"}} = Msg1 -> - io:format("~p~n", [Msg1]), - ok; - Other -> - ct:fail({unexpected, Other}) - end, + {Port, {data, "Hello port!"}} = Msg1 -> + io:format("~p~n", [Msg1]), + ok; + Other -> + ct:fail({unexpected, Other}) + end, Port ! {self(), close}, receive {Port, closed} -> ok end, loop(start, done, - fun(P) -> - Q = - (catch erlang:open_port({spawn, "echo_drv"}, [])), -%% io:format("~p ", [Q]), - if is_port(Q) -> - Q; - true -> - io:format("~p~n", [P]), - done - end - end), + fun(P) -> + Q = + (catch erlang:open_port({spawn, "echo_drv"}, [])), + %% io:format("~p ", [Q]), + if is_port(Q) -> + Q; + true -> + io:format("~p~n", [P]), + done + end + end), Port ! {self(), {command, "Hello again port!"}}, receive - Msg2 -> - ct:fail({unexpected, Msg2}) - after 1000 -> - ok - end, + Msg2 -> + ct:fail({unexpected, Msg2}) + after 1000 -> + ok + end, ok. loop(Stop, Stop, Fun) when is_function(Fun) -> @@ -1653,7 +1652,7 @@ otp_5112(Config) when is_list(Config) -> io:format("Links1: ~p~n",[Links1]), true = lists:member(Port, Links1), Port ! {self(), {command, ""}}, - ?line wait_until(fun () -> lists:member(Port, erlang:ports()) == false end), + wait_until(fun () -> lists:member(Port, erlang:ports()) == false end), {links, Links2} = process_info(self(),links), io:format("Links2: ~p~n",[Links2]), false = lists:member(Port, Links2), %% This used to fail @@ -1662,27 +1661,27 @@ otp_5112(Config) when is_list(Config) -> otp_5112_get_wrapped_port() -> P1 = erlang:open_port({spawn, "exit_drv"}, []), case port_ix(P1) < max_ports() of - true -> - io:format("Need to wrap port index (~p)~n", [P1]), - otp_5112_wrap_port_ix([P1]), - P2 = erlang:open_port({spawn, "exit_drv"}, []), - false = port_ix(P2) < max_ports(), - P2; - false -> - io:format("Port index already wrapped (~p)~n", [P1]), - P1 - end. + true -> + io:format("Need to wrap port index (~p)~n", [P1]), + otp_5112_wrap_port_ix([P1]), + P2 = erlang:open_port({spawn, "exit_drv"}, []), + false = port_ix(P2) < max_ports(), + P2; + false -> + io:format("Port index already wrapped (~p)~n", [P1]), + P1 + end. otp_5112_wrap_port_ix(Ports) -> case (catch erlang:open_port({spawn, "exit_drv"}, [])) of - Port when is_port(Port) -> - otp_5112_wrap_port_ix([Port|Ports]); - _ -> - %% Port table now full; empty port table - lists:foreach(fun (P) -> P ! {self(), close} end, - Ports), - ok - end. + Port when is_port(Port) -> + otp_5112_wrap_port_ix([Port|Ports]); + _ -> + %% Port table now full; empty port table + lists:foreach(fun (P) -> P ! {self(), close} end, + Ports), + ok + end. %% Test that port index is not unnecessarily wrapped @@ -1693,12 +1692,12 @@ otp_5119(Config) when is_list(Config) -> Port2 = erlang:open_port({spawn, "exit_drv"}, []), PI2 = port_ix(Port2), {PortIx1, PortIx2} = case PI2 > PI1 of - true -> - {PI1, PI2}; - false -> - {port_ix(otp_5119_fill_empty_port_tab([Port2])), - port_ix(erlang:open_port({spawn, "exit_drv"}, []))} - end, + true -> + {PI1, PI2}; + false -> + {port_ix(otp_5119_fill_empty_port_tab([Port2])), + port_ix(erlang:open_port({spawn, "exit_drv"}, []))} + end, MaxPorts = max_ports(), io:format("PortIx1 = ~p ~p~n", [PI1, PortIx1]), io:format("PortIx2 = ~p ~p~n", [PI2, PortIx2]), @@ -1709,22 +1708,22 @@ otp_5119(Config) when is_list(Config) -> otp_5119_fill_empty_port_tab(Ports) -> case (catch erlang:open_port({spawn, "exit_drv"}, [])) of - Port when is_port(Port) -> - otp_5119_fill_empty_port_tab([Port|Ports]); - _ -> - %% Port table now full; empty port table - lists:foreach(fun (P) -> P ! {self(), close} end, - Ports), - [LastPort|_] = Ports, - LastPort - end. + Port when is_port(Port) -> + otp_5119_fill_empty_port_tab([Port|Ports]); + _ -> + %% Port table now full; empty port table + lists:foreach(fun (P) -> P ! {self(), close} end, + Ports), + [LastPort|_] = Ports, + LastPort + end. max_ports() -> erlang:system_info(port_limit). port_ix(Port) when is_port(Port) -> ["#Port",_,PortIxStr] = string:tokens(erlang:port_to_list(Port), - "<.>"), + "<.>"), list_to_integer(PortIxStr). @@ -1734,25 +1733,25 @@ otp_6224(Config) when is_list(Config) -> ok = load_driver(Path, "failure_drv"), Go = make_ref(), Failer = spawn(fun () -> - receive Go -> ok end, - Port = open_port({spawn, "failure_drv"}, - []), - Port ! {self(), {command, "Fail, please!"}}, - otp_6224_loop() - end), + receive Go -> ok end, + Port = open_port({spawn, "failure_drv"}, + []), + Port ! {self(), {command, "Fail, please!"}}, + otp_6224_loop() + end), Mon = erlang:monitor(process, Failer), Failer ! Go, receive - {'DOWN', Mon, process, Failer, Reason} -> - case Reason of - {driver_failed, _} -> ok; - driver_failed -> ok; - _ -> ct:fail({unexpected_exit_reason, - Reason}) - end - end, + {'DOWN', Mon, process, Failer, Reason} -> + case Reason of + {driver_failed, _} -> ok; + driver_failed -> ok; + _ -> ct:fail({unexpected_exit_reason, + Reason}) + end + end, ok. - + otp_6224_loop() -> receive _ -> ok after 0 -> ok end, otp_6224_loop(). @@ -1764,23 +1763,23 @@ otp_6224_loop() -> exit_status_multi_scheduling_block(Config) when is_list(Config) -> Repeat = 3, case test_server:os_type() of - {unix, _} -> - ct:timetrap({minutes, 2*Repeat}), - SleepSecs = 6, - try - lists:foreach(fun (_) -> - exit_status_msb_test(Config, - SleepSecs) - end, - lists:seq(1, Repeat)) - after - %% Wait for the system to recover (regardless - %% of success or not) otherwise later testcases - %% may unnecessarily fail. - receive after SleepSecs+500 -> ok end - end; - _ -> {skip, "Not implemented for this OS"} - end. + {unix, _} -> + ct:timetrap({minutes, 2*Repeat}), + SleepSecs = 6, + try + lists:foreach(fun (_) -> + exit_status_msb_test(Config, + SleepSecs) + end, + lists:seq(1, Repeat)) + after + %% Wait for the system to recover (regardless + %% of success or not) otherwise later testcases + %% may unnecessarily fail. + receive after SleepSecs+500 -> ok end + end; + _ -> {skip, "Not implemented for this OS"} + end. exit_status_msb_test(Config, SleepSecs) when is_list(Config) -> %% @@ -1794,74 +1793,74 @@ exit_status_msb_test(Config, SleepSecs) when is_list(Config) -> PortProg = "sleep " ++ integer_to_list(SleepSecs), Start = erlang:monotonic_time(micro_seconds), NoProcs = case NoSchedsOnln of - NProcs when NProcs < ?EXIT_STATUS_MSB_MAX_PROCS -> - NProcs; - _ -> - ?EXIT_STATUS_MSB_MAX_PROCS - end, + NProcs when NProcs < ?EXIT_STATUS_MSB_MAX_PROCS -> + NProcs; + _ -> + ?EXIT_STATUS_MSB_MAX_PROCS + end, NoPortsPerProc = case 20*NoProcs of - TNPorts when TNPorts < ?EXIT_STATUS_MSB_MAX_PORTS -> 20; - _ -> ?EXIT_STATUS_MSB_MAX_PORTS div NoProcs - end, + TNPorts when TNPorts < ?EXIT_STATUS_MSB_MAX_PORTS -> 20; + _ -> ?EXIT_STATUS_MSB_MAX_PORTS div NoProcs + end, io:format("NoProcs = ~p~nNoPortsPerProc = ~p~n", - [NoProcs, NoPortsPerProc]), + [NoProcs, NoPortsPerProc]), ProcFun - = fun () -> - PrtSIds = lists:map( - fun (_) -> - erlang:yield(), - case catch open_port({spawn, PortProg}, - [exit_status]) of - Prt when is_port(Prt) -> - {Prt, - erlang:system_info(scheduler_id)}; - {'EXIT', {Err, _}} when Err == eagain; - Err == emfile; - Err == enomem -> - noop; - {'EXIT', Err} when Err == eagain; - Err == emfile; - Err == enomem -> - noop; - Error -> - ct:fail(Error) - end - end, - lists:seq(1, NoPortsPerProc)), - SIds = lists:filter(fun (noop) -> false; - (_) -> true - end, - lists:map(fun (noop) -> noop; - ({_, SId}) -> SId - end, - PrtSIds)), - process_flag(scheduler, 0), - Parent ! {self(), started, SIds}, - lists:foreach( - fun (noop) -> - noop; - ({Port, _}) -> - receive - {Port, {exit_status, 0}} -> - ok; - {Port, {exit_status, Status}} when Status > 128 -> - %% Sometimes happens when we have created - %% too many ports. - ok; - {Port, {exit_status, _}} = ESMsg -> - {Port, {exit_status, 0}} = ESMsg - end - end, - PrtSIds), - Parent ! {self(), done} - end, - Procs = lists:map(fun (N) -> - spawn_opt(ProcFun, - [link, - {scheduler, - (N rem NoSchedsOnln)+1}]) + = fun () -> + PrtSIds = lists:map( + fun (_) -> + erlang:yield(), + case catch open_port({spawn, PortProg}, + [exit_status]) of + Prt when is_port(Prt) -> + {Prt, + erlang:system_info(scheduler_id)}; + {'EXIT', {Err, _}} when Err == eagain; + Err == emfile; + Err == enomem -> + noop; + {'EXIT', Err} when Err == eagain; + Err == emfile; + Err == enomem -> + noop; + Error -> + ct:fail(Error) + end end, - lists:seq(1, NoProcs)), + lists:seq(1, NoPortsPerProc)), + SIds = lists:filter(fun (noop) -> false; + (_) -> true + end, + lists:map(fun (noop) -> noop; + ({_, SId}) -> SId + end, + PrtSIds)), + process_flag(scheduler, 0), + Parent ! {self(), started, SIds}, + lists:foreach( + fun (noop) -> + noop; + ({Port, _}) -> + receive + {Port, {exit_status, 0}} -> + ok; + {Port, {exit_status, Status}} when Status > 128 -> + %% Sometimes happens when we have created + %% too many ports. + ok; + {Port, {exit_status, _}} = ESMsg -> + {Port, {exit_status, 0}} = ESMsg + end + end, + PrtSIds), + Parent ! {self(), done} + end, + Procs = lists:map(fun (N) -> + spawn_opt(ProcFun, + [link, + {scheduler, + (N rem NoSchedsOnln)+1}]) + end, + lists:seq(1, NoProcs)), SIds = lists:map(fun (P) -> receive {P, started, SIds} -> SIds end end, @@ -1877,27 +1876,27 @@ exit_status_msb_test(Config, SleepSecs) when is_list(Config) -> ok = verify_multi_scheduling_blocked(), erlang:system_flag(multi_scheduling, unblock), case {length(lists:usort(lists:flatten(SIds))), NoSchedsOnln} of - {N, N} -> - ok; - {N, M} -> - ct:fail("Failed to create ports on all ~w available" - "schedulers. Only created ports on ~w schedulers.", [M, N]) - end. + {N, N} -> + ok; + {N, M} -> + ct:fail("Failed to create ports on all ~w available" + "schedulers. Only created ports on ~w schedulers.", [M, N]) + end. save_sid(SIds) -> SId = erlang:system_info(scheduler_id), case lists:member(SId, SIds) of - true -> SIds; - false -> [SId|SIds] + true -> SIds; + false -> [SId|SIds] end. sid_proc(SIds) -> NewSIds = save_sid(SIds), receive - {From, want_sids} -> - From ! {self(), sids, NewSIds} + {From, want_sids} -> + From ! {self(), sids, NewSIds} after 0 -> - sid_proc(NewSIds) + sid_proc(NewSIds) end. verify_multi_scheduling_blocked() -> @@ -1913,8 +1912,8 @@ verify_multi_scheduling_blocked() -> Procs), 1 = length(lists:usort(lists:flatten(SIds))), ok. - - + + %%% Pinging functions. stream_ping(Config, Size, CmdLine, Options) -> @@ -1923,10 +1922,10 @@ stream_ping(Config, Size, CmdLine, Options) -> ping(Config, Sizes, HSize, CmdLine, Options) -> Actions = lists:map(fun(Size) -> - [$p|Packet] = random_packet(Size, "ping"), - {[$p|Packet], [[$P|Packet]]} - end, - Sizes), + [$p|Packet] = random_packet(Size, "ping"), + {[$p|Packet], [[$P|Packet]]} + end, + Sizes), port_expect(Config, Actions, HSize, CmdLine, Options). %% expect_input(Sizes, HSize, CmdLine, Options) @@ -1948,7 +1947,7 @@ expect_input1(Config, [Size|Rest], Params, Expect, ReplyCommand) -> expect_input1(Config, [], {HSize, CmdLine0, Options}, Expect, ReplyCommand) -> CmdLine = build_cmd_line(CmdLine0, ReplyCommand, []), port_expect(Config, [{false, lists:reverse(Expect)}], - HSize, CmdLine, Options). + HSize, CmdLine, Options). build_cmd_line(FixedCmdLine, [Cmd|Rest], []) -> build_cmd_line(FixedCmdLine, Rest, [Cmd]); @@ -1971,15 +1970,15 @@ build_cmd_line(FixedCmdLine, [], Result) -> %% Returns the port. port_expect(Config, Actions, HSize, CmdLine, Options0) -> -% io:format("port_expect(~p, ~p, ~p, ~p)", -% [Actions, HSize, CmdLine, Options0]), + % io:format("port_expect(~p, ~p, ~p, ~p)", + % [Actions, HSize, CmdLine, Options0]), PortTest = port_test(Config), Cmd = lists:concat([PortTest, " -h", HSize, " ", CmdLine]), PortType = - case HSize of - 0 -> stream; - _ -> {packet, HSize} - end, + case HSize of + 0 -> stream; + _ -> {packet, HSize} + end, Options = [PortType|Options0], io:format("open_port({spawn, ~p}, ~p)", [Cmd, Options]), Port = open_port({spawn, Cmd}, Options), @@ -1990,11 +1989,11 @@ port_expect(Port, [{Send, Expects}|Rest], Options) when is_list(Expects) -> port_send(Port, Send), IsBinaryPort = lists:member(binary, Options), Receiver = - case {lists:member(stream, Options), line_option(Options)} of - {false, _} -> fun receive_all/2; - {true,false} -> fun stream_receive_all/2; - {_, true} -> fun receive_all/2 - end, + case {lists:member(stream, Options), line_option(Options)} of + {false, _} -> fun receive_all/2; + {true,false} -> fun stream_receive_all/2; + {_, true} -> fun receive_all/2 + end, Receiver(Port, maybe_to_binary(Expects, IsBinaryPort)), port_expect(Port, Rest, Options); port_expect(_, [], _) -> @@ -2022,34 +2021,34 @@ maybe_to_binary(Expects, false) -> port_send(_Port, false) -> ok; port_send(Port, Send) when is_list(Send) -> -% io:format("port_send(~p, ~p)", [Port, Send]), + % io:format("port_send(~p, ~p)", [Port, Send]), Port ! {self(), {command, Send}}. receive_all(Port, [Expect|Rest]) -> -% io:format("receive_all(~p, [~p|Rest])", [Port, Expect]), + % io:format("receive_all(~p, [~p|Rest])", [Port, Expect]), receive - {Port, {data, Expect}} -> - io:format("Received ~s", [format(Expect)]), - ok; - {Port, {data, Other}} -> - io:format("Received ~s; expected ~s", - [format(Other), format(Expect)]), - ct:fail(bad_message); - Other -> - %% (We're not yet prepared for receiving both 'eol' and - %% 'exit_status'; remember that they may appear in any order.) - case {Expect, Rest, Other} of - {eof, [], {Port, eof}} -> - io:format("Received soft EOF.",[]), - ok; - {{exit_status, S}, [], {Port, {exit_status, S}}} -> - io:format("Received exit status ~p.",[S]), - ok; - _ -> -%%% io:format("Unexpected message: ~s", [format(Other)]), - io:format("Unexpected message: ~w", [Other]), - ct:fail(unexpected_message) - end + {Port, {data, Expect}} -> + io:format("Received ~s", [format(Expect)]), + ok; + {Port, {data, Other}} -> + io:format("Received ~s; expected ~s", + [format(Other), format(Expect)]), + ct:fail(bad_message); + Other -> + %% (We're not yet prepared for receiving both 'eol' and + %% 'exit_status'; remember that they may appear in any order.) + case {Expect, Rest, Other} of + {eof, [], {Port, eof}} -> + io:format("Received soft EOF.",[]), + ok; + {{exit_status, S}, [], {Port, {exit_status, S}}} -> + io:format("Received exit status ~p.",[S]), + ok; + _ -> + %%% io:format("Unexpected message: ~s", [format(Other)]), + io:format("Unexpected message: ~w", [Other]), + ct:fail(unexpected_message) + end end, receive_all(Port, Rest); receive_all(_Port, []) -> @@ -2064,19 +2063,19 @@ stream_receive_all1(_Port, []) -> ok; stream_receive_all1(Port, Expect) -> receive - {Port, {data, Data}} -> - Remaining = compare(Data, Expect), - stream_receive_all1(Port, Remaining); - Other -> - ct:fail({bad_message, Other}) + {Port, {data, Data}} -> + Remaining = compare(Data, Expect), + stream_receive_all1(Port, Remaining); + Other -> + ct:fail({bad_message, Other}) end. compare(B1, B2) when is_binary(B1), is_binary(B2), byte_size(B1) =< byte_size(B2) -> case split_binary(B2, size(B1)) of - {B1,Remaining} -> - Remaining; - _Other -> - ct:fail(nomatch) + {B1,Remaining} -> + Remaining; + _Other -> + ct:fail(nomatch) end; compare(B1, B2) when is_binary(B1), is_binary(B2) -> ct:fail(too_much_data); @@ -2098,10 +2097,10 @@ format({Eol,List}) -> io_lib:format("tuple<~w,~s>",[Eol, maybe_to_list(List)]); format(List) when is_list(List) -> case list_at_least(50, List) of - true -> - io_lib:format("\"~-50s...\"", [List]); - false -> - io_lib:format("~p", [List]) + true -> + io_lib:format("\"~-50s...\"", [List]); + false -> + io_lib:format("~p", [List]) end; format(Bin) when is_binary(Bin), size(Bin) >= 50 -> io_lib:format("binary<~-50s...>", [binary_to_list(Bin, 1, 50)]); @@ -2128,17 +2127,17 @@ build_packet(0, Result, _NextChar) -> lists:reverse(Result); build_packet(Left, Result, NextChar0) -> NextChar = - if - NextChar0 >= 126 -> - 33; - true -> - NextChar0+1 - end, + if + NextChar0 >= 126 -> + 33; + true -> + NextChar0+1 + end, build_packet(Left-1, [NextChar0|Result], NextChar). sizes() -> [10, 13, 64, 127, 128, 255, 256, 1023, 1024, - 32767, 32768, 65535, 65536]. + 32767, 32768, 65535, 65536]. sizes(Header_Size) -> sizes(Header_Size, sizes(), []). @@ -2160,11 +2159,11 @@ random_char(Chars) -> uniform(N) -> case rand:export_seed() of - undefined -> - rand:seed(exsplus), - io:format("Random seed = ~p\n", [rand:export_seed()]); - _ -> - ok + undefined -> + rand:seed(exsplus), + io:format("Random seed = ~p\n", [rand:export_seed()]); + _ -> + ok end, rand:uniform(N). @@ -2206,7 +2205,7 @@ ports_snapshots(Iter, TrafficPid, OtherPorts) -> TrafficPid ! {self(), stop}, receive {TrafficPid, EventList, TrafficPorts} -> ok end, - + %%io:format("Snapshot=~p\n", [Snapshot]), ports_verify(Snapshot, OtherPorts ++ TrafficPorts, EventList), @@ -2218,69 +2217,69 @@ ports_traffic(MaxPorts) -> ports_traffic_stopped(MaxPorts, {PortList, PortCnt}) -> receive - start -> - %%io:format("Traffic started in ~p\n",[self()]), - ports_traffic_started(MaxPorts, {PortList, PortCnt}, []); - {Pid,die} -> - lists:foreach(fun(Port)-> erlang:port_close(Port) end, - PortList), - Pid ! {self(),dead} + start -> + %%io:format("Traffic started in ~p\n",[self()]), + ports_traffic_started(MaxPorts, {PortList, PortCnt}, []); + {Pid,die} -> + lists:foreach(fun(Port)-> erlang:port_close(Port) end, + PortList), + Pid ! {self(),dead} end. ports_traffic_started(MaxPorts, {PortList, PortCnt}, EventList) -> receive - {Pid, stop} -> - %%io:format("Traffic stopped in ~p\n",[self()]), - Pid ! {self(), EventList, PortList}, - ports_traffic_stopped(MaxPorts, {PortList, PortCnt}) + {Pid, stop} -> + %%io:format("Traffic stopped in ~p\n",[self()]), + Pid ! {self(), EventList, PortList}, + ports_traffic_stopped(MaxPorts, {PortList, PortCnt}) after 0 -> - ports_traffic_do(MaxPorts, {PortList, PortCnt}, EventList) + ports_traffic_do(MaxPorts, {PortList, PortCnt}, EventList) end. ports_traffic_do(MaxPorts, {PortList, PortCnt}, EventList) -> N = uniform(MaxPorts), case N > PortCnt of - true -> % Open port - P = open_port({spawn, "exit_drv"}, []), - %%io:format("Created port ~p\n",[P]), - ports_traffic_started(MaxPorts, {[P|PortList], PortCnt+1}, - [{open,P}|EventList]); - - false -> % Close port - P = lists:nth(N, PortList), - %%io:format("Close port ~p\n",[P]), - true = erlang:port_close(P), - ports_traffic_started(MaxPorts, {lists:delete(P,PortList), PortCnt-1}, - [{close,P}|EventList]) + true -> % Open port + P = open_port({spawn, "exit_drv"}, []), + %%io:format("Created port ~p\n",[P]), + ports_traffic_started(MaxPorts, {[P|PortList], PortCnt+1}, + [{open,P}|EventList]); + + false -> % Close port + P = lists:nth(N, PortList), + %%io:format("Close port ~p\n",[P]), + true = erlang:port_close(P), + ports_traffic_started(MaxPorts, {lists:delete(P,PortList), PortCnt-1}, + [{close,P}|EventList]) end. ports_verify(Ports, PortsAfter, EventList) -> %%io:format("Candidate=~p\nEvents=~p\n", [PortsAfter, EventList]), case lists:sort(Ports) =:= lists:sort(PortsAfter) of - true -> - io:format("Snapshot of ~p ports verified ok.\n",[length(Ports)]), - ok; - false -> - %% Note that we track the event list "backwards", undoing open/close: - case EventList of - [{open,P} | Tail] -> - ports_verify(Ports, lists:delete(P,PortsAfter), Tail); - - [{close,P} | Tail] -> - ports_verify(Ports, [P | PortsAfter], Tail); - - [] -> - ct:fail("Inconsistent snapshot from erlang:ports()") - end + true -> + io:format("Snapshot of ~p ports verified ok.\n",[length(Ports)]), + ok; + false -> + %% Note that we track the event list "backwards", undoing open/close: + case EventList of + [{open,P} | Tail] -> + ports_verify(Ports, lists:delete(P,PortsAfter), Tail); + + [{close,P} | Tail] -> + ports_verify(Ports, [P | PortsAfter], Tail); + + [] -> + ct:fail("Inconsistent snapshot from erlang:ports()") + end end. load_driver(Dir, Driver) -> case erl_ddll:load_driver(Dir, Driver) of - ok -> ok; - {error, Error} = Res -> - io:format("~s\n", [erl_ddll:format_error(Error)]), - Res + ok -> ok; + {error, Error} = Res -> + io:format("~s\n", [erl_ddll:format_error(Error)]), + Res end. @@ -2304,13 +2303,13 @@ close_deaf_port_1(200, _) -> close_deaf_port_1(N, Cmd) -> Timeout = integer_to_list(rand:uniform(5*1000)), try open_port({spawn_executable,Cmd},[{args,[Timeout]}]) of - Port -> - erlang:port_command(Port,"Hello, can you hear me!?!?"), - port_close(Port), - close_deaf_port_1(N+1, Cmd) + Port -> + erlang:port_command(Port,"Hello, can you hear me!?!?"), + port_close(Port), + close_deaf_port_1(N+1, Cmd) catch - _:eagain -> - {comment, "Could not spawn more than " ++ integer_to_list(N) ++ " OS processes."} + _:eagain -> + {comment, "Could not spawn more than " ++ integer_to_list(N) ++ " OS processes."} end. %% Test undocumented port_set_data/2 and port_get_data/1 @@ -2322,57 +2321,57 @@ port_setget_data(Config) when is_list(Config) -> NSched = erlang:system_info(schedulers_online), HeapData = {1,2,3,<<"A heap binary">>,fun()->"This is fun"end, - list_to_binary(lists:seq(1,100))}, + list_to_binary(lists:seq(1,100))}, PRs = lists:map(fun(I) -> - spawn_opt(fun() -> port_setget_data_hammer(Port,HeapData,false,1) end, - [monitor, {scheduler, I rem NSched}]) - end, - lists:seq(1,10)), + spawn_opt(fun() -> port_setget_data_hammer(Port,HeapData,false,1) end, + [monitor, {scheduler, I rem NSched}]) + end, + lists:seq(1,10)), receive after 100 -> ok end, Papa = self(), lists:foreach(fun({Pid,_}) -> Pid ! {Papa,prepare_for_close} end, PRs), lists:foreach(fun({Pid,_}) -> - receive {Pid,prepare_for_close} -> ok end - end, - PRs), + receive {Pid,prepare_for_close} -> ok end + end, + PRs), port_close(Port), lists:foreach(fun({Pid,Ref}) -> - receive {'DOWN', Ref, process, Pid, normal} -> ok end - end, - PRs), + receive {'DOWN', Ref, process, Pid, normal} -> ok end + end, + PRs), ok. port_setget_data_hammer(Port, HeapData, IsSet0, N) -> Rand = rand:uniform(3), IsSet1 = try case Rand of - 1 -> true = erlang:port_set_data(Port, atom), true; - 2 -> true = erlang:port_set_data(Port, HeapData), true; - 3 -> case erlang:port_get_data(Port) of - atom -> true; - HeapData -> true; - undefined -> false=IsSet0 - end - end - catch - error:badarg -> - true = get(prepare_for_close), - io:format("~p did ~p rounds before port closed\n", [self(), N]), - exit(normal) - end, + 1 -> true = erlang:port_set_data(Port, atom), true; + 2 -> true = erlang:port_set_data(Port, HeapData), true; + 3 -> case erlang:port_get_data(Port) of + atom -> true; + HeapData -> true; + undefined -> false=IsSet0 + end + end + catch + error:badarg -> + true = get(prepare_for_close), + io:format("~p did ~p rounds before port closed\n", [self(), N]), + exit(normal) + end, receive {Papa, prepare_for_close} -> - put(prepare_for_close, true), - Papa ! {self(),prepare_for_close} + put(prepare_for_close, true), + Papa ! {self(),prepare_for_close} after 0 -> - ok + ok end, port_setget_data_hammer(Port, HeapData, IsSet1, N+1). wait_until(Fun) -> case catch Fun() of - true -> - ok; - _ -> - receive after 100 -> ok end, - wait_until(Fun) + true -> + ok; + _ -> + receive after 100 -> ok end, + wait_until(Fun) end. |