From 2cacf6885cafa276985324924a038618b0bb10fd Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Tue, 8 Nov 2011 08:55:08 +0100 Subject: Add CSS stylesheet for the text and tables in Common Test and Test Server Also make general improvements of presentation of results. OTP-9706 --- lib/common_test/priv/Makefile.in | 8 +- lib/common_test/priv/ct_default.css | 185 ++++++++++++ lib/common_test/src/ct_framework.erl | 32 +- lib/common_test/src/ct_logs.erl | 494 +++++++++++++++++++++---------- lib/test_server/src/erl2html2.erl | 49 +-- lib/test_server/src/test_server.erl | 2 +- lib/test_server/src/test_server_ctrl.erl | 234 ++++++++++----- 7 files changed, 714 insertions(+), 290 deletions(-) create mode 100644 lib/common_test/priv/ct_default.css (limited to 'lib') diff --git a/lib/common_test/priv/Makefile.in b/lib/common_test/priv/Makefile.in index f4a0c181f9..d9033f6ef1 100644 --- a/lib/common_test/priv/Makefile.in +++ b/lib/common_test/priv/Makefile.in @@ -59,6 +59,7 @@ ifneq ($(findstring win32,$(TARGET)),win32) FILES = vts.tool SCRIPTS = IMAGES = tile1.jpg +CSS = ct_default.css # # Rules @@ -85,11 +86,11 @@ include $(ERL_TOP)/make/otp_release_targets.mk ifeq ($(XNIX),true) release_spec: opt $(INSTALL_DIR) $(RELSYSDIR)/priv - $(INSTALL_DATA) $(FILES) $(IMAGES) $(RELSYSDIR)/priv + $(INSTALL_DATA) $(FILES) $(IMAGES) $(CSS) $(RELSYSDIR)/priv else release_spec: opt $(INSTALL_DIR) $(RELSYSDIR)/priv - $(INSTALL_DATA) $(FILES) $(IMAGES) $(RELSYSDIR)/priv + $(INSTALL_DATA) $(FILES) $(IMAGES) $(CSS) $(RELSYSDIR)/priv endif release_docs_spec: @@ -105,6 +106,7 @@ else # FILES = vts.tool IMAGES = tile1.jpg +CSS = ct_default.css # # Rules @@ -124,7 +126,7 @@ include $(ERL_TOP)/make/otp_release_targets.mk release_spec: opt $(INSTALL_DIR) $(RELSYSDIR)/priv - $(INSTALL_DATA) $(FILES) $(IMAGES) $(RELSYSDIR)/priv + $(INSTALL_DATA) $(FILES) $(IMAGES) $(CSS) $(RELSYSDIR)/priv release_docs_spec: diff --git a/lib/common_test/priv/ct_default.css b/lib/common_test/priv/ct_default.css new file mode 100644 index 0000000000..94baf1f6f9 --- /dev/null +++ b/lib/common_test/priv/ct_default.css @@ -0,0 +1,185 @@ +/* Stylesheet for Common Test */ + +body { + padding: 10px; margin: 10px; + -webkit-font-smoothing: antialiased; + background-color: #FBFFFC; +} + +a:link { + color: #2B507D; +} + +a:visited { + color: #85ABD5 +} + +h1 { + font-family: verdana, arial, sans-serif; font-size: 200%; + letter-spacing: -2.5px; word-spacing: 2px; font-weight: bold; + color: #3F3F3F; +} + +h2 { + font-family: verdana, arial, sans-serif; font-size: 175%; + letter-spacing: -2.5px; word-spacing: 2px; font-weight: normal; + color: #3F3F3F; +} + +h3 { + font-family: verdana, arial, sans-serif; font-size: 140%; + letter-spacing: -2.5px; word-spacing: 2px; font-weight: bold; + color: #3F3F3F; +} + +h4 { + font-family: verdana, arial, sans-serif; font-size: 120%; + letter-spacing: -2.5px; word-spacing: 2px; font-weight: normal; + color: #3F3F3F; +} + +p { + font-family: "Trebuchet MS", "Lucida Sans Unicode", verdana, arial, sans-serif; + font-size: .9em; color: #000000; +} + +ul { + list-style-type: none; + padding: 0em; + margin: 1em; +} +li { + font-family: "Trebuchet MS", "Lucida Sans Unicode", verdana, arial, sans-serif; + font-size: .9em; color: #000000; + margin: .4em 0; +} + +pre { + color: black; + font-family: "Monaco", "Andale Mono", "Consolas", monospace; + font-size: .8em; + } + +code { + color: black; + font-family: "Monaco", "Andale Mono", "Consolas", monospace; + font-size: .8em; +} + +div.mono_sm { + font-family: "Courier New", monospace; font-size: 80%; + word-spacing: 1px; color: #000000; +} + +div.mono_la { + font-family: "Courier New", monospace; font-size: 100%; + color: #000000; +} + +div.copyright { + padding: 20px 0px 0px 0px; + font-family: "Courier New", monospace; font-size: 80%; + color: #000000; +} + +div.ct_internal { + background: lightgrey; color: black; + font-family: "Monaco", "Andale Mono", "Consolas", monospace; + font-size: 90%; +} + +div.default { + background: lightgreen; color: black; + font-family: "Monaco", "Andale Mono", "Consolas", monospace; + font-size: 90%; +} + +div.label { + font-family: verdana, arial, sans-serif; font-size: 200%; + letter-spacing: -2.5px; word-spacing: 2px; + font-weight: bold; color: #2B507D; +} + +table { + border-collapse: collapse; border: 6px solid #3F3F3F; + background: #FFFFFF; + font: .8em/1.2em "Lucida Sans Unicode", verdana, arial, sans-serif; + color: #222; +} + +caption { + font-size: 1.3em; font-weight: bold; + text-align: center; padding: 1em 4px; +} + +td, th { + padding: .5em 7px .5em 7px; line-height: 1.3em; + border-bottom: 3px solid #F5C4C1; + border-left: 2px dashed #809FFF; +} + +th { + background: #3F3F3F; color: #fff; + font-family: arial, sans-serif; font-size: 120%; + letter-spacing: -0.5px; + font-weight: bold; text-align: center; + padding-right: .5em; vertical-align: top; +} + +thead th { + background: #2C5755; text-align: center; +} + +.odd td { + background: #F3F3F3; +} +.odd th { + background: #F3F3F3; +} + +td a, td a:link { + color: #2B507D; +} + +td a:visited { + color: #85ABD5; +} + +tr:hover th[scope=row], tr:hover td { + background-color: #808080; + color: #fff; +} + +td a:hover, td a:focus { + color: #85ABD5; +} + +th a, td a:active { + color: #85ABD5; +} + +tfoot th, tfoot td { + background: #3F3F3F; color: #fff; +} + +th + td { + padding-left: .5em; +} + +#button_holder { + display: block; float: center; + font-family: arial, verdana, sans-serif; + font-size: 12px; text-shadow: 1px 1px lightgray; +} + +.btn a { + padding: 6px 12px; float: center; + text-decoration: none; color: #3F3F3F; + font-weight: bold; border: 3px outset #3F3F3F; + background-color: #F3F3F3; +} + +.btn a:hover { + color: #fff; + background-color: #809FFF; +} diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl index 482c5242ce..26c71dfb42 100644 --- a/lib/common_test/src/ct_framework.erl +++ b/lib/common_test/src/ct_framework.erl @@ -27,7 +27,7 @@ -export([init_tc/3, end_tc/3, end_tc/4, get_suite/2, get_all_cases/1]). -export([report/2, warn/1, error_notification/4]). --export([get_logopts/0, format_comment/1, overview_html_header/1]). +-export([get_logopts/0, format_comment/1, get_html_wrapper/2]). -export([error_in_suite/1, ct_init_per_group/2, ct_end_per_group/2]). @@ -1411,30 +1411,6 @@ format_comment(Comment) -> "" ++ Comment ++ "". %%%----------------------------------------------------------------- -%%% @spec overview_html_header(TestName) -> Header -overview_html_header(TestName) -> - TestName1 = lists:flatten(io_lib:format("~p", [TestName])), - Label = case application:get_env(common_test, test_label) of - {ok,Lbl} when Lbl =/= undefined -> - "

