aboutsummaryrefslogtreecommitdiffstats
path: root/lib/common_test/src/ct_master_logs.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/common_test/src/ct_master_logs.erl')
-rw-r--r--lib/common_test/src/ct_master_logs.erl256
1 files changed, 169 insertions, 87 deletions
diff --git a/lib/common_test/src/ct_master_logs.erl b/lib/common_test/src/ct_master_logs.erl
index 244faace06..d76288feef 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-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2012. 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
@@ -23,7 +23,10 @@
%%% node.</p>
-module(ct_master_logs).
--export([start/2, make_all_runs_index/0, log/3, nodedir/2, stop/0]).
+-export([start/2, make_all_runs_index/0, log/3, nodedir/2,
+ stop/0]).
+
+-include("ct_util.hrl").
-record(state, {log_fd, start_time, logdir, rundir,
nodedir_ix_fd, nodes, nodedirs=[]}).
@@ -87,6 +90,41 @@ init(Parent,LogDir,Nodes) ->
RunDirAbs = filename:join(LogDir,RunDir),
file:make_dir(RunDirAbs),
write_details_file(RunDirAbs,{node(),Nodes}),
+
+ case basic_html() of
+ true ->
+ put(basic_html, true);
+ BasicHtml ->
+ put(basic_html, BasicHtml),
+ %% copy priv files to log dir (both top dir and test run
+ %% dir) so logs are independent of Common Test installation
+ CTPath = code:lib_dir(common_test),
+ PrivFiles = [?css_default,?jquery_script,?tablesorter_script],
+ PrivFilesSrc = [filename:join(filename:join(CTPath, "priv"), F) ||
+ F <- PrivFiles],
+ PrivFilesDestTop = [filename:join(LogDir, F) || F <- PrivFiles],
+ PrivFilesDestRun = [filename:join(RunDirAbs, F) || F <- PrivFiles],
+ case copy_priv_files(PrivFilesSrc, PrivFilesDestTop) of
+ {error,Src1,Dest1,Reason1} ->
+ io:format(user, "ERROR! "++
+ "Priv file ~p could not be copied to ~p. "++
+ "Reason: ~p~n",
+ [Src1,Dest1,Reason1]),
+ exit({priv_file_error,Dest1});
+ ok ->
+ case copy_priv_files(PrivFilesSrc, PrivFilesDestRun) of
+ {error,Src2,Dest2,Reason2} ->
+ io:format(user, "ERROR! "++
+ "Priv file ~p could not be copied to ~p. "++
+ "Reason: ~p~n",
+ [Src2,Dest2,Reason2]),
+ exit({priv_file_error,Dest2});
+ ok ->
+ ok
+ end
+ end
+ end,
+
make_all_runs_index(LogDir),
CtLogFd = open_ct_master_log(RunDirAbs),
NodeStr =
@@ -96,7 +134,7 @@ init(Parent,LogDir,Nodes) ->
io:format(CtLogFd,int_header(),[log_timestamp(now()),"Test Nodes\n"]),
io:format(CtLogFd,"~s\n",[NodeStr]),
- io:format(CtLogFd,int_footer()++"\n",[]),
+ io:put_chars(CtLogFd,[int_footer(),"\n"]),
NodeDirIxFd = open_nodedir_index(RunDirAbs,Time),
Parent ! {started,self(),{Time,RunDirAbs}},
@@ -110,6 +148,16 @@ init(Parent,LogDir,Nodes) ->
{N,""}
end,Nodes)}).
+copy_priv_files([SrcF | SrcFs], [DestF | DestFs]) ->
+ case file:copy(SrcF, DestF) of
+ {error,Reason} ->
+ {error,SrcF,DestF,Reason};
+ _ ->
+ copy_priv_files(SrcFs, DestFs)
+ end;
+copy_priv_files([], []) ->
+ ok.
+
loop(State) ->
receive
{log,_From,List} ->
@@ -154,23 +202,21 @@ loop(State) ->
open_ct_master_log(Dir) ->
FullName = filename:join(Dir,?ct_master_log_name),
{ok,Fd} = file:open(FullName,[write]),
- io:format(Fd,header("Common Test Master Log"),[]),
+ io:put_chars(Fd,header("Common Test Master Log", {[],[1,2],[]})),
%% maybe add config info here later
- io:format(Fd, config_table([]), []),
- io:format(Fd,
- "<style>\n"
- "div.ct_internal { background:lightgrey; color:black }\n"
- "div.default { background:lightgreen; color:black }\n"
- "</style>\n",
- []),
- io:format(Fd,
- "<br><h2>Progress Log</h2>\n"
- "<pre>\n",[]),
+ io:put_chars(config_table([])),
+ io:put_chars(Fd,
+ "<style>\n"
+ "div.ct_internal { background:lightgrey; color:black }\n"
+ "div.default { background:lightgreen; color:black }\n"
+ "</style>\n"),
+ io:put_chars(Fd,
+ xhtml("<br><h2>Progress Log</h2>\n<pre>\n",
+ "<br /><h2>Progress Log</h2>\n<pre>\n")),
Fd.
close_ct_master_log(Fd) ->
- io:format(Fd,"</pre>",[]),
- io:format(Fd,footer(),[]),
+ io:put_chars(Fd,["</pre>",footer()]),
file:close(Fd).
config_table(Vars) ->
@@ -178,20 +224,15 @@ config_table(Vars) ->
config_table_header() ->
["<h2>Configuration</h2>\n",
- "<table border=\"3\" cellpadding=\"5\" bgcolor=\"",?table_color,
- "\"\n",
- "<tr><th>Key</th><th>Value</th></tr>\n"].
-
-%%
-%% keep for possible later use
-%%
-%%config_table1([{Key,Value}|Vars]) ->
-%% ["<tr><td>", atom_to_list(Key), "</td>\n",
-%% "<td><pre>",io_lib:format("~p",[Value]),"</pre></td></tr>\n" |
-%% config_table1(Vars)];
+ xhtml(["<table border=\"3\" cellpadding=\"5\" "
+ "bgcolor=\"",?table_color,"\"\n"],
+ ["<table id=\"",?sortable_table_name,"\">\n",
+ "<thead>\n"]),
+ "<tr><th>Key</th><th>Value</th></tr>\n",
+ xhtml("", "</thead>\n<tbody>\n")].
config_table1([]) ->
- ["</table>\n"].
+ ["</tbody>\n</table>\n"].
int_header() ->
"<div class=\"ct_internal\"><b>*** CT MASTER ~s *** ~s</b>".
@@ -204,31 +245,33 @@ int_footer() ->
open_nodedir_index(Dir,StartTime) ->
FullName = filename:join(Dir,?nodedir_index_name),
{ok,Fd} = file:open(FullName,[write]),
- io:format(Fd,nodedir_index_header(StartTime),[]),
+ io:put_chars(Fd,nodedir_index_header(StartTime)),
Fd.
print_nodedir(Node,RunDir,Fd) ->
Index = filename:join(RunDir,"index.html"),
- io:format(Fd,
- ["<TR>\n"
- "<TD ALIGN=center>",atom_to_list(Node),"</TD>\n",
- "<TD ALIGN=left><A HREF=\"",Index,"\">",Index,"</A></TD>\n",
- "</TR>\n"],[]),
+ io:put_chars(Fd,
+ ["<tr>\n"
+ "<td align=center>",atom_to_list(Node),"</td>\n",
+ "<td align=left><a href=\"",Index,"\">",Index,"</a></td>\n",
+ "</tr>\n"]),
ok.
close_nodedir_index(Fd) ->
- io:format(Fd,index_footer(),[]),
+ io:put_chars(Fd,index_footer()),
file:close(Fd).
nodedir_index_header(StartTime) ->
- [header("Log Files " ++ format_time(StartTime)) |
- ["<CENTER>\n",
- "<P><A HREF=\"",?ct_master_log_name,"\">Common Test Master Log</A></P>",
- "<TABLE border=\"3\" cellpadding=\"5\" ",
- "BGCOLOR=\"",?table_color,"\">\n",
- "<th><B>Node</B></th>\n",
- "<th><B>Log</B></th>\n",
- "\n"]].
+ [header("Log Files " ++ format_time(StartTime), {[],[1,2],[]}) |
+ ["<center>\n",
+ "<p><a href=\"",?ct_master_log_name,"\">Common Test Master Log</a></p>",
+ xhtml(["<table border=\"3\" cellpadding=\"5\" "
+ "bgcolor=\"",?table_color,"\">\n"],
+ ["<table id=\"",?sortable_table_name,"\">\n",
+ "<thead>\n<tr>\n"]),
+ "<th><b>Node</b></th>\n",
+ "<th><b>Log</b></th>\n",
+ xhtml("", "</tr>\n</thead>\n<tbody>\n")]].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% All Run Index functions %%%
@@ -279,21 +322,23 @@ runentry(Dir) ->
{"unknown",""}
end,
Index = filename:join(Dir,?nodedir_index_name),
- ["<TR>\n"
- "<TD ALIGN=center><A HREF=\"",Index,"\">",timestamp(Dir),"</A></TD>\n",
- "<TD ALIGN=center>",MasterStr,"</TD>\n",
- "<TD ALIGN=center>",NodesStr,"</TD>\n",
- "</TR>\n"].
+ ["<tr>\n"
+ "<td align=center><a href=\"",Index,"\">",timestamp(Dir),"</a></td>\n",
+ "<td align=center>",MasterStr,"</td>\n",
+ "<td align=center>",NodesStr,"</td>\n",
+ "</tr>\n"].
all_runs_header() ->
- [header("Master Test Runs") |
- ["<CENTER>\n",
- "<TABLE border=\"3\" cellpadding=\"5\" "
- "BGCOLOR=\"",?table_color,"\">\n"
- "<th><B>History</B></th>\n"
- "<th><B>Master Host</B></th>\n"
- "<th><B>Test Nodes</B></th>\n"
- "\n"]].
+ [header("Master Test Runs", {[1],[2,3],[]}) |
+ ["<center>\n",
+ xhtml(["<table border=\"3\" cellpadding=\"5\" "
+ "bgcolor=\"",?table_color,"\">\n"],
+ ["<table id=\"",?sortable_table_name,"\">\n",
+ "<thead>\n<tr>\n"]),
+ "<th><b>History</b></th>\n"
+ "<th><b>Master Host</b></th>\n"
+ "<th><b>Test Nodes</b></th>\n",
+ xhtml("", "</tr></thead>\n<tbody>\n")]].
timestamp(Dir) ->
[S,Min,H,D,M,Y|_] = lists:reverse(string:tokens(Dir,".-_")),
@@ -317,52 +362,71 @@ read_details_file(Dir) ->
%%% Internal functions
%%%--------------------------------------------------------------------
-header(Title) ->
- ["<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n"
- "<!-- autogenerated by '"++atom_to_list(?MODULE)++"'. -->\n"
- "<HTML>\n",
- "<HEAD>\n",
-
- "<TITLE>" ++ Title ++ "</TITLE>\n",
- "<META HTTP-EQUIV=\"CACHE-CONTROL\" CONTENT=\"NO-CACHE\">\n",
-
- "</HEAD>\n",
-
+header(Title, TableCols) ->
+ CSSFile = xhtml(fun() -> "" end,
+ fun() -> make_relative(locate_priv_file(?css_default)) end),
+ JQueryFile =
+ xhtml(fun() -> "" end,
+ fun() -> make_relative(locate_priv_file(?jquery_script)) end),
+ TableSorterFile =
+ xhtml(fun() -> "" end,
+ fun() -> make_relative(locate_priv_file(?tablesorter_script)) end),
+
+ [xhtml(["<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n",
+ "<html>\n"],
+ ["<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n",
+ "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n",
+ "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"]),
+ "<!-- autogenerated by '"++atom_to_list(?MODULE)++"' -->\n",
+ "<head>\n",
+ "<title>" ++ Title ++ "</title>\n",
+ "<meta http-equiv=\"cache-control\" content=\"no-cache\">\n",
+ xhtml("",
+ ["<link rel=\"stylesheet\" href=\"",CSSFile,"\" type=\"text/css\">"]),
+ xhtml("",
+ ["<script type=\"text/javascript\" src=\"",JQueryFile,
+ "\"></script>\n"]),
+ xhtml("",
+ ["<script type=\"text/javascript\" src=\"",TableSorterFile,
+ "\"></script>\n"]),
+ xhtml(fun() -> "" end,
+ fun() -> ct_logs:insert_javascript({tablesorter,
+ ?sortable_table_name,
+ TableCols}) end),
+ "</head>\n",
body_tag(),
-
- "<!-- ---- DOCUMENT TITLE ---- -->\n",
-
- "<CENTER>\n",
- "<H1>" ++ Title ++ "</H1>\n",
- "</CENTER>\n",
-
- "<!-- ---- CONTENT ---- -->\n"].
+ "<center>\n",
+ "<h1>" ++ Title ++ "</h1>\n",
+ "</center>\n"].
index_footer() ->
- ["</TABLE>\n"
- "</CENTER>\n" | footer()].
+ ["</tbody>\n</table>\n"
+ "</center>\n" | footer()].
footer() ->
- ["<P><CENTER>\n"
- "<HR>\n"
- "<P><FONT SIZE=-1>\n"
+ ["<center>\n",
+ xhtml("<br><hr>\n", "<br />\n"),
+ xhtml("<p><font size=\"-1\">\n", "<div class=\"copyright\">"),
"Copyright &copy; ", year(),
- " <A HREF=\"http://erlang.ericsson.se\">Open Telecom Platform</A><BR>\n"
- "Updated: <!date>", current_time(), "<!/date><BR>\n"
- "</FONT>\n"
- "</CENTER>\n"
+ " <a href=\"http://www.erlang.org\">Open Telecom Platform</a>",
+ xhtml("<br>\n", "<br />\n"),
+ "Updated: <!date>", current_time(), "<!/date>",
+ xhtml("<br>\n", "<br />\n"),
+ xhtml("</font></p>\n", "</div>\n"),
+ "</center>\n"
"</body>\n"].
body_tag() ->
- "<body bgcolor=\"#FFFFFF\" text=\"#000000\" link=\"#0000FF\""
- "vlink=\"#800080\" alink=\"#FF0000\">\n".
+ xhtml("<body bgcolor=\"#FFFFFF\" text=\"#000000\" link=\"#0000FF\" "
+ "vlink=\"#800080\" alink=\"#FF0000\">\n",
+ "<body>\n").
current_time() ->
format_time(calendar:local_time()).
format_time({{Y, Mon, D}, {H, Min, S}}) ->
Weekday = weekday(calendar:day_of_the_week(Y, Mon, D)),
- lists:flatten(io_lib:format("~s ~s ~p ~w ~2.2.0w:~2.2.0w:~2.2.0w",
+ lists:flatten(io_lib:format("~s ~s ~2.2.0w ~w ~2.2.0w:~2.2.0w:~2.2.0w",
[Weekday, month(Mon), D, Y, H, Min, S])).
weekday(1) -> "Mon";
@@ -404,6 +468,23 @@ log_timestamp(Now) ->
lists:flatten(io_lib:format("~2.2.0w:~2.2.0w:~2.2.0w",
[H,M,S])).
+basic_html() ->
+ case application:get_env(common_test_master, basic_html) of
+ {ok,true} ->
+ true;
+ _ ->
+ false
+ end.
+
+xhtml(HTML, XHTML) ->
+ ct_logs:xhtml(HTML, XHTML).
+
+locate_priv_file(File) ->
+ ct_logs:locate_priv_file(File).
+
+make_relative(Dir) ->
+ ct_logs:make_relative(Dir).
+
force_write_file(Name,Contents) ->
force_delete(Name),
file:write_file(Name,Contents).
@@ -452,3 +533,4 @@ cast(Msg) ->
_Pid ->
?MODULE ! Msg
end.
+