diff options
Diffstat (limited to 'lib/test_server/src/test_server_ctrl.erl')
-rw-r--r-- | lib/test_server/src/test_server_ctrl.erl | 337 |
1 files changed, 229 insertions, 108 deletions
diff --git a/lib/test_server/src/test_server_ctrl.erl b/lib/test_server/src/test_server_ctrl.erl index 4fad86d16d..3432b3bc8e 100644 --- a/lib/test_server/src/test_server_ctrl.erl +++ b/lib/test_server/src/test_server_ctrl.erl @@ -171,7 +171,7 @@ -export([kill_slavenodes/0]). %%% TEST_SERVER INTERFACE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --export([output/2, print/2, print/3, print_timestamp/2]). +-export([output/2, print/2, print/3, print/4, print_timestamp/2]). -export([start_node/3, stop_node/1, wait_for_node/1, is_release_available/1]). -export([format/1, format/2, format/3, to_string/1]). -export([get_target_info/0]). @@ -187,6 +187,7 @@ -export([handle_call/3, handle_cast/2, handle_info/2]). -export([do_test_cases/4]). -export([do_spec/2, do_spec_list/2]). +-export([xhtml/2]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -214,6 +215,9 @@ X == auto_skip -> skipped; true -> X end). +-define(auto_skip_color, "#FFA64D"). +-define(user_skip_color, "#FF8000"). + -record(state,{jobs=[],levels={1,19,10}, multiply_timetraps=1,scale_timetraps=true, finish=false, @@ -1668,7 +1672,7 @@ do_test_cases(TopCases, SkipCases, do_test_cases(TopCases, SkipCases, Config, TimetrapData) when is_list(TopCases), is_tuple(TimetrapData) -> - start_log_file(), + {ok,TestDir} = start_log_file(), FwMod = case os:getenv("TEST_SERVER_FRAMEWORK") of FW when FW =:= false; FW =:= "undefined" -> ?MODULE; @@ -1692,60 +1696,86 @@ do_test_cases(TopCases, SkipCases, [print_if_known(N, {", ~w test cases",[N]}, {" (with repeated test cases)",[]})]), Test = get(test_server_name), - test_server_sup:framework_call(report, [tests_start,{Test,N}]), + TestName = if is_list(Test) -> + lists:flatten(io_lib:format("~s", [Test])); + true -> + lists:flatten(io_lib:format("~p", [Test])) + end, + TestDescr = "Test " ++ TestName ++ " results", - Header = - case test_server_sup:framework_call(overview_html_header, [Test], "") of - "" -> - TestName = lists:flatten(io_lib:format("~p", [Test])), - ["<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n", - "<!-- autogenerated by '", atom_to_list(?MODULE), "'. -->\n", - "<html>\n", - "<head><title>Test ", TestName, " results</title>\n", - "<meta http-equiv=\"cache-control\" content=\"no-cache\">\n", - "</head>\n", - "<body bgcolor=\"white\" text=\"black\" ", - "link=\"blue\" vlink=\"purple\" alink=\"red\">", - "<h2>Results from test ", TestName, "</h2>\n"]; - Html -> - ["<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n", - "<!-- autogenerated by '", atom_to_list(?MODULE), "'. -->\n" | Html] + test_server_sup:framework_call(report, [tests_start,{Test,N}]), + {Header,Footer} = + case test_server_sup:framework_call(get_html_wrapper, + [TestDescr,true,TestDir], "") of + Empty when (Empty == "") ; (element(2,Empty) == "") -> + put(basic_html, true), + {["<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n", + "<!-- autogenerated by '", atom_to_list(?MODULE), "'. -->\n", + "<html>\n", + "<head><title>", TestDescr, "</title>\n", + "<meta http-equiv=\"cache-control\" content=\"no-cache\">\n", + "</head>\n", + "<body bgcolor=\"white\" text=\"black\" ", + "link=\"blue\" vlink=\"purple\" alink=\"red\">", + "<h2>Results for test ", TestName, "</h2>\n"], + "\n</body>\n</html>\n"}; + {basic_html,Html0,Html1} -> + put(basic_html, true), + {Html0++["<h1>Results for <i>",TestName,"</i></h1>\n"], + Html1}; + {xhtml,Html0,Html1} -> + put(basic_html, false), + {Html0++["<h1>Results for <i>",TestName,"</i></h1>\n"], + Html1} end, - print(html, Header, []), - print_timestamp(html, "Test started at "), - print(html, "<p>Host:<br>\n"), + print(html, Header), + + print(html, xhtml("<p>", "<h4>")), + print_timestamp(html, "Test started at "), + print(html, xhtml("</p>", "</h4>")), + + print(html, xhtml("\n<p><b>Host info:</b><br>\n", + "\n<p><b>Host info:</b><br />\n")), print_who(test_server_sup:hoststr(), test_server_sup:get_username()), - print(html, "<br>Used Erlang ~s in <tt>~s</tt>.\n", + print(html, xhtml("<br>Used Erlang v~s in <tt>~s</tt></p>\n", + "<br />Used Erlang v~s in \"~s\"</p>\n"), [erlang:system_info(version), code:root_dir()]), - + if FwMod == ?MODULE -> - print(html, "<p>Target:<br>\n"), + print(html, xhtml("\n<p><b>Target Info:</b><br>\n", + "\n<p><b>Target Info:</b><br />\n")), print_who(TI#target_info.host, TI#target_info.username), - print(html, "<br>Used Erlang ~s in <tt>~s</tt>.\n", + print(html, xhtml("<br>Used Erlang v~s in <tt>~s</tt></p>\n", + "<br />Used Erlang v~s in \"~s\"</p>\n"), [TI#target_info.version, TI#target_info.root_dir]); - true -> + true -> case test_server_sup:framework_call(target_info, []) of TargetInfo when is_list(TargetInfo), length(TargetInfo) > 0 -> - print(html, "<p>Target:<br>\n"), - print(html, "~s\n", [TargetInfo]); + print(html, xhtml("\n<p><b>Target info:</b><br>\n", + "\n<p><b>Target info:</b><br />\n")), + print(html, "~s</p>\n", [TargetInfo]); _ -> ok end end, - + print(html, - "<p><a href=\"~s\">Full textual log</a>\n" - "<br><a href=\"~s\">Coverage log</a>\n", + "<p><ul>\n" + "<li><a href=\"~s\">Full textual log</a></li>\n" + "<li><a href=\"~s\">Coverage log</a></li>\n</ul></p>\n", [?suitelog_name,?coverlog_name]), - print(html,"<p>~s" - "<p>\n" - "<table bgcolor=\"white\" border=\"3\" cellpadding=\"5\">" - "<tr><th>Num</th><th>Module</th><th>Case</th><th>Log</th>" - "<th>Time</th><th>Result</th><th>Comment</th></tr>\n", - [print_if_known(N, {"Suite contains ~p test cases.\n",[N]}, + print(html, + "<p>~s</p>\n" ++ + xhtml("<table bgcolor=\"white\" border=\"3\" cellpadding=\"5\">", + "<table>") ++ + "<tr><th>Num</th><th>Module</th><th>Case</th><th>Log</th>" + "<th>Time</th><th>Result</th><th>Comment</th></tr>\n", + [print_if_known(N, {"<i>Executing <b>~p</b> test cases...</i>\n",[N]}, {"",[]})]), + print(html, xhtml("<br>", "<br />")), + print(major, "=cases ~p", [get(test_server_cases)]), print(major, "=user ~s", [TI#target_info.username]), print(major, "=host ~s", [TI#target_info.host]), @@ -1764,6 +1794,9 @@ do_test_cases(TopCases, SkipCases, print(major, "=otp_release ~s", [TI#target_info.otp_release]), print(major, "=started ~s", [lists:flatten(timestamp_get(""))]), + + put(test_server_html_footer, Footer), + run_test_cases(TestSpec, Config, TimetrapData) end; @@ -1773,7 +1806,7 @@ do_test_cases(TopCase, SkipCases, Config, TimetrapSpec) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% start_log_file() -> ok | exit({Error,Reason}) +%% start_log_file() -> {ok,TestDirName} | exit({Error,Reason}) %% Stem = string() %% %% Creates the log directories, the major log file and the html log file. @@ -1793,18 +1826,27 @@ start_log_file() -> exit({cant_create_log_dir,{MkDirError,Dir}}) end, TestDir = timestamp_filename_get(filename:join(Dir, "run.")), - case file:make_dir(TestDir) of - ok -> - ok; - MkDirError2 -> - exit({cant_create_log_dir,{MkDirError2,TestDir}}) - end, - - ok = file:write_file(filename:join(Dir, ?last_file), TestDir ++ "\n"), - ok = file:write_file(?last_file, TestDir ++ "\n"), - - put(test_server_log_dir_base,TestDir), - MajorName = filename:join(TestDir, ?suitelog_name), + TestDir1 = + case file:make_dir(TestDir) of + ok -> + TestDir; + {error,eexist} -> + timer:sleep(1000), + %% we need min 1 second between timestamps unfortunately + TestDirX = timestamp_filename_get(filename:join(Dir, "run.")), + case file:make_dir(TestDirX) of + ok -> + TestDirX; + MkDirError2 -> + exit({cant_create_log_dir,{MkDirError2,TestDirX}}) + end; + MkDirError2 -> + exit({cant_create_log_dir,{MkDirError2,TestDir}}) + end, + ok = file:write_file(filename:join(Dir, ?last_file), TestDir1 ++ "\n"), + ok = file:write_file(?last_file, TestDir1 ++ "\n"), + put(test_server_log_dir_base,TestDir1), + MajorName = filename:join(TestDir1, ?suitelog_name), HtmlName = MajorName ++ ?html_ext, {ok,Major} = file:open(MajorName, [write]), {ok,Html} = file:open(HtmlName, [write]), @@ -1817,14 +1859,14 @@ start_log_file() -> make_html_link(LinkName ++ ?html_ext, HtmlName, filename:basename(Dir)), - PrivDir = filename:join(TestDir, ?priv_dir), + PrivDir = filename:join(TestDir1, ?priv_dir), ok = file:make_dir(PrivDir), put(test_server_priv_dir,PrivDir++"/"), print_timestamp(13,"Suite started at "), - LogInfo = [{topdir,Dir},{rundir,lists:flatten(TestDir)}], + LogInfo = [{topdir,Dir},{rundir,lists:flatten(TestDir1)}], test_server_sup:framework_call(report, [loginfo,LogInfo]), - ok. + {ok,TestDir1}. make_html_link(LinkName, Target, Explanation) -> %% if possible use a relative reference to Target. @@ -1881,16 +1923,32 @@ start_minor_log_file1(Mod, Func, LogDir, AbsName) -> {ok,Fd} = file:open(AbsName, [write]), Lev = get(test_server_minor_level)+1000, %% far down in the minor levels put(test_server_minor_fd, Fd), - io:fwrite(Fd, - "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n" - "<!-- autogenerated by '"++atom_to_list(?MODULE)++"'. -->\n" - "<html>\n" - "<head><title>"++cast_to_list(Mod)++"</title>\n" - "<meta http-equiv=\"cache-control\" content=\"no-cache\">\n" - "</head>\n" - "<body bgcolor=\"white\" text=\"black\"" - " link=\"blue\" vlink=\"purple\" alink=\"red\">\n", - []), + + TestDescr = io_lib:format("Test ~p:~p result", [Mod,Func]), + {Header,Footer} = + case test_server_sup:framework_call(get_html_wrapper, + [TestDescr,false, + filename:dirname(AbsName)], "") of + Empty when (Empty == "") ; (element(2,Empty) == "") -> + put(basic_html, true), + {["<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n", + "<!-- autogenerated by '", atom_to_list(?MODULE), "'. -->\n", + "<html>\n", + "<head><title>", TestDescr, "</title>\n", + "<meta http-equiv=\"cache-control\" content=\"no-cache\">\n", + "</head>\n", + "<body bgcolor=\"white\" text=\"black\" ", + "link=\"blue\" vlink=\"purple\" alink=\"red\">\n"], + "\n</body>\n</html>\n"}; + {basic_html,Html0,Html1} -> + put(basic_html, true), + {Html0,Html1}; + {xhtml,Html0,Html1} -> + put(basic_html, false), + {Html0,Html1} + end, + put(test_server_minor_footer, Footer), + io:fwrite(Fd, Header, []), SrcListing = downcase(cast_to_list(Mod)) ++ ?src_listing_ext, case {filelib:is_file(filename:join(LogDir, SrcListing)), @@ -1913,7 +1971,8 @@ start_minor_log_file1(Mod, Func, LogDir, AbsName) -> stop_minor_log_file() -> Fd = get(test_server_minor_fd), - io:fwrite(Fd, "</pre>\n</body>\n</html>\n", []), + Footer = get(test_server_minor_footer), + io:fwrite(Fd, "</pre>\n" ++ Footer, []), file:close(Fd), put(test_server_minor_fd, undefined). @@ -1992,12 +2051,29 @@ html_convert_modules([]) -> ok. %% Convert source code to HTML if possible and needed. html_possibly_convert(Src, SrcInfo, Dest) -> case file:read_file_info(Dest) of - {error,_Reason} -> % no dest file - erl2html2:convert(Src, Dest); - {ok,DestInfo} when DestInfo#file_info.mtime < SrcInfo#file_info.mtime -> - erl2html2:convert(Src, Dest); - {ok,_DestInfo} -> - ok % dest file up to date + {ok,DestInfo} when DestInfo#file_info.mtime >= SrcInfo#file_info.mtime -> + 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], "") of + Empty when (Empty == "") ; (element(2,Empty) == "") -> + ["<!DOCTYPE HTML PUBLIC", + "\"-//W3C//DTD HTML 3.2 Final//EN\">\n", + "<!-- autogenerated by 'erl2html2' -->\n", + "<html>\n", + "<head><title>Module ", Src, "</title>\n", + "<meta http-equiv=\"cache-control\" ", + "content=\"no-cache\">\n", + "</head>\n", + "<body bgcolor=\"white\" text=\"black\" ", + "link=\"blue\" vlink=\"purple\" alink=\"red\">\n"]; + {_,Html,_} -> + Html + end, + erl2html2:convert(Src, Dest, Header) end. %% Copy all HTML files in InDir to OutDir. @@ -2658,23 +2734,32 @@ run_test_cases_loop([{conf,Ref,Props,{Mod,Func}}|_Cases]=Cs0, "(configuration case ~w)", [What]); (_) -> ok end, - CfgProps = if StartConf -> if Shuffle == undefined -> [{tc_group_properties,Props}]; true -> - [{tc_group_properties,[Shuffle|delete_shuffle(Props)]}] + [{tc_group_properties, + [Shuffle|delete_shuffle(Props)]}] end; not StartConf -> {TcOk,TcSkip,TcFail} = get_tc_results(Status1), [{tc_group_properties,get_props(Mode0)}, - {tc_group_result,[{ok,TcOk},{skipped,TcSkip},{failed,TcFail}]}] + {tc_group_result,[{ok,TcOk}, + {skipped,TcSkip}, + {failed,TcFail}]}] end, - ActualCfg = - update_config(hd(Config), [{priv_dir,get(test_server_priv_dir)}, - {data_dir,get_data_dir(Mod)}] ++ CfgProps), + TSDirs = [{priv_dir,get(test_server_priv_dir)},{data_dir,get_data_dir(Mod)}], + ActualCfg = + if not StartConf -> + update_config(hd(Config), TSDirs ++ CfgProps); + true -> + GroupPath = lists:flatmap(fun({_Ref,[],_T}) -> []; + ({_Ref,GrProps,_T}) -> [GrProps] + end, Mode0), + update_config(hd(Config), + TSDirs ++ [{tc_group_path,GroupPath} | CfgProps]) + end, CurrMode = curr_mode(Ref, Mode0, Mode), - ConfCaseResult = run_test_case(Ref, 0, Mod, Func, [ActualCfg], skip_init, target, TimetrapData, CurrMode), @@ -3153,8 +3238,8 @@ skip_case(Type, Ref, CaseNum, Case, Comment, SendSync, Mode) -> skip_case1(Type, CaseNum, Mod, Func, Comment, Mode) -> {{Col0,Col1},_} = get_font_style((CaseNum > 0), Mode), - ResultCol = if Type == auto -> "#ffcc99"; - Type == user -> "#ff9933" + ResultCol = if Type == auto -> ?auto_skip_color; + Type == user -> ?user_skip_color end, Comment1 = reason_to_string(Comment), @@ -3163,9 +3248,9 @@ skip_case1(Type, CaseNum, Mod, Func, Comment, Mode) -> print(major, "=started ~s", [lists:flatten(timestamp_get(""))]), print(major, "=result skipped: ~s", [Comment1]), print(2,"*** Skipping test case #~w ~p ***", [CaseNum,{Mod,Func}]), + TR = xhtml("<tr valign=\"top\">", ["<tr class=\"",odd_or_even(),"\">"]), print(html, - "<tr valign=top>" - "<td>" ++ Col0 ++ "~s" ++ Col1 ++ "</td>" + TR ++ "<td>" ++ Col0 ++ "~s" ++ Col1 ++ "</td>" "<td>" ++ Col0 ++ "~p" ++ Col1 ++ "</td>" "<td>" ++ Col0 ++ "~p" ++ Col1 ++ "</td>" "<td>" ++ Col0 ++ "< >" ++ Col1 ++ "</td>" @@ -3558,25 +3643,29 @@ run_test_case1(Ref, Num, Mod, Func, Args, RunInit, Where, host -> ok end, - test_server_sup:framework_call(report, [tc_start,{?pl2a(Mod),Func}]), print(major, "=case ~p:~p", [Mod, Func]), MinorName = start_minor_log_file(Mod, Func), - print(minor, "<a name=top></a>", []), + print(minor, "<a name=\"top\"></a>", [], internal_raw), MinorBase = filename:basename(MinorName), print(major, "=logfile ~s", [filename:basename(MinorName)]), + + Args1 = [[{tc_logfile,MinorName} | proplists:delete(tc_logfile,hd(Args))]], + test_server_sup:framework_call(report, [tc_start,{{?pl2a(Mod),Func},MinorName}]), + print_props((RunInit==skip_init), get_props(Mode)), print(major, "=started ~s", [lists:flatten(timestamp_get(""))]), {{Col0,Col1},Style} = get_font_style((RunInit==run_init), Mode), - print(html, "<tr valign=top><td>" ++ Col0 ++ "~s" ++ Col1 ++ "</td>" - "<td>" ++ Col0 ++ "~p" ++ Col1 ++ "</td>" - "<td><a href=\"~s\">~p</a></td>" - "<td><a href=\"~s#top\"><</a> <a href=\"~s#end\">></a></td>", - [num2str(Num),Mod,MinorBase,Func,MinorBase,MinorBase]), + TR = xhtml("<tr valign=\"top\">", ["<tr class=\"",odd_or_even(),"\">"]), + print(html, TR ++ "<td>" ++ Col0 ++ "~s" ++ Col1 ++ "</td>" + "<td>" ++ Col0 ++ "~p" ++ Col1 ++ "</td>" + "<td><a href=\"~s\">~p</a></td>" + "<td><a href=\"~s#top\"><</a> <a href=\"~s#end\">></a></td>", + [num2str(Num),Mod,MinorBase,Func,MinorBase,MinorBase]), do_if_parallel(Main, ok, fun erlang:yield/0), %% run the test case {Result,DetectedFail,ProcsBefore,ProcsAfter} = - run_test_case_apply(Num, Mod, Func, Args, get_name(Mode), + run_test_case_apply(Num, Mod, Func, Args1, get_name(Mode), RunInit, Where, TimetrapData), {Time,RetVal,Loc,Opts,Comment} = case Result of @@ -3584,7 +3673,8 @@ run_test_case1(Ref, Num, Mod, Func, Args, RunInit, Where, {died,DReason,DLoc,DCmt} -> {died,DReason,DLoc,[],DCmt} end, - print(minor, "<a name=end></a>", []), + print(minor, "<a name=\"end\"></a>", [], internal_raw), + print(minor, "\n", [], internal_raw), print_timestamp(minor, "Ended at "), print(major, "=ended ~s", [lists:flatten(timestamp_get(""))]), @@ -3838,9 +3928,10 @@ check_new_crash_dumps(Where) -> progress(skip, CaseNum, Mod, Func, Loc, Reason, Time, Comment, {St0,St1}) -> - {Reason1,{Color,Ret}} = if_auto_skip(Reason, - fun() -> {"#ffcc99",auto_skip} end, - fun() -> {"#ff9933",skip} end), + {Reason1,{Color,Ret}} = + if_auto_skip(Reason, + fun() -> {?auto_skip_color,auto_skip} end, + fun() -> {?user_skip_color,skip} end), print(major, "=result skipped", []), print(1, "*** SKIPPED *** ~s", [get_info_str(Func, CaseNum, get(test_server_cases))]), @@ -3857,7 +3948,7 @@ progress(skip, CaseNum, Mod, Func, Loc, Reason, Time, end, Comment1 = case Comment of "" -> ""; - _ -> "<br>(" ++ to_string(Comment) ++ ")" + _ -> xhtml("<br>(","<br />(") ++ to_string(Comment) ++ ")" end, print(html, "<td>" ++ St0 ++ "~.3fs" ++ St1 ++ "</td>" @@ -3882,8 +3973,8 @@ progress(failed, CaseNum, Mod, Func, Loc, timetrap_timeout, T, Comment = case Comment0 of "" -> "<font color=\"red\">" ++ ErrorReason ++ "</font>"; - _ -> "<font color=\"red\">" ++ ErrorReason ++ "</font><br>" ++ - to_string(Comment0) + _ -> "<font color=\"red\">" ++ ErrorReason ++ + xhtml("</font><br>","</font><br />") ++ to_string(Comment0) end, print(html, "<td>" ++ St0 ++ "~.3fs" ++ St1 ++ "</td>" @@ -3908,8 +3999,8 @@ progress(failed, CaseNum, Mod, Func, Loc, {testcase_aborted,Reason}, _T, Comment = case Comment0 of "" -> "<font color=\"red\">" ++ ErrorReason ++ "</font>"; - _ -> "<font color=\"red\">" ++ ErrorReason ++ "</font><br>" ++ - to_string(Comment0) + _ -> "<font color=\"red\">" ++ ErrorReason ++ + xhtml("</font><br>","</font><br />") ++ to_string(Comment0) end, print(html, "<td>" ++ St0 ++ "died" ++ St1 ++ "</td>" @@ -3943,7 +4034,8 @@ progress(failed, CaseNum, Mod, Func, unknown, Reason, Time, Comment = case Comment0 of "" -> "<font color=\"red\">" ++ ErrorReason2 ++ "</font>"; - _ -> "<font color=\"red\">" ++ ErrorReason2 ++ "</font><br>" ++ + _ -> "<font color=\"red\">" ++ ErrorReason2 ++ + xhtml("</font><br>","</font><br />") ++ to_string(Comment0) end, print(html, @@ -3953,7 +4045,7 @@ progress(failed, CaseNum, Mod, Func, unknown, Reason, Time, [TimeStr,Comment]), print(minor, "=== location ~s", [unknown]), {FStr,FormattedReason} = format_exception(Reason), - print(minor, "=== reason = "++FStr, [FormattedReason]), + print(minor, "=== reason = " ++ FStr, [FormattedReason]), failed; progress(failed, CaseNum, Mod, Func, Loc, Reason, Time, @@ -3969,7 +4061,7 @@ progress(failed, CaseNum, Mod, Func, Loc, Reason, Time, Comment = case Comment0 of "" -> ""; - _ -> "<br>" ++ to_string(Comment0) + _ -> xhtml("<br>","<br />") ++ to_string(Comment0) end, FormatLastLoc = test_server_sup:format_loc(get_last_loc(Loc)), print(html, @@ -3980,7 +4072,7 @@ progress(failed, CaseNum, Mod, Func, Loc, Reason, Time, FormatLoc = test_server_sup:format_loc(Loc), print(minor, "=== location ~s", [FormatLoc]), {FStr,FormattedReason} = format_exception(Reason), - print(minor, "=== reason = "++FStr, [FormattedReason]), + print(minor, "=== reason = " ++ FStr, [FormattedReason]), failed; progress(ok, _CaseNum, Mod, Func, _Loc, RetVal, Time, @@ -3999,7 +4091,7 @@ progress(ok, _CaseNum, Mod, Func, _Loc, RetVal, Time, _ -> print(major, "=result ok", []), case Comment0 of - "" -> ""; + "" -> "<td></td>"; _ -> "<td>" ++ to_string(Comment0) ++ "</td>" end end, @@ -4349,7 +4441,13 @@ output({html,Msg}, _Sender) -> %% We are writing to a seekable file. Finalise so %% we get complete valid (and viewable) HTML code. %% Then rewind to overwrite the finalising code. - io:put_chars(Fd, "\n</table>\n</body>\n</html>\n"), + io:put_chars(Fd, "\n</table>\n"), + case get(test_server_html_footer) of + undefined -> + io:put_chars(Fd, "</body>\n</html>\n"); + Footer -> + io:put_chars(Fd, Footer) + end, file:position(Fd, Pos); {error, epipe} -> %% The file is not seekable. We cannot erase what @@ -4394,6 +4492,28 @@ output_to_fd(Fd, Msg, _Sender) -> end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% xhtml(BasicHtml, XHtml) -> BasicHtml | XHtml +%% +xhtml(HTML, XHTML) -> + case get(basic_html) of + true -> HTML; + _ -> XHTML + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% odd_or_even() -> "odd" | "even" +%% +odd_or_even() -> + case get(odd_or_even) of + even -> + put(odd_or_even, odd), + "even"; + _ -> + put(odd_or_even, even), + "odd" + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% timestamp_filename_get(Leader) -> string() %% Leader = string() %% @@ -5499,9 +5619,10 @@ write_default_cross_coverlog(TestDir) -> file:open(filename:join(TestDir,?cross_coverlog_name), [write]), write_coverlog_header(CrossCoverLog), io:fwrite(CrossCoverLog, - "No cross cover modules exist for this application,<br>" - "or cross cover analysis is not completed.\n" - "</body></html>\n", []), + ["No cross cover modules exist for this application,", + xhtml("<br>","<br />"), + "or cross cover analysis is not completed.\n" + "</body></html>\n"], []), file:close(CrossCoverLog). write_cover_result_table(CoverLog,Coverage) -> |