From 1f3ce8d2b9c07bee672efec9d6e3512633ffcf23 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Tue, 15 Jan 2013 10:48:04 +0100 Subject: Make arguments given with -s option to erl aware of file name encoding OTP-10702 Arguments to functions started with the -s option to erl were converted to atoms with list_to_atom(binary_to_list(Bin)) and thus were always seen as latin1 encoded. For other arguments to erl the conversion (to string) would take into account the file name translation mode (set with +fnl, +fnu or +fna switch to erl) and try to convert using unicode:characters_to_list/2. The reason behind this is that it must be possible to give paths and filenames on the command line and get the expected encoding. With the same reasoning, this commit changes the behaviour for arguments to functions started with the -s option to also take into account the file name translation mode. The arguments are now converted to atoms by list_to_atom(unicode:characters_to_list(Bin,file:native_name_encoding()) --- erts/preloaded/src/init.erl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/erts/preloaded/src/init.erl b/erts/preloaded/src/init.erl index 1d1087c7f2..61d8df2428 100644 --- a/erts/preloaded/src/init.erl +++ b/erts/preloaded/src/init.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2012. All Rights Reserved. +%% Copyright Ericsson AB 1996-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -184,12 +184,16 @@ prepare_run_args({run, [M,F|Args]}) -> [b2a(M), b2a(F) | bs2ss(Args)]. b2a(Bin) when is_binary(Bin) -> - list_to_atom(binary_to_list(Bin)); + list_to_atom(b2s(Bin)); b2a(A) when is_atom(A) -> A. b2s(Bin) when is_binary(Bin) -> - binary_to_list(Bin); + try + unicode:characters_to_list(Bin,file:native_name_encoding()) + catch + _:_ -> binary_to_list(Bin) + end; b2s(L) when is_list(L) -> L. @@ -1260,11 +1264,7 @@ get_arguments([]) -> []. to_strings([H|T]) when is_atom(H) -> [atom_to_list(H)|to_strings(T)]; -to_strings([H|T]) when is_binary(H) -> [try - unicode:characters_to_list(H,file:native_name_encoding()) - catch - _:_ -> binary_to_list(H) - end|to_strings(T)]; +to_strings([H|T]) when is_binary(H) -> [b2s(H)|to_strings(T)]; to_strings([]) -> []. get_argument(Arg,Flags) -> -- cgit v1.2.3 From 6025471459d7e80ab05118b9ec9f7cb0fe0668a1 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Tue, 15 Jan 2013 11:53:00 +0100 Subject: Update preloaded init.beam --- erts/preloaded/ebin/init.beam | Bin 48556 -> 48572 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/erts/preloaded/ebin/init.beam b/erts/preloaded/ebin/init.beam index 9710204552..2ac86aa67a 100644 Binary files a/erts/preloaded/ebin/init.beam and b/erts/preloaded/ebin/init.beam differ -- cgit v1.2.3 From e084233e56b43a47aa08cd3564124a25b8bfd2fb Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Tue, 15 Jan 2013 19:00:27 +0100 Subject: [test_server] Update test_server to handle unicode * Use UTF-8 encoding for all HTML files, except the HTML version of the test suite generated with erl2html2:convert, which will have the same encoding as the original test suite (.erl) file. * Encode link targets in HTML files, allowing both special characters like "/", "&", "?" etc, and latin1 or unicode characters. * Use unicode modifier 't' with ~s and ~p when appropriate. * Use unicode:characters_to_list and unicode:characters_to_binary for conversion between binaries and strings instead of binary_to_list and list_to_binary. --- lib/common_test/src/ct_logs.erl | 5 +- lib/test_server/src/test_server.erl | 82 ++--- lib/test_server/src/test_server_ctrl.erl | 572 ++++++++++++++++--------------- lib/test_server/src/test_server_gl.erl | 16 +- lib/test_server/src/test_server_h.erl | 6 +- lib/test_server/src/test_server_io.erl | 12 +- lib/test_server/src/test_server_node.erl | 14 +- lib/test_server/src/test_server_sup.erl | 35 +- 8 files changed, 384 insertions(+), 358 deletions(-) diff --git a/lib/common_test/src/ct_logs.erl b/lib/common_test/src/ct_logs.erl index 0b7a8bb075..ba678fd169 100644 --- a/lib/common_test/src/ct_logs.erl +++ b/lib/common_test/src/ct_logs.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2012. All Rights Reserved. +%% Copyright Ericsson AB 2003-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -1364,6 +1364,7 @@ header1(Title, SubTitle, TableCols) -> "\n", "" ++ Title ++ " " ++ SubTitle ++ "\n", "\n", + "\n", xhtml("", ["\n"]), xhtml("", @@ -2319,6 +2320,7 @@ get_ts_html_wrapper(TestName, PrintLabel, Cwd, TableCols) -> "\n", "", TestName1, "\n", "\n", + "\n", "\n", "\n", @@ -2363,6 +2365,7 @@ get_ts_html_wrapper(TestName, PrintLabel, Cwd, TableCols) -> "\n", "\n", TestName1, "\n", "\n", + "\n", "\n", "\n", "\n"] ++ diff --git a/lib/test_server/src/test_server.erl b/lib/test_server/src/test_server.erl index 37cd8fac99..43330d2c91 100644 --- a/lib/test_server/src/test_server.erl +++ b/lib/test_server/src/test_server.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2012. All Rights Reserved. +%% Copyright Ericsson AB 1996-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -123,7 +123,7 @@ cover_compile({App,all,Include,Cross}) -> io:format("\nWARNING: All modules in \'~w\' are excluded\n" "Only cover compiling modules in include list " "and the modules\nin the cross cover file:\n" - "~p\n", [App,CompileMods]), + "~tp\n", [App,CompileMods]), do_cover_compile(CompileMods), io:fwrite("done\n\n",[]), {ok,Include} @@ -143,7 +143,7 @@ cover_compile({App,Exclude,Include,Cross}) -> [App,length(CompileMods)]), io:format("\nWARNING: Can't find lib_dir for \'~w\'\n" "Only cover compiling modules in include list: " - "~p\n", [App,Include]), + "~tp\n", [App,Include]), do_cover_compile(CompileMods), io:fwrite("done\n\n",[]), {ok,Include} @@ -186,7 +186,7 @@ do_cover_compile1([M|Rest]) -> {ok,_} -> ok; Error -> - io:fwrite("\nWARNING: Could not cover compile ~w: ~p\n", + io:fwrite("\nWARNING: Could not cover compile ~w: ~tp\n", [M,Error]) end, code:stick_mod(M), @@ -196,7 +196,7 @@ do_cover_compile1([M|Rest]) -> {module,_} -> do_cover_compile1([M|Rest]); Error -> - io:fwrite("\nWARNING: Could not load ~w: ~p\n",[M,Error]), + io:fwrite("\nWARNING: Could not load ~w: ~tp\n",[M,Error]), do_cover_compile1(Rest) end; {false,_} -> @@ -204,7 +204,7 @@ do_cover_compile1([M|Rest]) -> {ok,_} -> ok; Error -> - io:fwrite("\nWARNING: Could not cover compile ~w: ~p\n", + io:fwrite("\nWARNING: Could not cover compile ~w: ~tp\n", [M,Error]) end, do_cover_compile1(Rest) @@ -286,7 +286,7 @@ cover_analyse(Analyse,Modules,Stop) -> {ok,{M,{Cov,NotCov}}} -> {M,{Cov,NotCov,DetailsFun(M)}}; Err -> - io:fwrite("WARNING: Analysis failed for ~w. Reason: ~p\n", + io:fwrite("WARNING: Analysis failed for ~w. Reason: ~tp\n", [M,Err]), {M,Err} end @@ -436,8 +436,8 @@ run_test_case_apply(Mod, Func, Args, Name, RunInit, TimetrapData) -> _ -> Args end, - print(minor, "Test case started with:\n~s:~s(~p)\n", [Mod,Func,Args2Print]), - print(minor, "Current directory is ~p\n", [Cwd]), + print(minor, "Test case started with:\n~w:~w(~tp)\n", [Mod,Func,Args2Print]), + print(minor, "Current directory is ~tp\n", [Cwd]), print_timestamp(minor,"Started at "), print(minor, "", [], internal_raw), TCCallback = get(test_server_testcase_callback), @@ -498,7 +498,7 @@ run_test_case_msgloop(#st{ref=Ref,pid=Pid,end_conf_pid=EndConfPid0}=St0) -> exit(Pid, kill), %% here's the only place we know Reason, so we save %% it as a comment, potentially replacing user data - Error = lists:flatten(io_lib:format("Aborted: ~p", + Error = lists:flatten(io_lib:format("Aborted: ~tp", [Reason])), Error1 = lists:flatten([string:strip(S,left) || S <- string:tokens(Error, @@ -742,8 +742,8 @@ call_end_conf(Mod,Func,TCPid,TCExitReason,Loc,Conf,TVal) -> timer:sleep(1), group_leader() ! {printout,12, "WARNING! " - "~p:end_per_testcase(~p, ~p)" - " crashed!\n\tReason: ~p\n", + "~w:end_per_testcase(~w, ~tp)" + " crashed!\n\tReason: ~tp\n", [Mod,Func,Conf,Why]}; _ -> ok @@ -756,8 +756,8 @@ call_end_conf(Mod,Func,TCPid,TCExitReason,Loc,Conf,TVal) -> Starter ! {self(),{call_end_conf,Data,ok}}; {'EXIT',Pid,Reason} -> group_leader() ! {printout,12, - "WARNING! ~p:end_per_testcase(~p, ~p)" - " failed!\n\tReason: ~p\n", + "WARNING! ~w:end_per_testcase(~w, ~tp)" + " failed!\n\tReason: ~tp\n", [Mod,Func,Conf,Reason]}, Starter ! {self(),{call_end_conf,Data,{error,Reason}}}; {'EXIT',_OtherPid,Reason} -> @@ -802,7 +802,7 @@ spawn_fw_call(Mod,{end_per_testcase,Func},EndConf,Pid, {Result,E} end, group_leader() ! {printout,12, - "WARNING! ~p:end_per_testcase(~p, ~p)" + "WARNING! ~w:end_per_testcase(~w, ~tp)" " failed!\n\tReason: timetrap timeout" " after ~w ms!\n", [Mod,Func,EndConf,TVal]}, FailLoc = proplists:get_value(tc_fail_loc, EndConf), @@ -1180,7 +1180,7 @@ do_init_per_testcase(Mod, Args) -> Bad -> group_leader() ! {printout,12, "ERROR! init_per_testcase has returned " - "bad elements in Config: ~p\n",[Bad]}, + "bad elements in Config: ~tp\n",[Bad]}, {skip,{failed,{Mod,init_per_testcase,bad_return}}} end; {fail,_Reason}=Res -> @@ -1197,7 +1197,7 @@ do_init_per_testcase(Mod, Args) -> FormattedLoc = test_server_sup:format_loc(Line), group_leader() ! {printout,12, "ERROR! init_per_testcase thrown!\n" - "\tLocation: ~s\n\tReason: ~p\n", + "\tLocation: ~ts\n\tReason: ~tp\n", [FormattedLoc, Other]}, {skip,{failed,{Mod,init_per_testcase,Other}}}; _:Reason0 -> @@ -1208,7 +1208,7 @@ do_init_per_testcase(Mod, Args) -> FormattedLoc = test_server_sup:format_loc(Line), group_leader() ! {printout,12, "ERROR! init_per_testcase crashed!\n" - "\tLocation: ~s\n\tReason: ~p\n", + "\tLocation: ~ts\n\tReason: ~tp\n", [FormattedLoc,Reason]}, {skip,{failed,{Mod,init_per_testcase,Reason}}} end. @@ -1244,13 +1244,13 @@ do_end_per_testcase(Mod,EndFunc,Func,Conf) -> "
") end, set_loc(erlang:get_stacktrace()), - comment(io_lib:format("~s" + comment(io_lib:format("~ts" "WARNING: ~w thrown!" "\n",[Comment0,EndFunc])), group_leader() ! {printout,12, "WARNING: ~w thrown!\n" - "Reason: ~p\n" - "Line: ~s\n", + "Reason: ~tp\n" + "Line: ~ts\n", [EndFunc, Other, test_server_sup:format_loc(get_loc())]}, {failed,{Mod,end_per_testcase,Other}}; @@ -1266,13 +1266,13 @@ do_end_per_testcase(Mod,EndFunc,Func,Conf) -> Cmt -> Cmt ++ test_server_ctrl:xhtml("
", "
") end, - comment(io_lib:format("~s" + comment(io_lib:format("~ts" "WARNING: ~w crashed!" "\n",[Comment0,EndFunc])), group_leader() ! {printout,12, "WARNING: ~w crashed!\n" - "Reason: ~p\n" - "Line: ~s\n", + "Reason: ~tp\n" + "Line: ~ts\n", [EndFunc, Reason, test_server_sup:format_loc(get_loc())]}, {failed,{Mod,end_per_testcase,Why}} @@ -1351,7 +1351,7 @@ lookup_config(Key,Config) -> {value,{Key,Val}} -> Val; _ -> - io:format("Could not find element ~p in Config.~n",[Key]), + io:format("Could not find element ~tp in Config.~n",[Key]), undefined end. @@ -1433,7 +1433,7 @@ format(Detail, Format, Args) -> Str = case catch io_lib:format(Format,Args) of {'EXIT',_} -> - io_lib:format("illegal format; ~p with args ~p.\n", + io_lib:format("illegal format; ~tp with args ~tp.\n", [Format,Args]); Valid -> Valid end, @@ -1564,7 +1564,7 @@ fail(Reason) -> cast_to_list(X) when is_list(X) -> X; cast_to_list(X) when is_atom(X) -> atom_to_list(X); -cast_to_list(X) -> lists:flatten(io_lib:format("~p", [X])). +cast_to_list(X) -> lists:flatten(io_lib:format("~tp", [X])). @@ -1608,10 +1608,10 @@ break(CBM, TestCase, Comment) -> end, io:format(user, "\n\n\n--- SEMIAUTOMATIC TESTING ---" - "\nThe test case~s executes on process ~w" - "\n\n\n~s" + "\nThe test case~ts executes on process ~w" + "\n\n\n~ts" "\n\n\n-----------------------------\n\n" - "Continue with --> ~w:continue(~s).\n", + "Continue with --> ~w:continue(~ts).\n", [TCName,self(),Comment,CBM,CntArg]), case whereis(PName) of undefined -> @@ -1735,7 +1735,7 @@ ensure_timetrap(Config) -> Garbage -> erase(test_server_default_timetrap), format("=== WARNING: garbage in " - "test_server_default_timetrap: ~p~n", + "test_server_default_timetrap: ~tp~n", [Garbage]) end, DTmo = case lists:keysearch(default_timeout,1,Config) of @@ -1743,7 +1743,7 @@ ensure_timetrap(Config) -> _ -> ?DEFAULT_TIMETRAP_SECS end, format("=== test_server setting default " - "timetrap of ~p seconds~n", + "timetrap of ~tp seconds~n", [DTmo]), put(test_server_default_timetrap, timetrap(seconds(DTmo))) end. @@ -1764,7 +1764,7 @@ cancel_default_timetrap(true) -> Garbage -> erase(test_server_default_timetrap), format("=== WARNING: garbage in " - "test_server_default_timetrap: ~p~n", + "test_server_default_timetrap: ~tp~n", [Garbage]), error end. @@ -1773,7 +1773,7 @@ time_ms({hours,N}, _, _) -> hours(N); time_ms({minutes,N}, _, _) -> minutes(N); time_ms({seconds,N}, _, _) -> seconds(N); time_ms({Other,_N}, _, _) -> - format("=== ERROR: Invalid time specification: ~p. " + format("=== ERROR: Invalid time specification: ~tp. " "Should be seconds, minutes, or hours.~n", [Other]), exit({invalid_time_format,Other}); time_ms(Ms, _, _) when is_integer(Ms) -> Ms; @@ -2266,14 +2266,14 @@ stop_node(Slave) -> slave:stop(Slave), receive {nodedown, Slave} -> - format(minor, "Stopped slave node: ~p", [Slave]), - format(major, "=node_stop ~p", [Slave]), + format(minor, "Stopped slave node: ~w", [Slave]), + format(major, "=node_stop ~w", [Slave]), if Cover -> do_cover_for_node(Slave,stop,false); true -> ok end, true after 30000 -> - format("=== WARNING: Node ~p does not seem to terminate.", + format("=== WARNING: Node ~w does not seem to terminate.", [Slave]), erlang:monitor_node(Slave, false), receive {nodedown, Slave} -> ok after 0 -> ok end, @@ -2283,7 +2283,7 @@ stop_node(Slave) -> %% Either, the node is already dead or it was started %% with the {cleanup,false} option, or it was started %% in some other way than test_server:start_node/3 - format("=== WARNING: Attempt to stop a nonexisting slavenode (~p)~n" + format("=== WARNING: Attempt to stop a nonexisting slavenode (~w)~n" "=== Trying to kill it anyway!!!", [Slave]), case net_adm:ping(Slave)of @@ -2292,14 +2292,14 @@ stop_node(Slave) -> slave:stop(Slave), receive {nodedown, Slave} -> - format(minor, "Stopped slave node: ~p", [Slave]), - format(major, "=node_stop ~p", [Slave]), + format(minor, "Stopped slave node: ~w", [Slave]), + format(major, "=node_stop ~w", [Slave]), if Cover -> do_cover_for_node(Slave,stop,false); true -> ok end, true after 30000 -> - format("=== WARNING: Node ~p does not seem to terminate.", + format("=== WARNING: Node ~w does not seem to terminate.", [Slave]), erlang:monitor_node(Slave, false), receive {nodedown, Slave} -> ok after 0 -> ok end, diff --git a/lib/test_server/src/test_server_ctrl.erl b/lib/test_server/src/test_server_ctrl.erl index c5c57426b4..f800b93d0c 100644 --- a/lib/test_server/src/test_server_ctrl.erl +++ b/lib/test_server/src/test_server_ctrl.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2002-2012. All Rights Reserved. +%% Copyright Ericsson AB 2002-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -17,7 +17,6 @@ %% %CopyrightEnd% %% -module(test_server_ctrl). - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %% %% The Erlang Test Server %% @@ -65,6 +64,7 @@ -export([get_target_info/0]). -export([get_hosts/0]). -export([node_started/1]). +-export([uri_encode/1,uri_encode/2]). %%% DEBUGGER INTERFACE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -export([i/0, p/1, p/3, pi/2, pi/4, t/0, t/1]). @@ -229,12 +229,12 @@ parse_cmd_line(['SPEC',Spec|Cmds], SpecList, Names, Param, Trc, Cov, TCCB) -> parse_cmd_line(Cmds, TermList++SpecList, [Name|Names], Param, Trc, Cov, TCCB); {error,Reason} -> - io:format("Can't open ~s: ~p\n", - [cast_to_list(Spec), file:format_error(Reason)]), + io:format("Can't open ~w: ~tp\n",[Spec, file:format_error(Reason)]), parse_cmd_line(Cmds, SpecList, Names, Param, Trc, Cov, TCCB) end; parse_cmd_line(['NAME',Name|Cmds], SpecList, Names, Param, Trc, Cov, TCCB) -> - parse_cmd_line(Cmds, SpecList, [{name,Name}|Names], Param, Trc, Cov, TCCB); + parse_cmd_line(Cmds, SpecList, [{name,atom_to_list(Name)}|Names], + Param, Trc, Cov, TCCB); parse_cmd_line(['SKIPMOD',Mod|Cmds], SpecList, Names, Param, Trc, Cov, TCCB) -> parse_cmd_line(Cmds, [{skip,{Mod,"by command line"}}|SpecList], Names, Param, Trc, Cov, TCCB); @@ -242,14 +242,14 @@ parse_cmd_line(['SKIPCASE',Mod,Case|Cmds], SpecList, Names, Param, Trc, Cov, TCC parse_cmd_line(Cmds, [{skip,{Mod,Case,"by command line"}}|SpecList], Names, Param, Trc, Cov, TCCB); parse_cmd_line(['DIR',Dir|Cmds], SpecList, Names, Param, Trc, Cov, TCCB) -> - Name = cast_to_list(filename:basename(Dir)), + Name = filename:basename(Dir), parse_cmd_line(Cmds, [{topcase,{dir,Name}}|SpecList], [Name|Names], Param, Trc, Cov, TCCB); parse_cmd_line(['MODULE',Mod|Cmds], SpecList, Names, Param, Trc, Cov, TCCB) -> - parse_cmd_line(Cmds, [{topcase,{Mod,all}}|SpecList], [Mod|Names], + parse_cmd_line(Cmds,[{topcase,{Mod,all}}|SpecList],[atom_to_list(Mod)|Names], Param, Trc, Cov, TCCB); parse_cmd_line(['CASE',Mod,Case|Cmds], SpecList, Names, Param, Trc, Cov, TCCB) -> - parse_cmd_line(Cmds, [{topcase,{Mod,Case}}|SpecList], [Mod|Names], + parse_cmd_line(Cmds,[{topcase,{Mod,Case}}|SpecList],[atom_to_list(Mod)|Names], Param, Trc, Cov, TCCB); parse_cmd_line(['PARAMETERS',Param|Cmds], SpecList, Names, _Param, Trc, Cov, TCCB) -> parse_cmd_line(Cmds, SpecList, Names, Param, Trc, Cov, TCCB); @@ -260,17 +260,17 @@ parse_cmd_line(['COVER',App,CF,Analyse|Cmds], SpecList, Names, Param, Trc, _Cov, parse_cmd_line(['TESTCASE_CALLBACK',Mod,Func|Cmds], SpecList, Names, Param, Trc, Cov, _) -> parse_cmd_line(Cmds, SpecList, Names, Param, Trc, Cov, {Mod,Func}); parse_cmd_line([Obj|_Cmds], _SpecList, _Names, _Param, _Trc, _Cov, _TCCB) -> - io:format("~p: Bad argument: ~p\n", [?MODULE,Obj]), + io:format("~w: Bad argument: ~w\n", [?MODULE,Obj]), io:format(" Use the `ts' module to start tests.\n", []), io:format(" (If you ARE using `ts', there is a bug in `ts'.)\n", []), halt(1); parse_cmd_line([], SpecList, Names, Param, Trc, Cov, TCCB) -> - NameList = lists:reverse(Names, [suite]), + NameList = lists:reverse(Names, ["suite"]), Name = case lists:keysearch(name, 1, NameList) of {value,{name,N}} -> N; false -> hd(NameList) end, - {lists:reverse(SpecList), cast_to_list(Name), Param, Trc, Cov, TCCB}. + {lists:reverse(SpecList), Name, Param, Trc, Cov, TCCB}. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% cast_to_list(X) -> string() @@ -1011,9 +1011,9 @@ handle_info({'EXIT',Pid,Reason}, State) -> normal -> fine; killed -> - io:format("Suite ~s was killed\n", [Name]); + io:format("Suite ~ts was killed\n", [Name]); _Other -> - io:format("Suite ~s was killed with reason ~p\n", + io:format("Suite ~ts was killed with reason ~tp\n", [Name,Reason]) end, State2 = State#state{jobs=NewJobs}, @@ -1057,8 +1057,8 @@ handle_info({tcp,_MainSock,<<1,Request/binary>>}, State) -> %% The local job proc will soon be killed by the closed socket or %% because the job is finished. Then the above clause ('EXIT') will %% handle the problem. - io:format("Suite ~s was killed on remote target with reason" - " ~p\n", [Name,Reason]); + io:format("Suite ~ts was killed on remote target with reason" + " ~tp\n", [Name,Reason]); _ -> ignore end, @@ -1192,10 +1192,10 @@ init_tester(Mod, Func, Args, Dir, Name, {_,_,MinLev}=Levels, {'EXIT',test_suites_done} -> ok; {'EXIT',_Pid,Reason} -> - print(1, "EXIT, reason ~p", [Reason]); + print(1, "EXIT, reason ~tp", [Reason]); {'EXIT',Reason} -> report_severe_error(Reason), - print(1, "EXIT, reason ~p", [Reason]) + print(1, "EXIT, reason ~tp", [Reason]) end, Time = TimeMy/1000000, SuccessStr = @@ -1206,13 +1206,13 @@ init_tester(Mod, Func, Args, Dir, Name, {_,_,MinLev}=Levels, {SkippedN,SkipStr} = case get(test_server_skipped) of {0,_} -> {0,""}; - {Skipped,_} -> {Skipped,io_lib:format(", ~p Skipped", [Skipped])} + {Skipped,_} -> {Skipped,io_lib:format(", ~w Skipped", [Skipped])} end, OkN = get(test_server_ok), FailedN = get(test_server_failed), print(html,"\n\n\n" "TOTAL" - "~.3fs~s~p Ok, ~p Failed~s of ~p\n" + "~.3fs~ts~w Ok, ~w Failed~ts of ~w\n" "\n", [Time,SuccessStr,OkN,FailedN,SkipStr,OkN+FailedN+SkippedN]), test_server_io:stop(). @@ -1285,7 +1285,7 @@ do_spec(SpecName, TimetrapSpec) when is_list(SpecName) -> {ok,TermList} -> do_spec_list(TermList,TimetrapSpec); {error,Reason} -> - io:format("Can't open ~s: ~p\n", [SpecName,Reason]), + io:format("Can't open ~ts: ~tp\n", [SpecName,Reason]), {error,{cant_open_spec,Reason}} end. @@ -1368,7 +1368,7 @@ do_spec_terms([{require_nodenames,NumNames}|Terms], TopCases, SkipList, Config) do_spec_terms(Terms, TopCases, SkipList, update_config(Config, {nodenames,NodeNames})); do_spec_terms([Other|Terms], TopCases, SkipList, Config) -> - io:format("** WARNING: Spec file contains unknown directive ~p\n", + io:format("** WARNING: Spec file contains unknown directive ~tp\n", [Other]), do_spec_terms(Terms, TopCases, SkipList, Config). @@ -1387,7 +1387,7 @@ generate_nodenames(Num) -> generate_nodenames2(0, _Hosts, Acc) -> Acc; generate_nodenames2(N, Hosts, Acc) -> - Host=cast_to_list(lists:nth((N rem (length(Hosts)))+1, Hosts)), + Host=lists:nth((N rem (length(Hosts)))+1, Hosts), Name=list_to_atom(temp_nodename("nod", []) ++ "@" ++ Host), generate_nodenames2(N-1, Hosts, [Name|Acc]). @@ -1507,7 +1507,7 @@ do_test_cases(TopCases, SkipCases, FwMod = get_fw_mod(?MODULE), case collect_all_cases(TopCases, SkipCases) of {error,Why} -> - print(1, "Error starting: ~p", [Why]), + print(1, "Error starting: ~tp", [Why]), exit(test_suites_done); TestSpec0 -> N = case remove_conf(TestSpec0) of @@ -1519,32 +1519,25 @@ do_test_cases(TopCases, SkipCases, TestSpec = add_init_and_end_per_suite(TestSpec0, undefined, undefined, FwMod), TI = get_target_info(), - print(1, "Starting test~s", + print(1, "Starting test~ts", [print_if_known(N, {", ~w test cases",[N]}, {" (with repeated test cases)",[]})]), Test = get(test_server_name), TestName = if is_list(Test) -> - lists:flatten(io_lib:format("~s", [Test])); + lists:flatten(io_lib:format("~ts", [Test])); true -> - lists:flatten(io_lib:format("~p", [Test])) + lists:flatten(io_lib:format("~tp", [Test])) end, TestDescr = "Test " ++ TestName ++ " results", test_server_sup:framework_call(report, [tests_start,{Test,N}]), {Header,Footer} = - case test_server_sup:framework_call(get_html_wrapper, + case test_server_sup:framework_call(get_html_wrapper, [TestDescr,true,TestDir, {[],[2,3,4,7,8],[1,6]}], "") of Empty when (Empty == "") ; (element(2,Empty) == "") -> put(basic_html, true), - {["\n", - "\n", - "\n", - "", TestDescr, "\n", - "\n", - "\n", - "", + {[html_header(TestDescr), "

Results for test ", TestName, "

\n"], "\n\n\n"}; {basic_html,Html0,Html1} -> @@ -1566,16 +1559,16 @@ do_test_cases(TopCases, SkipCases, print(html, xhtml("\n

Host info:
\n", "\n

Host info:
\n")), print_who(test_server_sup:hoststr(), test_server_sup:get_username()), - print(html, xhtml("
Used Erlang v~s in ~s

\n", - "
Used Erlang v~s in \"~s\"

\n"), + print(html, xhtml("
Used Erlang v~ts in ~ts

\n", + "
Used Erlang v~ts in \"~ts\"

\n"), [erlang:system_info(version), code:root_dir()]), if FwMod == ?MODULE -> print(html, xhtml("\n

Target Info:
\n", "\n

Target Info:
\n")), print_who(TI#target_info.host, TI#target_info.username), - print(html, xhtml("
Used Erlang v~s in ~s

\n", - "
Used Erlang v~s in \"~s\"

\n"), + print(html,xhtml("
Used Erlang v~ts in ~ts

\n", + "
Used Erlang v~ts in \"~ts\"

\n"), [TI#target_info.version, TI#target_info.root_dir]); true -> case test_server_sup:framework_call(target_info, []) of @@ -1583,7 +1576,7 @@ do_test_cases(TopCases, SkipCases, length(TargetInfo) > 0 -> print(html, xhtml("\n

Target info:
\n", "\n

Target info:
\n")), - print(html, "~s

\n", [TargetInfo]); + print(html, "~ts

\n", [TargetInfo]); _ -> ok end @@ -1591,39 +1584,39 @@ do_test_cases(TopCases, SkipCases, print(html, "

\n", + "
  • Full textual log
  • \n" + "
  • Coverage log
  • \n" + "
  • Unexpected I/O log
  • \n

    \n", [?suitelog_name,?coverlog_name,?unexpected_io_log]), print(html, - "

    ~s

    \n" ++ + "

    ~ts

    \n" ++ xhtml("", ["
    \n", "\n"]) ++ "" ++ "" ++ "\n\n\n", - [print_if_known(N, {"Executing ~p test cases..." ++ - xhtml("\n
    \n", "\n
    \n"),[N]}, + [print_if_known(N, {"Executing ~w test cases..." + ++ xhtml("\n
    \n", "\n
    \n"),[N]}, {"",[]})]), - print(major, "=cases ~p", [get(test_server_cases)]), - print(major, "=user ~s", [TI#target_info.username]), - print(major, "=host ~s", [TI#target_info.host]), + print(major, "=cases ~w", [get(test_server_cases)]), + print(major, "=user ~ts", [TI#target_info.username]), + print(major, "=host ~ts", [TI#target_info.host]), %% If there are no hosts specified,use only the local host case controller_call(get_hosts) of [] -> - print(major, "=hosts ~s", [TI#target_info.host]), + print(major, "=hosts ~ts", [TI#target_info.host]), controller_call({set_hosts, [TI#target_info.host]}); Hosts -> Str = lists:flatten(lists:map(fun(X) -> [X," "] end, Hosts)), - print(major, "=hosts ~s", [Str]) + print(major, "=hosts ~ts", [Str]) end, - print(major, "=emulator_vsn ~s", [TI#target_info.version]), - print(major, "=emulator ~s", [TI#target_info.emulator]), - print(major, "=otp_release ~s", [TI#target_info.otp_release]), - print(major, "=started ~s", + print(major, "=emulator_vsn ~ts", [TI#target_info.version]), + print(major, "=emulator ~ts", [TI#target_info.emulator]), + print(major, "=otp_release ~ts", [TI#target_info.otp_release]), + print(major, "=started ~ts", [lists:flatten(timestamp_get(""))]), put(test_server_html_footer, Footer), @@ -1674,21 +1667,18 @@ start_log_file() -> MkDirError2 -> log_file_error(MkDirError2, TestDir) end, - ok = file:write_file(filename:join(Dir, ?last_file), TestDir1 ++ "\n"), - ok = file:write_file(?last_file, TestDir1 ++ "\n"), + ok = write_file(filename:join(Dir, ?last_file), TestDir1 ++ "\n"), + ok = write_file(?last_file, TestDir1 ++ "\n"), put(test_server_log_dir_base,TestDir1), MajorName = filename:join(TestDir1, ?suitelog_name), HtmlName = MajorName ++ ?html_ext, UnexpectedName = filename:join(TestDir1, ?unexpected_io_log), - {ok,Major} = file:open(MajorName, [write]), - {ok,Html} = file:open(HtmlName, [write]), - {ok,Unexpected} = file:open(UnexpectedName, [write]), + {ok,Major} = open_file(MajorName), + {ok,Html} = open_html_file(HtmlName), + {ok,Unexpected} = open_file(UnexpectedName), test_server_io:set_fd(major, Major), test_server_io:set_fd(html, Html), test_server_io:set_fd(unexpected_io, Unexpected), - put(test_server_major_fd,Major), - put(test_server_html_fd,Html), - put(test_server_unexpected_io, Unexpected), make_html_link(filename:absname(?last_test ++ ?html_ext), HtmlName, filename:basename(Dir)), @@ -1714,21 +1704,15 @@ make_html_link(LinkName, Target, Explanation) -> PwdL = filename:split(filename:dirname(LinkName)), Href = case lists:prefix(PwdL, TargetL) of true -> - filename:join(lists:nthtail(length(PwdL), TargetL)); + uri_encode(filename:join(lists:nthtail(length(PwdL),TargetL))); false -> - "file:" ++ Target + "file:" ++ uri_encode(Target) end, - H = io_lib:format("\n" - "\n" - "\n" - "~s\n" - "\n" - "

    Last test

    \n" - "~s~n" - "\n\n", - [Explanation,Href,Explanation]), - ok = file:write_file(LinkName, H). + H = [html_header(Explanation), + "

    Last test

    \n" + "",Explanation,"\n" + "\n\n"], + ok = write_html_file(LinkName, H). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% start_minor_log_file(Mod, Func) -> AbsName @@ -1743,7 +1727,7 @@ make_html_link(LinkName, Target, Explanation) -> start_minor_log_file(Mod, Func) -> MFA = {Mod,Func,1}, LogDir = get(test_server_log_dir_base), - Name0 = lists:flatten(io_lib:format("~s.~s~s", [Mod,Func,?html_ext])), + Name0 = lists:flatten(io_lib:format("~w.~w~ts", [Mod,Func,?html_ext])), Name = downcase(Name0), AbsName = filename:join(LogDir, Name), case file:read_file_info(AbsName) of @@ -1752,37 +1736,29 @@ start_minor_log_file(Mod, Func) -> {ok,_} -> %% special case, duplicate names {_,S,Us} = now(), Name1_0 = - lists:flatten(io_lib:format("~s.~s.~w.~w~s", [Mod,Func,S, - trunc(Us/1000), - ?html_ext])), + lists:flatten(io_lib:format("~w.~w.~w.~w~ts", [Mod,Func,S, + trunc(Us/1000), + ?html_ext])), Name1 = downcase(Name1_0), AbsName1 = filename:join(LogDir, Name1), start_minor_log_file1(Mod, Func, LogDir, AbsName1, MFA) end. start_minor_log_file1(Mod, Func, LogDir, AbsName, MFA) -> - {ok,Fd} = file:open(AbsName, [write]), + {ok,Fd} = open_html_file(AbsName), Lev = get(test_server_minor_level)+1000, %% far down in the minor levels put(test_server_minor_fd, Fd), test_server_gl:set_minor_fd(group_leader(), Fd, MFA), - TestDescr = io_lib:format("Test ~p:~p result", [Mod,Func]), + TestDescr = io_lib:format("Test ~w:~w result", [Mod,Func]), {Header,Footer} = - case test_server_sup:framework_call(get_html_wrapper, + case test_server_sup:framework_call(get_html_wrapper, [TestDescr,false, filename:dirname(AbsName), undefined], "") of Empty when (Empty == "") ; (element(2,Empty) == "") -> put(basic_html, true), - {["\n", - "\n", - "\n", - "", TestDescr, "\n", - "\n", - "\n", - "\n"], - "\n\n\n"}; + {html_header(TestDescr), "\n\n\n"}; {basic_html,Html0,Html1} -> put(basic_html, true), {Html0,Html1}; @@ -1791,24 +1767,21 @@ start_minor_log_file1(Mod, Func, LogDir, AbsName, MFA) -> {Html0,Html1} end, put(test_server_minor_footer, Footer), - io:fwrite(Fd, Header, []), + io:put_chars(Fd, Header), - SrcListing = downcase(cast_to_list(Mod)) ++ ?src_listing_ext, + SrcListing = downcase(atom_to_list(Mod)) ++ ?src_listing_ext, case {filelib:is_file(filename:join(LogDir, SrcListing)), lists:member(no_src, get(test_server_logopts))} of {true,false} -> - print(Lev, "source code for ~p:~p/1\n", - [SrcListing,atom_to_list(Func)++"-1",Mod,Func]); - _ -> ok + print(Lev, "source code for ~w:~w/1\n", + [uri_encode(SrcListing), + uri_encode(atom_to_list(Func)++"-1",utf8), + Mod,Func]); + _ -> + ok end, - io:fwrite(Fd, "
    \n", []),
    -
    -% Stupid BUG!
    -%    case catch apply(Mod, Func, [doc]) of
    -%	{'EXIT', _Why} -> ok;
    -%	Comment -> print(Lev, "Comment: ~s~n
    ", [Comment]) -% end, + io:put_chars(Fd, "
    \n"),
     
         AbsName.
     
    @@ -1816,8 +1789,8 @@ stop_minor_log_file() ->
         test_server_gl:unset_minor_fd(group_leader()),
         Fd = get(test_server_minor_fd),
         Footer = get(test_server_minor_footer),
    -    io:fwrite(Fd, "
    \n" ++ Footer, []), - file:close(Fd), + io:put_chars(Fd, "
    \n" ++ Footer), + ok = file:close(Fd), put(test_server_minor_fd, undefined). downcase(S) -> downcase(S, []). @@ -1899,25 +1872,14 @@ html_possibly_convert(Src, SrcInfo, Dest) -> ok; % dest file up to date _ -> OutDir = get(test_server_log_dir_base), - Header = - case test_server_sup:framework_call(get_html_wrapper, - ["Module "++Src,false, - OutDir,undefined], "") of - Empty when (Empty == "") ; (element(2,Empty) == "") -> - ["\n", - "\n", - "\n", - "Module ", Src, "\n", - "\n", - "\n", - "\n"]; - {_,Html,_} -> - Html - end, - erl2html2:convert(Src, Dest, Header) + case test_server_sup:framework_call(get_html_wrapper, + ["Module "++Src,false, + OutDir,undefined], "") of + Empty when (Empty == "") ; (element(2,Empty) == "") -> + erl2html2:convert(Src, Dest); + {_,Header,_} -> + erl2html2:convert(Src, Dest, Header) + end end. %% Copy all HTML files in InDir to OutDir. @@ -1929,9 +1891,9 @@ copy_html_file(Src, DestDir) -> Dest = filename:join(DestDir, filename:basename(Src)), case file:read_file(Src) of {ok,Bin} -> - ok = file:write_file(Dest, Bin); + ok = write_file(Dest, Bin); {error,_Reason} -> - io:format("File ~p: read failed\n", [Src]) + io:format("File ~tp: read failed\n", [Src]) end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -2106,15 +2068,15 @@ run_test_cases(TestSpec, Config, TimetrapData) -> end, OkN = get(test_server_ok), FailedN = get(test_server_failed), - print(1, "TEST COMPLETE, ~w ok, ~w failed~s of ~w test cases\n", + print(1, "TEST COMPLETE, ~w ok, ~w failed~ts of ~w test cases\n", [OkN,FailedN,SkipStr,OkN+FailedN+AllSkippedN]), test_server_sup:framework_call(report, [tests_done, {OkN,FailedN,{UserSkipN,AutoSkipN}}]), - print(major, "=finished ~s", [lists:flatten(timestamp_get(""))]), - print(major, "=failed ~p", [FailedN]), - print(major, "=successful ~p", [OkN]), - print(major, "=user_skipped ~p", [UserSkipN]), - print(major, "=auto_skipped ~p", [AutoSkipN]), + print(major, "=finished ~ts", [lists:flatten(timestamp_get(""))]), + print(major, "=failed ~w", [FailedN]), + print(major, "=successful ~w", [OkN]), + print(major, "=user_skipped ~w", [UserSkipN]), + print(major, "=auto_skipped ~w", [AutoSkipN]), exit(test_suites_done). @@ -2645,7 +2607,8 @@ run_test_cases_loop([{conf,Ref,Props,{Mod,Func}}|_Cases]=Cs0, run_test_cases_loop(Cases, [NewCfg|Config], TimetrapData, Mode, Status2); Bad -> - print(minor, "~n*** ~p returned bad elements in Config: ~p.~n", + print(minor, + "~n*** ~w returned bad elements in Config: ~tp.~n", [Func,Bad]), Reason = {failed,{Mod,init_per_suite,bad_return}}, Cases2 = skip_cases_upto(Ref, Cases, Reason, conf, CurrMode), @@ -2660,8 +2623,9 @@ run_test_cases_loop([{conf,Ref,Props,{Mod,Func}}|_Cases]=Cs0, stop_minor_log_file(), run_test_cases_loop(Cases, [NewCfg|Config], TimetrapData, Mode, Status2); {_,{framework_error,{FwMod,FwFunc},Reason},_} -> - print(minor, "~n*** ~p failed in ~p. Reason: ~p~n", [FwMod,FwFunc,Reason]), - print(1, "~p failed in ~p. Reason: ~p~n", [FwMod,FwFunc,Reason]), + print(minor, "~n*** ~w failed in ~w. Reason: ~tp~n", + [FwMod,FwFunc,Reason]), + print(1, "~w failed in ~w. Reason: ~tp~n", [FwMod,FwFunc,Reason]), exit(framework_error); {_,Fail,_} when element(1,Fail) == 'EXIT'; element(1,Fail) == timetrap_timeout; @@ -2670,7 +2634,7 @@ run_test_cases_loop([{conf,Ref,Props,{Mod,Func}}|_Cases]=Cs0, {Cases2,Config1,Status3} = if StartConf -> ReportAbortRepeat(failed), - print(minor, "~n*** ~p failed.~n" + print(minor, "~n*** ~w failed.~n" " Skipping all cases.", [Func]), Reason = {failed,{Mod,Func,Fail}}, {skip_cases_upto(Ref, Cases, Reason, conf, CurrMode), @@ -2687,7 +2651,7 @@ run_test_cases_loop([{conf,Ref,Props,{Mod,Func}}|_Cases]=Cs0, run_test_cases_loop(Cases2, Config1, TimetrapData, Mode, Status3); {_,{Skip,Reason},_} when StartConf and ((Skip==skip) or (Skip==skipped)) -> ReportAbortRepeat(skipped), - print(minor, "~n*** ~p skipped.~n" + print(minor, "~n*** ~w skipped.~n" " Skipping all cases.", [Func]), set_io_buffering(IOHandler), stop_minor_log_file(), @@ -2696,7 +2660,7 @@ run_test_cases_loop([{conf,Ref,Props,{Mod,Func}}|_Cases]=Cs0, delete_status(Ref, Status2)); {_,{skip_and_save,Reason,_SavedConfig},_} when StartConf -> ReportAbortRepeat(skipped), - print(minor, "~n*** ~p skipped.~n" + print(minor, "~n*** ~w skipped.~n" " Skipping all cases.", [Func]), set_io_buffering(IOHandler), stop_minor_log_file(), @@ -2757,7 +2721,7 @@ run_test_cases_loop([{conf,Ref,Props,{Mod,Func}}|_Cases]=Cs0, run_test_cases_loop([{make,Ref,{Mod,Func,Args}}|Cases0], Config, TimetrapData, Mode, Status) -> case run_test_case(Ref, 0, Mod, Func, Args, skip_init, TimetrapData) of {_,Why={'EXIT',_},_} -> - print(minor, "~n*** ~p failed.~n" + print(minor, "~n*** ~w failed.~n" " Skipping all cases.", [Func]), Reason = {failed,{Mod,Func,Why}}, Cases = skip_cases_upto(Ref, Cases0, Reason, conf, Mode), @@ -2803,8 +2767,9 @@ run_test_cases_loop([{Mod,Func,Args}|Cases], Config, TimetrapData, Mode, Status) run_init, TimetrapData, Mode) of %% callback to framework module failed, exit immediately {_,{framework_error,{FwMod,FwFunc},Reason},_} -> - print(minor, "~n*** ~p failed in ~p. Reason: ~p~n", [FwMod,FwFunc,Reason]), - print(1, "~p failed in ~p. Reason: ~p~n", [FwMod,FwFunc,Reason]), + print(minor, "~n*** ~w failed in ~w. Reason: ~tp~n", + [FwMod,FwFunc,Reason]), + print(1, "~w failed in ~w. Reason: ~tp~n", [FwMod,FwFunc,Reason]), stop_minor_log_file(), exit(framework_error); %% sequential execution of test case finished @@ -2836,8 +2801,9 @@ run_test_cases_loop([{Mod,Func,Args}|Cases], Config, TimetrapData, Mode, Status) stop_minor_log_file(), run_test_cases_loop(Cases, Config, TimetrapData, Mode, Status1); true -> % skip rest of cases in sequence - print(minor, "~n*** ~p failed.~n" - " Skipping all other cases in sequence.", [Func]), + print(minor, "~n*** ~w failed.~n" + " Skipping all other cases in sequence.", + [Func]), Reason = {failed,{Mod,Func}}, Cases2 = skip_cases_upto(Ref, Cases, Reason, tc, Mode), stop_minor_log_file(), @@ -2953,7 +2919,7 @@ get_data_dir(Mod, Suite) -> end, case code:which(UseMod) of non_existing -> - print(12, "The module ~p is not loaded", [Mod]), + print(12, "The module ~w is not loaded", [Mod]), []; cover_compiled -> MainCoverNode = cover:get_main_node(), @@ -2964,7 +2930,7 @@ get_data_dir(Mod, Suite) -> end. do_get_data_dir(Mod,File) -> - filename:dirname(File) ++ "/" ++ cast_to_list(Mod) ++ ?data_dir_suffix. + filename:dirname(File) ++ "/" ++ atom_to_list(Mod) ++ ?data_dir_suffix. print_conf_time(0) -> ok; @@ -2975,8 +2941,8 @@ print_conf_time(ConfTime) -> print_props(_, []) -> ok; print_props(true, Props) -> - print(major, "=group_props ~p", [Props]), - print(minor, "Group properties: ~p~n", [Props]); + print(major, "=group_props ~tp", [Props]), + print(minor, "Group properties: ~tp~n", [Props]); print_props(_, _) -> ok. @@ -3126,24 +3092,24 @@ skip_case1(Type, CaseNum, Mod, Func, Comment, Mode) -> Comment1 = reason_to_string(Comment), - print(major, "~n=case ~p:~p", [Mod,Func]), - print(major, "=started ~s", [lists:flatten(timestamp_get(""))]), - print(major, "=result skipped: ~s", [Comment1]), - print(2,"*** Skipping test case #~w ~p ***", [CaseNum,{Mod,Func}]), + print(major, "~n=case ~w:~w", [Mod,Func]), + print(major, "=started ~ts", [lists:flatten(timestamp_get(""))]), + print(major, "=result skipped: ~ts", [Comment1]), + print(2,"*** Skipping test case #~w ~w ***", [CaseNum,{Mod,Func}]), TR = xhtml("", [""]), GroupName = case get_name(Mode) of undefined -> ""; Name -> cast_to_list(Name) end, print(html, - TR ++ "" - "" - "" - "" + TR ++ "" + "" + "" + "" "" "" - "" - "\n", + "" + "\n", [num2str(CaseNum),fw_name(Mod),GroupName,Func,ResultCol,Comment1]), if CaseNum > 0 -> {US,AS} = get(test_server_skipped), @@ -3325,7 +3291,7 @@ wait_and_resend(Ref, [{_,CurrPid,CaseNum,Mod,Func}|Ps] = Cases, Ok,Skip,Fail) -> {'EXIT',CurrPid,Reason} when Reason /= normal -> %% unexpected termination of test case process {value,{_,_,CaseNum,Mod,Func}} = lists:keysearch(CurrPid, 2, Cases), - print(1, "Error! Process for test case #~p (~p:~p) died! Reason: ~p", + print(1, "Error! Process for test case #~w (~w:~w) died! Reason: ~tp", [CaseNum, Mod, Func, Reason]), exit({unexpected_termination,{CaseNum,Mod,Func},{CurrPid,Reason}}) end; @@ -3464,7 +3430,7 @@ handle_io_and_exits(Main, CurrPid, CaseNum, Mod, Func, Cases) -> {'EXIT',TCPid,Reason} when Reason /= normal -> test_server_io:print_buffered(CurrPid), {value,{_,_,Num,M,F}} = lists:keysearch(TCPid, 2, Cases), - print(1, "Error! Process for test case #~p (~p:~p) died! Reason: ~p", + print(1, "Error! Process for test case #~w (~w:~w) died! Reason: ~tp", [Num, M, F, Reason]), exit({unexpected_termination,{Num,M,F},{TCPid,Reason}}) end. @@ -3540,11 +3506,11 @@ run_test_case1(Ref, Num, Mod, Func, Args, RunInit, end, TSDir = get(test_server_dir), - print(major, "=case ~p:~p", [Mod, Func]), + print(major, "=case ~w:~w", [Mod, Func]), MinorName = start_minor_log_file(Mod, Func), print(minor, "", [], internal_raw), MinorBase = filename:basename(MinorName), - print(major, "=logfile ~s", [filename:basename(MinorName)]), + print(major, "=logfile ~ts", [filename:basename(MinorName)]), UpdatedArgs = %% maybe create unique private directory for test case or config func @@ -3552,14 +3518,13 @@ run_test_case1(Ref, Num, Mod, Func, Args, RunInit, auto_per_run -> update_config(hd(Args), [{tc_logfile,MinorName}]); PrivDirMode -> + %% create unique private directory for test case RunDir = filename:dirname(MinorName), Ext = if Num == 0 -> {_,S,Us} = now(), lists:flatten(io_lib:format(".~w.~w", [S,Us])); true -> - %% create unique private directory for test case - RunDir = filename:dirname(MinorName), lists:flatten(io_lib:format(".~w", [Num])) end, PrivDir = filename:join(RunDir, ?priv_dir) ++ Ext, @@ -3580,16 +3545,17 @@ run_test_case1(Ref, Num, Mod, Func, Args, RunInit, undefined -> ""; Name -> cast_to_list(Name) end, - print(major, "=started ~s", [lists:flatten(timestamp_get(""))]), + print(major, "=started ~ts", [lists:flatten(timestamp_get(""))]), {{Col0,Col1},Style} = get_font_style((RunInit==run_init), Mode), TR = xhtml("", [""]), - print(html, TR ++ "" - "" - "" - "" - "", - [num2str(Num),fw_name(Mod),GroupName,MinorBase,Func, - MinorBase,MinorBase]), + EncMinorBase = uri_encode(MinorBase), + print(html, TR ++ "" + "" + "" + "" + "", + [num2str(Num),fw_name(Mod),GroupName,EncMinorBase,Func, + EncMinorBase,EncMinorBase]), do_unless_parallel(Main, fun erlang:yield/0), @@ -3606,7 +3572,7 @@ run_test_case1(Ref, Num, Mod, Func, Args, RunInit, print(minor, "", [], internal_raw), print(minor, "\n", [], internal_raw), print_timestamp(minor, "Ended at "), - print(major, "=ended ~s", [lists:flatten(timestamp_get(""))]), + print(major, "=ended ~ts", [lists:flatten(timestamp_get(""))]), do_unless_parallel(Main, fun() -> file:set_cwd(filename:dirname(TSDir)) end), @@ -3690,13 +3656,13 @@ run_test_case1(Ref, Num, Mod, Func, Args, RunInit, {'EXIT',_} = Exit -> print(minor, "WARNING: There might be slavenodes left in the" - " system. I tried to kill them, but I failed: ~p\n", + " system. I tried to kill them, but I failed: ~tp\n", [Exit]); [] -> ok; List -> print(minor, "WARNING: ~w slave nodes in system after test"++ "case. Tried to killed them.~n"++ - " Names:~p", + " Names:~tp", [length(List),List]) end; false -> @@ -3756,7 +3722,7 @@ progress(skip, CaseNum, Mod, Func, Loc, Reason, Time, fun() -> {?auto_skip_color,auto_skip} end, fun() -> {?user_skip_color,skip} end), print(major, "=result skipped", []), - print(1, "*** SKIPPED *** ~s", + print(1, "*** SKIPPED *** ~ts", [get_info_str(Func, CaseNum, get(test_server_cases))]), test_server_sup:framework_call(report, [tc_done,{Mod,Func, {skipped,Reason1}}]), @@ -3775,24 +3741,24 @@ progress(skip, CaseNum, Mod, Func, Loc, Reason, Time, end, print(html, "" - "" - "\n", + "" + "\n", [Time,Color,ReasonStr2,Comment1]), FormatLoc = test_server_sup:format_loc(Loc), - print(minor, "=== location ~s", [FormatLoc]), - print(minor, "=== reason = ~s", [ReasonStr1]), + print(minor, "=== location ~ts", [FormatLoc]), + print(minor, "=== reason = ~ts", [ReasonStr1]), Ret; progress(failed, CaseNum, Mod, Func, Loc, timetrap_timeout, T, Comment0, {St0,St1}) -> - print(major, "=result failed: timeout, ~p", [Loc]), - print(1, "*** FAILED *** ~s", + print(major, "=result failed: timeout, ~tp", [Loc]), + print(1, "*** FAILED *** ~ts", [get_info_str(Func, CaseNum, get(test_server_cases))]), test_server_sup:framework_call(report, [tc_done,{Mod,Func, {failed,timetrap_timeout}}]), FormatLastLoc = test_server_sup:format_loc(get_last_loc(Loc)), - ErrorReason = io_lib:format("{timetrap_timeout,~s}", [FormatLastLoc]), + ErrorReason = io_lib:format("{timetrap_timeout,~ts}", [FormatLastLoc]), Comment = case Comment0 of "" -> "" ++ ErrorReason ++ ""; @@ -3802,23 +3768,23 @@ progress(failed, CaseNum, Mod, Func, Loc, timetrap_timeout, T, print(html, "" "" - "\n", + "\n", [T/1000,Comment]), FormatLoc = test_server_sup:format_loc(Loc), - print(minor, "=== location ~s", [FormatLoc]), + print(minor, "=== location ~ts", [FormatLoc]), print(minor, "=== reason = timetrap timeout", []), failed; progress(failed, CaseNum, Mod, Func, Loc, {testcase_aborted,Reason}, _T, Comment0, {St0,St1}) -> - print(major, "=result failed: testcase_aborted, ~p", [Loc]), - print(1, "*** FAILED *** ~s", + print(major, "=result failed: testcase_aborted, ~tp", [Loc]), + print(1, "*** FAILED *** ~ts", [get_info_str(Func, CaseNum, get(test_server_cases))]), test_server_sup:framework_call(report, [tc_done,{Mod,Func, {failed,testcase_aborted}}]), FormatLastLoc = test_server_sup:format_loc(get_last_loc(Loc)), - ErrorReason = io_lib:format("{testcase_aborted,~s}", [FormatLastLoc]), + ErrorReason = io_lib:format("{testcase_aborted,~ts}", [FormatLastLoc]), Comment = case Comment0 of "" -> "" ++ ErrorReason ++ ""; @@ -3828,24 +3794,24 @@ progress(failed, CaseNum, Mod, Func, Loc, {testcase_aborted,Reason}, _T, print(html, "" "" - "\n", + "\n", [Comment]), FormatLoc = test_server_sup:format_loc(Loc), - print(minor, "=== location ~s", [FormatLoc]), - print(minor, "=== reason = {testcase_aborted,~p}", [Reason]), + print(minor, "=== location ~ts", [FormatLoc]), + print(minor, "=== reason = {testcase_aborted,~tp}", [Reason]), failed; progress(failed, CaseNum, Mod, Func, unknown, Reason, Time, Comment0, {St0,St1}) -> - print(major, "=result failed: ~p, ~p", [Reason,unknown]), - print(1, "*** FAILED *** ~s", + print(major, "=result failed: ~tp, ~w", [Reason,unknown]), + print(1, "*** FAILED *** ~ts", [get_info_str(Func, CaseNum, get(test_server_cases))]), test_server_sup:framework_call(report, [tc_done,{Mod,Func, {failed,Reason}}]), TimeStr = io_lib:format(if is_float(Time) -> "~.3fs"; true -> "~w" end, [Time]), - ErrorReason = lists:flatten(io_lib:format("~p", [Reason])), + ErrorReason = lists:flatten(io_lib:format("~tp", [Reason])), ErrorReason1 = lists:flatten([string:strip(S,left) || S <- string:tokens(ErrorReason,[$\n])]), ErrorReason2 = @@ -3862,19 +3828,19 @@ progress(failed, CaseNum, Mod, Func, unknown, Reason, Time, to_string(Comment0) end, print(html, - "" + "" "" - "\n", + "\n", [TimeStr,Comment]), - print(minor, "=== location ~s", [unknown]), + print(minor, "=== location ~w", [unknown]), {FStr,FormattedReason} = format_exception(Reason), print(minor, "=== reason = " ++ FStr, [FormattedReason]), failed; progress(failed, CaseNum, Mod, Func, Loc, Reason, Time, Comment0, {St0,St1}) -> - print(major, "=result failed: ~p, ~p", [Reason,Loc]), - print(1, "*** FAILED *** ~s", + print(major, "=result failed: ~tp, ~tp", [Reason,Loc]), + print(1, "*** FAILED *** ~ts", [get_info_str(Func, CaseNum, get(test_server_cases))]), test_server_sup:framework_call(report, [tc_done,{Mod,Func, {failed,Reason}}]), @@ -3888,12 +3854,12 @@ progress(failed, CaseNum, Mod, Func, Loc, Reason, Time, end, FormatLastLoc = test_server_sup:format_loc(get_last_loc(Loc)), print(html, - "" + "" "" - "\n", + "\n", [TimeStr,FormatLastLoc,Comment]), FormatLoc = test_server_sup:format_loc(Loc), - print(minor, "=== location ~s", [FormatLoc]), + print(minor, "=== location ~ts", [FormatLoc]), {FStr,FormattedReason} = format_exception(Reason), print(minor, "=== reason = " ++ FStr, [FormattedReason]), failed; @@ -3909,7 +3875,7 @@ progress(ok, _CaseNum, Mod, Func, _Loc, RetVal, Time, HtmlCmt = test_server_sup:framework_call(format_comment, [String], String), - print(major, "=result ok: ~s", [String]), + print(major, "=result ok: ~ts", [String]), ""; _ -> print(major, "=result ok", []), @@ -3918,13 +3884,13 @@ progress(ok, _CaseNum, Mod, Func, _Loc, RetVal, Time, _ -> "" end end, - print(major, "=elapsed ~p", [Time]), + print(major, "=elapsed ~tp", [Time]), print(html, "" "" - "~s\n", + "~ts\n", [Time,Comment]), - print(minor, "=== returned value = ~p", [RetVal]), + print(minor, "=== returned value = ~tp", [RetVal]), ok. %%-------------------------------------------------------------------- @@ -4000,12 +3966,12 @@ print_if_known(Known, {SK,AK}, {SU,AU}) -> io_lib:format(S, A). to_string(Term) when is_list(Term) -> - case (catch io_lib:format("~s", [Term])) of - {'EXIT',_} -> io_lib:format("~p", [Term]); + case (catch io_lib:format("~ts", [Term])) of + {'EXIT',_} -> lists:flatten(io_lib:format("~tp", [Term])); String -> lists:flatten(String) end; to_string(Term) -> - lists:flatten(io_lib:format("~p", [Term])). + lists:flatten(io_lib:format("~tp", [Term])). get_last_loc(Loc) when is_tuple(Loc) -> Loc; @@ -4077,14 +4043,14 @@ format_exception(Reason={_Error,Stack}) when is_list(Stack) -> undefined -> case application:get_env(test_server, format_exception) of {ok,false} -> - {"~p",Reason}; + {"~tp",Reason}; _ -> do_format_exception(Reason) end; FW -> case application:get_env(FW, format_exception) of {ok,false} -> - {"~p",Reason}; + {"~tp",Reason}; _ -> do_format_exception(Reason) end @@ -4099,10 +4065,10 @@ do_format_exception(Reason={Error,Stack}) -> end, case catch lib:format_exception(1, error, Error, Stack, StackFun, PF) of {'EXIT',_} -> - {"~p",Reason}; + {"~tp",Reason}; Formatted -> Formatted1 = re:replace(Formatted, "exception error: ", "", [{return,list}]), - {"~s",lists:flatten(Formatted1)} + {"~ts",lists:flatten(Formatted1)} end. @@ -4173,7 +4139,7 @@ print_who(Host, User) -> "" -> ""; _ -> " by " ++ User end, - print(html, "Run~s on ~s", [UserStr,Host]). + print(html, "Run~ts on ~ts", [UserStr,Host]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% format(Format) -> IoLibReturn @@ -4208,7 +4174,7 @@ format(Detail, Format, Args) -> Str = case catch io_lib:format(Format, Args) of {'EXIT',_} -> - io_lib:format("illegal format; ~p with args ~p.\n", + io_lib:format("illegal format; ~tp with args ~tp.\n", [Format,Args]); Valid -> Valid end, @@ -4244,7 +4210,7 @@ odd_or_even() -> %% date and time. The resulting string is suitable as a filename. timestamp_filename_get(Leader) -> timestamp_get_internal(Leader, - "~s~w-~2.2.0w-~2.2.0w_~2.2.0w.~2.2.0w.~2.2.0w"). + "~ts~w-~2.2.0w-~2.2.0w_~2.2.0w.~2.2.0w.~2.2.0w"). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% timestamp_get(Leader) -> string() @@ -4254,7 +4220,7 @@ timestamp_filename_get(Leader) -> %% date and time. The resulting string is suitable for display. timestamp_get(Leader) -> timestamp_get_internal(Leader, - "~s~w-~2.2.0w-~2.2.0w ~2.2.0w:~2.2.0w:~2.2.0w"). + "~ts~w-~2.2.0w-~2.2.0w ~2.2.0w:~2.2.0w:~2.2.0w"). timestamp_get_internal(Leader, Format) -> {YY,MM,DD,H,M,S} = time_get(), @@ -4588,14 +4554,18 @@ collect_files(Dir, Pattern, St) -> Wc = filename:join([Dir1,Pattern++code:objfile_extension()]), case catch filelib:wildcard(Wc) of {'EXIT', Reason} -> - io:format("Could not collect files: ~p~n", [Reason]), + io:format("Could not collect files: ~tp~n", [Reason]), {error,{collect_fail,Dir,Pattern}}; Mods0 -> Mods = [{path_to_module(Mod),all} || Mod <- lists:sort(Mods0)], collect_cases(Mods, St) end. -path_to_module(Path) -> +path_to_module(Path) when is_list(Path) -> + %% If this is called with a binary, then we are probably in +fnu + %% mode and have found a beam file with name encoded as latin1. We + %% will let this crash since it can not work to load such a module + %% anyway. It should be removed or renamed! list_to_atom(filename:rootname(filename:basename(Path))). collect_case_deny(Mod, Case, MFA, ReqList, SubCases, St) -> @@ -4617,16 +4587,16 @@ check_deny([], _DenyList) -> granted; check_deny(Req, DenyList) -> check_deny([Req], DenyList). check_deny_req({Req,Val}, DenyList) -> - %%io:format("ValCheck ~p=~p in ~p\n", [Req,Val,DenyList]), + %%io:format("ValCheck ~tp=~tp in ~tp\n", [Req,Val,DenyList]), case lists:keysearch(Req, 1, DenyList) of {value,{_Req,DenyVal}} when Val >= DenyVal -> - {denied,io_lib:format("Requirement ~p=~p", [Req,Val])}; + {denied,io_lib:format("Requirement ~tp=~tp", [Req,Val])}; _ -> check_deny_req(Req, DenyList) end; check_deny_req(Req, DenyList) -> case lists:member(Req, DenyList) of - true -> {denied,io_lib:format("Requirement ~p", [Req])}; + true -> {denied,io_lib:format("Requirement ~tp", [Req])}; false -> granted end. @@ -4727,14 +4697,14 @@ get_target_info() -> start_node(Name, Type, Options) -> T = 10 * ?ACCEPT_TIMEOUT * test_server:timetrap_scale_factor(), - format(minor, "Attempt to start ~w node ~p with options ~p", + format(minor, "Attempt to start ~w node ~tp with options ~tp", [Type, Name, Options]), case controller_call({start_node,Name,Type,Options}, T) of {{ok,Nodename}, Host, Cmd, Info, Warning} -> format(minor, - "Successfully started node ~p on ~p with command: ~p", + "Successfully started node ~w on ~tp with command: ~tp", [Nodename, Host, Cmd]), - format(major, "=node_start ~p", [Nodename]), + format(major, "=node_start ~w", [Nodename]), case Info of [] -> ok; _ -> format(minor, Info) @@ -4748,17 +4718,17 @@ start_node(Name, Type, Options) -> {ok, Nodename}; {fail,{Ret, Host, Cmd}} -> format(minor, - "Failed to start node ~p on ~p with command: ~p~n" - "Reason: ~p", + "Failed to start node ~tp on ~tp with command: ~tp~n" + "Reason: ~tp", [Name, Host, Cmd, Ret]), {fail,Ret}; {Ret, undefined, undefined} -> - format(minor, "Failed to start node ~p: ~p", [Name,Ret]), + format(minor, "Failed to start node ~tp: ~tp", [Name,Ret]), Ret; {Ret, Host, Cmd} -> format(minor, - "Failed to start node ~p on ~p with command: ~p~n" - "Reason: ~p", + "Failed to start node ~tp on ~tp with command: ~tp~n" + "Reason: ~tp", [Name, Host, Cmd, Ret]), Ret end. @@ -4972,11 +4942,11 @@ read_cover_file(CoverFile) -> case check_cover_file(List, [], [], []) of {ok,Exclude,Include,Cross} -> {Exclude,Include,Cross}; error -> - io:fwrite("Faulty format of CoverFile ~p\n", [CoverFile]), + io:fwrite("Faulty format of CoverFile ~tp\n", [CoverFile]), {[],[],[]} end; {error,Reason} -> - io:fwrite("Can't read CoverFile ~p\nReason: ~p\n", + io:fwrite("Can't read CoverFile ~ts\nReason: ~tp\n", [CoverFile,Reason]), {[],[],[]} end. @@ -5029,11 +4999,11 @@ check_cross([]) -> cover_analyse({App,CoverInfo}, Analyse, AnalyseMods, Stop, TestDir) -> write_default_cross_coverlog(TestDir), - {ok,CoverLog} = file:open(filename:join(TestDir, ?coverlog_name), [write]), + {ok,CoverLog} = open_html_file(filename:join(TestDir, ?coverlog_name)), write_coverlog_header(CoverLog), io:fwrite(CoverLog, "

    Coverage for application '~w'

    \n", [App]), io:fwrite(CoverLog, - "

    Coverdata collected over all tests

    ", + "

    Coverdata collected over all tests

    ", [?cross_coverlog_name]), {CoverFile,_Included,Excluded,Cross} = @@ -5045,7 +5015,7 @@ cover_analyse({App,CoverInfo}, Analyse, AnalyseMods, Stop, TestDir) -> {Excl,Incl,Cr} = read_cover_file(File), {File,Incl,Excl,Cr} end, - io:fwrite(CoverLog, "

    CoverFile: ~p\n", [CoverFile]), + io:fwrite(CoverLog, "

    CoverFile: ~tp\n", [CoverFile]), write_cross_cover_info(TestDir,Cross), case length(cover:imported_modules()) of @@ -5056,11 +5026,11 @@ cover_analyse({App,CoverInfo}, Analyse, AnalyseMods, Stop, TestDir) -> ok end, - io:fwrite(CoverLog, "

    Excluded module(s): ~p\n", [Excluded]), + io:fwrite(CoverLog, "

    Excluded module(s): ~tp\n", [Excluded]), Coverage = cover_analyse(Analyse, AnalyseMods, Stop), - file:write_file(filename:join(TestDir,?raw_coverlog_name), - term_to_binary(Coverage)), + write_file(filename:join(TestDir,?raw_coverlog_name), + term_to_binary(Coverage)), case lists:filter(fun({_M,{_,_,_}}) -> false; (_) -> true @@ -5074,8 +5044,7 @@ cover_analyse({App,CoverInfo}, Analyse, AnalyseMods, Stop, TestDir) -> end, TotPercent = write_cover_result_table(CoverLog, Coverage), - file:write_file(filename:join(TestDir, ?cover_total), - term_to_binary(TotPercent)). + write_file(filename:join(TestDir, ?cover_total),term_to_binary(TotPercent)). cover_analyse(Analyse, AnalyseMods, Stop) -> TestDir = get(test_server_log_dir_base), @@ -5122,25 +5091,25 @@ cross_cover_analyse(Analyse, TagDirs0) -> write_cross_cover_info(_Dir,[]) -> ok; write_cross_cover_info(Dir,Cross) -> - {ok,Fd} = file:open(filename:join(Dir,?cross_cover_info),[write]), - lists:foreach(fun(C) -> io:format(Fd,"~p.~n",[C]) end, Cross), - file:close(Fd). + {ok,Fd} = open_file(filename:join(Dir,?cross_cover_info)), + lists:foreach(fun(C) -> io:format(Fd,"~tp.~n",[C]) end, Cross), + ok = file:close(Fd). %% For each test from which there are cross cover analysed %% modules, write a cross cover log (cross_cover.html). write_cross_cover_logs([{Tag,Coverage}|T],TagDirMods) -> case lists:keyfind(Tag,1,TagDirMods) of {_,Dir,Mods} when Mods=/=[] -> - file:write_file(filename:join(Dir,?raw_cross_coverlog_name), - term_to_binary(Coverage)), + write_file(filename:join(Dir,?raw_cross_coverlog_name), + term_to_binary(Coverage)), CoverLogName = filename:join(Dir,?cross_coverlog_name), - {ok,CoverLog} = file:open(CoverLogName, [write]), + {ok,CoverLog} = open_html_file(CoverLogName), write_coverlog_header(CoverLog), io:fwrite(CoverLog, "

    Coverage results for \'~w\' from all tests

    \n", [Tag]), write_cover_result_table(CoverLog, Coverage), - io:fwrite("Written file ~p\n", [CoverLogName]); + io:fwrite("Written file ~tp\n", [CoverLogName]); _ -> ok end, @@ -5224,19 +5193,11 @@ analyse_modules(_Dir, [], _DetailsFun, Acc) -> %% Support functions for writing the cover logs (both cross and normal) write_coverlog_header(CoverLog) -> - case catch - io:fwrite(CoverLog, - "\n" - "\n" - "\n" - "Coverage results\n" - "", - [?MODULE]) of + case catch io:put_chars(CoverLog,html_header("Coverage results")) of {'EXIT',Reason} -> io:format("\n\nERROR: Could not write normal heading in coverlog.\n" "CoverLog: ~w\n" - "Reason: ~p\n", + "Reason: ~tp\n", [CoverLog,Reason]), io:format(CoverLog,"\n", []); _ -> @@ -5251,20 +5212,22 @@ format_analyse(M,Cov,NotCov,undefined) -> "\n", [M,pc(Cov,NotCov),Cov,NotCov]); format_analyse(M,Cov,NotCov,{file,File}) -> - io_lib:fwrite("" + io_lib:fwrite("" "" "" "\n", - [filename:basename(File),M,pc(Cov,NotCov),Cov,NotCov]); + [uri_encode(filename:basename(File)), + M,pc(Cov,NotCov),Cov,NotCov]); format_analyse(M,Cov,NotCov,{lines,Lines}) -> CoverOutName = atom_to_list(M)++".COVER.html", - {ok,CoverOut} = file:open(CoverOutName, [write]), + {ok,CoverOut} = open_html_file(CoverOutName), write_not_covered(CoverOut,M,Lines), - io_lib:fwrite("" + ok = file:close(CoverOut), + io_lib:fwrite("" "" "" "\n", - [CoverOutName,M,pc(Cov,NotCov),Cov,NotCov]); + [uri_encode(CoverOutName),M,pc(Cov,NotCov),Cov,NotCov]); format_analyse(M,Cov,NotCov,{error,_}) -> io_lib:fwrite("" "" @@ -5280,8 +5243,8 @@ pc(Cov,NotCov) -> write_not_covered(CoverOut,M,Lines) -> + io:put_chars(CoverOut,html_header("Coverage results for "++atom_to_list(M))), io:fwrite(CoverOut, - "\n" "The following lines in module ~w are not covered:\n" "
    NumModuleGroupCaseLogTimeResultComment
    " ++ Col0 ++ "~s" ++ Col1 ++ "" ++ Col0 ++ "~p" ++ Col1 ++ "" ++ Col0 ++ "~s" ++ Col1 ++ "" ++ Col0 ++ "~p" ++ Col1 ++ "" ++ Col0 ++ "~ts" ++ Col1 ++ "" ++ Col0 ++ "~w" ++ Col1 ++ "" ++ Col0 ++ "~ts" ++ Col1 ++ "" ++ Col0 ++ "~w" ++ Col1 ++ "" ++ Col0 ++ "< >" ++ Col1 ++ "" ++ Col0 ++ "0.000s" ++ Col1 ++ "SKIPPED~s
    SKIPPED~ts
    " ++ Col0 ++ "~s" ++ Col1 ++ "" ++ Col0 ++ "~p" ++ Col1 ++ "" ++ Col0 ++ "~s" ++ Col1 ++ "~p< >" ++ Col0 ++ "~ts" ++ Col1 ++ "" ++ Col0 ++ "~w" ++ Col1 ++ "" ++ Col0 ++ "~ts" ++ Col1 ++ "~w< >" ++ St0 ++ "~.3fs" ++ St1 ++ "SKIPPED~s~s
    SKIPPED~ts~ts
    " ++ St0 ++ "~.3fs" ++ St1 ++ "FAILED~s
    ~ts
    " ++ St0 ++ "died" ++ St1 ++ "FAILED~s
    ~ts
    " ++ St0 ++ "~s" ++ St1 ++ "" ++ St0 ++ "~ts" ++ St1 ++ "FAILED~s
    ~ts
    " ++ St0 ++ "~s" ++ St1 ++ "" ++ St0 ++ "~ts" ++ St1 ++ "FAILED~s~s
    ~ts~ts
    " ++ HtmlCmt ++ "" ++ to_string(Comment0) ++ "" ++ St0 ++ "~.3fs" ++ St1 ++ "Ok
    ~w
    ~w
    ~w~w %~w~w
    ~w
    ~w~w %~w~w
    ~w~w %
    \n" "\n", @@ -5292,25 +5255,25 @@ write_not_covered(CoverOut,M,Lines) -> ok end, Lines), - io:fwrite(CoverOut,"
    Line Number
    \n\n", []). + io:put_chars(CoverOut,"\n\n\n"). write_default_coverlog(TestDir) -> - {ok,CoverLog} = file:open(filename:join(TestDir,?coverlog_name), [write]), + {ok,CoverLog} = open_html_file(filename:join(TestDir,?coverlog_name)), write_coverlog_header(CoverLog), - io:fwrite(CoverLog,"Cover tool is not used\n\n", []), - file:close(CoverLog). + io:put_chars(CoverLog,"Cover tool is not used\n\n"), + ok = file:close(CoverLog). write_default_cross_coverlog(TestDir) -> {ok,CrossCoverLog} = - file:open(filename:join(TestDir,?cross_coverlog_name), [write]), + open_html_file(filename:join(TestDir,?cross_coverlog_name)), write_coverlog_header(CrossCoverLog), io:put_chars(CrossCoverLog, ["No cross cover modules exist for this application,", xhtml("
    ","
    "), "or cross cover analysis is not completed.\n" "\n"]), - file:close(CrossCoverLog). + ok = file:close(CrossCoverLog). write_cover_result_table(CoverLog,Coverage) -> io:fwrite(CoverLog, @@ -5321,7 +5284,7 @@ write_cover_result_table(CoverLog,Coverage) -> {TotCov,TotNotCov} = lists:foldl(fun({M,{Cov,NotCov,Details}},{AccCov,AccNotCov}) -> Str = format_analyse(M,Cov,NotCov,Details), - io:fwrite(CoverLog,"~s", [Str]), + io:fwrite(CoverLog,"~ts", [Str]), {AccCov+Cov,AccNotCov+NotCov}; ({_M,{error,_Reason}},{AccCov,AccNotCov}) -> {AccCov,AccNotCov} @@ -5336,5 +5299,72 @@ write_cover_result_table(CoverLog,Coverage) -> "\n" "\n", [TotPercent,TotCov,TotNotCov]), - file:close(CoverLog), + ok = file:close(CoverLog), TotPercent. + + +%%%----------------------------------------------------------------- +%%% Support functions for writing files + +%% HTML files are always written with utf8 encoding +html_header(Title) -> + ["\n" + "\n" + "\n" + "\n" + "", Title, "\n" + "\n" + "\n" + "\n" + "\n"]. + +open_html_file(File) -> + file:open(File,[write,{encoding,utf8}]). + +write_html_file(File,Content) -> + file:write_file(File,unicode:characters_to_binary(Content)). + + +%% Text files are written with default encoding +open_file(File) -> + file:open(File,[write]). + +write_file(File,Content) -> + file:write_file(File,Content). + +%% Encoding of hyperlinks in HTML files +uri_encode(File) -> + Encoding = file:native_name_encoding(), + uri_encode(File,Encoding). + +uri_encode(File,Encoding) -> + Components = filename:split(File), + filename:join([uri_encode_comp(C,Encoding) || C <- Components]). + +uri_encode_comp("/",_) -> + "/"; +uri_encode_comp(Chars,utf8) -> + http_uri:encode(Chars); +uri_encode_comp(Chars,latin1) -> + do_uri_encode(Chars). + +%% Encode a file reference to a latin1 filename so it can be inserted +%% in a utf8 encoded HTML file. +%% This does the same as http_uri:encode/1, except it also encodes all +%% characters >127 - i.e. latin1 but not ASCII. +do_uri_encode([Char|Chars]) -> + case Char>127 orelse sets:is_element(Char, reserved()) of + true -> + [ $% | http_util:integer_to_hexlist(Char)] ++ do_uri_encode(Chars); + false -> + [Char | do_uri_encode(Chars)] + end; +do_uri_encode([]) -> + []. + +%% Copied from http_uri.erl +reserved() -> + sets:from_list([$;, $:, $@, $&, $=, $+, $,, $/, $?, + $#, $[, $], $<, $>, $\", ${, $}, $|, + $\\, $', $^, $%, $ ]). diff --git a/lib/test_server/src/test_server_gl.erl b/lib/test_server/src/test_server_gl.erl index d32c7c07dc..0ab0d58040 100644 --- a/lib/test_server/src/test_server_gl.erl +++ b/lib/test_server/src/test_server_gl.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2012. All Rights Reserved. +%% Copyright Ericsson AB 2012-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -223,20 +223,12 @@ do_set_props([{reject_io_reqs,Bool}|Ps], St) -> do_set_props([], St) -> St. io_req({put_chars,Enc,Bytes}, _, _) when Enc =:= latin1; Enc =:= unicode -> - to_latin1(Enc, Bytes); + unicode:characters_to_list(Bytes, Enc); io_req({put_chars,Encoding,Mod,Func,[Format,Args]}, _, _) -> Str = Mod:Func(Format, Args), - to_latin1(Encoding, Str); + unicode:characters_to_list(Str, Encoding); io_req(_, _, _) -> passthrough. -to_latin1(unicode, Str) -> - [if C > 255 -> - io_lib:format("\\{~.8B}", [C]); - true -> - C - end || C <- unicode:characters_to_list(Str, unicode)]; -to_latin1(latin1, Str) -> Str. - output(Level, Str, Sender, From, St) when is_integer(Level) -> case selected_by_level(Level, stdout, St) of true -> output(stdout, Str, Sender, From, St); @@ -258,7 +250,7 @@ output(Level, Str, Sender, From, St) when is_atom(Level) -> output_to_file(Level, dress_output(Str, Sender, St), From, St). output_to_file(minor, Data0, From, #st{tc={M,F,A},minor=none}) -> - Data = [io_lib:format("=== ~p:~p/~p\n", [M,F,A]),Data0], + Data = [io_lib:format("=== ~w:~w/~w\n", [M,F,A]),Data0], test_server_io:print(From, unexpected_io, Data), ok; output_to_file(minor, Data, From, #st{minor=Fd}) -> diff --git a/lib/test_server/src/test_server_h.erl b/lib/test_server/src/test_server_h.erl index 78daba855d..c624947306 100644 --- a/lib/test_server/src/test_server_h.erl +++ b/lib/test_server/src/test_server_h.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2012. All Rights Reserved. +%% Copyright Ericsson AB 2005-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -140,9 +140,9 @@ report_receiver(info_report, _) -> kernel; report_receiver(_, _) -> none. tag({M,F,A}) when is_atom(M), is_atom(F), is_integer(A) -> - io:format(user, "~n=TESTCASE: ~p:~p/~p", [M,F,A]); + io:format(user, "~n=TESTCASE: ~w:~w/~w", [M,F,A]); tag(Testcase) -> - io:format(user, "~n=TESTCASE: ~p", [Testcase]). + io:format(user, "~n=TESTCASE: ~tp", [Testcase]). tag_event(Event) -> {calendar:local_time(), Event}. diff --git a/lib/test_server/src/test_server_io.erl b/lib/test_server/src/test_server_io.erl index 777b377201..662ee11515 100644 --- a/lib/test_server/src/test_server_io.erl +++ b/lib/test_server/src/test_server_io.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2012. All Rights Reserved. +%% Copyright Ericsson AB 2012-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -235,7 +235,7 @@ handle_info(kill_group_leaders, #st{gls=Gls,stopping=From}=St) -> gen_server:reply(From, ok), {stop,normal,St}; handle_info(Other, St) -> - io:format("Ignoring: ~p\n", [Other]), + io:format("Ignoring: ~tp\n", [Other]), {noreply,St}. terminate(_, _) -> @@ -256,12 +256,12 @@ output(From, Tag, Str, #st{io_buffering=Buffered,buffered=Buf0}=St) -> do_output(stdout, Str, #st{job_name=undefined}) -> io:put_chars(Str); do_output(stdout, Str0, #st{job_name=Name}) -> - Str = io_lib:format("Testing ~s: ~s\n", [Name,Str0]), + Str = io_lib:format("Testing ~ts: ~ts\n", [Name,Str0]), io:put_chars(Str); do_output(Tag, Str, #st{fds=Fds}=St) -> case gb_trees:lookup(Tag, Fds) of none -> - S = io_lib:format("\n*** ERROR: ~p, line ~p: No known '~p' log file\n", + S = io_lib:format("\n*** ERROR: ~w, line ~w: No known '~tp' log file\n", [?MODULE,?LINE,Tag]), do_output(stdout, [S,Str], St); {value,Fd} -> @@ -272,8 +272,8 @@ do_output(Tag, Str, #st{fds=Fds}=St) -> _ -> ok end catch _:Error -> - S = io_lib:format("\n*** ERROR: ~p, line ~p: Error writing to " - "log file '~p': ~p\n", + S = io_lib:format("\n*** ERROR: ~w, line ~w: Error writing to " + "log file '~tp': ~tp\n", [?MODULE,?LINE,Tag,Error]), do_output(stdout, [S,Str], St) end diff --git a/lib/test_server/src/test_server_node.erl b/lib/test_server/src/test_server_node.erl index b307d93c7d..62248af4db 100644 --- a/lib/test_server/src/test_server_node.erl +++ b/lib/test_server/src/test_server_node.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2002-2012. All Rights Reserved. +%% Copyright Ericsson AB 2002-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -249,7 +249,7 @@ print_trc(Out,{trace_ts,P,call,{M,F,A},C,Ts},N) -> "~w: ~s~n" "Process : ~w~n" "Call : ~w:~w/~w~n" - "Arguments : ~p~n" + "Arguments : ~tp~n" "Caller : ~w~n~n", [N,ts(Ts),P,M,F,length(A),A,C]); print_trc(Out,{trace_ts,P,call,{M,F,A},Ts},N) -> @@ -257,14 +257,14 @@ print_trc(Out,{trace_ts,P,call,{M,F,A},Ts},N) -> "~w: ~s~n" "Process : ~w~n" "Call : ~w:~w/~w~n" - "Arguments : ~p~n~n", + "Arguments : ~tp~n~n", [N,ts(Ts),P,M,F,length(A),A]); print_trc(Out,{trace_ts,P,return_from,{M,F,A},R,Ts},N) -> io:format(Out, "~w: ~s~n" "Process : ~w~n" "Return from : ~w:~w/~w~n" - "Return value : ~p~n~n", + "Return value : ~tp~n~n", [N,ts(Ts),P,M,F,A,R]); print_trc(Out,{drop,X},N) -> io:format(Out, @@ -274,7 +274,7 @@ print_trc(Out,Trace,N) -> Ts = element(size(Trace),Trace), io:format(Out, "~w: ~s~n" - "Trace : ~p~n~n", + "Trace : ~tp~n~n", [N,ts(Ts),Trace]). ts({_, _, Micro} = Now) -> {{Y,M,D},{H,Min,S}} = calendar:now_to_local_time(Now), @@ -465,8 +465,8 @@ handle_start_node_return(Version,VsnStr,{started, Node, OVersion, OVsnStr}) -> Str = io_lib:format("WARNING: Started node " "reports different system " "version than current node! " - "Current node version: ~p, ~p " - "Started node version: ~p, ~p", + "Current node version: ~tp, ~tp " + "Started node version: ~tp, ~tp", [Version, VsnStr, OVersion, OVsnStr]), Str1 = lists:flatten(Str), diff --git a/lib/test_server/src/test_server_sup.erl b/lib/test_server/src/test_server_sup.erl index a6d426887e..cd96568970 100644 --- a/lib/test_server/src/test_server_sup.erl +++ b/lib/test_server/src/test_server_sup.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2012. All Rights Reserved. +%% Copyright Ericsson AB 1998-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -72,10 +72,10 @@ timetrap(Timeout0, ReportTVal, Scale, Pid) -> after 10000 -> %% Pid is probably trapping exits, hit it harder... catch error_logger:warning_msg( - "Testcase process ~p not " + "Testcase process ~w not " "responding to timetrap " "timeout:~n" - " ~p.~n" + " ~tp.~n" "Killing testcase...~n", [Pid, Trap]), exit(Pid, kill) @@ -142,11 +142,11 @@ call_crash(Time,Crash,M,F,A) -> {'EXIT',Pid,_Reason} when Crash==any -> ok; {'EXIT',Reason} -> - test_server:format(12, "Wrong crash reason. Wanted ~p, got ~p.", + test_server:format(12, "Wrong crash reason. Wanted ~tp, got ~tp.", [Crash, Reason]), exit({wrong_crash_reason,Reason}); {'EXIT',Pid,Reason} -> - test_server:format(12, "Wrong crash reason. Wanted ~p, got ~p.", + test_server:format(12, "Wrong crash reason. Wanted ~tp, got ~tp.", [Crash, Reason]), exit({wrong_crash_reason,Reason}); {'EXIT',OtherPid,Reason} when OldTrapExit == false -> @@ -312,7 +312,7 @@ check_dict(Dict, Reason) -> [] -> 1; % All ok. List -> - io:format("** ~s (~s) ->~n~p~n",[Reason, Dict, List]), + io:format("** ~ts (~ts) ->~n~tp~n",[Reason, Dict, List]), 0 end. @@ -321,7 +321,7 @@ check_dict_tolerant(Dict, Reason, Mode) -> [] -> 1; % All ok. List -> - io:format("** ~s (~s) ->~n~p~n",[Reason, Dict, List]), + io:format("** ~ts (~ts) ->~n~tp~n",[Reason, Dict, List]), case Mode of pedantic -> 0; @@ -377,7 +377,7 @@ check_new_crash_dumps() -> ok; Num -> test_server_ctrl:format(minor, - "Found ~p crash dumps:~n", [Num]), + "Found ~w crash dumps:~n", [Num]), append_files_to_logfile(Dumps), delete_files(Dumps) end. @@ -385,7 +385,7 @@ check_new_crash_dumps() -> append_files_to_logfile([]) -> ok; append_files_to_logfile([File|Files]) -> NodeName=from($., File), - test_server_ctrl:format(minor, "Crash dump from node ~p:~n",[NodeName]), + test_server_ctrl:format(minor, "Crash dump from node ~tp:~n",[NodeName]), Fd=get(test_server_minor_fd), case file:read_file(File) of {ok, Bin} -> @@ -397,22 +397,22 @@ append_files_to_logfile([File|Files]) -> %% fail, but in that case it will throw an exception so that %% we will be aware of the problem. io:format(Fd, "Unable to write the crash dump " - "to this file: ~p~n", [file:format_error(Error)]) + "to this file: ~tp~n", [file:format_error(Error)]) end; _Error -> - io:format(Fd, "Failed to read: ~s\n", [File]) + io:format(Fd, "Failed to read: ~ts\n", [File]) end, append_files_to_logfile(Files). delete_files([]) -> ok; delete_files([File|Files]) -> - io:format("Deleting file: ~s~n", [File]), + io:format("Deleting file: ~ts~n", [File]), case file:delete(File) of {error, _} -> case file:rename(File, File++".old") of {error, Error} -> io:format("Could neither delete nor rename file " - "~s: ~s.~n", [File, Error]); + "~ts: ~ts.~n", [File, Error]); _ -> ok end; @@ -555,7 +555,7 @@ format_loc([{Mod,LineOrFunc}]) -> format_loc({Mod,Func}) when is_atom(Func) -> io_lib:format("{~w,~w}",[Mod,Func]); format_loc(Loc) -> - io_lib:format("~p",[Loc]). + io_lib:format("~tp",[Loc]). format_loc1([{Mod,Func,Line}]) -> [" ",format_loc1({Mod,Func,Line}),"]"]; @@ -566,9 +566,10 @@ format_loc1({Mod,Func,Line}) -> case {lists:member(no_src, get(test_server_logopts)), lists:reverse(ModStr)} of {false,[$E,$T,$I,$U,$S,$_|_]} -> - io_lib:format("{~w,~w,~w}", - [Mod,Func,downcase(ModStr),?src_listing_ext, - Line,Line]); + io_lib:format("{~w,~w,~w}", + [Mod,Func, + test_server_ctrl:uri_encode(downcase(ModStr)), + ?src_listing_ext,Line,Line]); _ -> io_lib:format("{~w,~w,~w}",[Mod,Func,Line]) end. -- cgit v1.2.3 From a26159db792be4fb0266f8eeba3f22f530034eb0 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Thu, 17 Jan 2013 12:21:17 +0100 Subject: [test_server] Write link target with correct encoding in erl2html2 If the encoding of the source file was utf-8, then the link target could be faulty encoded in the resulting HTML file. This has been corrected. --- lib/test_server/src/erl2html2.erl | 68 +++++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/lib/test_server/src/erl2html2.erl b/lib/test_server/src/erl2html2.erl index 1729257809..9c0ca64173 100644 --- a/lib/test_server/src/erl2html2.erl +++ b/lib/test_server/src/erl2html2.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2012. All Rights Reserved. +%% Copyright Ericsson AB 1997-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -34,16 +34,17 @@ convert(File, Dest) -> %% %% FIXME: The colours should *really* be set with %% stylesheets... + %% + %% The html file is written with the same encoding as the input file. Encoding = encoding(File), Header = ["\n" - "\n" + "\n" "\n" "\n" "\n" - "", File, "\n" + "charset=",html_encoding(Encoding),"\"/>\n" + "", to_raw_list(File,Encoding), "\n" "\n\n" "\n"], @@ -61,7 +62,7 @@ convert(File, Dest, Header) -> case file:open(Dest,[write,raw]) of {ok,DFd} -> file:write(DFd,[Header,"
    \n"]),
    -			    _Lines = build_html(SFd,DFd,Functions),
    +			    _Lines = build_html(SFd,DFd,encoding(File),Functions),
     			    file:write(DFd,["
    \n",footer(), "\n\n"]), %% {_, Time2} = statistics(runtime), @@ -121,21 +122,21 @@ parse_file(Epp,File,InCorrectFile) -> %%%----------------------------------------------------------------- %%% Add a link target for each line and one for each function definition. -build_html(SFd,DFd,Functions) -> - build_html(SFd,DFd,file:read_line(SFd),1,Functions,false). +build_html(SFd,DFd,Encoding,Functions) -> + build_html(SFd,DFd,Encoding,file:read_line(SFd),1,Functions,false). -build_html(SFd,DFd,{ok,Str},L,[{F,A,L}|Functions],_IsFuncDef) -> +build_html(SFd,DFd,Encoding,{ok,Str},L,[{F,A,L}|Functions],_IsFuncDef) -> FALink = http_uri:encode(F++"-"++integer_to_list(A)), - file:write(DFd,[""]), - build_html(SFd,DFd,{ok,Str},L,Functions,true); -build_html(SFd,DFd,{ok,Str},L,[{clause,L}|Functions],_IsFuncDef) -> - build_html(SFd,DFd,{ok,Str},L,Functions,true); -build_html(SFd,DFd,{ok,Str},L,Functions,IsFuncDef) -> + file:write(DFd,[""]), + build_html(SFd,DFd,Encoding,{ok,Str},L,Functions,true); +build_html(SFd,DFd,Encoding,{ok,Str},L,[{clause,L}|Functions],_IsFuncDef) -> + build_html(SFd,DFd,Encoding,{ok,Str},L,Functions,true); +build_html(SFd,DFd,Encoding,{ok,Str},L,Functions,IsFuncDef) -> LStr = line_number(L), Str1 = line(Str,IsFuncDef), file:write(DFd,[LStr,Str1]), - build_html(SFd,DFd,file:read_line(SFd),L+1,Functions,false); -build_html(_SFd,_DFd,eof,L,_Functions,_IsFuncDef) -> + build_html(SFd,DFd,Encoding,file:read_line(SFd),L+1,Functions,false); +build_html(_SFd,_DFd,_Encoding,eof,L,_Functions,_IsFuncDef) -> L. line_number(L) -> @@ -190,16 +191,35 @@ footer() -> %%%----------------------------------------------------------------- %%% Read encoding from source file encoding(File) -> - Encoding = - case epp:read_encoding(File) of - none -> - epp:default_encoding(); - E -> - E - end, - html_encoding(Encoding). + case epp:read_encoding(File) of + none -> + epp:default_encoding(); + E -> + E + end. +%%%----------------------------------------------------------------- +%%% Covert encoding atom to string for use in HTML header html_encoding(latin1) -> "iso-8859-1"; html_encoding(utf8) -> "utf-8". + +%%%----------------------------------------------------------------- +%%% Convert a string to a list of raw printable characters in the +%%% given encoding. This is necessary since the files (source and +%%% destination) are both opened in raw mode (default encoding). Byte +%%% by byte is read from source and written to the destination. This +%%% conversion is needed when printing data that is not first read +%%% from the source. +%%% +%%% Example: if the encoding of the file is utf8, and we have a string +%%% containing "å" = [229], then we need to convert this to [195,165] +%%% before writing. Note that this conversion is only necessary +%%% because the destination file is not (necessarily) opened with utf8 +%%% encoding - it is opened with default encoding in order to allow +%%% raw file mode and byte by byte copying from source. +to_raw_list(X,latin1) when is_list(X) -> + X; +to_raw_list(X,utf8) when is_list(X) -> + binary_to_list(unicode:characters_to_binary(X)). -- cgit v1.2.3 From c463aaf0355d3a958df2335d13dc88aafb667f40 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Thu, 17 Jan 2013 18:55:21 +0100 Subject: [test_server] Add tests for unicode support --- lib/test_server/test/test_server_SUITE.erl | 226 +++++++++++++++++++-- .../test/test_server_SUITE_data/Makefile.src | 3 +- .../test_server_unicode_SUITE.erl | 82 ++++++++ lib/test_server/test/test_server_test_lib.erl | 66 +++--- 4 files changed, 333 insertions(+), 44 deletions(-) create mode 100644 lib/test_server/test/test_server_SUITE_data/test_server_unicode_SUITE.erl diff --git a/lib/test_server/test/test_server_SUITE.erl b/lib/test_server/test/test_server_SUITE.erl index fb82a87fd0..bad35b2d51 100644 --- a/lib/test_server/test/test_server_SUITE.erl +++ b/lib/test_server/test/test_server_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2012. All Rights Reserved. +%% Copyright Ericsson AB 2010-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -31,6 +31,7 @@ -include_lib("common_test/include/ct.hrl"). -include("test_server_test_lib.hrl"). +-include_lib("kernel/include/file.hrl"). %%-------------------------------------------------------------------- %% COMMON TEST CALLBACK FUNCTIONS @@ -68,6 +69,13 @@ init_per_testcase(_TestCase, Config) -> %% @spec end_per_testcase(TestCase, Config0) -> %% void() | {save_config,Config1} | {fail,Reason} +end_per_testcase(test_server_unicode, _Config) -> + [_,Host] = string:tokens(atom_to_list(node()), "@"), + N1 = list_to_atom("test_server_tester_latin1" ++ "@" ++ Host), + N2 = list_to_atom("test_server_tester_utf8" ++ "@" ++ Host), + test_server:stop_node(N1), + test_server:stop_node(N2), + ok; end_per_testcase(_TestCase, _Config) -> ok. @@ -80,7 +88,8 @@ all() -> [test_server_SUITE, test_server_parallel01_SUITE, test_server_conf02_SUITE, test_server_conf01_SUITE, test_server_skip_SUITE, test_server_shuffle01_SUITE, - test_server_break_SUITE, test_server_cover_SUITE]. + test_server_break_SUITE, test_server_cover_SUITE, + test_server_unicode]. %%-------------------------------------------------------------------- @@ -171,7 +180,23 @@ test_server_cover_SUITE(Config) -> ok end. +test_server_unicode(Config) -> + run_test_server_tests("test_server_unicode_SUITE", [], + 5, 0, 3, 3, 0, 0, 0, 0, 5, Config), + %% Create and run two test suites - one with filename and content + %% in latin1 (not on windows) and one with filename and content in + %% utf8. Both have name and content including letters äöå. Check + %% that all logs are generated with utf8 encoded filenames. + case os:type() of + {win32,_} -> + ok; + _ -> + generate_and_run_unicode_test(Config,latin1) + end, + generate_and_run_unicode_test(Config,utf8). + +%%%----------------------------------------------------------------- run_test_server_tests(SuiteName, Skip, NCases, NFail, NExpected, NSucc, NUsrSkip, NAutoSkip, NActualSkip, NActualFail, NActualSucc, Config) -> @@ -182,12 +207,13 @@ run_test_server_tests(SuiteName, Skip, NCases, NFail, NExpected, NSucc, run_test_server_tests(SuiteName, Skip, NCases, NFail, NExpected, NSucc, NUsrSkip, NAutoSkip, NActualSkip, NActualFail, NActualSucc, Cover, Config) -> - + Node = proplists:get_value(node, Config), + Encoding = rpc:call(Node,file,native_name_encoding,[]), WorkDir = proplists:get_value(work_dir, Config), - ct:log("Test case log files\n", - [filename:join(WorkDir, SuiteName++".logs")]), + LogDir = filename:join(WorkDir, SuiteName++".logs"), + LogDirUri = test_server_ctrl:uri_encode(LogDir, Encoding), + ct:log("Test case log files\n", [LogDirUri]), - Node = proplists:get_value(node, Config), {ok,_Pid} = rpc:call(Node,test_server_ctrl, start, []), case Cover of false -> @@ -207,12 +233,10 @@ run_test_server_tests(SuiteName, Skip, NCases, NFail, NExpected, NSucc, rpc:call(Node,test_server_ctrl, stop, []), - {ok,Data} = test_server_test_lib:parse_suite( - lists:last( - lists:sort( - filelib:wildcard( - filename:join([WorkDir,SuiteName++".logs", - "run*","suite.log"]))))), + LogDir1 = translate_filename(LogDir,Encoding), + LastRunDir = get_latest_run_dir(LogDir1), + LastSuiteLog = filename:join(LastRunDir,"suite.log"), + {ok,Data} = test_server_test_lib:parse_suite(LastSuiteLog), check([{"Number of cases",NCases,Data#suite.n_cases}, {"Number failed",NFail,Data#suite.n_cases_failed}, {"Number expected",NExpected,Data#suite.n_cases_expected}, @@ -229,6 +253,47 @@ run_test_server_tests(SuiteName, Skip, NCases, NFail, NExpected, NSucc, end,{0,0,0},Data#suite.cases), Data. +translate_filename(Filename,EncodingOnTestNode) -> + case {file:native_name_encoding(),EncodingOnTestNode} of + {X,X} -> Filename; + {utf8,latin1} -> list_to_binary(Filename); + {latin1,utf8} -> unicode:characters_to_binary(Filename) + end. + +get_latest_run_dir(Dir) -> + %% For the time being, filelib:wildcard can not take a binary + %% argument, so we avoid using this here. + case file:list_dir(Dir) of + {ok,Files} -> + {ok,RE} = re:compile(<<"^run.[1-2][-_\.0-9]*$">>), + RunDirs = lists:filter( + fun(F) -> + L = l(F), + case re:run(F,RE) of + {match,[{0,L}]} -> true; + _ -> false + end + end, Files), + case RunDirs of + [] -> + Dir; + [H|T] -> + filename:join(Dir,get_latest_dir(T,H)) + end; + _ -> + Dir + end. + +l(X) when is_binary(X) -> size(X); +l(X) when is_list(X) -> length(X). + +get_latest_dir([H|T],Latest) when H>Latest -> + get_latest_dir(T,H); +get_latest_dir([_|T],Latest) -> + get_latest_dir(T,Latest); +get_latest_dir([],Latest) -> + Latest. + check([{Str,Same,Same}|T], Status) -> io:format("~s: ~p\n", [Str,Same]), check(T, Status); @@ -246,4 +311,139 @@ until(Fun) -> timer:sleep(100), until(Fun) end. - + +generate_and_run_unicode_test(Config0,Encoding) -> + DataDir = ?config(data_dir,Config0), + Suite = create_unicode_test_suite(DataDir,Encoding), + + %% We can not run this test on default node since it must be + %% started with correct file name mode (+fnu/+fnl). + %% OBS: the node are stopped by end_per_testcase/2 + Config1 = lists:keydelete(node,1,Config0), + Config2 = lists:keydelete(work_dir,1,Config1), + NodeName = list_to_atom("test_server_tester_" ++ atom_to_list(Encoding)), + ErtsSwitch = case Encoding of + latin1 -> "+fnl"; + utf8 -> "+fnu" + end, + Config = start_node(Config2,NodeName,ErtsSwitch), + + %% Compile the suite + Node = proplists:get_value(node,Config), + {ok,Mod} = rpc:call(Node,compile,file,[Suite,[{outdir,DataDir}]]), + ModStr = atom_to_list(Mod), + + %% Clean logdir + LogDir0 = filename:join(DataDir,ModStr++".logs"), + LogDir = translate_filename(LogDir0,Encoding), + rm_dir(LogDir), + + %% Run the test + run_test_server_tests(ModStr, [], 3, 0, 1, 1, 0, 0, 0, 0, 3, Config), + + %% Check that all logs are created with utf8 encoded filenames + true = filelib:is_dir(LogDir), + + RunDir = get_latest_run_dir(LogDir), + true = filelib:is_dir(RunDir), + + LowerModStr = string:to_lower(ModStr), + SuiteHtml = translate_filename(LowerModStr++".src.html",Encoding), + true = filelib:is_regular(filename:join(RunDir,SuiteHtml)), + + TCLog = translate_filename(LowerModStr++".tc_äöå.html",Encoding), + true = filelib:is_regular(filename:join(RunDir,TCLog)), + ok. + +%% Same as test_server_test_lib:start_slave, but starts a peer with +%% additional arguments. +%% The reason for this is that we need to start nodes with +fnu/+fnl, +%% and that will not work well with a slave node since slave nodes run +%% remote file system on master - i.e. they will use same file name +%% mode as the master. +start_node(Config,Name,Args) -> + [_,Host] = string:tokens(atom_to_list(node()), "@"), + ct:log("Trying to start ~w@~s~n",[Name,Host]), + case test_server:start_node(Name, peer, [{args,Args}]) of + {error,Reason} -> + test_server:fail(Reason); + {ok,Node} -> + ct:log("Node ~p started~n", [Node]), + test_server_test_lib:prepare_tester_node(Node,Config) + end. + +create_unicode_test_suite(Dir,Encoding) -> + ModStr = "test_server_"++atom_to_list(Encoding)++"_äöå_SUITE", + File = filename:join(Dir,ModStr++".erl"), + Suite = + ["%% -*- ",epp:encoding_to_string(Encoding)," -*-\n", + "-module(",ModStr,").\n" + "\n" + "-export([all/1, init_per_suite/1, end_per_suite/1]).\n" + "-export([init_per_testcase/2, end_per_testcase/2]).\n" + "-export([tc_äöå/1]).\n" + "\n" + "-include_lib(\"test_server/include/test_server.hrl\").\n" + "\n" + "all(suite) ->\n" + " [tc_äöå].\n" + "\n" + "init_per_suite(Config) ->\n" + " Config.\n" + "\n" + "end_per_suite(_Config) ->\n" + " ok.\n" + "\n" + "init_per_testcase(_Case,Config) ->\n" + " init_timetrap(500,Config).\n" + "\n" + "init_timetrap(T,Config) ->\n" + " Dog = ?t:timetrap(T),\n" + " [{watchdog, Dog}|Config].\n" + "\n" + "end_per_testcase(_Case,Config) ->\n" + " cancel_timetrap(Config).\n" + "\n" + "cancel_timetrap(Config) ->\n" + " Dog=?config(watchdog, Config),\n" + " ?t:timetrap_cancel(Dog),\n" + " ok.\n" + "\n" + "tc_äöå(Config) when is_list(Config) ->\n" + " true = filelib:is_dir(?config(priv_dir,Config)),\n" + " ok.\n"], + {ok,Fd} = file:open(raw_filename(File,Encoding),[write,{encoding,Encoding}]), + io:put_chars(Fd,Suite), + ok = file:close(Fd), + File. + +raw_filename(Name,latin1) -> list_to_binary(Name); +raw_filename(Name,utf8) -> unicode:characters_to_binary(Name). + +rm_dir(Dir) -> + case file:list_dir(Dir) of + {error,enoent} -> + ok; + {ok,Files} -> + rm_files([filename:join(Dir, F) || F <- Files]), + file:del_dir(Dir) + end. + +rm_files([F | Fs]) -> + case file:read_file_info(F) of + {ok,#file_info{type=directory}} -> + rm_dir(F), + rm_files(Fs); + {ok,_Regular} -> + case file:delete(F) of + ok -> + rm_files(Fs); + {error,Errno} -> + exit({del_failed,F,Errno}) + end + end; +rm_files([]) -> + ok. + +erts_switch(latin1) -> "+fnl"; +erts_switch(utf8) -> "+fnu". diff --git a/lib/test_server/test/test_server_SUITE_data/Makefile.src b/lib/test_server/test/test_server_SUITE_data/Makefile.src index c770627f04..5aeb035572 100644 --- a/lib/test_server/test/test_server_SUITE_data/Makefile.src +++ b/lib/test_server/test/test_server_SUITE_data/Makefile.src @@ -7,4 +7,5 @@ all: erlc test_server_skip_SUITE.erl erlc test_server_break_SUITE.erl erlc test_server_cover_SUITE.erl - erlc +debug_info test_server_cover_SUITE_data/cover_helper.erl \ No newline at end of file + erlc +debug_info test_server_cover_SUITE_data/cover_helper.erl + erlc test_server_unicode_SUITE.erl diff --git a/lib/test_server/test/test_server_SUITE_data/test_server_unicode_SUITE.erl b/lib/test_server/test/test_server_SUITE_data/test_server_unicode_SUITE.erl new file mode 100644 index 0000000000..efdc626c24 --- /dev/null +++ b/lib/test_server/test/test_server_SUITE_data/test_server_unicode_SUITE.erl @@ -0,0 +1,82 @@ +%% -*- coding: utf-8 -*- +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2013. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +-module(test_server_unicode_SUITE). + +-export([all/1, init_per_suite/1, end_per_suite/1]). +-export([init_per_testcase/2, end_per_testcase/2]). +-export(['#difficult_case_name_äöå'/1, + print_and_log_unicode/1, + print_and_log_latin1/1]). + +-include_lib("test_server/include/test_server.hrl"). + +all(suite) -> + ['#difficult_case_name_äöå', + print_and_log_unicode, + print_and_log_latin1]. + +init_per_suite(Config) -> + Config. + +end_per_suite(_Config) -> + ok. + +init_per_testcase(_Case,Config) -> + init_timetrap(500,Config). + +init_timetrap(T,Config) -> + Dog = ?t:timetrap(T), + [{watchdog, Dog}|Config]. + +end_per_testcase(_Case,Config) -> + cancel_timetrap(Config). + +cancel_timetrap(Config) -> + Dog=?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + + +%%%----------------------------------------------------------------- +%%% Test cases + +'#difficult_case_name_äöå'(Config) when is_list(Config) -> + ok. + +print_and_log_unicode(Config) when is_list(Config) -> + String = "שלו×-שלו×+של 日本語", + test_server:comment(String), + test_server:capture_start(), + io:format("String with ts: ~ts",[String]), + test_server:capture_stop(), + "String with ts: "++String = lists:flatten(test_server:capture_get()), + ok. + +print_and_log_latin1(Config) when is_list(Config) -> + String = "æøå", + test_server:comment(String), + test_server:capture_start(), + io:format("String with s: ~s",[String]), + io:format("String with ts: ~ts",[String]), + test_server:capture_stop(), + ["String with s: "++String, + "String with ts: "++String] = + [lists:flatten(L) || L<- test_server:capture_get()], + ok. diff --git a/lib/test_server/test/test_server_test_lib.erl b/lib/test_server/test/test_server_test_lib.erl index d466aa0110..cd6804f7ad 100644 --- a/lib/test_server/test/test_server_test_lib.erl +++ b/lib/test_server/test/test_server_test_lib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2009-2012. All Rights Reserved. +%% Copyright Ericsson AB 2009-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -20,6 +20,9 @@ -export([parse_suite/1]). -export([init/2, pre_init_per_testcase/3, post_end_per_testcase/4]). +%% for test_server_SUITE when node can not be started as slave +-export([prepare_tester_node/2]). + -include("test_server_test_lib.hrl"). %% The CTH hooks all tests @@ -49,38 +52,41 @@ start_slave(Config,_Level) -> ct:log("Node ~p started~n", [Node]), IsCover = test_server:is_cover(), if IsCover -> - cover:start(Node); - true-> - ok + cover:start(Node); + true-> + ok end, - DataDir = proplists:get_value(data_dir, Config), - %% We would normally use priv_dir for temporary data, - %% but the pathnames gets too long on Windows. - %% Until the run-time system can support long pathnames, - %% use the data dir. - WorkDir = DataDir, - - %% WorkDir as well as directory of Test Server suites - %% have to be in code path on Test Server node. - [_ | Parts] = lists:reverse(filename:split(DataDir)), - TSDir = filename:join(lists:reverse(Parts)), - AddPathDirs = case proplists:get_value(path_dirs, Config) of - undefined -> []; - Ds -> Ds - end, - PathDirs = [WorkDir,TSDir | AddPathDirs], - [true = rpc:call(Node, code, add_patha, [D]) || D <- PathDirs], - io:format("Dirs added to code path (on ~w):~n", - [Node]), - [io:format("~s~n", [D]) || D <- PathDirs], - - true = rpc:call(Node, os, putenv, - ["TEST_SERVER_FRAMEWORK", "undefined"]), - - ok = rpc:call(Node, file, set_cwd, [WorkDir]), - [{node,Node}, {work_dir,WorkDir} | Config] + prepare_tester_node(Node,Config) end. +prepare_tester_node(Node,Config) -> + DataDir = proplists:get_value(data_dir, Config), + %% We would normally use priv_dir for temporary data, + %% but the pathnames gets too long on Windows. + %% Until the run-time system can support long pathnames, + %% use the data dir. + WorkDir = DataDir, + + %% WorkDir as well as directory of Test Server suites + %% have to be in code path on Test Server node. + [_ | Parts] = lists:reverse(filename:split(DataDir)), + TSDir = filename:join(lists:reverse(Parts)), + AddPathDirs = case proplists:get_value(path_dirs, Config) of + undefined -> []; + Ds -> Ds + end, + PathDirs = [WorkDir,TSDir | AddPathDirs], + [true = rpc:call(Node, code, add_patha, [D]) || D <- PathDirs], + io:format("Dirs added to code path (on ~w):~n", + [Node]), + [io:format("~s~n", [D]) || D <- PathDirs], + + true = rpc:call(Node, os, putenv, + ["TEST_SERVER_FRAMEWORK", "undefined"]), + + ok = rpc:call(Node, file, set_cwd, [WorkDir]), + [{node,Node}, {work_dir,WorkDir} | Config]. + post_end_per_testcase(_TC, Config, Return, State) -> Node = proplists:get_value(node, Config), Cover = test_server:is_cover(), -- cgit v1.2.3 From 9c262fece1241bd006cd78ce84b63e4924c55325 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Fri, 18 Jan 2013 17:38:11 +0100 Subject: [ts] Use unicode:characters_to_list/2 instead of binary_to_list/1 When reading text files with file:read_file/1, assume that the file has the default encding (epp:default_encoding()) and covert the binary to string by unicode:characters_to_list(Bin,DefaultEncoding) instead of binary_to_list(Bin) as before. --- lib/test_server/src/ts_install.erl | 13 ++++++------- lib/test_server/src/ts_lib.erl | 15 ++++++++++++--- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/lib/test_server/src/ts_install.erl b/lib/test_server/src/ts_install.erl index ba8952f10f..e9e559df5d 100644 --- a/lib/test_server/src/ts_install.erl +++ b/lib/test_server/src/ts_install.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2012. All Rights Reserved. +%% Copyright Ericsson AB 1997-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -93,7 +93,7 @@ autoconf1(_,_) -> throw(cross_installation_failed). autoconf2({ok, Bin}) -> - get_vars(binary_to_list(Bin), name, [], []); + get_vars(ts_lib:b2s(Bin), name, [], []); autoconf2(Error) -> Error. @@ -170,12 +170,12 @@ parse_xcomp_file(Filepath) -> parse_xcomp_file([<> = Line|R],Envs,Flags) when $A =< A, A =< $Z -> [Var,Value] = binary:split(Line,<<"=">>), - parse_xcomp_file(R,[{binary_to_list(Var), - binary_to_list(Value)}|Envs],Flags); + parse_xcomp_file(R,[{ts_lib:b2s(Var), + ts_lib:b2s(Value)}|Envs],Flags); parse_xcomp_file([<<"erl_xcomp_",Line/binary>>|R],Envs,Flags) -> [Var,Value] = binary:split(Line,<<"=">>), - parse_xcomp_file(R,Envs,[{binary_to_list(Var), - binary_to_list(Value)}|Flags]); + parse_xcomp_file(R,Envs,[{ts_lib:b2s(Var), + ts_lib:b2s(Value)}|Flags]); parse_xcomp_file([_|R],Envs,Flags) -> parse_xcomp_file(R,Envs,Flags); parse_xcomp_file([],Envs,Flags) -> @@ -407,4 +407,3 @@ extra_platform_label() -> [_|_]=Label -> "/" ++ Label; false -> "" end. - diff --git a/lib/test_server/src/ts_lib.erl b/lib/test_server/src/ts_lib.erl index c0200ab67c..a00f607fc1 100644 --- a/lib/test_server/src/ts_lib.erl +++ b/lib/test_server/src/ts_lib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2012. All Rights Reserved. +%% Copyright Ericsson AB 1997-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -29,7 +29,8 @@ specs/1, suites/2, subst_file/3, subst/2, print_data/1, make_non_erlang/2, - maybe_atom_to_list/1, progress/4 + maybe_atom_to_list/1, progress/4, + b2s/1 ]). error(Reason) -> @@ -155,7 +156,7 @@ suite_order(_) -> 200. subst_file(In, Out, Vars) -> case file:read_file(In) of {ok, Bin} -> - Subst = subst(binary_to_list(Bin), Vars, []), + Subst = subst(b2s(Bin), Vars, []), case file:write_file(Out, Subst) of ok -> ok; @@ -334,3 +335,11 @@ make_non_erlang_do(DataDir, Variables) -> after timer:sleep(100) %% maybe unnecessary now when we don't do set_cwd anymore end. + +b2s(Bin) -> + unicode:characters_to_list(Bin,default_encoding()). + +default_encoding() -> + try epp:default_encoding() + catch error:undef -> latin1 + end. -- cgit v1.2.3 From 0df8de4fa21d650b3f2795e3aa6d29952e4b08de Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Wed, 23 Jan 2013 14:44:21 +0100 Subject: [common_test] Update common test modules to handle unicode * Use UTF-8 encoding for all HTML files, except the HTML version of the test suite generated with erl2html2:convert, which will have the same encoding as the original test suite (.erl) file. * Encode link targets in HTML files with test_server_ctrl:uri_encode/1. * Use unicode modifier 't' with ~s when appropriate. * Use unicode:characters_to_list and unicode:characters_to_binary for conversion between binaries and strings instead of binary_to_list and list_to_binary. --- lib/common_test/src/ct.erl | 4 +- lib/common_test/src/ct_config.erl | 8 +- lib/common_test/src/ct_config_plain.erl | 4 +- lib/common_test/src/ct_conn_log_h.erl | 33 +++-- lib/common_test/src/ct_event.erl | 4 +- lib/common_test/src/ct_framework.erl | 27 ++-- lib/common_test/src/ct_gen_conn.erl | 4 +- lib/common_test/src/ct_groups.erl | 4 +- lib/common_test/src/ct_hooks.erl | 6 +- lib/common_test/src/ct_logs.erl | 142 ++++++++++++++------- lib/common_test/src/ct_make.erl | 8 +- lib/common_test/src/ct_master.erl | 42 +++--- lib/common_test/src/ct_master_event.erl | 6 +- lib/common_test/src/ct_master_logs.erl | 24 ++-- lib/common_test/src/ct_master_status.erl | 4 +- lib/common_test/src/ct_netconfc.erl | 40 +++--- lib/common_test/src/ct_run.erl | 30 ++--- lib/common_test/src/ct_telnet.erl | 32 ++--- lib/common_test/src/ct_telnet_client.erl | 4 +- lib/common_test/src/ct_testspec.erl | 6 +- lib/common_test/src/ct_util.erl | 10 +- lib/common_test/src/cth_conn_log.erl | 7 +- lib/common_test/src/cth_surefire.erl | 4 +- lib/common_test/src/unix_telnet.erl | 4 +- lib/common_test/test/ct_netconfc_SUITE_data/ns.erl | 21 +-- 25 files changed, 277 insertions(+), 201 deletions(-) diff --git a/lib/common_test/src/ct.erl b/lib/common_test/src/ct.erl index 8eafdff29f..1c7fafc491 100644 --- a/lib/common_test/src/ct.erl +++ b/lib/common_test/src/ct.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2012. All Rights Reserved. +%% Copyright Ericsson AB 2003-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -735,7 +735,7 @@ fail(Format, Args) -> %%% overwrites the string set by this function.

    comment(Comment) when is_list(Comment) -> Formatted = - case (catch io_lib:format("~s",[Comment])) of + case (catch io_lib:format("~ts",[Comment])) of {'EXIT',_} -> % it's a list not a string io_lib:format("~p",[Comment]); String -> diff --git a/lib/common_test/src/ct_config.erl b/lib/common_test/src/ct_config.erl index b1d709bc75..ee5f868689 100644 --- a/lib/common_test/src/ct_config.erl +++ b/lib/common_test/src/ct_config.erl @@ -1,7 +1,7 @@ %%-------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2012. All Rights Reserved. +%% Copyright Ericsson AB 2010-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -607,7 +607,7 @@ encrypt_config_file(SrcFileName, EncryptFileName, {key,Key}) -> EncBin = crypto:des3_cbc_encrypt(K1, K2, K3, IVec, Bin2), case file:write_file(EncryptFileName, EncBin) of ok -> - io:format("~s --(encrypt)--> ~s~n", + io:format("~ts --(encrypt)--> ~ts~n", [SrcFileName,EncryptFileName]), ok; {error,Reason} -> @@ -649,7 +649,7 @@ decrypt_config_file(EncryptFileName, TargetFileName, {key,Key}) -> _ -> case file:write_file(TargetFileName, SrcBin) of ok -> - io:format("~s --(decrypt)--> ~s~n", + io:format("~ts --(decrypt)--> ~ts~n", [EncryptFileName,TargetFileName]), ok; {error,Reason} -> @@ -700,7 +700,7 @@ get_crypt_key_from_file() -> _ -> case catch string:tokens(binary_to_list(Result), [$\n,$\r]) of [Key] -> - io:format("~nCrypt key file: ~s~n", [FullName]), + io:format("~nCrypt key file: ~ts~n", [FullName]), Key; _ -> {error,{bad_crypt_file,FullName}} diff --git a/lib/common_test/src/ct_config_plain.erl b/lib/common_test/src/ct_config_plain.erl index 237df5c8f3..c6547f0a40 100644 --- a/lib/common_test/src/ct_config_plain.erl +++ b/lib/common_test/src/ct_config_plain.erl @@ -1,7 +1,7 @@ %%-------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2011. All Rights Reserved. +%% Copyright Ericsson AB 2010-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -47,7 +47,7 @@ read_config(ConfigFile) -> {error,no_crypt_file} -> {error,{config_file_error, lists:flatten( - io_lib:format("~s",[file:format_error(Reason)]))}}; + io_lib:format("~ts",[file:format_error(Reason)]))}}; {error,CryptError} -> {error,{decrypt_file_error,CryptError}}; _ when is_list(Key) -> diff --git a/lib/common_test/src/ct_conn_log_h.erl b/lib/common_test/src/ct_conn_log_h.erl index d7bd18606b..ac08a3e0ad 100644 --- a/lib/common_test/src/ct_conn_log_h.erl +++ b/lib/common_test/src/ct_conn_log_h.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2012. All Rights Reserved. +%% Copyright Ericsson AB 2012-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -52,7 +52,7 @@ open_files([],State) -> do_open_files([{Tag,File}|Logs],Acc) -> - case file:open(File, [write]) of + case file:open(File, [write,{encoding,utf8}]) of {ok,Fd} -> do_open_files(Logs,[{Tag,Fd}|Acc]); {error,Reason} -> @@ -98,9 +98,9 @@ terminate(_,#state{logs=Logs}) -> %%% Writing reports write_report(Time,#conn_log{module=ConnMod}=Info,Data,State) -> {LogType,Fd} = get_log(Info,State), - io:format(Fd,"~n~s~s~s",[format_head(ConnMod,LogType,Time), - format_title(LogType,Info), - format_data(ConnMod,LogType,Data)]). + io:format(Fd,"~n~ts~ts~ts",[format_head(ConnMod,LogType,Time), + format_title(LogType,Info), + format_data(ConnMod,LogType,Data)]). write_error(Time,#conn_log{module=ConnMod}=Info,Report,State) -> case get_log(Info,State) of @@ -109,9 +109,10 @@ write_error(Time,#conn_log{module=ConnMod}=Info,Report,State) -> %% sasl error handler, so don't write it again. ok; {LogType,Fd} -> - io:format(Fd,"~n~s~s~s",[format_head(ConnMod,LogType,Time," ERROR"), - format_title(LogType,Info), - format_error(LogType,Report)]) + io:format(Fd,"~n~ts~ts~ts", + [format_head(ConnMod,LogType,Time," ERROR"), + format_title(LogType,Info), + format_error(LogType,Report)]) end. get_log(Info,State) -> @@ -140,16 +141,16 @@ format_head(ConnMod,LogType,Time) -> format_head(ConnMod,LogType,Time,""). format_head(ConnMod,raw,Time,Text) -> - io_lib:format("~n~p, ~p~s, ",[now_to_time(Time),ConnMod,Text]); + io_lib:format("~n~w, ~w~ts, ",[now_to_time(Time),ConnMod,Text]); format_head(ConnMod,_,Time,Text) -> Head = pad_char_end(?WIDTH,pretty_head(now_to_time(Time),ConnMod,Text),$=), - io_lib:format("~n~s",[Head]). + io_lib:format("~n~ts",[Head]). format_title(raw,#conn_log{client=Client}=Info) -> - io_lib:format("Client ~p ~s ~s",[Client,actionstr(Info),serverstr(Info)]); + io_lib:format("Client ~w ~s ~ts",[Client,actionstr(Info),serverstr(Info)]); format_title(_,Info) -> Title = pad_char_end(?WIDTH,pretty_title(Info),$=), - io_lib:format("~n~s", [Title]). + io_lib:format("~n~ts", [Title]). format_data(_,_,NoData) when NoData == ""; NoData == <<>> -> ""; @@ -162,8 +163,6 @@ format_error(pretty,Report) -> [io_lib:format("~n ~p: ~p",[K,V]) || {K,V} <- Report]. - - %%%----------------------------------------------------------------- %%% Helpers conn_info(LoggingProc, #conn_log{client=undefined} = ConnInfo) -> @@ -187,12 +186,12 @@ now_to_time({_,_,MicroS}=Now) -> pretty_head({{{Y,Mo,D},{H,Mi,S}},MicroS},ConnMod,Text0) -> Text = string:to_upper(atom_to_list(ConnMod) ++ Text0), - io_lib:format("= ~s ==== ~s-~s-~p::~s:~s:~s,~s ", + io_lib:format("= ~s ==== ~s-~s-~w::~s:~s:~s,~s ", [Text,t(D),month(Mo),Y,t(H),t(Mi),t(S), micro2milli(MicroS)]). pretty_title(#conn_log{client=Client}=Info) -> - io_lib:format("= Client ~p ~s Server ~s ", + io_lib:format("= Client ~w ~s Server ~ts ", [Client,actionstr(Info),serverstr(Info)]). actionstr(#conn_log{action=send}) -> "----->"; @@ -204,7 +203,7 @@ actionstr(_) -> "<---->". serverstr(#conn_log{name=undefined,address=Address}) -> io_lib:format("~p",[Address]); serverstr(#conn_log{name=Alias,address=Address}) -> - io_lib:format("~p(~p)",[Alias,Address]). + io_lib:format("~w(~p)",[Alias,Address]). month(1) -> "Jan"; month(2) -> "Feb"; diff --git a/lib/common_test/src/ct_event.erl b/lib/common_test/src/ct_event.erl index 49e0635d79..c1c1d943b9 100644 --- a/lib/common_test/src/ct_event.erl +++ b/lib/common_test/src/ct_event.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2012. All Rights Reserved. +%% Copyright Ericsson AB 2006-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -150,7 +150,7 @@ init(RecvPids) -> %%-------------------------------------------------------------------- handle_event(Event,State=#state{receivers=RecvPids}) -> print("~n=== ~w ===~n", [?MODULE]), - print("~p: ~p~n", [Event#event.name,Event#event.data]), + print("~w: ~w~n", [Event#event.name,Event#event.data]), lists:foreach(fun(Recv) -> report_event(Recv,Event) end, RecvPids), {ok,State}. diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl index c1abf27e9f..5fe4eaf511 100644 --- a/lib/common_test/src/ct_framework.erl +++ b/lib/common_test/src/ct_framework.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2012. All Rights Reserved. +%% Copyright Ericsson AB 2004-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -750,12 +750,12 @@ error_notification(Mod,Func,_Args,{Error,Loc}) -> Descr1 = lists:flatten(io_lib:format("~P",[Descr,10])), if length(Descr1) > 50 -> Descr2 = string:substr(Descr1,1,50), - io_lib:format("{badmatch,~s...}",[Descr2]); + io_lib:format("{badmatch,~ts...}",[Descr2]); true -> - io_lib:format("{badmatch,~s}",[Descr1]) + io_lib:format("{badmatch,~ts}",[Descr1]) end; {test_case_failed,Reason} -> - case (catch io_lib:format("{test_case_failed,~s}", [Reason])) of + case (catch io_lib:format("{test_case_failed,~ts}", [Reason])) of {'EXIT',_} -> io_lib:format("{test_case_failed,~p}", [Reason]); Result -> Result @@ -788,7 +788,7 @@ error_notification(Mod,Func,_Args,{Error,Loc}) -> "" ++ "(" ++ "" ++ Comment ++ "" ++ ")" ++ "", - Str = io_lib:format("~s ~s", [ErrorHtml,CommentHtml]), + Str = io_lib:format("~ts ~ts", [ErrorHtml,CommentHtml]), test_server:comment(Str) end end, @@ -803,24 +803,24 @@ error_notification(Mod,Func,_Args,{Error,Loc}) -> end, case Loc of [{?MODULE,error_in_suite}] -> - PrintErr("Error in suite detected: ~s", [ErrStr]); + PrintErr("Error in suite detected: ~ts", [ErrStr]); R when R == unknown; R == undefined -> - PrintErr("Error detected: ~s", [ErrStr]); + PrintErr("Error detected: ~ts", [ErrStr]); %% if a function specified by all/0 does not exist, we %% pick up undef here [{LastMod,LastFunc}|_] when ErrStr == "undef" -> - PrintErr("~w:~w could not be executed~nReason: ~s", + PrintErr("~w:~w could not be executed~nReason: ~ts", [LastMod,LastFunc,ErrStr]); [{LastMod,LastFunc}|_] -> - PrintErr("~w:~w failed~nReason: ~s", [LastMod,LastFunc,ErrStr]); + PrintErr("~w:~w failed~nReason: ~ts", [LastMod,LastFunc,ErrStr]); [{LastMod,LastFunc,LastLine}|_] -> %% print error to console, we are only %% interested in the last executed expression - PrintErr("~w:~w failed on line ~w~nReason: ~s", + PrintErr("~w:~w failed on line ~w~nReason: ~ts", [LastMod,LastFunc,LastLine,ErrStr]), case ct_util:read_suite_data({seq,Mod,Func}) of @@ -1184,7 +1184,7 @@ report(What,Data) -> ok; {error,Reason} -> ct_logs:log("COVER INFO", - "Importing cover data from: ~s fails! " + "Importing cover data from: ~ts fails! " "Reason: ~p", [Imp,Reason]) end end, Imps) @@ -1349,4 +1349,7 @@ format_comment(Comment) -> %%%----------------------------------------------------------------- %%% @spec get_html_wrapper(TestName, PrintLabel, Cwd) -> Header get_html_wrapper(TestName, PrintLabel, Cwd, TableCols) -> - ct_logs:get_ts_html_wrapper(TestName, PrintLabel, Cwd, TableCols). + get_html_wrapper(TestName, PrintLabel, Cwd, TableCols, utf8). + +get_html_wrapper(TestName, PrintLabel, Cwd, TableCols, Encoding) -> + ct_logs:get_ts_html_wrapper(TestName, PrintLabel, Cwd, TableCols, Encoding). diff --git a/lib/common_test/src/ct_gen_conn.erl b/lib/common_test/src/ct_gen_conn.erl index 1f01d84601..2d4b1d1f52 100644 --- a/lib/common_test/src/ct_gen_conn.erl +++ b/lib/common_test/src/ct_gen_conn.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2012. All Rights Reserved. +%% Copyright Ericsson AB 2003-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -272,7 +272,7 @@ call(Pid, Msg, Timeout) -> after Timeout -> erlang:demonitor(MRef, [flush]), log("ct_gen_conn", - "Connection process ~p not responding. Killing now!", + "Connection process ~w not responding. Killing now!", [Pid]), exit(Pid, kill), {error,{process_down,Pid,forced_termination}} diff --git a/lib/common_test/src/ct_groups.erl b/lib/common_test/src/ct_groups.erl index 74ab5e5439..14a8aab881 100644 --- a/lib/common_test/src/ct_groups.erl +++ b/lib/common_test/src/ct_groups.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2012. All Rights Reserved. +%% Copyright Ericsson AB 2004-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -462,7 +462,7 @@ make_conf(Mod, Name, Props, TestSpec) -> false -> ct_logs:log("TEST INFO", "init_per_group/2 and " "end_per_group/2 missing for group " - "~p in ~p, using default.", + "~w in ~w, using default.", [Name,Mod]), {{ct_framework,init_per_group}, {ct_framework,end_per_group}, diff --git a/lib/common_test/src/ct_hooks.erl b/lib/common_test/src/ct_hooks.erl index 1bcc63738e..3d87a82e24 100644 --- a/lib/common_test/src/ct_hooks.erl +++ b/lib/common_test/src/ct_hooks.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2012. All Rights Reserved. +%% Copyright Ericsson AB 2004-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -362,11 +362,11 @@ catch_apply(M,F,A, Default) -> [{M,F,A,_}|_] when Reason == undef -> Default; Trace -> - ct_logs:log("Suite Hook","Call to CTH failed: ~p:~p", + ct_logs:log("Suite Hook","Call to CTH failed: ~w:~p", [error,{Reason,Trace}]), throw({error_in_cth_call, lists:flatten( - io_lib:format("~p:~p/~p CTH call failed", + io_lib:format("~w:~w/~w CTH call failed", [M,F,length(A)]))}) end end. diff --git a/lib/common_test/src/ct_logs.erl b/lib/common_test/src/ct_logs.erl index ba678fd169..5924930072 100644 --- a/lib/common_test/src/ct_logs.erl +++ b/lib/common_test/src/ct_logs.erl @@ -35,9 +35,10 @@ -export([add_external_logs/1, add_link/3]). -export([make_last_run_index/0]). -export([make_all_suites_index/1,make_all_runs_index/1]). --export([get_ts_html_wrapper/4]). +-export([get_ts_html_wrapper/5]). -export([xhtml/2, locate_priv_file/1, make_relative/1]). -export([insert_javascript/1]). +-export([uri/1]). %% Logging stuff directly from testcase -export([tc_log/3, tc_log/4, tc_log_async/3, tc_print/3, tc_print/4, @@ -307,8 +308,8 @@ end_log() -> %%% calling test suite.

    add_external_logs(Logs) -> start_log("External Logs"), - [cont_log("~s\n", - [filename:join("log_private",Log),Log]) || Log <- Logs], + [cont_log("~ts\n", + [uri(filename:join("log_private",Log)),Log]) || Log <- Logs], end_log(). %%%----------------------------------------------------------------- @@ -320,8 +321,8 @@ add_external_logs(Logs) -> %%% @doc Print a link to a given file stored in the priv_dir of the %%% calling test suite. add_link(Heading,File,Type) -> - log(Heading,"~s\n", - [filename:join("log_private",File),Type,File]). + log(Heading,"~ts\n", + [uri(filename:join("log_private",File)),Type,File]). %%%----------------------------------------------------------------- @@ -469,7 +470,7 @@ ct_log(Category,Format,Args) -> %%%================================================================= %%% Internal functions int_header() -> - "
    *** CT ~s *** ~s". + "
    *** CT ~s *** ~ts". int_footer() -> "
    ". @@ -692,7 +693,7 @@ logger_loop(State) -> logger_loop(State); {set_stylesheet,TC,SSFile} -> Fd = State#logger_state.ct_log_fd, - io:format(Fd, "~p loading external style sheet: ~s~n", + io:format(Fd, "~p loading external style sheet: ~ts~n", [TC,SSFile]), logger_loop(State#logger_state{stylesheet = SSFile}); {clear_stylesheet,_} when State#logger_state.stylesheet == undefined -> @@ -752,7 +753,7 @@ print_to_log(sync, FromPid, TCGL, List, State) -> IoProc = if FromPid /= TCGL -> TCGL; true -> State#logger_state.ct_log_fd end, - io:format(IoProc, "~s", [lists:foldl(IoFun, [], List)]), + io:format(IoProc, "~ts", [lists:foldl(IoFun, [], List)]), State; print_to_log(async, FromPid, TCGL, List, State) -> @@ -764,7 +765,7 @@ print_to_log(async, FromPid, TCGL, List, State) -> end, Printer = fun() -> test_server:permit_io(IoProc, self()), - io:format(IoProc, "~s", [lists:foldl(IoFun, [], List)]) + io:format(IoProc, "~ts", [lists:foldl(IoFun, [], List)]) end, case State#logger_state.async_print_jobs of [] -> @@ -868,7 +869,7 @@ set_evmgr_gl(GL) -> end. open_ctlog() -> - {ok,Fd} = file:open(?ct_log_name,[write]), + {ok,Fd} = file:open(?ct_log_name,[write,{encoding,utf8}]), io:format(Fd, header("Common Test Framework Log", {[],[1,2],[]}), []), case file:consult(ct_run:variables_file_name("../")) of {ok,Vars} -> @@ -878,7 +879,7 @@ open_ctlog() -> Dir = filename:dirname(Cwd), Variables = ct_run:variables_file_name(Dir), io:format(Fd, - "Can not read the file \'~s\' Reason: ~w\n" + "Can not read the file \'~ts\' Reason: ~w\n" "No configuration found for test!!\n", [Variables,Reason]) end, @@ -904,7 +905,7 @@ print_style(Fd,undefined) -> print_style(Fd,StyleSheet) -> case file:read_file(StyleSheet) of {ok,Bin} -> - Str = binary_to_list(Bin), + Str = b2s(Bin,encoding(StyleSheet)), Pos0 = case string:str(Str,"\n",[Str]) + io:format(Fd,"\n",[Str]) end; {error,Reason} -> print_style_error(Fd,StyleSheet,Reason) @@ -934,7 +935,7 @@ print_style(Fd,StyleSheet) -> %% [StyleSheet]). print_style_error(Fd,StyleSheet,Reason) -> - io:format(Fd,"\n\n", + io:format(Fd,"\n\n", [StyleSheet,Reason]), print_style(Fd,undefined). @@ -963,7 +964,7 @@ make_last_run_index(StartTime) -> % io:put_chars("done\n"), ok; Err -> - io:format("Unknown internal error while updating ~s. " + io:format("Unknown internal error while updating ~ts. " "Please report.\n(Err: ~p, ID: 1)", [AbsIndexName,Err]), {error, Err} @@ -1001,7 +1002,7 @@ make_last_run_index1(StartTime,IndexName) -> %% write current Totals to file, later to be used in all_runs log write_totals_file(?totals_name,Label,Logs1,Totals), Index = [Index0|index_footer()], - case force_write_file(IndexName, Index) of + case force_write_file(IndexName, unicode:characters_to_binary(Index)) of ok -> ok; {error, Reason} -> @@ -1085,7 +1086,7 @@ make_one_index_entry1(SuiteName, Link, Label, Success, Fail, UserSkip, AutoSkip, CrashDumpName = SuiteName ++ "_erl_crash.dump", case filelib:is_file(CrashDumpName) of true -> - [" (CrashDump)"]; false -> "" @@ -1115,10 +1116,10 @@ make_one_index_entry1(SuiteName, Link, Label, Success, Fail, UserSkip, AutoSkip, [] -> "none"; _ -> "Old Runs" end, - A = xhtml(["CT Log\n", "",OldRunsLink,"\n"], - ["CT Log\n", + ["CT Log\n", "",OldRunsLink,"\n"]), {L,T,N,A}; false -> @@ -1128,7 +1129,8 @@ make_one_index_entry1(SuiteName, Link, Label, Success, Fail, UserSkip, AutoSkip, if NotBuilt == 0 -> ["",integer_to_list(NotBuilt),"\n"]; true -> - ["", + ["", integer_to_list(NotBuilt),"\n"] end, FailStr = @@ -1151,7 +1153,7 @@ make_one_index_entry1(SuiteName, Link, Label, Success, Fail, UserSkip, AutoSkip, [xhtml("\n", ["\n"]), xhtml("",SuiteName,"", CrashDumpLink, + uri(LogFile),"\">",SuiteName,"", CrashDumpLink, xhtml("\n", "\n"), Lbl, Timestamp, "",integer_to_list(Success),"\n", @@ -1366,7 +1368,7 @@ header1(Title, SubTitle, TableCols) -> "\n", "\n", xhtml("", - ["\n"]), + ["\n"]), xhtml("", ["\n"]), @@ -1463,7 +1465,7 @@ count_cases(Dir) -> LogFile = filename:join(Dir, ?suitelog_name), case file:read_file(LogFile) of {ok, Bin} -> - case count_cases1(binary_to_list(Bin), + case count_cases1(b2s(Bin), {undefined,undefined,undefined,undefined}) of {error,not_complete} -> %% The test is not complete - dont write summary @@ -1558,7 +1560,7 @@ config_table1([{Key,Value}|Vars]) -> "
    ",io_lib:format("~p",[Value]),"
    \n"], ["\n", "", atom_to_list(Key), "\n", - "", io_lib:format("~p",[Value]), "\n\n"]) | + "", io_lib:format("~p",[Value]), "\n\n"]) | config_table1(Vars)]; config_table1([]) -> ["\n\n"]. @@ -1575,8 +1577,9 @@ make_all_runs_index(When) -> DirsSorted = (catch sort_all_runs(Dirs)), Header = all_runs_header(), Index = [runentry(Dir) || Dir <- DirsSorted], - Result = file:write_file(AbsName,Header++Index++ - all_runs_index_footer()), + Result = file:write_file(AbsName, + unicode:characters_to_binary( + Header++Index++all_runs_index_footer())), if When == start -> ok; true -> io:put_chars("done\n") end, @@ -1603,10 +1606,27 @@ sort_all_runs(Dirs) -> interactive_link() -> [Dir|_] = lists:reverse(filelib:wildcard(logdir_prefix()++"*.*")), CtLog = filename:join(Dir,"ctlog.html"), - Body = ["Log from last interactive run: ", - timestamp(Dir),""], - file:write_file("last_interactive.html",Body), - io:format("~n~nUpdated ~s\n" + Body = + [xhtml( + ["\n", + "\n"], + ["\n", + "\n"]), + "\n", + "\n", + "Last interactive run\n", + "\n", + "\n", + "\n", + "\n", + "Log from last interactive run: ", + timestamp(Dir),"", + "\n", + "\n" + ], + file:write_file("last_interactive.html",unicode:characters_to_binary(Body)), + io:format("~n~nUpdated ~ts\n" "Any CT activities will be logged here\n", [?abs("last_interactive.html")]). @@ -1656,7 +1676,7 @@ runentry(Dir) -> TestNames; true -> Trunc = Polish(string:substr(TestNames,1,?testname_width-3)), - lists:flatten(io_lib:format("~s...",[Trunc])) + lists:flatten(io_lib:format("~ts...",[Trunc])) end, Total = TotSucc+TotFail+AllSkip, A = xhtml(["",Node, @@ -1696,7 +1716,7 @@ runentry(Dir) -> "?\n"], A++B++C end, - Index = filename:join(Dir,?index_name), + Index = uri(filename:join(Dir,?index_name)), [xhtml("\n", ["\n"]), xhtml(["",timestamp(Dir),"", TotalsStr,"\n"], @@ -1837,7 +1857,7 @@ make_all_suites_index(NewTestData = {_TestName,DirName}) -> ok -> ok; Err -> - io:format("Unknown internal error while updating ~s. " + io:format("Unknown internal error while updating ~ts. " "Please report.\n(Err: ~p, ID: 1)", [AbsIndexName,Err]), {error, Err} @@ -1901,7 +1921,7 @@ make_all_suites_index1(When, AbsIndexName, AllLogDirs) -> ok end; Err -> - io:format("Unknown internal error while updating ~s. " + io:format("Unknown internal error while updating ~ts. " "Please report.\n(Err: ~p, ID: 1)", [AbsIndexName,Err]), {error, Err} @@ -1913,7 +1933,7 @@ make_all_suites_index2(IndexName, AllTestLogDirs) -> all_suites_index_header(), 0, 0, 0, 0, 0, [], []), Index = [Index0|index_footer()], - case force_write_file(IndexName, Index) of + case force_write_file(IndexName, unicode:characters_to_binary(Index)) of ok -> {ok,CacheData}; {error, Reason} -> @@ -1971,7 +1991,7 @@ make_all_suites_ix_cached(AbsIndexName, NewTestData, Label, AllTestLogDirs) -> all_suites_index_header(IndexDir), 0, 0, 0, 0, 0), Index = [Index0|index_footer()], - case force_write_file(AbsIndexName, Index) of + case force_write_file(AbsIndexName, unicode:characters_to_binary(Index)) of ok -> ok; {error, Reason} -> @@ -2117,7 +2137,7 @@ simulate_logger_loop() -> receive {log,_,_,_,_,_,List} -> S = [[io_lib:format(Str,Args),io_lib:nl()] || {Str,Args} <- List], - io:format("~s",[S]), + io:format("~ts",[S]), simulate_logger_loop(); stop -> ok @@ -2274,11 +2294,12 @@ make_relative1(DirTs, CwdTs) -> Ups ++ DirTs. %%%----------------------------------------------------------------- -%%% @spec get_ts_html_wrapper(TestName, PrintLabel, Cwd) -> {Mode,Header,Footer} +%%% @spec get_ts_html_wrapper(TestName, PrintLabel, Cwd, TableCols, Encoding) +%%% -> {Mode,Header,Footer} %%% %%% @doc %%% -get_ts_html_wrapper(TestName, PrintLabel, Cwd, TableCols) -> +get_ts_html_wrapper(TestName, PrintLabel, Cwd, TableCols, Encoding) -> TestName1 = if is_list(TestName) -> lists:flatten(TestName); true -> @@ -2320,15 +2341,16 @@ get_ts_html_wrapper(TestName, PrintLabel, Cwd, TableCols) -> "\n", "", TestName1, "\n", "\n", - "\n", + "\n", "\n", "\n", LabelStr, "\n"], ["
    \n

    \n", - "Test run history\n | ", - "Top level test index\n\n

    \n", Copyright,"
    \n\n\n"]}; _ -> @@ -2366,14 +2388,14 @@ get_ts_html_wrapper(TestName, PrintLabel, Cwd, TableCols) -> "\n", TestName1, "\n", "\n", "\n", - "\n", + "\n", "\n", "\n"] ++ TableSorterScript ++ ["\n","\n", LabelStr, "\n"], ["
    \n

    \n", - "Test run history\n | ", - "Top level test index\n\n

    \n", Copyright,"
    \n\n\n"]} end. @@ -2463,3 +2485,31 @@ insert_javascript({tablesorter,TableName, " $(\"#",TableName,"\").trigger(\"update\");\n", " $(\"#",TableName,"\").trigger(\"appendCache\");\n", "});\n\n"]. + +uri("") -> + ""; +uri(Href) -> + test_server_ctrl:uri_encode(Href). + +%% Read magic comment to get encoding of text file. +%% If no magic comment exists, assume default encoding +encoding(File) -> + case epp:read_encoding(File) of + none -> + epp:default_encoding(); + E -> + E + end. + +%% Convert binary to string using default encoding +b2s(Bin) -> + b2s(Bin,epp:default_encoding()). + +%% Convert binary to string using given encoding +b2s(Bin,Encoding) -> + unicode:characters_to_list(Bin,Encoding). + +html_encoding(latin1) -> + "iso-8859-1"; +html_encoding(utf8) -> + "utf-8". diff --git a/lib/common_test/src/ct_make.erl b/lib/common_test/src/ct_make.erl index 8ddb91d355..d4bd81e78d 100644 --- a/lib/common_test/src/ct_make.erl +++ b/lib/common_test/src/ct_make.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2009-2011. All Rights Reserved. +%% Copyright Ericsson AB 2009-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -280,13 +280,13 @@ recompile(File, NoExec, Load, Opts) -> do_recompile(_File, true, _Load, _Opts) -> out_of_date; do_recompile(File, false, noload, Opts) -> - io:format("Recompile: ~s\n",[File]), + io:format("Recompile: ~ts\n",[File]), compile:file(File, [report_errors, report_warnings, error_summary |Opts]); do_recompile(File, false, load, Opts) -> - io:format("Recompile: ~s\n",[File]), + io:format("Recompile: ~ts\n",[File]), c:c(File, Opts); do_recompile(File, false, netload, Opts) -> - io:format("Recompile: ~s\n",[File]), + io:format("Recompile: ~ts\n",[File]), c:nc(File, Opts). exists(File) -> diff --git a/lib/common_test/src/ct_master.erl b/lib/common_test/src/ct_master.erl index f29eba605c..73ef15c500 100644 --- a/lib/common_test/src/ct_master.erl +++ b/lib/common_test/src/ct_master.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2012. All Rights Reserved. +%% Copyright Ericsson AB 2006-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -244,7 +244,7 @@ run_all([],AllLogDirs,_,AllEvHs,_AllIncludes, {value,{_,Dir}} -> Dir; false -> "." end, - log(tty,"Master Logdir","~s",[MasterLogDir]), + log(tty,"Master Logdir","~ts",[MasterLogDir]), start_master(lists:reverse(NodeOpts),Handlers,MasterLogDir,LogDirs,InitOptions,Specs), ok. @@ -331,7 +331,7 @@ init_master(Parent,NodeOptsList,EvHandlers,MasterLogDir,LogDirs,InitOptions,Spec SpecsStr = lists:map(fun(Name) -> Name ++ " " end,Specs), - ct_master_logs:log("Test Specification file(s)","~s", + ct_master_logs:log("Test Specification file(s)","~ts", [lists:flatten(SpecsStr)]) end, @@ -340,7 +340,7 @@ init_master(Parent,NodeOptsList,EvHandlers,MasterLogDir,LogDirs,InitOptions,Spec ct_master_event:add_handler(), %% add user handlers for master event manager Add = fun({H,Args}) -> - log(all,"Adding Event Handler","~p",[H]), + log(all,"Adding Event Handler","~w",[H]), case gen_event:add_handler(?CT_MEVMGR_REF,H,Args) of ok -> ok; {'EXIT',Why} -> exit(Why); @@ -391,7 +391,7 @@ init_master2(Parent,NodeOptsList,LogDirs) -> SpawnAndMon = fun({Node,Opts}) -> monitor_node(Node,true), - log(all,"Test Info","Starting test(s) on ~p...",[Node]), + log(all,"Test Info","Starting test(s) on ~w...",[Node]), {spawn_link(Node,?MODULE,init_node_ctrl,[self(),Cookie,Opts]),Node} end, NodeCtrlPids = lists:map(SpawnAndMon,NodeOptsList), @@ -404,7 +404,8 @@ master_loop(#state{node_ctrl_pids=[], results=Finished}) -> Str = lists:map(fun({Node,Result}) -> - io_lib:format("~-40.40.*s~p\n",[$_,atom_to_list(Node),Result]) + io_lib:format("~-40.40.*ts~p\n", + [$_,atom_to_list(Node),Result]) end,lists:reverse(Finished)), log(all,"TEST RESULTS",Str,[]), log(all,"Info","Updating log files",[]), @@ -448,7 +449,7 @@ master_loop(State=#state{node_ctrl_pids=NodeCtrlPids, undefined -> %% ignore (but report) exit from master_logger etc log(all,"Test Info", - "Warning! Process ~p has terminated. Reason: ~p", + "Warning! Process ~w has terminated. Reason: ~p", [Pid,Reason]), master_loop(State) end; @@ -531,7 +532,7 @@ update_queue(take,Node,From,Lock={Op,Resource},Locks,Blocked) -> %% Blocked: [{{Operation,Resource},Node,WaitingPid},...] case lists:keysearch(Lock,1,Locks) of {value,{_Lock,Owner}} -> % other node has lock - log(html,"Lock Info","Node ~p blocked on ~w by ~w. Resource: ~p", + log(html,"Lock Info","Node ~w blocked on ~w by ~w. Resource: ~p", [Node,Op,Owner,Resource]), Blocked1 = Blocked ++ [{Lock,Node,From}], {Locks,Blocked1}; @@ -546,7 +547,7 @@ update_queue(release,Node,_From,Lock={Op,Resource},Locks,Blocked) -> case lists:keysearch(Lock,1,Blocked) of {value,E={Lock,SomeNode,WaitingPid}} -> Blocked1 = lists:delete(E,Blocked), - log(html,"Lock Info","Node ~p proceeds with ~w. Resource: ~p", + log(html,"Lock Info","Node ~w proceeds with ~w. Resource: ~p", [SomeNode,Op,Resource]), reply(ok,WaitingPid), % waiting process may start {Locks1,Blocked1}; @@ -625,7 +626,8 @@ refresh_logs([D|Dirs],Refreshed) -> refresh_logs([],Refreshed) -> Str = lists:map(fun({D,Result}) -> - io_lib:format("Refreshing logs in ~p... ~p",[D,Result]) + io_lib:format("Refreshing logs in ~p... ~p", + [D,Result]) end,Refreshed), log(all,"Info",Str,[]). @@ -638,7 +640,7 @@ init_node_ctrl(MasterPid,Cookie,Opts) -> process_flag(trap_exit, true), MasterNode = node(MasterPid), group_leader(whereis(user),self()), - io:format("~n********** node_ctrl process ~p started on ~p **********~n", + io:format("~n********** node_ctrl process ~w started on ~w **********~n", [self(),node()]), %% initially this node must have the same cookie as the master node %% but now we set it explicitly for the connection so that test suites @@ -671,7 +673,7 @@ init_node_ctrl(MasterPid,Cookie,Opts) -> pong -> MasterPid ! {self(),{result,Result}}; pang -> - io:format("Warning! Connection to master node ~p is lost. " + io:format("Warning! Connection to master node ~w is lost. " "Can't report result!~n~n", [MasterNode]) end. @@ -752,21 +754,21 @@ start_nodes(InitOptions)-> IsAlive = lists:member(NodeName, nodes()), case {HasNodeStart, IsAlive} of {false, false}-> - io:format("WARNING: Node ~p is not alive but has no node_start option~n", [NodeName]); + io:format("WARNING: Node ~w is not alive but has no node_start option~n", [NodeName]); {false, true}-> - io:format("Node ~p is alive~n", [NodeName]); + io:format("Node ~w is alive~n", [NodeName]); {true, false}-> {node_start, NodeStart} = lists:keyfind(node_start, 1, Options), {value, {callback_module, Callback}, NodeStart2}= lists:keytake(callback_module, 1, NodeStart), case Callback:start(Host, Node, NodeStart2) of {ok, NodeName} -> - io:format("Node ~p started successfully with callback ~p~n", [NodeName,Callback]); + io:format("Node ~w started successfully with callback ~w~n", [NodeName,Callback]); {error, Reason, _NodeName} -> - io:format("Failed to start node ~p with callback ~p! Reason: ~p~n", [NodeName, Callback, Reason]) + io:format("Failed to start node ~w with callback ~w! Reason: ~p~n", [NodeName, Callback, Reason]) end; {true, true}-> - io:format("WARNING: Node ~p is alive but has node_start option~n", [NodeName]) + io:format("WARNING: Node ~w is alive but has node_start option~n", [NodeName]) end end, InitOptions). @@ -779,7 +781,7 @@ eval_on_nodes(InitOptions)-> {false,_}-> ok; {true,false}-> - io:format("WARNING: Node ~p is not alive but has eval option ~n", [NodeName]); + io:format("WARNING: Node ~w is not alive but has eval option ~n", [NodeName]); {true,true}-> {eval, MFAs} = lists:keyfind(eval, 1, Options), evaluate(NodeName, MFAs) @@ -790,9 +792,9 @@ eval_on_nodes(InitOptions)-> evaluate(Node, [{M,F,A}|MFAs])-> case rpc:call(Node, M, F, A) of {badrpc,Reason}-> - io:format("WARNING: Failed to call ~p:~p/~p on node ~p due to ~p~n", [M,F,length(A),Node,Reason]); + io:format("WARNING: Failed to call ~w:~w/~w on node ~w due to ~p~n", [M,F,length(A),Node,Reason]); Result-> - io:format("Called ~p:~p/~p on node ~p, result: ~p~n", [M,F,length(A),Node,Result]) + io:format("Called ~w:~w/~w on node ~w, result: ~p~n", [M,F,length(A),Node,Result]) end, evaluate(Node, MFAs); evaluate(_Node, [])-> diff --git a/lib/common_test/src/ct_master_event.erl b/lib/common_test/src/ct_master_event.erl index a70baefaaf..5877b7c6f2 100644 --- a/lib/common_test/src/ct_master_event.erl +++ b/lib/common_test/src/ct_master_event.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2009. All Rights Reserved. +%% Copyright Ericsson AB 2006-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -114,13 +114,13 @@ init(_) -> %% each installed event handler to handle the event. %%-------------------------------------------------------------------- handle_event(#event{name=start_logging,node=Node,data=RunDir},State) -> - ct_master_logs:log("CT Master Event Handler","Got ~s from ~p",[RunDir,Node]), + ct_master_logs:log("CT Master Event Handler","Got ~ts from ~w",[RunDir,Node]), ct_master_logs:nodedir(Node,RunDir), {ok,State}; handle_event(#event{name=Name,node=Node,data=Data},State) -> print("~n=== ~w ===~n", [?MODULE]), - print("~p on ~p: ~p~n", [Name,Node,Data]), + print("~w on ~w: ~p~n", [Name,Node,Data]), {ok,State}. %%-------------------------------------------------------------------- diff --git a/lib/common_test/src/ct_master_logs.erl b/lib/common_test/src/ct_master_logs.erl index 84f175c0a9..5393097f57 100644 --- a/lib/common_test/src/ct_master_logs.erl +++ b/lib/common_test/src/ct_master_logs.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2012. All Rights Reserved. +%% Copyright Ericsson AB 2006-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -133,7 +133,7 @@ init(Parent,LogDir,Nodes) -> end,Nodes)), io:format(CtLogFd,int_header(),[log_timestamp(now()),"Test Nodes\n"]), - io:format(CtLogFd,"~s\n",[NodeStr]), + io:format(CtLogFd,"~ts\n",[NodeStr]), io:put_chars(CtLogFd,[int_footer(),"\n"]), NodeDirIxFd = open_nodedir_index(RunDirAbs,Time), @@ -201,7 +201,7 @@ loop(State) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%% open_ct_master_log(Dir) -> FullName = filename:join(Dir,?ct_master_log_name), - {ok,Fd} = file:open(FullName,[write]), + {ok,Fd} = file:open(FullName,[write,{encoding,utf8}]), io:put_chars(Fd,header("Common Test Master Log", {[],[1,2],[]})), %% maybe add config info here later io:put_chars(Fd,config_table([])), @@ -235,7 +235,7 @@ config_table1([]) -> ["\n\n"]. int_header() -> - "
    *** CT MASTER ~s *** ~s". + "
    *** CT MASTER ~s *** ~ts". int_footer() -> "
    ". @@ -244,7 +244,7 @@ int_footer() -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% open_nodedir_index(Dir,StartTime) -> FullName = filename:join(Dir,?nodedir_index_name), - {ok,Fd} = file:open(FullName,[write]), + {ok,Fd} = file:open(FullName,[write,{encoding,utf8}]), io:put_chars(Fd,nodedir_index_header(StartTime)), Fd. @@ -253,7 +253,8 @@ print_nodedir(Node,RunDir,Fd) -> io:put_chars(Fd, ["\n" "",atom_to_list(Node),"\n", - "",Index,"\n", + "",Index, + "\n", "\n"]), ok. @@ -283,7 +284,9 @@ make_all_runs_index(LogDir) -> DirsSorted = (catch sort_all_runs(Dirs)), Header = all_runs_header(), Index = [runentry(Dir) || Dir <- DirsSorted], - Result = file:write_file(FullName,Header++Index++index_footer()), + Result = file:write_file(FullName, + unicode:characters_to_binary( + Header++Index++index_footer())), Result. sort_all_runs(Dirs) -> @@ -323,7 +326,8 @@ runentry(Dir) -> end, Index = filename:join(Dir,?nodedir_index_name), ["\n" - "",timestamp(Dir),"\n", + "", + timestamp(Dir),"\n", "",MasterStr,"\n", "",NodesStr,"\n", "\n"]. @@ -381,8 +385,10 @@ header(Title, TableCols) -> "\n", "" ++ Title ++ "\n", "\n", + "\n", xhtml("", - [""]), + [""]), xhtml("", ["\n"]), diff --git a/lib/common_test/src/ct_master_status.erl b/lib/common_test/src/ct_master_status.erl index 76060fb7bb..f9f511ecca 100644 --- a/lib/common_test/src/ct_master_status.erl +++ b/lib/common_test/src/ct_master_status.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2009. All Rights Reserved. +%% Copyright Ericsson AB 2006-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -70,7 +70,7 @@ init(_) -> %% handle_event(#event{name=Name,node=Node,data=Data},State) -> print("~n=== ~w ===~n", [?MODULE]), - print("~p on ~p: ~p~n", [Name,Node,Data]), + print("~w on ~w: ~p~n", [Name,Node,Data]), {ok,State}. %%-------------------------------------------------------------------- diff --git a/lib/common_test/src/ct_netconfc.erl b/lib/common_test/src/ct_netconfc.erl index 1ccbc86d8f..1339e53780 100644 --- a/lib/common_test/src/ct_netconfc.erl +++ b/lib/common_test/src/ct_netconfc.erl @@ -1,7 +1,7 @@ %%---------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2012. All Rights Reserved. +%% Copyright Ericsson AB 2012-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -1281,10 +1281,11 @@ do_send(Connection, SimpleXml) -> to_xml_doc(Simple) -> Prolog = "", - Xml = list_to_binary(xmerl:export_simple([Simple], - xmerl_xml, - [#xmlAttribute{name=prolog, - value=Prolog}])), + Xml = unicode:characters_to_binary( + xmerl:export_simple([Simple], + xmerl_xml, + [#xmlAttribute{name=prolog, + value=Prolog}])), <>. %%%----------------------------------------------------------------- @@ -1688,18 +1689,27 @@ log(#connection{host=Host,port=Port,name=Name},Action,Data) -> %% Log callback - called from the error handler process -format_data(raw,Data) -> - io_lib:format("~n~s~n",[hide_password(Data)]); -format_data(pretty,Data) -> - io_lib:format("~n~s~n",[indent(Data)]); -format_data(html,Data) -> - io_lib:format("~n~s~n",[html_format(Data)]). +format_data(How,Data) -> + %% Assuming that the data is encoded as UTF-8. If it is not, then + %% the printout might be wrong, but the format function will not + %% crash! + %% FIXME: should probably read encoding from the data and do + %% unicode:characters_to_binary(Data,InEncoding,utf8) when calling + %% log/3 instead of assuming utf8 in as done here! + do_format_data(How,unicode:characters_to_binary(Data)). + +do_format_data(raw,Data) -> + io_lib:format("~n~ts~n",[hide_password(Data)]); +do_format_data(pretty,Data) -> + io_lib:format("~n~ts~n",[indent(Data)]); +do_format_data(html,Data) -> + io_lib:format("~n~ts~n",[html_format(Data)]). %%%----------------------------------------------------------------- %%% Hide password elements from XML data hide_password(Bin) -> re:replace(Bin,<<"(]*>)[^<]*()">>,<<"\\1*****\\2">>, - [global,{return,binary}]). + [global,{return,binary},unicode]). %%%----------------------------------------------------------------- %%% HTML formatting @@ -1717,13 +1727,13 @@ indent(Bin) -> Part -> indent1(lists:reverse(Part)++String,erase(indent)) end, - list_to_binary(IndentedString). + unicode:characters_to_binary(IndentedString). %% Normalizes the XML document by removing all space and newline %% between two XML tags. %% Returns a list, no matter if the input was a list or a binary. -normalize(Str) -> - re:replace(Str,<<">[ \r\n\t]+<">>,<<"><">>,[global,{return,list}]). +normalize(Bin) -> + re:replace(Bin,<<">[ \r\n\t]+<">>,<<"><">>,[global,{return,list},unicode]). indent1(" diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl index eb05c90ba8..acea6b5cb5 100644 --- a/lib/common_test/src/ct_run.erl +++ b/lib/common_test/src/ct_run.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2012. All Rights Reserved. +%% Copyright Ericsson AB 2004-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -148,7 +148,7 @@ script_start(Args) -> _ -> "" end end, - io:format("~nCommon Test~s starting (cwd is ~s)~n~n", + io:format("~nCommon Test~s starting (cwd is ~ts)~n~n", [CTVsn,Cwd]), Self = self(), Pid = spawn_link(fun() -> script_start1(Self, Args) end), @@ -378,7 +378,7 @@ run_or_refresh(StartOpts = #opts{logdir = LogDir}, Args) -> {error,{all_suites_index,ASReason}}; _ -> file:set_cwd(Cwd), - io:format("Logs in ~s refreshed!~n~n", [LogDir1]), + io:format("Logs in ~ts refreshed!~n~n", [LogDir1]), timer:sleep(500), % time to flush io before quitting ok end @@ -848,7 +848,7 @@ run_test1(StartOpts) when is_list(StartOpts) -> undefined -> Tracing = start_trace(StartOpts), {ok,Cwd} = file:get_cwd(), - io:format("~nCommon Test starting (cwd is ~s)~n~n", [Cwd]), + io:format("~nCommon Test starting (cwd is ~ts)~n~n", [Cwd]), Res = case ct_repeat:loop_test(func, StartOpts) of false -> @@ -1332,7 +1332,7 @@ run_testspec(TestSpec) -> run_testspec1(TestSpec) -> {ok,Cwd} = file:get_cwd(), - io:format("~nCommon Test starting (cwd is ~s)~n~n", [Cwd]), + io:format("~nCommon Test starting (cwd is ~ts)~n~n", [Cwd]), case catch run_testspec2(TestSpec) of {'EXIT',Reason} -> file:set_cwd(Cwd), @@ -1469,7 +1469,7 @@ refresh_logs(LogDir) -> {error,{all_runs_index,ARReason}}; _ -> file:set_cwd(Cwd), - io:format("Logs in ~s refreshed!~n",[LogDir]), + io:format("Logs in ~ts refreshed!~n",[LogDir]), ok end end @@ -1792,7 +1792,7 @@ possibly_spawn(true, Tests, Skip, Opts) -> end, unlink(CTUtilSrv), SupPid = spawn(Supervisor), - io:format(user, "~nTest control handed over to process ~p~n~n", + io:format(user, "~nTest control handed over to process ~w~n~n", [SupPid]), SupPid. @@ -1880,7 +1880,7 @@ verify_suites(TestSuites) -> Suite)), io:format(user, "Suite ~w not found" - "in directory ~s~n", + "in directory ~ts~n", [Suite,TestDir]), {Found,[{DS,[Name]}|NotFound]} end @@ -1895,7 +1895,7 @@ verify_suites(TestSuites) -> ActualDir = filename:dirname(SuiteFile), {[{ActualDir,Suite}|Found],NotFound}; false -> - io:format(user, "Directory ~s is " + io:format(user, "Directory ~ts is " "invalid~n", [Dir]), Name = filename:join(Dir, atom_to_list(Suite)), {Found,[{DS,[Name]}|NotFound]} @@ -2135,7 +2135,7 @@ do_run_test(Tests, Skip, Opts) -> cross = CovCross, src = _CovSrc}} -> ct_logs:log("COVER INFO", - "Using cover specification file: ~s~n" + "Using cover specification file: ~ts~n" "App: ~w~n" "Cross cover: ~w~n" "Including ~w modules~n" @@ -2150,7 +2150,7 @@ do_run_test(Tests, Skip, Opts) -> DelResult = file:delete(CovExport), ct_logs:log("COVER INFO", "Warning! " - "Export file ~s already exists. " + "Export file ~ts already exists. " "Deleting with result: ~p", [CovExport,DelResult]); false -> @@ -2632,7 +2632,7 @@ log_ts_names(Specs) -> List = lists:map(fun(Name) -> Name ++ " " end, Specs), - ct_logs:log("Test Specification file(s)", "~s", + ct_logs:log("Test Specification file(s)", "~ts", [lists:flatten(List)]). merge_arguments(Args) -> @@ -2743,10 +2743,10 @@ event_handler_args2opts(Default, Args) -> event_handler_init_args2opts(EHs) end. event_handler_init_args2opts([EH, Arg, "and" | EHs]) -> - [{list_to_atom(EH),lists:flatten(io_lib:format("~s",[Arg]))} | + [{list_to_atom(EH),lists:flatten(io_lib:format("~ts",[Arg]))} | event_handler_init_args2opts(EHs)]; event_handler_init_args2opts([EH, Arg]) -> - [{list_to_atom(EH),lists:flatten(io_lib:format("~s",[Arg]))}]; + [{list_to_atom(EH),lists:flatten(io_lib:format("~ts",[Arg]))}]; event_handler_init_args2opts([]) -> []. @@ -3064,7 +3064,7 @@ start_trace(Args) -> false end; {_,Error} -> - io:format("Warning! Tracing not started. Reason: ~s~n~n", + io:format("Warning! Tracing not started. Reason: ~ts~n~n", [file:format_error(Error)]), false end; diff --git a/lib/common_test/src/ct_telnet.erl b/lib/common_test/src/ct_telnet.erl index b13c050e32..02186864a5 100644 --- a/lib/common_test/src/ct_telnet.erl +++ b/lib/common_test/src/ct_telnet.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2012. All Rights Reserved. +%% Copyright Ericsson AB 2003-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -201,7 +201,7 @@ open(KeyOrName,ConnType,TargetMod,Extra) -> close(Connection) -> case get_handle(Connection) of {ok,Pid} -> - log("ct_telnet:close","Handle: ~p",[Pid]), + log("ct_telnet:close","Handle: ~w",[Pid]), case ct_gen_conn:stop(Pid) of {error,{process_down,Pid,noproc}} -> {error,already_closed}; @@ -558,7 +558,7 @@ reconnect(Ip,Port,N,State=#state{target_mod=TargetMod, Error when N==0 -> Error; _Error -> - log("Reconnect failed!","Retries left: ~p",[N]), + log("Reconnect failed!","Retries left: ~w",[N]), timer:sleep(ReconnInt), reconnect(Ip,Port,N-1,State) end. @@ -567,7 +567,7 @@ reconnect(Ip,Port,N,State=#state{target_mod=TargetMod, %% @hidden terminate(TelnPid,State) -> log(heading(terminate,State#state.name), - "Closing telnet connection.\nId: ~p", + "Closing telnet connection.\nId: ~w", [TelnPid]), ct_telnet_client:close(TelnPid). @@ -899,7 +899,7 @@ one_expect(Data,Pattern,EO) -> [Prompt] when Prompt==prompt; Prompt=={prompt,PromptType} -> %% Only searching for prompt log_lines(UptoPrompt), - try_cont_log("PROMPT: ~s", [PromptType]), + try_cont_log("PROMPT: ~ts", [PromptType]), {match,{prompt,PromptType},Rest}; [{prompt,_OtherPromptType}] -> %% Only searching for one specific prompt, not thisone @@ -969,7 +969,7 @@ seq_expect1(Data,[prompt|Patterns],Acc,Rest,EO) -> {continue,[prompt|Patterns],Acc,LastLine}; PromptType -> log_lines(Data), - try_cont_log("PROMPT: ~s", [PromptType]), + try_cont_log("PROMPT: ~ts", [PromptType]), seq_expect(Rest,Patterns,[{prompt,PromptType}|Acc],EO) end; seq_expect1(Data,[{prompt,PromptType}|Patterns],Acc,Rest,EO) -> @@ -980,7 +980,7 @@ seq_expect1(Data,[{prompt,PromptType}|Patterns],Acc,Rest,EO) -> {continue,[{prompt,PromptType}|Patterns],Acc,LastLine}; PromptType -> log_lines(Data), - try_cont_log("PROMPT: ~s", [PromptType]), + try_cont_log("PROMPT: ~ts", [PromptType]), seq_expect(Rest,Patterns,[{prompt,PromptType}|Acc],EO); _OtherPromptType -> log_lines(Data), @@ -1032,13 +1032,13 @@ match_line(Line,Patterns,FoundPrompt,EO) -> match_line(Line,[prompt|Patterns],false,EO,RetTag) -> match_line(Line,Patterns,false,EO,RetTag); match_line(Line,[prompt|_Patterns],FoundPrompt,_EO,RetTag) -> - try_cont_log(" ~s", [Line]), - try_cont_log("PROMPT: ~s", [FoundPrompt]), + try_cont_log(" ~ts", [Line]), + try_cont_log("PROMPT: ~ts", [FoundPrompt]), {RetTag,{prompt,FoundPrompt}}; match_line(Line,[{prompt,PromptType}|_Patterns],FoundPrompt,_EO,RetTag) when PromptType==FoundPrompt -> - try_cont_log(" ~s", [Line]), - try_cont_log("PROMPT: ~s", [FoundPrompt]), + try_cont_log(" ~ts", [Line]), + try_cont_log("PROMPT: ~ts", [FoundPrompt]), {RetTag,{prompt,FoundPrompt}}; match_line(Line,[{prompt,PromptType}|Patterns],FoundPrompt,EO,RetTag) when PromptType=/=FoundPrompt -> @@ -1048,7 +1048,7 @@ match_line(Line,[{Tag,Pattern}|Patterns],FoundPrompt,EO,RetTag) -> nomatch -> match_line(Line,Patterns,FoundPrompt,EO,RetTag); {match,Match} -> - try_cont_log("MATCH: ~s", [Line]), + try_cont_log("MATCH: ~ts", [Line]), {RetTag,{Tag,Match}} end; match_line(Line,[Pattern|Patterns],FoundPrompt,EO,RetTag) -> @@ -1056,13 +1056,13 @@ match_line(Line,[Pattern|Patterns],FoundPrompt,EO,RetTag) -> nomatch -> match_line(Line,Patterns,FoundPrompt,EO,RetTag); {match,Match} -> - try_cont_log("MATCH: ~s", [Line]), + try_cont_log("MATCH: ~ts", [Line]), {RetTag,Match} end; match_line(Line,[],FoundPrompt,EO,match) -> match_line(Line,EO#eo.haltpatterns,FoundPrompt,EO,halt); match_line(Line,[],_FoundPrompt,_EO,halt) -> - try_cont_log(" ~s", [Line]), + try_cont_log(" ~ts", [Line]), nomatch. one_line([$\n|Rest],Line) -> @@ -1086,7 +1086,7 @@ log_lines(String) -> [] -> ok; LastLine -> - try_cont_log(" ~s", [LastLine]) + try_cont_log(" ~ts", [LastLine]) end. log_lines_not_last(String) -> @@ -1094,7 +1094,7 @@ log_lines_not_last(String) -> {[],LastLine} -> LastLine; {String1,LastLine} -> - try_cont_log("~s",[String1]), + try_cont_log("~ts",[String1]), LastLine end. diff --git a/lib/common_test/src/ct_telnet_client.erl b/lib/common_test/src/ct_telnet_client.erl index d703b39ac5..7329498ed6 100644 --- a/lib/common_test/src/ct_telnet_client.erl +++ b/lib/common_test/src/ct_telnet_client.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2010. All Rights Reserved. +%% Copyright Ericsson AB 2003-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -308,7 +308,7 @@ cmd_dbg(_Cmd) -> [Opt] -> Opt; _ -> Opts end, - io:format("~s(~w): ~w\n", [CtrlStr,Ctrl,Opts1]); + io:format("~ts(~w): ~w\n", [CtrlStr,Ctrl,Opts1]); Any -> io:format("Unexpected in cmd_dbg:~n~w~n",[Any]) end. diff --git a/lib/common_test/src/ct_testspec.erl b/lib/common_test/src/ct_testspec.erl index 202d8f9373..af81edf90b 100644 --- a/lib/common_test/src/ct_testspec.erl +++ b/lib/common_test/src/ct_testspec.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2012. All Rights Reserved. +%% Copyright Ericsson AB 2006-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -265,7 +265,7 @@ collect_tests_from_file1([Spec|Specs],TestSpec,Relaxed) -> end; {error,Reason} -> ReasonStr = - lists:flatten(io_lib:format("~s", + lists:flatten(io_lib:format("~ts", [file:format_error(Reason)])), throw({error,{Spec,ReasonStr}}) end. @@ -588,7 +588,7 @@ add_option({Key,Value},Node,List,WarnIfExists) when is_list(Value) -> NewOption = case lists:keyfind(Key,1,OldOptions) of {Key,OldOption} when WarnIfExists,OldOption/=[]-> io:format("There is an option ~w=~w already " - "defined for node ~p, skipping new ~w~n", + "defined for node ~w, skipping new ~w~n", [Key,OldOption,Node,Value]), OldOption; {Key,OldOption}-> diff --git a/lib/common_test/src/ct_util.erl b/lib/common_test/src/ct_util.erl index cf891ed043..0f2b2081d9 100644 --- a/lib/common_test/src/ct_util.erl +++ b/lib/common_test/src/ct_util.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2012. All Rights Reserved. +%% Copyright Ericsson AB 2003-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -396,14 +396,14 @@ loop(Mode,TestData,StartDir) -> %% A connection crashed - remove the connection but don't die ct_logs:tc_log_async(ct_error_notify, "Connection process died: " - "Pid: ~p, Address: ~p, Callback: ~p\n" + "Pid: ~w, Address: ~p, Callback: ~w\n" "Reason: ~p\n\n", [Pid,A,CB,Reason]), catch CB:close(Pid), loop(Mode,TestData,StartDir); _ -> %% Let process crash in case of error, this shouldn't happen! - io:format("\n\nct_util_server got EXIT from ~p: ~p\n\n", + io:format("\n\nct_util_server got EXIT from ~w: ~p\n\n", [Pid,Reason]), file:set_cwd(StartDir), exit(Reason) @@ -956,7 +956,7 @@ open_url(iexplore, Args, URL) -> Path = proplists:get_value(default, Paths), [Cmd | _] = string:tokens(Path, "%"), Cmd1 = Cmd ++ " " ++ Args ++ " " ++ URL, - io:format(user, "~nOpening ~s with command:~n ~s~n", [URL,Cmd1]), + io:format(user, "~nOpening ~ts with command:~n ~ts~n", [URL,Cmd1]), open_port({spawn,Cmd1}, []); _ -> io:format("~nNo path to iexplore.exe~n",[]) @@ -969,6 +969,6 @@ open_url(Prog, Args, URL) -> is_list(Prog) -> Prog end, Cmd = ProgStr ++ " " ++ Args ++ " " ++ URL, - io:format(user, "~nOpening ~s with command:~n ~s~n", [URL,Cmd]), + io:format(user, "~nOpening ~ts with command:~n ~ts~n", [URL,Cmd]), open_port({spawn,Cmd},[]), ok. diff --git a/lib/common_test/src/cth_conn_log.erl b/lib/common_test/src/cth_conn_log.erl index 255f3ec78a..644594e34d 100644 --- a/lib/common_test/src/cth_conn_log.erl +++ b/lib/common_test/src/cth_conn_log.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2012. All Rights Reserved. +%% Copyright Ericsson AB 2012-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -105,8 +105,9 @@ pre_init_per_testcase(TestCase,Config,CthState) -> "" "" ++ ConnModStr ++ " logs:\n" ++ [io_lib:format( - "", - [S,L,filename:basename(L)]) + "", + [S,ct_logs:uri(L),filename:basename(L)]) || {S,L} <- Ls] ++ "
    ~p~s
    ~p~ts" + "
    ", io:format(Str,[]), diff --git a/lib/common_test/src/cth_surefire.erl b/lib/common_test/src/cth_surefire.erl index e6eaad8d48..1a38b6584b 100644 --- a/lib/common_test/src/cth_surefire.erl +++ b/lib/common_test/src/cth_surefire.erl @@ -1,7 +1,7 @@ %%-------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2012. All Rights Reserved. +%% Copyright Ericsson AB 2012-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -297,7 +297,7 @@ sanitize([]) -> now_to_string(Now) -> {{YY,MM,DD},{HH,Mi,SS}} = calendar:now_to_local_time(Now), - io_lib:format("~p-~2..0B-~2..0BT~2..0B:~2..0B:~2..0B",[YY,MM,DD,HH,Mi,SS]). + io_lib:format("~w-~2..0B-~2..0BT~2..0B:~2..0B:~2..0B",[YY,MM,DD,HH,Mi,SS]). make_url(undefined,_) -> undefined; diff --git a/lib/common_test/src/unix_telnet.erl b/lib/common_test/src/unix_telnet.erl index 25b9d4d5d2..99ce92e9f1 100644 --- a/lib/common_test/src/unix_telnet.erl +++ b/lib/common_test/src/unix_telnet.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2010. All Rights Reserved. +%% Copyright Ericsson AB 2004-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -110,7 +110,7 @@ connect1(Ip,Port,Timeout,KeepAlive,Username,Password) -> case ct_telnet:silent_teln_expect(Pid,[],[prompt],?prx,[]) of {ok,{prompt,?username},_} -> ok = ct_telnet_client:send_data(Pid,Username), - cont_log("Username: ~s",[Username]), + cont_log("Username: ~ts",[Username]), case ct_telnet:silent_teln_expect(Pid,[],prompt,?prx,[]) of {ok,{prompt,?password},_} -> ok = ct_telnet_client:send_data(Pid,Password), diff --git a/lib/common_test/test/ct_netconfc_SUITE_data/ns.erl b/lib/common_test/test/ct_netconfc_SUITE_data/ns.erl index 2427f37f52..09217f60a3 100644 --- a/lib/common_test/test/ct_netconfc_SUITE_data/ns.erl +++ b/lib/common_test/test/ct_netconfc_SUITE_data/ns.erl @@ -1,7 +1,7 @@ %%-------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2012. All Rights Reserved. +%% Copyright Ericsson AB 2012-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -426,7 +426,7 @@ reply(ConnRef,Reply) -> send(ConnRef, make_msg(Reply)). from_simple(Simple) -> - list_to_binary(xmerl:export_simple_element(Simple,xmerl_xml)). + unicode_c2b(xmerl:export_simple_element(Simple,xmerl_xml)). xml(Content) -> <<"\n", @@ -435,30 +435,30 @@ xml(Content) -> rpc_reply(Content) when is_binary(Content) -> MsgId = case erase(msg_id) of undefined -> <<>>; - Id -> list_to_binary([" message-id=\"",Id,"\""]) + Id -> unicode_c2b([" message-id=\"",Id,"\""]) end, <<"\n", Content/binary,"\n">>; rpc_reply(Content) -> - rpc_reply(list_to_binary(Content)). + rpc_reply(unicode_c2b(Content)). session_id(no_session_id) -> <<>>; session_id(SessionId0) -> - SessionId = list_to_binary(integer_to_list(SessionId0)), + SessionId = unicode_c2b(integer_to_list(SessionId0)), <<"",SessionId/binary,"\n">>. capabilities(undefined) -> - CapsXml = list_to_binary([["",C,"\n"] + CapsXml = unicode_c2b([["",C,"\n"] || C <- ?CAPABILITIES]), <<"\n",CapsXml/binary,"\n">>; capabilities({base,Vsn}) -> - CapsXml = list_to_binary([["",C,"\n"] + CapsXml = unicode_c2b([["",C,"\n"] || C <- ?CAPABILITIES_VSN(Vsn)]), <<"\n",CapsXml/binary,"\n">>; capabilities(no_base) -> [_|Caps] = ?CAPABILITIES, - CapsXml = list_to_binary([["",C,"\n"] || C <- Caps]), + CapsXml = unicode_c2b([["",C,"\n"] || C <- Caps]), <<"\n",CapsXml/binary,"\n">>; capabilities(no_caps) -> <<>>. @@ -553,3 +553,8 @@ make_msg(Xml) when is_binary(Xml) -> xml(Xml); make_msg(Simple) when is_tuple(Simple) -> xml(from_simple(Simple)). + +%%%----------------------------------------------------------------- +%%% Convert to unicode binary, since we use UTF-8 encoding in XML +unicode_c2b(Characters) -> + unicode:characters_to_binary(Characters). -- cgit v1.2.3 From f234422cd0599a935909da936ea8893cb2087f9a Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Wed, 23 Jan 2013 14:58:40 +0100 Subject: [test_server] Ensure correct encoding in header for erl2html2:convert When running under framework common_test, the encoding statement in the HTML header of the file generated with erl2html2:convert would sometimes be faulty. This has been corrected. --- lib/test_server/src/test_server_ctrl.erl | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/test_server/src/test_server_ctrl.erl b/lib/test_server/src/test_server_ctrl.erl index f800b93d0c..b7e7926fd6 100644 --- a/lib/test_server/src/test_server_ctrl.erl +++ b/lib/test_server/src/test_server_ctrl.erl @@ -1874,7 +1874,8 @@ html_possibly_convert(Src, SrcInfo, Dest) -> OutDir = get(test_server_log_dir_base), case test_server_sup:framework_call(get_html_wrapper, ["Module "++Src,false, - OutDir,undefined], "") of + OutDir,undefined, + encoding(Src)], "") of Empty when (Empty == "") ; (element(2,Empty) == "") -> erl2html2:convert(Src, Dest); {_,Header,_} -> @@ -5368,3 +5369,11 @@ reserved() -> sets:from_list([$;, $:, $@, $&, $=, $+, $,, $/, $?, $#, $[, $], $<, $>, $\", ${, $}, $|, $\\, $', $^, $%, $ ]). + +encoding(File) -> + case epp:read_encoding(File) of + none -> + epp:default_encoding(); + E -> + E + end. -- cgit v1.2.3 From b7777781864df9df281b521326db4210beaf9f6e Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Fri, 25 Jan 2013 11:31:28 +0100 Subject: [test_server] Don't create latin1 filenames if filename mode is utf8 Skipping test_server_latin1_***_SUITE if filename:native_name_encoding is utf8. --- lib/test_server/test/test_server_SUITE.erl | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/test_server/test/test_server_SUITE.erl b/lib/test_server/test/test_server_SUITE.erl index bad35b2d51..bea2c0dc49 100644 --- a/lib/test_server/test/test_server_SUITE.erl +++ b/lib/test_server/test/test_server_SUITE.erl @@ -185,13 +185,14 @@ test_server_unicode(Config) -> 5, 0, 3, 3, 0, 0, 0, 0, 5, Config), %% Create and run two test suites - one with filename and content - %% in latin1 (not on windows) and one with filename and content in - %% utf8. Both have name and content including letters äöå. Check - %% that all logs are generated with utf8 encoded filenames. - case os:type() of - {win32,_} -> + %% in latin1 (if the default filename mode is latin1) and one with + %% filename and content in utf8. Both have name and content + %% including letters äöå. Check that all logs are generated with + %% utf8 encoded filenames. + case file:native_name_encoding() of + utf8 -> ok; - _ -> + latin1 -> generate_and_run_unicode_test(Config,latin1) end, generate_and_run_unicode_test(Config,utf8). -- cgit v1.2.3 From 7a056d997ca002a99fec6d303b7077294c1d999b Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Fri, 25 Jan 2013 11:33:57 +0100 Subject: [test_server] Don't escape : and @ in test log links If escaping :, then links of type "file:///c:/ldisk..." will not work. Escaping @ does not create any problems, but the link becomes harder to read and most modern browsers can handle this. --- lib/test_server/src/test_server_ctrl.erl | 7 ++++--- .../test/test_server_SUITE_data/test_server_unicode_SUITE.erl | 6 +++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/test_server/src/test_server_ctrl.erl b/lib/test_server/src/test_server_ctrl.erl index b7e7926fd6..e5d75e43c9 100644 --- a/lib/test_server/src/test_server_ctrl.erl +++ b/lib/test_server/src/test_server_ctrl.erl @@ -5364,11 +5364,12 @@ do_uri_encode([Char|Chars]) -> do_uri_encode([]) -> []. -%% Copied from http_uri.erl +%% Copied from http_uri.erl, but slightly modified +%% (not converting @ and :) reserved() -> - sets:from_list([$;, $:, $@, $&, $=, $+, $,, $/, $?, + sets:from_list([$;, $&, $=, $+, $,, $/, $?, $#, $[, $], $<, $>, $\", ${, $}, $|, - $\\, $', $^, $%, $ ]). + $\\, $', $^, $%, $ ]). encoding(File) -> case epp:read_encoding(File) of diff --git a/lib/test_server/test/test_server_SUITE_data/test_server_unicode_SUITE.erl b/lib/test_server/test/test_server_SUITE_data/test_server_unicode_SUITE.erl index efdc626c24..662adedd4c 100644 --- a/lib/test_server/test/test_server_SUITE_data/test_server_unicode_SUITE.erl +++ b/lib/test_server/test/test_server_SUITE_data/test_server_unicode_SUITE.erl @@ -21,14 +21,14 @@ -export([all/1, init_per_suite/1, end_per_suite/1]). -export([init_per_testcase/2, end_per_testcase/2]). --export(['#difficult_case_name_äöå'/1, +-export([':#"|@\\ difficult_case_name_äöå'/1, print_and_log_unicode/1, print_and_log_latin1/1]). -include_lib("test_server/include/test_server.hrl"). all(suite) -> - ['#difficult_case_name_äöå', + [':#"|@\\ difficult_case_name_äöå', print_and_log_unicode, print_and_log_latin1]. @@ -57,7 +57,7 @@ cancel_timetrap(Config) -> %%%----------------------------------------------------------------- %%% Test cases -'#difficult_case_name_äöå'(Config) when is_list(Config) -> +':#"|@\\ difficult_case_name_äöå'(Config) when is_list(Config) -> ok. print_and_log_unicode(Config) when is_list(Config) -> -- cgit v1.2.3