" ++ Lbl ++ "

\n"; - _ -> - "" - end, - Bgr = case ct_logs:basic_html() of - true -> - ""; - false -> - CTPath = code:lib_dir(common_test), - TileFile = filename:join(filename:join(CTPath,"priv"),"tile1.jpg"), - " background=\"" ++ TileFile ++ "\"" - end, - - ["\n", - "Test ", TestName1, " results\n", - "\n", - "\n", - "\n", - Label, - "

Results from test ", TestName1, "

\n"]. - +%%% @spec get_html_wrapper(TestName, PrintLabel) -> Header +get_html_wrapper(TestName, PrintLabel) -> + ct_logs:get_ts_html_wrapper(TestName, PrintLabel). diff --git a/lib/common_test/src/ct_logs.erl b/lib/common_test/src/ct_logs.erl index c1523509a5..af45ecf235 100644 --- a/lib/common_test/src/ct_logs.erl +++ b/lib/common_test/src/ct_logs.erl @@ -29,11 +29,13 @@ -module(ct_logs). -export([init/1,close/2,init_tc/1,end_tc/1]). --export([get_log_dir/0,log/3,start_log/1,cont_log/2,end_log/0]). +-export([get_log_dir/0,get_log_dir/1]). +-export([log/3,start_log/1,cont_log/2,end_log/0]). -export([set_stylesheet/2,clear_stylesheet/1]). -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/2]). %% Logging stuff directly from testcase -export([tc_log/3,tc_print/3,tc_pal/3,ct_log/3, @@ -162,7 +164,12 @@ clear_stylesheet(TC) -> %%%----------------------------------------------------------------- %%% @spec get_log_dir() -> {ok,Dir} | {error,Reason} get_log_dir() -> - call(get_log_dir). + call({get_log_dir,false}). + +%%%----------------------------------------------------------------- +%%% @spec get_log_dir(Abs) -> {ok,Dir} | {error,Reason} +get_log_dir(Abs) -> + call({get_log_dir,Abs}). %%%----------------------------------------------------------------- %%% make_last_run_index() -> ok @@ -437,6 +444,8 @@ log_timestamp({MS,S,US}) -> logger(Parent,Mode) -> register(?MODULE,self()), + put(basic_html, basic_html()), + %%! Below is a temporary workaround for the limitation of %%! max one test run per second. %%! ---> @@ -456,8 +465,9 @@ logger(Parent,Mode) -> %%! <--- file:make_dir(Dir), + AbsDir = ?abs(Dir), ct_event:notify(#event{name=start_logging,node=node(), - data=?abs(Dir)}), + data=AbsDir}), make_all_runs_index(start), make_all_suites_index(start), case Mode of @@ -472,7 +482,7 @@ logger(Parent,Mode) -> Parent ! {started,self(),{Time,filename:absname("")}}, set_evmgr_gl(CtLogFd), logger_loop(#logger_state{parent=Parent, - log_dir=Dir, + log_dir=AbsDir, start_time=Time, orig_GL=group_leader(), ct_log_fd=CtLogFd, @@ -536,12 +546,15 @@ logger_loop(State) -> set_evmgr_gl(State#logger_state.ct_log_fd), return(From,ok), logger_loop(State#logger_state{tc_groupleaders=rm_tc_gl(TCPid,State)}); - {get_log_dir,From} -> + {{get_log_dir,true},From} -> return(From,{ok,State#logger_state.log_dir}), logger_loop(State); + {{get_log_dir,false},From} -> + return(From,{ok,filename:basename(State#logger_state.log_dir)}), + logger_loop(State); {make_last_run_index,From} -> make_last_run_index(State#logger_state.start_time), - return(From,State#logger_state.log_dir), + return(From,filename:basename(State#logger_state.log_dir)), logger_loop(State); {set_stylesheet,_,SSFile} when State#logger_state.stylesheet == SSFile -> logger_loop(State); @@ -657,7 +670,7 @@ set_evmgr_gl(GL) -> open_ctlog() -> {ok,Fd} = file:open(?ct_log_name,[write]), - io:format(Fd,header("Common Test Framework"),[]), + io:format(Fd,header("Common Test Framework Log"),[]), case file:consult(ct_run:variables_file_name("../")) of {ok,Vars} -> io:format(Fd, config_table(Vars), []); @@ -672,17 +685,22 @@ open_ctlog() -> end, print_style(Fd,undefined), io:format(Fd, - "

Progress Log

\n" - "
\n",[]),
+	      xhtml("

Progress Log

\n
\n",
+		    "

PROGRESS LOG

\n
\n"), []),
     Fd.
 
 print_style(Fd,undefined) ->
-    io:format(Fd,
-	      "\n",
-	      []);
+    case basic_html() of
+	true ->
+	    io:format(Fd,
+		      "\n",
+		      []);
+	_ ->
+	    ok
+    end;
 
 print_style(Fd,StyleSheet) ->
     case file:read_file(StyleSheet) of
@@ -854,8 +872,8 @@ make_one_index_entry1(SuiteName, Link, Label, Success, Fail, UserSkip, AutoSkip,
 			    CrashDumpName = SuiteName ++ "_erl_crash.dump",
 			    case filelib:is_file(CrashDumpName) of
 				true ->
-				    [" (CrashDump)"];
+				    [" (CrashDump)"];
 				false ->
 				    ""
 			    end
@@ -869,32 +887,41 @@ make_one_index_entry1(SuiteName, Link, Label, Success, Fail, UserSkip, AutoSkip,
 			    0 -> "-";
 			    _ -> NodeOrDate
 			end,
-		N = ["",Node1,"\n"],
-		L = ["",Label,"\n"],
-		T = ["",timestamp(CtRunDir),"\n"],
+		TS = timestamp(CtRunDir),
+		N = xhtml(["",Node1,
+			   "\n"],
+			  ["",Node1,"\n"]),
+		L = xhtml(["",Label,
+			   "\n"],
+			  ["",Label,"\n"]),
+		T = xhtml(["",TS,"\n"],
+			  ["",TS,"\n"]),
 		CtLogFile = filename:join(CtRunDir,?ct_log_name),
 		OldRunsLink = 
 		    case OldRuns of
 			[] -> "none";
-			_ ->  "Old Runs"
+			_ ->  "Old Runs"
 		    end,
-		A=["CT Log\n",
-		   "",OldRunsLink,"\n"],
+		A = xhtml(["CT Log\n",
+			   "",OldRunsLink,"\n"],
+			  ["CT Log\n",
+			   "",OldRunsLink,"\n"]),
 		{L,T,N,A};
 	    false ->
 		{"","","",""}
 	end,
     NotBuiltStr =
 	if NotBuilt == 0 ->
-		["",integer_to_list(NotBuilt),"\n"];
+		["",integer_to_list(NotBuilt),"\n"];
 	   true ->
-		["",
-		integer_to_list(NotBuilt),"\n"]
+		["",
+		integer_to_list(NotBuilt),"\n"]
 	end,
     FailStr =
 	if Fail > 0 ->  
-		["",
-		 integer_to_list(Fail),""];
+		["",
+		 integer_to_list(Fail),""];
 	   true ->
 		integer_to_list(Fail)
 	end,
@@ -902,31 +929,33 @@ make_one_index_entry1(SuiteName, Link, Label, Success, Fail, UserSkip, AutoSkip,
 	if AutoSkip == undefined -> {UserSkip,"?","?"};
 	   true ->
 		ASStr = if AutoSkip > 0 ->
-				["",
-				 integer_to_list(AutoSkip),""];
+				["",
+				 integer_to_list(AutoSkip),""];
 			   true -> integer_to_list(AutoSkip)
 			end,
 		{UserSkip+AutoSkip,integer_to_list(UserSkip),ASStr}
 	end,
-    ["\n",
-     "",SuiteName,"",CrashDumpLink,"\n",
-     Lbl,
-     Timestamp,
-     "",integer_to_list(Success),"\n",
-     "",FailStr,"\n",
-     "",integer_to_list(AllSkip),
-     " (",UserSkipStr,"/",AutoSkipStr,")\n",  
-     NotBuiltStr,
-     Node,
-     AllInfo,
-     "\n"].
+    [xhtml("\n",
+	   ["\n"]),
+     xhtml("",SuiteName,"", CrashDumpLink,
+     xhtml("\n", "\n"),
+     Lbl, Timestamp,
+     "",integer_to_list(Success),"\n",
+     "",FailStr,"\n",
+     "",integer_to_list(AllSkip),
+     " (",UserSkipStr,"/",AutoSkipStr,")\n",  
+     NotBuiltStr, Node, AllInfo, "\n"].
+
 total_row(Success, Fail, UserSkip, AutoSkip, NotBuilt, All) ->
     {Label,TimestampCell,AllInfo} =
 	case All of
 	    true ->
-		{" \n",
-		 " \n",
-		 " \n \n"};
+		{" \n",
+		 " \n",
+		 " \n"
+		 " \n"
+		 " \n"};
 	    false ->
 		{"","",""}
 	end,
@@ -936,17 +965,15 @@ total_row(Success, Fail, UserSkip, AutoSkip, NotBuilt, All) ->
 	   true -> {UserSkip+AutoSkip,
 		    integer_to_list(UserSkip),integer_to_list(AutoSkip)}
 	end,
-    ["\n",
-     "Total",
-     Label,
-     TimestampCell,
-     "",integer_to_list(Success),"\n",
-     "",integer_to_list(Fail),"\n",
-     "",integer_to_list(AllSkip),
-     " (",UserSkipStr,"/",AutoSkipStr,")\n",  
-     "",integer_to_list(NotBuilt),"\n",
-     AllInfo,
-     "\n"].
+    [xhtml("\n", 
+	   ["\n"]),
+     "Total\n", Label, TimestampCell,
+     "",integer_to_list(Success),"\n",
+     "",integer_to_list(Fail),"\n",
+     "",integer_to_list(AllSkip),
+     " (",UserSkipStr,"/",AutoSkipStr,")\n",  
+     "",integer_to_list(NotBuilt),"\n",
+     AllInfo, "\n"].
 
 not_built(_BaseName,_LogDir,_All,[]) ->
     0;
@@ -1005,41 +1032,52 @@ index_header(Label, StartTime) ->
 	    undefined ->
 		header("Test Results", format_time(StartTime));
 	    _ ->
-		header("Test Results for \"" ++ Label ++ "\"",
+		header("Test Results for '" ++ Label ++ "'",
 		       format_time(StartTime))
 	end,
     [Head |
-     ["
\n", - "

Common Test Framework Log

", - "\n" - "\n", - "\n" + ["
\n", + xhtml(["

Common Test Framework Log

"], + ["
" + ""]), + xhtml("
\n", "


\n"), + xhtml(["
Test Name_Ok" - "_
\n"], "
\n"), + "\n", + xhtml(["\n"], + "\n"), "\n", - "\n" - "\n" + "\n" + "\n" "\n"]]. - all_suites_index_header() -> {ok,Cwd} = file:get_cwd(), all_suites_index_header(Cwd). all_suites_index_header(IndexDir) -> LogDir = filename:basename(IndexDir), - AllRuns = "All test runs in \"" ++ LogDir ++ "\"", + AllRuns = xhtml(["All test runs in \"" ++ LogDir ++ "\""], + "ALL RUNS"), + AllRunsLink = xhtml(["",AllRuns,"\n"], + ["
\n" + "",AllRuns,"\n
"]), [header("Test Results") | - ["
\n", - "",AllRuns,"\n", - "

\n", - "
Test Name_Ok" + "_OkFailedSkipped
(User/Auto)
Missing
Suites
Skipped", xhtml("
", "
"), "(User/Auto)
Missing", xhtml("
", "
"), "Suites
\n" + ["
\n", + AllRunsLink, + xhtml("

\n", "

\n"), + xhtml(["
\n"], "
\n"), "\n", "\n", "\n", - "\n" + xhtml(["\n"], + "\n"), "\n", "\n" "\n" @@ -1052,17 +1090,25 @@ all_runs_header() -> {ok,Cwd} = file:get_cwd(), LogDir = filename:basename(Cwd), Title = "All test runs in \"" ++ LogDir ++ "\"", + IxLink = [xhtml(["

Test Index Page

"], + [""]), + xhtml("
\n", "

\n")], [header(Title) | - ["
Test NameLabelTest Run Started_Ok" - "__Ok" + "_OkFailedSkipped
(User/Auto)
Missing
Suites
\n" - "\n" - "\n" - "\n" + ["
\n", IxLink, + xhtml(["
HistoryNodeLabel
\n"], "
\n"), + "\n" + "\n" + "\n" "\n" - "\n" - "\n" - "\n" + "\n" + "\n", + xhtml(["\n"], + "\n"), "\n" "\n" "\n" @@ -1075,60 +1121,56 @@ header(Title, SubTitle) -> header1(Title, SubTitle) -> SubTitleHTML = if SubTitle =/= "" -> - ["
\n", - "

" ++ SubTitle ++ "

\n", - "
\n
\n"]; - true -> "
\n" + ["
\n", + "

" ++ SubTitle ++ "

\n", + xhtml("
\n
\n", "\n
\n")]; + true -> xhtml("
\n", "
\n") end, - ["\n" - "\n" - "\n", - "\n", - - "" ++ Title ++ " " ++ SubTitle ++ "\n", - "\n", - - "\n", - - body_tag(), - - "\n", - - "
\n", - "

" ++ Title ++ "

\n", - "
\n", - SubTitleHTML, - - "\n"]. + CTPath = code:lib_dir(common_test), + CSSFile = filename:join(filename:join(CTPath, "priv"), "ct_default.css"), + [xhtml(["\n", + "\n"], + ["\n", + "\n"]), + "\n", + "\n", + "" ++ Title ++ " " ++ SubTitle ++ "\n", + "\n", + xhtml("", + [""]), + "\n", + body_tag(), + "
\n", + "

" ++ Title ++ "

\n", + "
\n", + SubTitleHTML,"\n"]. index_footer() -> - ["
HistoryNodeLabelTestsTest NamesTotal_Ok" - "_Test NamesTotal_Ok" + "_OkFailedSkipped
(User/Auto)
Missing
Suites
\n" - "
\n" | footer()]. + ["\n" + "\n" | footer()]. footer() -> - ["

\n" - "

\n" - "
\n" - "

\n" + ["

\n", + xhtml("

\n
\n", "

\n"), + xhtml("

\n", "

"), "Copyright © ", year(), - " Open Telecom Platform
\n" - "Updated: ", current_time(), "
\n" - "
\n" - "
\n" + " Open Telecom Platform", + xhtml("
\n", "
\n"), + "Updated: ", current_time(), "", + xhtml("
\n", "
\n"), + xhtml("

\n", "\n"), + "
\n" "\n"]. body_tag() -> - case basic_html() of - true -> - "\n"; - false -> - CTPath = code:lib_dir(common_test), - TileFile = filename:join(filename:join(CTPath,"priv"),"tile1.jpg"), - "\n" - end. + CTPath = code:lib_dir(common_test), + TileFile = filename:join(filename:join(CTPath,"priv"),"tile1.jpg"), + xhtml("\n", + "\n"). current_time() -> format_time(calendar:local_time()). @@ -1258,20 +1300,25 @@ config_table(Vars) -> [config_table_header()|config_table1(Vars)]. config_table_header() -> - ["

Configuration

\n", - "Configuration\n" + "
CONFIGURATION\n
\n"), "\n"]. config_table1([{Key,Value}|Vars]) -> - ["\n", - "\n" | + [xhtml(["\n", + "\n"], + ["\n", + "\n", + "\n\n"]) | config_table1(Vars)]; config_table1([]) -> ["
KeyValue
", atom_to_list(Key), "
",io_lib:format("~p",[Value]),"
", atom_to_list(Key), "
",io_lib:format("~p",[Value]),"
", atom_to_list(Key), "", io_lib:format("~p",[Value]), "
\n"]. make_all_runs_index(When) -> + put(basic_html, basic_html()), AbsName = ?abs(?all_runs_name), notify_and_lock_file(AbsName), if When == start -> ok; @@ -1280,8 +1327,7 @@ make_all_runs_index(When) -> Dirs = filelib:wildcard(logdir_prefix()++"*.*"), DirsSorted = (catch sort_all_runs(Dirs)), Header = all_runs_header(), - BasicHtml = basic_html(), - Index = [runentry(Dir, BasicHtml) || Dir <- DirsSorted], + Index = [runentry(Dir) || Dir <- DirsSorted], Result = file:write_file(AbsName,Header++Index++index_footer()), if When == start -> ok; true -> io:put_chars("done\n") @@ -1309,22 +1355,22 @@ 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),""], + Body = ["Log from last interactive run: ", + timestamp(Dir),""], file:write_file("last_interactive.html",Body), io:format("~n~nUpdated ~s\n" "Any CT activities will be logged here\n", [?abs("last_interactive.html")]). -runentry(Dir, BasicHtml) -> +runentry(Dir) -> TotalsFile = filename:join(Dir,?totals_name), TotalsStr = case read_totals_file(TotalsFile) of {Node,Label,Logs,{TotSucc,TotFail,UserSkip,AutoSkip,NotBuilt}} -> TotFailStr = if TotFail > 0 -> - ["", - integer_to_list(TotFail),""]; + ["", + integer_to_list(TotFail),""]; true -> integer_to_list(TotFail) end, @@ -1332,8 +1378,8 @@ runentry(Dir, BasicHtml) -> if AutoSkip == undefined -> {UserSkip,"?","?"}; true -> ASStr = if AutoSkip > 0 -> - ["", - integer_to_list(AutoSkip),""]; + ["", + integer_to_list(AutoSkip),""]; true -> integer_to_list(AutoSkip) end, {UserSkip+AutoSkip,integer_to_list(UserSkip),ASStr} @@ -1365,30 +1411,49 @@ runentry(Dir, BasicHtml) -> lists:flatten(io_lib:format("~s...",[Trunc])) end, Total = TotSucc+TotFail+AllSkip, - A = ["",Node,"\n", - "",Label,"\n", - "",NoOfTests,"\n"], - B = if BasicHtml -> - ["",TestNamesTrunc,"\n"]; - true -> - [" ", - TestNamesTrunc,"\n"] - end, - C = ["",integer_to_list(Total),"\n", - "",integer_to_list(TotSucc),"\n", - "",TotFailStr,"\n", - "",integer_to_list(AllSkip), - " (",UserSkipStr,"/",AutoSkipStr,")\n", - "",integer_to_list(NotBuilt),"\n"], + A = xhtml(["",Node, + "\n", + "",Label, + "\n", + "",NoOfTests,"\n"], + ["",Node,"\n", + "",Label,"\n", + "",NoOfTests,"\n"]), + B = xhtml([" ", + TestNamesTrunc,"\n"], + [" ", + TestNamesTrunc,"\n"]), + C = ["",integer_to_list(Total),"\n", + "",integer_to_list(TotSucc),"\n", + "",TotFailStr,"\n", + "",integer_to_list(AllSkip), + " (",UserSkipStr,"/",AutoSkipStr,")\n", + "",integer_to_list(NotBuilt),"\n"], A++B++C; _ -> - ["", - "Test data missing or corrupt","\n"] + A = xhtml(["" + "Test data missing or corrupt\n", + "?\n", + "?\n"], + ["" + "Test data missing or corrupt\n", + "?\n", + "?\n"]), + B = xhtml(["?\n"], + ["?\n"]), + C = ["?\n", + "?\n", + "?\n", + "?\n", + "?\n"], + A++B++C end, Index = filename:join(Dir,?index_name), - ["\n" - "",timestamp(Dir),"",TotalsStr,"\n" - "\n"]. + [xhtml("\n", ["\n"]), + xhtml(["",timestamp(Dir),"", + TotalsStr,"\n"], + ["",timestamp(Dir),"",TotalsStr,"\n"]), + "\n"]. write_totals_file(Name,Label,Logs,Totals) -> AbsName = ?abs(Name), @@ -1482,6 +1547,7 @@ timestamp(Dir) -> %% Creates the top level index file. When == start | refresh. %% A copy of the dir tree under logdir is cached as a result. make_all_suites_index(When) when is_atom(When) -> + put(basic_html, basic_html()), AbsIndexName = ?abs(?index_name), notify_and_lock_file(AbsIndexName), LogDirs = filelib:wildcard(logdir_prefix()++".*/*"++?logdir_ext), @@ -1493,6 +1559,7 @@ make_all_suites_index(When) when is_atom(When) -> %% This updates the top level index file using cached data from %% the initial index file creation. make_all_suites_index(NewTestData = {_TestName,DirName}) -> + put(basic_html, basic_html()), %% AllLogDirs = [{TestName,Label,Missing,{LastLogDir,Summary},OldDirs}|...] {AbsIndexName,LogDirData} = ct_util:get_testdata(test_index), @@ -1849,6 +1916,32 @@ last_test([_|Rest], Latest) -> last_test([], Latest) -> Latest. +%%%----------------------------------------------------------------- +%%% @spec xhtml(HTML, XHTML) -> HTML | XHTML +%%% +%%% @doc +%%% +xhtml(HTML, XHTML) -> + case get(basic_html) of + true -> HTML; + _ -> XHTML + end. + +%%%----------------------------------------------------------------- +%%% @spec odd_or_even() -> "odd" | "even" +%%% +%%% @doc +%%% +odd_or_even() -> + case get(odd_or_even) of + even -> + put(odd_or_even, odd), + "even"; + _ -> + put(odd_or_even, even), + "odd" + end. + %%%----------------------------------------------------------------- %%% @spec basic_html() -> true | false %%% @@ -1861,3 +1954,80 @@ basic_html() -> _ -> false end. + +%%%----------------------------------------------------------------- +%%% @spec get_ts_html_wrapper(TestName, PrintLabel) -> {Mode,Header,Footer} +%%% +%%% @doc +%%% +get_ts_html_wrapper(TestName, PrintLabel) -> + TestName1 = lists:flatten(io_lib:format("~p", [TestName])), + Basic = basic_html(), + LabelStr = + if not PrintLabel -> + ""; + true -> + case {Basic,application:get_env(common_test, test_label)} of + {true,{ok,Lbl}} when Lbl =/= undefined -> + "

" ++ Lbl ++ "

\n"; + {_,{ok,Lbl}} when Lbl =/= undefined -> + "
'" ++ Lbl ++ "'
\n"; + _ -> + "" + end + end, + CTPath = code:lib_dir(common_test), + {ok,CtLogdir} = get_log_dir(true), + AllRuns = filename:join(filename:dirname(CtLogdir), ?all_runs_name), + TestIndex = filename:join(filename:dirname(CtLogdir), ?index_name), + case Basic of + true -> + TileFile = filename:join(filename:join(CTPath,"priv"),"tile1.jpg"), + Bgr = " background=\"" ++ TileFile ++ "\"", + Copyright = + ["

\n", + "Copyright © ", year(), + " ", + "Open Telecom Platform
\n", + "Updated: ", current_time(), "", + "
\n

\n"], + {basic_html, + ["\n", + "\n", + "Test ", TestName1, " results\n", + "\n", + "\n", + "\n", + LabelStr, "\n"], + ["
\n

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

\n", + Copyright,"
\n\n\n"]}; + _ -> + Copyright = + ["
", + "Copyright © ", year(), + " ", + "Open Telecom Platform
\n", + "Updated: ", current_time(), "", + "
\n
\n"], + CSSFile = filename:join(filename:join(CTPath, "priv"), "ct_default.css"), + {xhtml, + ["\n", + "\n", + "\nTest ", TestName1, " results\n", + "\n", + "", + "\n","\n", + LabelStr, "\n"], + ["
\n

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

\n", + Copyright,"
\n\n\n"]} + end. diff --git a/lib/test_server/src/erl2html2.erl b/lib/test_server/src/erl2html2.erl index c94d4627f9..0520f05df7 100644 --- a/lib/test_server/src/erl2html2.erl +++ b/lib/test_server/src/erl2html2.erl @@ -32,32 +32,34 @@ %-------------------------------------------------------------------- -module(erl2html2). --export([convert/2]). +-export([convert/2, convert/3]). convert([], _Dest) -> % Fake clause. ok; convert(File, Dest) -> + %% The generated code uses the BGCOLOR attribute in the + %% BODY tag, which wasn't valid until HTML 3.2. Also, + %% good HTML should either override all colour attributes + %% or none of them -- *never* just a few. + %% + %% FIXME: The colours should *really* be set with + %% stylesheets... + Header = ["\n" + "\n" + "\n" + "", File, "\n\n" + "\n"], + convert(File, Dest, Header). + +convert(File, Dest, Header) -> case file:read_file(File) of {ok, Bin} -> Code=binary_to_list(Bin), statistics(runtime), - %% The generated code uses the BGCOLOR attribute in the - %% BODY tag, which wasn't valid until HTML 3.2. Also, - %% good HTML should either override all colour attributes - %% or none of them -- *never* just a few. - %% - %% FIXME: The colours should *really* be set with - %% stylesheets... - Html0 - = ["\n" - "\n" - "\n" - "", File, "\n\n" - "\n"], {Html1, Lines} = root(Code, [], 1), - Html = [Html0, + Html = [Header, "
\n", Html1, "
\n", footer(Lines),"\n\n"], file:write_file(Dest, Html); @@ -174,9 +176,10 @@ linenum(Line) -> [A,Pred,integer_to_list(Line),":"]. footer(Lines) -> - {_, Time} = statistics(runtime), -% io:format("Converted ~p lines in ~.2f Seconds.~n", -% [Lines, Time/1000]), - S = "The transformation of this file (~p lines) took ~.2f seconds", - F = lists:flatten(io_lib:format(S, [Lines, Time/1000])), - ["
",F,"
\n"]. + "". +%% {_, Time} = statistics(runtime), +%% io:format("Converted ~p lines in ~.2f Seconds.~n", +%% [Lines, Time/1000]), +%% S = "The transformation of this file (~p lines) took ~.2f seconds", +%% F = lists:flatten(io_lib:format(S, [Lines, Time/1000])), +%% ["
",F,"
\n"]. diff --git a/lib/test_server/src/test_server.erl b/lib/test_server/src/test_server.erl index 49f97686a0..0026b95872 100644 --- a/lib/test_server/src/test_server.erl +++ b/lib/test_server/src/test_server.erl @@ -1525,7 +1525,7 @@ get_loc(Pid) -> get_mf(MFs) -> get_mf(MFs, {undefined,undefined}). -get_mf([MF|MFs], Found) when is_tuple(MF) -> +get_mf([MF|MFs], _Found) when is_tuple(MF) -> ModFunc = {Mod,_} = case MF of {M,F,_} -> {M,F}; MF -> MF diff --git a/lib/test_server/src/test_server_ctrl.erl b/lib/test_server/src/test_server_ctrl.erl index 4fad86d16d..49cce9c429 100644 --- a/lib/test_server/src/test_server_ctrl.erl +++ b/lib/test_server/src/test_server_ctrl.erl @@ -1692,60 +1692,83 @@ do_test_cases(TopCases, SkipCases, [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])); + true -> + lists:flatten(io_lib:format("~p", [Test])) + end, + test_server_sup:framework_call(report, [tests_start,{Test,N}]), - Header = - case test_server_sup:framework_call(overview_html_header, [Test], "") of - "" -> - TestName = lists:flatten(io_lib:format("~p", [Test])), - ["\n", - "\n", - "\n", - "Test ", TestName, " results\n", - "\n", - "\n", - "", - "

Results from test ", TestName, "

\n"]; - Html -> - ["\n", - "\n" | Html] + {Header,Footer} = + case test_server_sup:framework_call(get_html_wrapper, + [Test,true], "") of + Empty when (Empty == "") ; (element(2,Empty) == "") -> + put(basic_html, true), + {["\n", + "\n", + "\n", + "Test ", TestName, " results\n", + "\n", + "\n", + "", + "

Results for test ", TestName, "

\n"], + "\n\n\n"}; + {basic_html,Html0,Html1} -> + put(basic_html, true), + {Html0++["

Results for ",TestName,"

\n"], + Html1}; + {xhtml,Html0,Html1} -> + put(basic_html, false), + {Html0++["

Results for ",TestName,"

\n"], + Html1} end, - print(html, Header, []), - print_timestamp(html, "Test started at "), - print(html, "

Host:
\n"), + print(html, Header), + + print(html, xhtml("

", "

")), + print_timestamp(html, "Test started at "), + print(html, xhtml("

", "

")), + + print(html, xhtml("

HOST:
\n", "

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

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

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

Target:
\n"), + print(html, xhtml("

TARGET:
\n", "

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

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

\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, "

Target:
\n"), - print(html, "~s\n", [TargetInfo]); + print(html, xhtml("

TARGET:
\n", "

TARGET:
\n")), + print(html, "~s

\n", [TargetInfo]); _ -> ok end end, - + print(html, - "

Full textual log\n" - "
Coverage log\n", + "

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

~s" - "

\n" - "" - "" - "\n", - [print_if_known(N, {"Suite contains ~p test cases.\n",[N]}, + print(html, + "

~s

\n" ++ + xhtml("
NumModuleCaseLogTimeResultComment
", + "
") ++ + "" + "\n", + [print_if_known(N, {"Executing ~p test cases...\n",[N]}, {"",[]})]), + print(html, xhtml("
", "
")), + 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 +1787,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; @@ -1881,16 +1907,31 @@ 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, - "\n" - "\n" - "\n" - ""++cast_to_list(Mod)++"\n" - "\n" - "\n" - "\n", - []), + + TestName = io_lib:format("~p:~p", [Mod,Func]), + {Header,Footer} = + case test_server_sup:framework_call(get_html_wrapper, + [TestName,false], "") of + Empty when (Empty == "") ; (element(2,Empty) == "") -> + put(basic_html, true), + {["\n", + "\n", + "\n", + "Test ", TestName, "\n", + "\n", + "\n", + "\n"], + "\n\n\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 +1954,8 @@ start_minor_log_file1(Mod, Func, LogDir, AbsName) -> stop_minor_log_file() -> Fd = get(test_server_minor_fd), - io:fwrite(Fd, "\n\n\n", []), + Footer = get(test_server_minor_footer), + io:fwrite(Fd, "\n" ++ Footer, []), file:close(Fd), put(test_server_minor_fd, undefined). @@ -1992,12 +2034,27 @@ 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 + _ -> + Header = + case test_server_sup:framework_call(get_html_header, + [Src,false], "") of + Empty when (Empty == "") ; (element(2,Empty) == "") -> + ["\n", + "\n", + "\n", + "Test ", Src, "\n", + "\n", + "\n", + "\n"]; + {_,Html,_} -> + Html + end, + erl2html2:convert(Src, Dest, Header) end. %% Copy all HTML files in InDir to OutDir. @@ -3163,9 +3220,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("", [""]), print(html, - "" - "" + TR ++ "" "" "" "" @@ -3567,11 +3624,12 @@ run_test_case1(Ref, Num, Mod, Func, Args, RunInit, Where, 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, "" - "" - "" - "", - [num2str(Num),Mod,MinorBase,Func,MinorBase,MinorBase]), + TR = xhtml("", [""]), + print(html, TR ++ "" + "" + "" + "", + [num2str(Num),Mod,MinorBase,Func,MinorBase,MinorBase]), do_if_parallel(Main, ok, fun erlang:yield/0), %% run the test case @@ -3857,7 +3915,7 @@ progress(skip, CaseNum, Mod, Func, Loc, Reason, Time, end, Comment1 = case Comment of "" -> ""; - _ -> "
(" ++ to_string(Comment) ++ ")" + _ -> xhtml("
(","
(") ++ to_string(Comment) ++ ")" end, print(html, "" @@ -3882,8 +3940,8 @@ progress(failed, CaseNum, Mod, Func, Loc, timetrap_timeout, T, Comment = case Comment0 of "" -> "" ++ ErrorReason ++ ""; - _ -> "" ++ ErrorReason ++ "
" ++ - to_string(Comment0) + _ -> "" ++ ErrorReason ++ + xhtml("
","
") ++ to_string(Comment0) end, print(html, "" @@ -3908,8 +3966,8 @@ progress(failed, CaseNum, Mod, Func, Loc, {testcase_aborted,Reason}, _T, Comment = case Comment0 of "" -> "" ++ ErrorReason ++ ""; - _ -> "" ++ ErrorReason ++ "
" ++ - to_string(Comment0) + _ -> "" ++ ErrorReason ++ + xhtml("
","
") ++ to_string(Comment0) end, print(html, "" @@ -3943,7 +4001,8 @@ progress(failed, CaseNum, Mod, Func, unknown, Reason, Time, Comment = case Comment0 of "" -> "" ++ ErrorReason2 ++ ""; - _ -> "" ++ ErrorReason2 ++ "
" ++ + _ -> "" ++ ErrorReason2 ++ + xhtml("
","
") ++ to_string(Comment0) end, print(html, @@ -3953,7 +4012,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 +4028,7 @@ progress(failed, CaseNum, Mod, Func, Loc, Reason, Time, Comment = case Comment0 of "" -> ""; - _ -> "
" ++ to_string(Comment0) + _ -> xhtml("
","
") ++ to_string(Comment0) end, FormatLastLoc = test_server_sup:format_loc(get_last_loc(Loc)), print(html, @@ -3980,7 +4039,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 +4058,7 @@ progress(ok, _CaseNum, Mod, Func, _Loc, RetVal, Time, _ -> print(major, "=result ok", []), case Comment0 of - "" -> ""; + "" -> ""; _ -> "" end end, @@ -4349,7 +4408,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
NumModuleCaseLogTimeResultComment
" ++ Col0 ++ "~s" ++ Col1 ++ "" ++ Col0 ++ "~s" ++ Col1 ++ "" ++ Col0 ++ "~p" ++ Col1 ++ "" ++ Col0 ++ "~p" ++ Col1 ++ "" ++ Col0 ++ "< >" ++ Col1 ++ "
" ++ Col0 ++ "~s" ++ Col1 ++ "" ++ Col0 ++ "~p" ++ Col1 ++ "~p< >
" ++ Col0 ++ "~s" ++ Col1 ++ "" ++ Col0 ++ "~p" ++ Col1 ++ "~p< >" ++ St0 ++ "~.3fs" ++ St1 ++ "" ++ St0 ++ "~.3fs" ++ St1 ++ "" ++ St0 ++ "died" ++ St1 ++ "" ++ to_string(Comment0) ++ "
\n\n\n"), + io:put_chars(Fd, "\n\n"), + case get(test_server_html_footer) of + undefined -> + io:put_chars(Fd, "\n\n"); + Footer -> + io:put_chars(Fd, Footer) + end, file:position(Fd, Pos); {error, epipe} -> %% The file is not seekable. We cannot erase what @@ -4393,6 +4458,28 @@ output_to_fd(Fd, Msg, _Sender) -> _ -> io:put_chars(Fd, "\n") 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 +5586,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,
" - "or cross cover analysis is not completed.\n" - "\n", []), + ["No cross cover modules exist for this application,", + xhtml("
","
"), + "or cross cover analysis is not completed.\n" + "\n"], []), file:close(CrossCoverLog). write_cover_result_table(CoverLog,Coverage) -> -- cgit v1.2.3