From f6c1c3127f027cd717d01613cd356c5ada35041c Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Mon, 22 Oct 2012 16:06:32 +0200 Subject: [common_test] Add option cover_stop By default, test_server will always stop cover (and thus load back the non cover compiled original beam files) after a test with code coverage analysis is completed. The new option allows the common_test user to specify that cover shall not be stopped. This can be useful if there are processes still running old code, i.e. processes that have not done any fully qualified function call after the cover compilation, since loading the original code then will kill those processes. This is only recommended if the erlang node is to be stopped after the test run, or if cover can be manually stopped. --- lib/test_server/src/test_server.erl | 57 ++++++++++++++++++++------------ lib/test_server/src/test_server_ctrl.erl | 34 +++++++++---------- lib/test_server/src/ts_run.erl | 2 +- 3 files changed, 54 insertions(+), 39 deletions(-) (limited to 'lib/test_server') diff --git a/lib/test_server/src/test_server.erl b/lib/test_server/src/test_server.erl index 330c4cc8a9..2b15d07990 100644 --- a/lib/test_server/src/test_server.erl +++ b/lib/test_server/src/test_server.erl @@ -25,7 +25,7 @@ %%% TEST_SERVER_CTRL INTERFACE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -export([run_test_case_apply/1,init_target_info/0,init_purify/0]). --export([cover_compile/1,cover_analyse/2]). +-export([cover_compile/1,cover_analyse/3]). %%% TEST_SERVER_SUP INTERFACE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -export([get_loc/1]). @@ -414,7 +414,7 @@ do_cover_compile1([]) -> ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% cover_analyse(Analyse,Modules) -> [{M,{Cov,NotCov,Details}}] +%% cover_analyse(Analyse,Modules,Stop) -> [{M,{Cov,NotCov,Details}}] %% %% Analyse = {details,Dir} | details | {overview,void()} | overview %% Modules = [atom()], the modules to analyse @@ -430,7 +430,18 @@ do_cover_compile1([]) -> %% %% Also, if a Dir exists, cover data will be exported to a file called %% all.coverdata in that directory. -cover_analyse(Analyse,Modules) -> +%% +%% Finally, if Stop==true, then cover will be stopped after the +%% analysis is completed. Stopping cover causes the original (non +%% cover compiled) modules to be loaded back in. If a process at this +%% point is still running old code of any of the cover compiled +%% modules, meaning that is has not done any fully qualified function +%% call after the cover compilation, the process will now be +%% killed. To avoid this scenario, it is possible to set Stop=false, +%% which means that the modules will stay cover compiled. Note that +%% this is only recommended if the erlang node is being terminated +%% after the test is completed. +cover_analyse(Analyse,Modules,Stop) -> io:fwrite("Cover analysing...\n",[]), DetailsFun = case Analyse of @@ -482,12 +493,14 @@ cover_analyse(Analyse,Modules) -> end end, Modules), -%%! SIRI: This must be checked further - is it always ok not to stop -%%! cover? Will the node always terminate after this? Probably not - -%%! maybe use an option? -% Sticky = unstick_all_sticky(node()), -% cover:stop(), -% stick_all_sticky(node(),Sticky), + case Stop of + true -> + Sticky = unstick_all_sticky(node()), + cover:stop(), + stick_all_sticky(node(),Sticky); + false -> + ok + end, R. pmap(Fun,List) -> @@ -504,6 +517,17 @@ pmap(Fun,List) -> end end, Pids). + +do_cover_for_node(Node,CoverFunc) -> + %% In case a slave node is starting another slave node! I.e. this + %% function is executed on a slave node - then the cover function + %% must be executed on the master node. This is for instance the + %% case in test_server's own tests. + MainCoverNode = cover:get_main_node(), + Sticky = unstick_all_sticky(MainCoverNode,Node), + rpc:call(MainCoverNode,cover,CoverFunc,[Node]), + stick_all_sticky(Node,Sticky). + unstick_all_sticky(Node) -> unstick_all_sticky(node(),Node). unstick_all_sticky(MainCoverNode,Node) -> @@ -2581,10 +2605,7 @@ start_node(Name, Type, Options) -> net_adm:ping(Node), case Cover of true -> - MainCoverNode = cover:get_main_node(), - Sticky = unstick_all_sticky(MainCoverNode,Node), - rpc:call(MainCoverNode,cover,start,[Node]), - stick_all_sticky(Node,Sticky); + do_cover_for_node(Node,start); _ -> ok end, @@ -2625,10 +2646,7 @@ wait_for_node(Slave) -> net_adm:ping(Slave), case Cover of true -> - MainCoverNode = cover:get_main_node(), - Sticky = unstick_all_sticky(MainCoverNode,Slave), - rpc:call(MainCoverNode,cover,start,[Slave]), - stick_all_sticky(Slave,Sticky); + do_cover_for_node(Slave,start); _ -> ok end; @@ -2647,10 +2665,7 @@ stop_node(Slave) -> Nocover = is_shielded(Slave) orelse not same_version(Slave), case is_cover() of true when not Nocover -> - MainCoverNode = cover:get_main_node(), - Sticky = unstick_all_sticky(MainCoverNode,Slave), - rpc:call(MainCoverNode,cover,flush,[Slave]), - stick_all_sticky(Slave,Sticky); + do_cover_for_node(Slave,flush); _ -> ok end, diff --git a/lib/test_server/src/test_server_ctrl.erl b/lib/test_server/src/test_server_ctrl.erl index 08761988bc..50208410a9 100644 --- a/lib/test_server/src/test_server_ctrl.erl +++ b/lib/test_server/src/test_server_ctrl.erl @@ -165,7 +165,7 @@ -export([reject_io_reqs/1, get_levels/0, set_levels/3]). -export([multiply_timetraps/1, scale_timetraps/1, get_timetrap_parameters/0]). -export([create_priv_dir/1]). --export([cover/2, cover/3, cover/7, +-export([cover/2, cover/3, cover/8, cross_cover_analyse/2, cross_cover_analyse/3, trc/1, stop_trace/0]). -export([testcase_callback/1]). -export([set_random_seed/1]). @@ -521,9 +521,9 @@ cover(App, Analyse) when is_atom(App) -> cover(CoverFile, Analyse) -> cover(none, CoverFile, Analyse). cover(App, CoverFile, Analyse) -> - controller_call({cover,{App,CoverFile},Analyse}). -cover(App, CoverFile, Exclude, Include, Cross, Export, Analyse) -> - controller_call({cover,{App,{CoverFile,Exclude,Include,Cross,Export}},Analyse}). + controller_call({cover,{App,CoverFile},Analyse,true}). +cover(App, CoverFile, Exclude, Include, Cross, Export, Analyse, Stop) -> + controller_call({cover,{App,{CoverFile,Exclude,Include,Cross,Export}},Analyse,Stop}). testcase_callback(ModFunc) -> controller_call({testcase_callback,ModFunc}). @@ -796,7 +796,7 @@ handle_call({add_job,Dir,Name,TopCase,Skip}, _From, State) -> ExtraTools = case State#state.cover of false -> []; - {App,Analyse} -> [{cover,App,Analyse}] + {App,Analyse,Stop} -> [{cover,App,Analyse,Stop}] end, ExtraTools1 = case State#state.random_seed of @@ -1052,13 +1052,13 @@ handle_call(stop_trace, _From, State) -> {reply,R,State#state{trc=false}}; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% handle_call({cover,App,Analyse}, _, State) -> ok | {error,Reason} +%% handle_call({cover,App,Analyse,Stop}, _, State) -> ok | {error,Reason} %% %% All modules inn application App are cover compiled %% Analyse indicates on which level the coverage should be analysed -handle_call({cover,App,Analyse}, _From, State) -> - {reply,ok,State#state{cover={App,Analyse}}}; +handle_call({cover,App,Analyse,Stop}, _From, State) -> + {reply,ok,State#state{cover={App,Analyse,Stop}}}; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% handle_call({create_priv_dir,Value}, _, State) -> ok | {error,Reason} @@ -1465,11 +1465,11 @@ elapsed_time(Before, After) -> start_extra_tools(ExtraTools) -> start_extra_tools(ExtraTools, []). -start_extra_tools([{cover,App,Analyse} | ExtraTools], Started) -> +start_extra_tools([{cover,App,Analyse,Stop} | ExtraTools], Started) -> case cover_compile(App) of {ok,AnalyseMods} -> start_extra_tools(ExtraTools, - [{cover,App,Analyse,AnalyseMods}|Started]); + [{cover,App,Analyse,AnalyseMods,Stop}|Started]); {error,_} -> start_extra_tools(ExtraTools, Started) end; @@ -1488,8 +1488,8 @@ stop_extra_tools(ExtraTools) -> end, stop_extra_tools(ExtraTools, TestDir). -stop_extra_tools([{cover,App,Analyse,AnalyseMods}|ExtraTools], TestDir) -> - cover_analyse(App, Analyse, AnalyseMods, TestDir), +stop_extra_tools([{cover,App,Analyse,AnalyseMods,Stop}|ExtraTools], TestDir) -> + cover_analyse(App, Analyse, AnalyseMods, Stop, TestDir), stop_extra_tools(ExtraTools, TestDir); %%stop_extra_tools([_ | ExtraTools], TestDir) -> %% stop_extra_tools(ExtraTools, TestDir); @@ -5448,7 +5448,7 @@ check_cover_file([], Exclude, Include) -> %% %% This per application analysis writes the file cover.html in the %% application's run. directory. -cover_analyse({App,CoverInfo}, Analyse, AnalyseMods, TestDir) -> +cover_analyse({App,CoverInfo}, Analyse, AnalyseMods, Stop, TestDir) -> write_default_cross_coverlog(TestDir), {ok,CoverLog} = file:open(filename:join(TestDir, ?coverlog_name), [write]), @@ -5479,7 +5479,7 @@ cover_analyse({App,CoverInfo}, Analyse, AnalyseMods, TestDir) -> io:fwrite(CoverLog, "

Excluded module(s): ~p\n", [Excluded]), - Coverage = cover_analyse(Analyse, AnalyseMods), + Coverage = cover_analyse(Analyse, AnalyseMods, Stop), case lists:filter(fun({_M,{_,_,_}}) -> false; (_) -> true @@ -5496,17 +5496,17 @@ cover_analyse({App,CoverInfo}, Analyse, AnalyseMods, TestDir) -> file:write_file(filename:join(TestDir, ?cover_total), term_to_binary(TotPercent)). -cover_analyse(Analyse, AnalyseMods) -> +cover_analyse(Analyse, AnalyseMods, Stop) -> TestDir = get(test_server_log_dir_base), case get(test_server_ctrl_job_sock) of undefined -> %% local target - test_server:cover_analyse({Analyse,TestDir}, AnalyseMods); + test_server:cover_analyse({Analyse,TestDir}, AnalyseMods, Stop); JobSock -> %% remote target request(JobSock, {sync_apply,{test_server, cover_analyse, - [Analyse,AnalyseMods]}}), + [Analyse,AnalyseMods, Stop]}}), read_job_sock_loop(JobSock) end. diff --git a/lib/test_server/src/ts_run.erl b/lib/test_server/src/ts_run.erl index 57d1b8806e..741dd483f5 100644 --- a/lib/test_server/src/ts_run.erl +++ b/lib/test_server/src/ts_run.erl @@ -368,7 +368,7 @@ make_common_test_args(Args0, Options0, _Vars) -> io:format("No cover file found for ~p~n",[App]), []; {value,{cover,_App,File,_Analyse}} -> - [{cover,to_list(File)}]; + [{cover,to_list(File)},{cover_stop,false}]; false -> [] end, -- cgit v1.2.3