From 9b9879b1ccbeff9ec87494ba7ed59273d679740e Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Tue, 8 Mar 2016 01:40:19 +0100 Subject: Fix problems with formatted test_server printouts --- lib/common_test/src/ct_logs.erl | 6 +- lib/common_test/src/ct_util.erl | 6 +- lib/test_server/src/test_server.erl | 109 ++++++++++++++++++--------------- lib/test_server/src/test_server_gl.erl | 76 ++++++++++++++++------- 4 files changed, 120 insertions(+), 77 deletions(-) diff --git a/lib/common_test/src/ct_logs.erl b/lib/common_test/src/ct_logs.erl index d9e9328bbd..e3f995ad3f 100644 --- a/lib/common_test/src/ct_logs.erl +++ b/lib/common_test/src/ct_logs.erl @@ -269,7 +269,7 @@ cast(Msg) -> %%%

This function is called by ct_framework:init_tc/3

init_tc(RefreshLog) -> call({init_tc,self(),group_leader(),RefreshLog}), - io:format(xhtml("", "
")), + io:format(["$tc_html",xhtml("", "
")]), ok. %%%----------------------------------------------------------------- @@ -919,7 +919,7 @@ print_to_log(sync, FromPid, Category, TCGL, Content, EscChars, State) -> if FromPid /= TCGL -> IoFun = create_io_fun(FromPid, CtLogFd, EscChars), IoList = lists:foldl(IoFun, [], Content), - io:format(TCGL,"~ts", [IoList]); + io:format(TCGL,["$tc_html","~ts"], [IoList]); true -> unexpected_io(FromPid, Category, ?MAX_IMPORTANCE, Content, CtLogFd, EscChars) @@ -945,7 +945,7 @@ print_to_log(async, FromPid, Category, TCGL, Content, EscChars, State) -> case erlang:is_process_alive(TCGL) of true -> - try io:format(TCGL, "~ts", + try io:format(TCGL, ["$tc_html","~ts"], [lists:foldl(IoFun,[],Content)]) of _ -> ok catch diff --git a/lib/common_test/src/ct_util.erl b/lib/common_test/src/ct_util.erl index 445fce1db8..b7fa7947e2 100644 --- a/lib/common_test/src/ct_util.erl +++ b/lib/common_test/src/ct_util.erl @@ -485,6 +485,8 @@ loop(Mode,TestData,StartDir) -> {'EXIT',Pid,Reason} -> case ets:lookup(?conn_table,Pid) of [#conn{address=A,callback=CB}] -> + ErrorStr = io_lib:format("~tp", [Reason]), + ErrorHtml = ct_logs:escape_chars(ErrorStr), %% A connection crashed - remove the connection but don't die ct_logs:tc_log_async(ct_error_notify, ?MAX_IMPORTANCE, @@ -492,8 +494,8 @@ loop(Mode,TestData,StartDir) -> "Connection process died: " "Pid: ~w, Address: ~p, " "Callback: ~w\n" - "Reason: ~p\n\n", - [Pid,A,CB,Reason]), + "Reason: ~ts\n\n", + [Pid,A,CB,ErrorHtml]), catch CB:close(Pid), %% in case CB:close failed to do this: unregister_connection(Pid), diff --git a/lib/test_server/src/test_server.erl b/lib/test_server/src/test_server.erl index 538f8abbae..67c3eff440 100644 --- a/lib/test_server/src/test_server.erl +++ b/lib/test_server/src/test_server.erl @@ -732,15 +732,10 @@ do_call_end_conf(Starter,Mod,Func,Data,Conf,TVal) -> try apply(Mod,end_per_testcase,[Func,Conf]) of _ -> ok catch - _:Why -> + _:Error -> timer:sleep(1), - WhyStr = test_server_ctrl:escape_chars( - io_lib:format("~tp", [Why])), - group_leader() ! {printout,12, - "WARNING! " - "~w:end_per_testcase(~w, ~p)" - " crashed!\n\tReason: ~ts\n", - [Mod,Func,Conf,WhyStr]} + print_end_conf_result(Mod,Func,Conf, + "crashed",Error) end, Supervisor ! {self(),end_conf} end, @@ -749,12 +744,7 @@ do_call_end_conf(Starter,Mod,Func,Data,Conf,TVal) -> {Pid,end_conf} -> Starter ! {self(),{call_end_conf,Data,ok}}; {'EXIT',Pid,Reason} -> - ReasonStr = test_server_ctrl:escape_chars( - io_lib:format("~tp", [Reason])), - group_leader() ! {printout,12, - "WARNING! ~w:end_per_testcase(~w, ~p)" - " failed!\n\tReason: ~ts\n", - [Mod,Func,Conf,ReasonStr]}, + print_end_conf_result(Mod,Func,Conf,"failed",Reason), Starter ! {self(),{call_end_conf,Data,{error,Reason}}}; {'EXIT',_OtherPid,Reason} -> %% Probably the parent - not much to do about that @@ -763,6 +753,22 @@ do_call_end_conf(Starter,Mod,Func,Data,Conf,TVal) -> end, spawn_link(EndConfProc). +print_end_conf_result(Mod,Func,Conf,Cause,Error) -> + Str2Print = + fun(NoHTML) when NoHTML == stdout; NoHTML == major -> + io_lib:format("WARNING! " + "~w:end_per_testcase(~w, ~tp)" + " ~s!\n\tReason: ~tp\n", + [Mod,Func,Conf,Cause,Error]); + (minor) -> + ErrorStr = test_server_ctrl:escape_chars(Error), + io_lib:format("WARNING! " + "~w:end_per_testcase(~w, ~tp)" + " ~s!\n\tReason: ~ts\n", + [Mod,Func,Conf,Cause,ErrorStr]) + end, + group_leader() ! {printout,12,Str2Print}. + spawn_fw_call(Mod,{init_per_testcase,Func},CurrConf,Pid, {timetrap_timeout,TVal}=Why, Loc,SendTo) -> @@ -1203,11 +1209,9 @@ do_init_per_testcase(Mod, Args) -> [] -> {ok,NewConf}; Bad -> - ErrorStr = - test_server_ctrl:escape_chars( - io_lib:format("ERROR! init_per_testcase has returned " - "bad elements in Config: ~p\n",[Bad])), - group_leader() ! {printout,12,ErrorStr,[]}, + group_leader() ! {printout,12, + "ERROR! init_per_testcase has returned " + "bad elements in Config: ~tp\n",[Bad]}, {skip,{failed,{Mod,init_per_testcase,bad_return}}} end; {fail,_Reason}=Res -> @@ -1225,31 +1229,33 @@ do_init_per_testcase(Mod, Args) -> throw:Other -> set_loc(erlang:get_stacktrace()), Line = get_loc(), - FormattedLoc = test_server_sup:format_loc(Line), - ReasonStr = - test_server_ctrl:escape_chars(io_lib:format("~tp", [Other])), - ErrorStr = - io_lib:format("ERROR! init_per_testcase thrown!\n" - "\tLocation: ~ts\n\tReason: ~ts\n", - [FormattedLoc,ReasonStr]), - group_leader() ! {printout,12,ErrorStr,[]}, + print_init_conf_result(Line,"thrown",Other), {skip,{failed,{Mod,init_per_testcase,Other}}}; _:Reason0 -> Stk = erlang:get_stacktrace(), Reason = {Reason0,Stk}, set_loc(Stk), Line = get_loc(), - FormattedLoc = test_server_sup:format_loc(Line), - ReasonStr = - test_server_ctrl:escape_chars(io_lib:format("~tp", [Reason])), - ErrorStr = - io_lib:format("ERROR! init_per_testcase crashed!\n" - "\tLocation: ~ts\n\tReason: ~ts\n", - [FormattedLoc,ReasonStr]), - group_leader() ! {printout,12,ErrorStr,[]}, + print_init_conf_result(Line,"crashed",Reason), {skip,{failed,{Mod,init_per_testcase,Reason}}} end. +print_init_conf_result(Line,Cause,Reason) -> + FormattedLoc = test_server_sup:format_loc(Line), + Str2Print = + fun(NoHTML) when NoHTML == stdout; NoHTML == major -> + io_lib:format("ERROR! init_per_testcase ~s!\n" + "\tLocation: ~p\n\tReason: ~tp\n", + [Cause,Line,Reason]); + (minor) -> + ReasonStr = test_server_ctrl:escape_chars(Reason), + io_lib:format("ERROR! init_per_testcase ~s!\n" + "\tLocation: ~ts\n\tReason: ~ts\n", + [Cause,FormattedLoc,ReasonStr]) + end, + group_leader() ! {printout,12,Str2Print}. + + end_per_testcase(Mod, Func, Conf) -> case erlang:function_exported(Mod,end_per_testcase,2) of true -> @@ -1284,14 +1290,7 @@ do_end_per_testcase(Mod,EndFunc,Func,Conf) -> comment(io_lib:format("~ts" "WARNING: ~w thrown!" "\n",[Comment0,EndFunc])), - ReasonStr = - test_server_ctrl:escape_chars(io_lib:format("~tp", [Other])), - group_leader() ! {printout,12, - "WARNING: ~w thrown!\n" - "Reason: ~ts\n" - "Line: ~ts\n", - [EndFunc, ReasonStr, - test_server_sup:format_loc(get_loc())]}, + print_end_tc_warning(EndFunc,Other,"thrown",get_loc()), {failed,{Mod,end_per_testcase,Other}}; Class:Reason -> Stk = erlang:get_stacktrace(), @@ -1308,17 +1307,25 @@ do_end_per_testcase(Mod,EndFunc,Func,Conf) -> comment(io_lib:format("~ts" "WARNING: ~w crashed!" "\n",[Comment0,EndFunc])), - ReasonStr = - test_server_ctrl:escape_chars(io_lib:format("~tp", [Reason])), - group_leader() ! {printout,12, - "WARNING: ~w crashed!\n" - "Reason: ~ts\n" - "Line: ~ts\n", - [EndFunc, ReasonStr, - test_server_sup:format_loc(get_loc())]}, + print_end_tc_warning(EndFunc,Reason,"crashed",get_loc()), {failed,{Mod,end_per_testcase,Why}} end. +print_end_tc_warning(EndFunc,Reason,Cause,Loc) -> + FormattedLoc = test_server_sup:format_loc(Loc), + Str2Print = + fun(NoHTML) when NoHTML == stdout; NoHTML == major -> + io_lib:format("WARNING: ~w ~s!\n" + "Reason: ~tp\nLine: ~p\n", + [EndFunc,Cause,Reason,Loc]); + (minor) -> + ReasonStr = test_server_ctrl:escape_chars(Reason), + io_lib:format("WARNING: ~w ~s!\n" + "Reason: ~ts\nLine: ~ts\n", + [EndFunc,Cause,ReasonStr,FormattedLoc]) + end, + group_leader() ! {printout,12,Str2Print}. + get_loc() -> get(test_server_loc). diff --git a/lib/test_server/src/test_server_gl.erl b/lib/test_server/src/test_server_gl.erl index 356a3288b8..6abc68db54 100644 --- a/lib/test_server/src/test_server_gl.erl +++ b/lib/test_server/src/test_server_gl.erl @@ -182,7 +182,7 @@ handle_info({io_request,From,ReplyAs,Req}=IoReq, St) -> try io_req(Req, From, St) of passthrough -> group_leader() ! IoReq; - Data -> + {EscapeHtml,Data} -> case is_io_permitted(From, St) of false -> ok; @@ -193,15 +193,12 @@ handle_info({io_request,From,ReplyAs,Req}=IoReq, St) -> #st{capture=CapturePid} -> CapturePid ! {captured,Data} end, - - - %%! PROBLEM HERE! - %%! Data could come html tagged from CT!! - - %EscapedChars = test_server_ctrl:escape_chars(Data), - EscapedChars = Data, - - output(minor, EscapedChars, From, From, St) + if EscapeHtml -> + output(minor, test_server_ctrl:escape_chars(Data), + From, From, St); + not EscapeHtml -> + output(minor, Data, From, From, St) + end end, From ! {io_reply,ReplyAs,ok} catch @@ -212,6 +209,13 @@ handle_info({io_request,From,ReplyAs,Req}=IoReq, St) -> handle_info({structured_io,ClientPid,{Detail,Str}}, St) -> output(Detail, Str, ClientPid, ClientPid, St), {noreply,St}; +handle_info({printout,Detail,["$tc_html",Format],Args}, St) -> + Str = io_lib:format(Format, Args), + output(Detail, ["$tc_html",Str], internal, none, St), + {noreply,St}; +handle_info({printout,Detail,Fun}, St) when is_function(Fun)-> + output(Detail, Fun, internal, none, St), + {noreply,St}; handle_info({printout,Detail,Format,Args}, St) -> Str = io_lib:format(Format, Args), output(Detail, Str, internal, none, St), @@ -239,25 +243,55 @@ do_set_props([{reject_io_reqs,Bool}|Ps], St) -> do_set_props(Ps, St#st{reject_io=Bool}); do_set_props([], St) -> St. -io_req({put_chars,Enc,Bytes}, _, _) when Enc =:= latin1; Enc =:= unicode -> - unicode:characters_to_list(Bytes, Enc); +io_req({put_chars,Enc,Str}, _, _) when Enc =:= latin1; Enc =:= unicode -> + case Str of + ["$tc_html",Str0] -> + {false,unicode:characters_to_list(Str0, Enc)}; + _ -> + {true,unicode:characters_to_list(Str, Enc)} + end; io_req({put_chars,Encoding,Mod,Func,[Format,Args]}, _, _) -> - Str = Mod:Func(Format, Args), - unicode:characters_to_list(Str, Encoding); + case Format of + ["$tc_html",Format0] -> + Str = Mod:Func(Format0, Args), + {false,unicode:characters_to_list(Str, Encoding)}; + _ -> + Str = Mod:Func(Format, Args), + {true,unicode:characters_to_list(Str, Encoding)} + end; io_req(_, _, _) -> passthrough. -output(Level, Str, Sender, From, St) when is_integer(Level) -> +output(Level, StrOrFun, Sender, From, St) when is_integer(Level) -> case selected_by_level(Level, stdout, St) of - true -> output(stdout, Str, Sender, From, St); - false -> ok + true when hd(StrOrFun) == "$tc_html" -> + output(stdout, tl(StrOrFun), Sender, From, St); + true when is_function(StrOrFun) -> + output(stdout, StrOrFun(stdout), Sender, From, St); + true -> + output(stdout, StrOrFun, Sender, From, St); + false -> + ok end, case selected_by_level(Level, major, St) of - true -> output(major, Str, Sender, From, St); - false -> ok + true when hd(StrOrFun) == "$tc_html" -> + output(major, tl(StrOrFun), Sender, From, St); + true when is_function(StrOrFun) -> + output(major, StrOrFun(major), Sender, From, St); + true -> + output(major, StrOrFun, Sender, From, St); + false -> + ok end, case selected_by_level(Level, minor, St) of - true -> output(minor, Str, Sender, From, St); - false -> ok + true when hd(StrOrFun) == "$tc_html" -> + output(minor, tl(StrOrFun), Sender, From, St); + true when is_function(StrOrFun) -> + output(minor, StrOrFun(minor), Sender, From, St); + true -> + output(minor, test_server_ctrl:escape_chars(StrOrFun), + Sender, From, St); + false -> + ok end; output(stdout, Str, _Sender, From, St) -> output_to_file(stdout, Str, From, St); -- cgit v1.2.3