From 851f61719985651e769f8df8246d5ddb855cc022 Mon Sep 17 00:00:00 2001 From: Aleksandr Vinokurov Date: Thu, 8 Nov 2012 13:59:12 +0400 Subject: Fix deep list argument error under Windows in os:cmd/1 Because of leeway in implementing os:cmd/1 under different OS there is a difference in results when calling it with deep list argument. os:cmd/1 specifies io_lib:chars() type for its argument and io_lib functions can produce deep lists inspite of io_lib:chars() result type specification. This commit flattens the argument for erlang:open_port/2 (which is used under Windows) and expands the os_SUITE to regress the bug. --- lib/kernel/src/os.erl | 5 ++++- lib/kernel/test/os_SUITE.erl | 17 ++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/os.erl b/lib/kernel/src/os.erl index 742c000cc1..2bded77fc4 100644 --- a/lib/kernel/src/os.erl +++ b/lib/kernel/src/os.erl @@ -187,11 +187,14 @@ cmd(Cmd) -> {unix, _} -> unix_cmd(Cmd); {win32, Wtype} -> - Command = case {os:getenv("COMSPEC"),Wtype} of + Command0 = case {os:getenv("COMSPEC"),Wtype} of {false,windows} -> lists:concat(["command.com /c", Cmd]); {false,_} -> lists:concat(["cmd /c", Cmd]); {Cspec,_} -> lists:concat([Cspec," /c",Cmd]) end, + %% open_port/2 awaits string() in Command, but io_lib:chars() can be + %% deep lists according to io_lib module description. + Command = lists:flatten(Command0), Port = open_port({spawn, Command}, [stream, in, eof, hide]), get_data(Port, []) end. diff --git a/lib/kernel/test/os_SUITE.erl b/lib/kernel/test/os_SUITE.erl index 382fd6f6a9..e302bf7378 100644 --- a/lib/kernel/test/os_SUITE.erl +++ b/lib/kernel/test/os_SUITE.erl @@ -29,7 +29,8 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [space_in_cwd, quoting, space_in_name, bad_command, - find_executable, unix_comment_in_command, evil]. + find_executable, unix_comment_in_command, deep_list_command, + evil]. groups() -> []. @@ -237,6 +238,20 @@ unix_comment_in_command(Config) when is_list(Config) -> ?line test_server:timetrap_cancel(Dog), ok. +deep_list_command(doc) -> + "Check that a deep list in command works equally on unix and on windows."; +deep_list_command(suite) -> []; +deep_list_command(Config) when is_list(Config) -> + %% As a 'io_lib' module description says: "There is no guarantee that the + %% character lists returned from some of the functions are flat, they can + %% be deep lists." + %% That's why os:cmd/1 can have arguments that are deep lists. + %% It is not a problem for unix, but for windows it is (in R15B02 for ex.). + ?line os:cmd([$e, $c, "ho"]), + %% FYI: [$e, $c, "ho"] =:= io_lib:format("ec~s", ["ho"]) + ok. + + -define(EVIL_PROCS, 100). -define(EVIL_LOOPS, 100). -define(PORT_CREATOR, os_cmd_port_creator). -- cgit v1.2.3 From 2fe1d3ca9caabda3abf3d1cf438d3159999a06eb Mon Sep 17 00:00:00 2001 From: Aleksandr Vinokurov Date: Thu, 8 Nov 2012 14:01:40 +0400 Subject: Remove unnecessary whitespaces in os.erl and os_SUITE.erl Conflicts: lib/kernel/test/os_SUITE.erl --- lib/kernel/src/os.erl | 18 +++++++++--------- lib/kernel/test/os_SUITE.erl | 25 ++++++++++++------------- 2 files changed, 21 insertions(+), 22 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/os.erl b/lib/kernel/src/os.erl index 2bded77fc4..ded03361ee 100644 --- a/lib/kernel/src/os.erl +++ b/lib/kernel/src/os.erl @@ -126,7 +126,7 @@ verify_executable(Name0, [Ext|Rest], OrigExtensions) -> end; verify_executable(Name, [], OrigExtensions) when OrigExtensions =/= [""] -> %% Windows %% Will only happen on windows, hence case insensitivity - case can_be_full_name(string:to_lower(Name),OrigExtensions) of + case can_be_full_name(string:to_lower(Name),OrigExtensions) of true -> verify_executable(Name,[""],[""]); _ -> @@ -150,7 +150,7 @@ split_path(Path) -> {win32, _} -> {ok,Curr} = file:get_cwd(), split_path(Path, $;, [], [Curr]); - _ -> + _ -> split_path(Path, $:, [], []) end. @@ -216,7 +216,7 @@ unix_cmd(Cmd) -> end. %% The -s flag implies that only the positional parameters are set, -%% and the commands are read from standard input. We set the +%% and the commands are read from standard input. We set the %% $1 parameter for easy identification of the resident shell. %% -define(SHELL, "/bin/sh -s unix:cmd 2>&1"). @@ -229,7 +229,7 @@ unix_cmd(Cmd) -> -spec start_port() -> port(). start_port() -> Ref = make_ref(), - Request = {Ref,self()}, + Request = {Ref,self()}, {Pid, Mon} = case whereis(?PORT_CREATOR_NAME) of undefined -> spawn_monitor(fun() -> @@ -276,7 +276,7 @@ start_port_srv_handle({Ref,Client}) -> Port catch error:Reason -> - {Reason,erlang:get_stacktrace()} + {Reason,erlang:get_stacktrace()} end, Client ! {Ref,Reply}. @@ -358,16 +358,16 @@ get_data(Port, Sofar) -> {Port, {data, Bytes}} -> get_data(Port, [Sofar|Bytes]); {Port, eof} -> - Port ! {self(), close}, + Port ! {self(), close}, receive {Port, closed} -> true - end, + end, receive - {'EXIT', Port, _} -> + {'EXIT', Port, _} -> ok after 1 -> % force context switch ok - end, + end, lists:flatten(Sofar) end. diff --git a/lib/kernel/test/os_SUITE.erl b/lib/kernel/test/os_SUITE.erl index e302bf7378..7dbaf2ca8a 100644 --- a/lib/kernel/test/os_SUITE.erl +++ b/lib/kernel/test/os_SUITE.erl @@ -18,7 +18,7 @@ %% -module(os_SUITE). --export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, +-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2]). -export([space_in_cwd/1, quoting/1, space_in_name/1, bad_command/1, find_executable/1, unix_comment_in_command/1, evil/1]). @@ -27,12 +27,12 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. -all() -> +all() -> [space_in_cwd, quoting, space_in_name, bad_command, find_executable, unix_comment_in_command, deep_list_command, evil]. -groups() -> +groups() -> []. init_per_suite(Config) -> @@ -118,9 +118,9 @@ space_in_name(Config) when is_list(Config) -> ?line ok = file:change_mode(Echo, 8#777), % Make it executable on Unix. %% Run the echo program. - %% Quoting on windows depends on if the full path of the executable + %% Quoting on windows depends on if the full path of the executable %% contains special characters. Paths when running common_tests always - %% include @, why Windows would always fail if we do not double the + %% include @, why Windows would always fail if we do not double the %% quotes (this is the behaviour of cmd.exe, not Erlang's idea). Quote = case os:type() of {win32,_} -> @@ -136,7 +136,7 @@ space_in_name(Config) when is_list(Config) -> ?t:sleep(5), ?line [] = receive_all(), ok. - + bad_command(doc) -> "Check that a bad command doesn't crasch the server or the emulator (it used to)."; bad_command(suite) -> []; @@ -154,17 +154,17 @@ find_executable(suite) -> []; find_executable(doc) -> []; find_executable(Config) when is_list(Config) -> case os:type() of - {win32, _} -> + {win32, _} -> ?line DataDir = filename:join(?config(data_dir, Config), "win32"), ?line ok = file:set_cwd(filename:join([DataDir, "current"])), ?line Bin = filename:join(DataDir, "bin"), ?line Abin = filename:join(DataDir, "abin"), ?line UsrBin = filename:join([DataDir, "usr", "bin"]), ?line {ok, Current} = file:get_cwd(), - + ?line Path = lists:concat([Bin, ";", Abin, ";", UsrBin]), ?line io:format("Path = ~s", [Path]), - + %% Search for programs in Bin (second element in PATH). ?line find_exe(Abin, "my_ar", ".exe", Path), ?line find_exe(Abin, "my_ascii", ".com", Path), @@ -176,18 +176,18 @@ find_executable(Config) when is_list(Config) -> ?line find_exe(Abin, "my_ar.EXE", "", Path), ?line find_exe(Abin, "my_ascii.COM", "", Path), ?line find_exe(Abin, "MY_ADB.BAT", "", Path), - + %% Search for programs in Abin (second element in PATH). ?line find_exe(Abin, "my_ar", ".exe", Path), ?line find_exe(Abin, "my_ascii", ".com", Path), ?line find_exe(Abin, "my_adb", ".bat", Path), - + %% Search for programs in the current working directory. ?line find_exe(Current, "my_program", ".exe", Path), ?line find_exe(Current, "my_command", ".com", Path), ?line find_exe(Current, "my_batch", ".bat", Path), ok; - {unix, _} -> + {unix, _} -> DataDir = ?config(data_dir, Config), %% Smoke test. @@ -318,4 +318,3 @@ receive_all() -> X -> [X|receive_all()] after 0 -> [] end. - -- cgit v1.2.3 From 59affc4ef18fe00b2eecbc57905c581ddf7a9646 Mon Sep 17 00:00:00 2001 From: Fredrik Gustafsson Date: Tue, 30 Apr 2013 11:05:34 +0200 Subject: kernel: redefined deep_list_command test --- lib/kernel/test/os_SUITE.erl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/test/os_SUITE.erl b/lib/kernel/test/os_SUITE.erl index 7dbaf2ca8a..191d34686e 100644 --- a/lib/kernel/test/os_SUITE.erl +++ b/lib/kernel/test/os_SUITE.erl @@ -247,7 +247,8 @@ deep_list_command(Config) when is_list(Config) -> %% be deep lists." %% That's why os:cmd/1 can have arguments that are deep lists. %% It is not a problem for unix, but for windows it is (in R15B02 for ex.). - ?line os:cmd([$e, $c, "ho"]), + Echo = os:cmd([$e, $c, "ho"]), + true = erlang:is_list(Echo), %% FYI: [$e, $c, "ho"] =:= io_lib:format("ec~s", ["ho"]) ok. -- cgit v1.2.3 From 914cf9c1df6e36e2811e677ed69c86beeaae7a1b Mon Sep 17 00:00:00 2001 From: Fredrik Gustafsson Date: Thu, 2 May 2013 09:40:25 +0200 Subject: Add testcase to exported --- lib/kernel/test/os_SUITE.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/test/os_SUITE.erl b/lib/kernel/test/os_SUITE.erl index 191d34686e..73ed704ae3 100644 --- a/lib/kernel/test/os_SUITE.erl +++ b/lib/kernel/test/os_SUITE.erl @@ -21,7 +21,7 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2]). -export([space_in_cwd/1, quoting/1, space_in_name/1, bad_command/1, - find_executable/1, unix_comment_in_command/1, evil/1]). + find_executable/1, unix_comment_in_command/1, deep_list_command/1, evil/1]). -include_lib("test_server/include/test_server.hrl"). -- cgit v1.2.3