aboutsummaryrefslogtreecommitdiffstats
path: root/lib/common_test/src/ct_util.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/common_test/src/ct_util.erl')
-rw-r--r--lib/common_test/src/ct_util.erl135
1 files changed, 103 insertions, 32 deletions
diff --git a/lib/common_test/src/ct_util.erl b/lib/common_test/src/ct_util.erl
index 445fce1db8..468edc4bee 100644
--- a/lib/common_test/src/ct_util.erl
+++ b/lib/common_test/src/ct_util.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -65,6 +65,9 @@
-export([warn_duplicates/1]).
+-export([mark_process/0, mark_process/1, is_marked/1, is_marked/2,
+ remaining_test_procs/0]).
+
-export([get_profile_data/0, get_profile_data/1,
get_profile_data/2, open_url/3]).
@@ -126,19 +129,20 @@ start(Mode, LogDir, Verbosity) ->
do_start(Parent, Mode, LogDir, Verbosity) ->
process_flag(trap_exit,true),
register(ct_util_server,self()),
+ mark_process(),
create_table(?conn_table,#conn.handle),
create_table(?board_table,2),
create_table(?suite_table,#suite_data.key),
create_table(?verbosity_table,1),
- [ets:insert(?verbosity_table,{Cat,Lvl}) || {Cat,Lvl} <- Verbosity],
+ _ = [ets:insert(?verbosity_table,{Cat,Lvl}) || {Cat,Lvl} <- Verbosity],
{ok,StartDir} = file:get_cwd(),
case file:set_cwd(LogDir) of
ok -> ok;
E -> exit(E)
end,
- DoExit = fun(Reason) -> file:set_cwd(StartDir), exit(Reason) end,
+ DoExit = fun(Reason) -> ok = file:set_cwd(StartDir), exit(Reason) end,
Opts = case read_opts() of
{ok,Opts1} ->
Opts1;
@@ -169,7 +173,7 @@ do_start(Parent, Mode, LogDir, Verbosity) ->
end,
%% add user event handlers
- case lists:keysearch(event_handler,1,Opts) of
+ _ = case lists:keysearch(event_handler,1,Opts) of
{value,{_,Handlers}} ->
Add = fun({H,Args}) ->
case catch gen_event:add_handler(?CT_EVMGR_REF,H,Args) of
@@ -188,6 +192,8 @@ do_start(Parent, Mode, LogDir, Verbosity) ->
ok
end,
+ ct_default_gl:start_link(group_leader()),
+
{StartTime,TestLogDir} = ct_logs:init(Mode, Verbosity),
ct_event:notify(#event{name=test_start,
@@ -195,24 +201,17 @@ do_start(Parent, Mode, LogDir, Verbosity) ->
data={StartTime,
lists:flatten(TestLogDir)}}),
%% Initialize ct_hooks
- try ct_hooks:init(Opts) of
+ _ = try ct_hooks:init(Opts) of
ok ->
Parent ! {self(),started};
{fail,CTHReason} ->
- ErrorInfo = if is_atom(CTHReason) ->
- io_lib:format("{~p,~p}",
- [CTHReason,
- erlang:get_stacktrace()]);
- true ->
- CTHReason
- end,
- ct_logs:tc_print('Suite Callback',ErrorInfo,[]),
+ ct_logs:tc_print('Suite Callback',CTHReason,[]),
self() ! {{stop,{self(),{user_error,CTHReason}}},
{Parent,make_ref()}}
catch
_:CTHReason ->
ErrorInfo = if is_atom(CTHReason) ->
- io_lib:format("{~p,~p}",
+ io_lib:format("{~tp,~tp}",
[CTHReason,
erlang:get_stacktrace()]);
true ->
@@ -228,7 +227,8 @@ create_table(TableName,KeyPos) ->
create_table(TableName,set,KeyPos).
create_table(TableName,Type,KeyPos) ->
catch ets:delete(TableName),
- ets:new(TableName,[Type,named_table,public,{keypos,KeyPos}]).
+ _ = ets:new(TableName,[Type,named_table,public,{keypos,KeyPos}]),
+ ok.
read_opts() ->
case file:consult(ct_run:variables_file_name("./")) of
@@ -459,6 +459,7 @@ loop(Mode,TestData,StartDir) ->
error:badarg -> []
end,
ct_hooks:terminate(Callbacks),
+
close_connections(ets:tab2list(?conn_table)),
ets:delete(?conn_table),
ets:delete(?board_table),
@@ -472,7 +473,8 @@ loop(Mode,TestData,StartDir) ->
ct_logs:close(Info, StartDir),
ct_event:stop(),
ct_config:stop(),
- file:set_cwd(StartDir),
+ ct_default_gl:stop(),
+ ok = file:set_cwd(StartDir),
return(From, Info);
{Ref, _Msg} when is_reference(Ref) ->
%% This clause is used when doing cast operations.
@@ -485,15 +487,17 @@ 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,
"CT Error Notification",
"Connection process died: "
- "Pid: ~w, Address: ~p, "
+ "Pid: ~w, Address: ~tp, "
"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),
@@ -501,8 +505,8 @@ loop(Mode,TestData,StartDir) ->
_ ->
%% Let process crash in case of error, this shouldn't happen!
io:format("\n\nct_util_server got EXIT "
- "from ~w: ~p\n\n", [Pid,Reason]),
- file:set_cwd(StartDir),
+ "from ~w: ~tp\n\n", [Pid,Reason]),
+ ok = file:set_cwd(StartDir),
exit(Reason)
end
end.
@@ -922,7 +926,8 @@ warn_duplicates(Suites) ->
[] ->
ok;
_ ->
- io:format(user,"~nWARNING! Deprecated function: ~w:sequences/0.~n"
+ io:format(?def_gl,
+ "~nWARNING! Deprecated function: ~w:sequences/0.~n"
" Use group with sequence property instead.~n",[Mod])
end
end,
@@ -933,6 +938,70 @@ warn_duplicates(Suites) ->
%%% @spec
%%%
%%% @doc
+mark_process() ->
+ mark_process(system).
+
+mark_process(Type) ->
+ put(ct_process_type, Type).
+
+is_marked(Pid) ->
+ is_marked(Pid, system).
+
+is_marked(Pid, Type) ->
+ case process_info(Pid, dictionary) of
+ {dictionary,List} ->
+ Type == proplists:get_value(ct_process_type, List);
+ undefined ->
+ false
+ end.
+
+remaining_test_procs() ->
+ Procs = processes(),
+ {SharedGL,OtherGLs,Procs2} =
+ lists:foldl(
+ fun(Pid, ProcTypes = {Shared,Other,Procs1}) ->
+ case is_marked(Pid, group_leader) of
+ true ->
+ if not is_pid(Shared) ->
+ case test_server_io:get_gl(true) of
+ Pid ->
+ {Pid,Other,
+ lists:delete(Pid,Procs1)};
+ _ ->
+ {Shared,[Pid|Other],Procs1}
+ end;
+ true -> % SharedGL already found
+ {Shared,[Pid|Other],Procs1}
+ end;
+ false ->
+ case is_marked(Pid) of
+ true ->
+ {Shared,Other,lists:delete(Pid,Procs1)};
+ false ->
+ ProcTypes
+ end
+ end
+ end, {undefined,[],Procs}, Procs),
+
+ AllGLs = [SharedGL | OtherGLs],
+ TestProcs =
+ lists:flatmap(fun(Pid) ->
+ case process_info(Pid, group_leader) of
+ {group_leader,GL} ->
+ case lists:member(GL, AllGLs) of
+ true -> [{Pid,GL}];
+ false -> []
+ end;
+ undefined ->
+ []
+ end
+ end, Procs2),
+ {TestProcs, SharedGL, OtherGLs}.
+
+%%%-----------------------------------------------------------------
+%%% @spec
+%%%
+%%% @doc
get_profile_data() ->
get_profile_data(all).
@@ -976,12 +1045,12 @@ get_profile_data(Profile, Key, StartDir) ->
end,
case Result of
{error,enoent} when Profile /= default ->
- io:format(user, "~nERROR! Missing profile file ~p~n", [File]),
+ io:format(?def_gl, "~nERROR! Missing profile file ~tp~n", [File]),
undefined;
{error,enoent} when Profile == default ->
undefined;
{error,Reason} ->
- io:format(user,"~nERROR! Error in profile file ~p: ~p~n",
+ io:format(?def_gl,"~nERROR! Error in profile file ~tp: ~tp~n",
[WhichFile,Reason]),
undefined;
{ok,Data} ->
@@ -991,8 +1060,8 @@ get_profile_data(Profile, Key, StartDir) ->
_ when is_list(Data) ->
Data;
_ ->
- io:format(user,
- "~nERROR! Invalid profile data in ~p~n",
+ io:format(?def_gl,
+ "~nERROR! Invalid profile data in ~tp~n",
[WhichFile]),
[]
end,
@@ -1032,10 +1101,12 @@ call(Msg, Timeout) ->
end.
return({To,Ref},Result) ->
- To ! {Ref, Result}.
+ To ! {Ref, Result},
+ ok.
cast(Msg) ->
- ct_util_server ! {Msg, {ct_util_server, make_ref()}}.
+ ct_util_server ! {Msg, {ct_util_server, make_ref()}},
+ ok.
seconds(T) ->
test_server:seconds(T).
@@ -1071,15 +1142,15 @@ abs_name2([],Acc) ->
open_url(iexplore, Args, URL) ->
{ok,R} = win32reg:open([read]),
ok = win32reg:change_key(R,"applications\\iexplore.exe\\shell\\open\\command"),
- case win32reg:values(R) of
+ _ = case win32reg:values(R) of
{ok, Paths} ->
Path = proplists:get_value(default, Paths),
[Cmd | _] = string:tokens(Path, "%"),
Cmd1 = Cmd ++ " " ++ Args ++ " " ++ URL,
- io:format(user, "~nOpening ~ts with command:~n ~ts~n", [URL,Cmd1]),
+ io:format(?def_gl, "~nOpening ~ts with command:~n ~ts~n", [URL,Cmd1]),
open_port({spawn,Cmd1}, []);
_ ->
- io:format("~nNo path to iexplore.exe~n",[])
+ io:format(?def_gl, "~nNo path to iexplore.exe~n",[])
end,
win32reg:close(R),
ok;
@@ -1089,6 +1160,6 @@ open_url(Prog, Args, URL) ->
is_list(Prog) -> Prog
end,
Cmd = ProgStr ++ " " ++ Args ++ " " ++ URL,
- io:format(user, "~nOpening ~ts with command:~n ~ts~n", [URL,Cmd]),
+ io:format(?def_gl, "~nOpening ~ts with command:~n ~ts~n", [URL,Cmd]),
open_port({spawn,Cmd},[]),
ok.