aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Andersson <[email protected]>2011-07-08 20:46:17 +0200
committerPeter Andersson <[email protected]>2011-09-23 12:24:53 +0200
commit0075b97214d6c037eca3888bca29d68c9b5fbb74 (patch)
tree06734de9077352d0422a0525b1cbfbb1b0bd2041
parent312005eb3d09f5bf00ce129c1dd900de1475fc0a (diff)
downloadotp-0075b97214d6c037eca3888bca29d68c9b5fbb74.tar.gz
otp-0075b97214d6c037eca3888bca29d68c9b5fbb74.tar.bz2
otp-0075b97214d6c037eca3888bca29d68c9b5fbb74.zip
Modify start options and introduce CT profiles
OTP-9155: Improve handling of start options in Common Test OTP-9428: Introduce first version of CT profiles (for evaluation)
-rw-r--r--lib/common_test/src/ct_logs.erl21
-rw-r--r--lib/common_test/src/ct_make.erl2
-rw-r--r--lib/common_test/src/ct_run.erl296
-rw-r--r--lib/common_test/src/ct_util.erl111
-rw-r--r--lib/common_test/src/ct_util.hrl3
5 files changed, 329 insertions, 104 deletions
diff --git a/lib/common_test/src/ct_logs.erl b/lib/common_test/src/ct_logs.erl
index b839521e24..5c4eb88c1f 100644
--- a/lib/common_test/src/ct_logs.erl
+++ b/lib/common_test/src/ct_logs.erl
@@ -28,7 +28,7 @@
-module(ct_logs).
--export([init/1,close/1,init_tc/0,end_tc/1]).
+-export([init/1,close/2,init_tc/0,end_tc/1]).
-export([get_log_dir/0,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]).
@@ -97,11 +97,11 @@ logdir_node_prefix() ->
logdir_prefix()++"."++atom_to_list(node()).
%%%-----------------------------------------------------------------
-%%% @spec close(Info) -> ok
+%%% @spec close(Info, StartDir) -> ok
%%%
%%% @doc Create index pages with test results and close the CT Log
%%% (tool-internal use only).
-close(Info) ->
+close(Info, StartDir) ->
make_last_run_index(),
ct_event:notify(#event{name=stop_logging,node=node(),data=[]}),
@@ -132,6 +132,21 @@ close(Info) ->
make_all_suites_index(stop),
make_all_runs_index(stop),
+ case ct_util:get_profile_data(browser, StartDir) of
+ undefined ->
+ ok;
+ BrowserData ->
+ case {proplists:get_value(prog, BrowserData),
+ proplists:get_value(args, BrowserData),
+ proplists:get_value(page, BrowserData)} of
+ {Prog,Args,Page} when is_list(Args),
+ is_list(Page) ->
+ URL = "file://" ++ ?abs(Page),
+ ct_util:open_url(Prog, Args, URL);
+ _ ->
+ ok
+ end
+ end,
ok.
%%%-----------------------------------------------------------------
diff --git a/lib/common_test/src/ct_make.erl b/lib/common_test/src/ct_make.erl
index 233e45248e..40e9e99f37 100644
--- a/lib/common_test/src/ct_make.erl
+++ b/lib/common_test/src/ct_make.erl
@@ -177,7 +177,7 @@ members([],_MakefileMods,I,Rest) ->
{I,Rest}.
-%% Any flags that are not recognixed as make flags are passed directly
+%% Any flags that are not recognised as make flags are passed directly
%% to the compiler.
%% So for example make:all([load,debug_info]) will make everything
%% with the debug_info flag and load it.
diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl
index 877ec9c7dd..00b5a53cf4 100644
--- a/lib/common_test/src/ct_run.erl
+++ b/lib/common_test/src/ct_run.erl
@@ -46,6 +46,7 @@
-define(testdir(Name, Suite), ct_util:get_testdir(Name, Suite)).
-record(opts, {label,
+ profile,
vts,
shell,
cover,
@@ -161,6 +162,7 @@ script_start(Args) ->
script_start1(Parent, Args) ->
%% read general start flags
Label = get_start_opt(label, fun([Lbl]) -> Lbl end, Args),
+ Profile = get_start_opt(profile, fun([Prof]) -> Prof end, Args),
Vts = get_start_opt(vts, true, Args),
Shell = get_start_opt(shell, true, Args),
Cover = get_start_opt(cover, fun([CoverFile]) -> ?abs(CoverFile) end, Args),
@@ -234,7 +236,8 @@ script_start1(Parent, Args) ->
application:set_env(common_test, basic_html, true)
end,
- StartOpts = #opts{label = Label, vts = Vts, shell = Shell, cover = Cover,
+ StartOpts = #opts{label = Label, profile = Profile,
+ vts = Vts, shell = Shell, cover = Cover,
logdir = LogDir, event_handlers = EvHandlers,
ct_hooks = CTHooks,
include = IncludeDirs,
@@ -297,6 +300,9 @@ script_start2(StartOpts = #opts{vts = undefined,
Label = choose_val(StartOpts#opts.label,
SpecStartOpts#opts.label),
+ Profile = choose_val(StartOpts#opts.profile,
+ SpecStartOpts#opts.profile),
+
LogDir = choose_val(StartOpts#opts.logdir,
SpecStartOpts#opts.logdir),
@@ -317,6 +323,7 @@ script_start2(StartOpts = #opts{vts = undefined,
application:set_env(common_test, include, AllInclude),
{TS,StartOpts#opts{label = Label,
+ profile = Profile,
testspecs = Specs,
cover = Cover,
logdir = LogDir,
@@ -392,45 +399,67 @@ check_and_install_configfiles(Configs, LogDir, EvHandlers, CTHooks) ->
end.
script_start3(StartOpts, Args) ->
- case proplists:get_value(dir, Args) of
- [] ->
+ StartOpts1 = get_start_opt(step,
+ fun(Step) ->
+ StartOpts#opts{step = Step,
+ cover = undefined}
+ end, StartOpts, Args),
+ case {proplists:get_value(dir, Args),
+ proplists:get_value(suite, Args),
+ groups_and_cases(proplists:get_value(group, Args),
+ proplists:get_value(testcase, Args))} of
+ %% flag specified without data
+ {_,_,Error={error,_}} ->
+ Error;
+ {_,[],_} ->
+ {error,no_suite_specified};
+ {[],_,_} ->
{error,no_dir_specified};
- Dirs when is_list(Dirs) ->
+
+ {Dirs,undefined,[]} when is_list(Dirs) ->
script_start4(StartOpts#opts{tests = tests(Dirs)}, Args);
- undefined ->
- case proplists:get_value(suite, Args) of
- [] ->
- {error,no_suite_specified};
- Suites when is_list(Suites) ->
- StartOpts1 =
- get_start_opt(step,
- fun(Step) ->
- StartOpts#opts{step = Step,
- cover = undefined}
- end, StartOpts, Args),
- DirMods = [suite_to_test(S) || S <- Suites],
- case groups_and_cases(proplists:get_value(group, Args),
- proplists:get_value(testcase, Args)) of
- Error = {error,_} ->
- Error;
- [] when DirMods =/= [] ->
- Ts = tests(DirMods),
- script_start4(StartOpts1#opts{tests = Ts}, Args);
- GroupsAndCases when length(DirMods) == 1 ->
- Ts = tests(DirMods, GroupsAndCases),
- script_start4(StartOpts1#opts{tests = Ts}, Args);
- [_,_|_] when length(DirMods) > 1 ->
- {error,multiple_suites_and_cases};
- _ ->
- {error,incorrect_suite_option}
- end;
- undefined ->
- if StartOpts#opts.vts ; StartOpts#opts.shell ->
- script_start4(StartOpts#opts{tests = []}, Args);
- true ->
- script_usage(),
- {error,incorrect_usage}
- end
+
+ {undefined,Suites,[]} when is_list(Suites) ->
+ Ts = tests([suite_to_test(S) || S <- Suites]),
+ script_start4(StartOpts1#opts{tests = Ts}, Args);
+
+ {undefined,Suite,GsAndCs} when is_list(Suite) ->
+ case [suite_to_test(S) || S <- Suite] of
+ DirMods = [_] ->
+ Ts = tests(DirMods, GsAndCs),
+ script_start4(StartOpts1#opts{tests = Ts}, Args);
+ [_,_|_] ->
+ {error,multiple_suites_and_cases};
+ _ ->
+ {error,incorrect_start_options}
+ end;
+
+ {[_,_|_],Suite,[]} when is_list(Suite) ->
+ {error,multiple_dirs_and_suites};
+
+ {[Dir],Suite,GsAndCs} when is_list(Dir), is_list(Suite) ->
+ case [suite_to_test(Dir,S) || S <- Suite] of
+ DirMods when GsAndCs == [] ->
+ Ts = tests(DirMods),
+ script_start4(StartOpts1#opts{tests = Ts}, Args);
+ DirMods = [_] when GsAndCs /= [] ->
+ Ts = tests(DirMods, GsAndCs),
+ script_start4(StartOpts1#opts{tests = Ts}, Args);
+ [_,_|_] when GsAndCs /= [] ->
+ {error,multiple_suites_and_cases};
+ _ ->
+ {error,incorrect_start_options}
+ end;
+
+ {undefined,undefined,GsAndCs} when GsAndCs /= [] ->
+ {error,incorrect_start_options};
+
+ {undefined,undefined,_} ->
+ if StartOpts#opts.vts ; StartOpts#opts.shell ->
+ script_start4(StartOpts#opts{tests = []}, Args);
+ true ->
+ script_usage(),
+ {error,missing_start_options}
end
end.
@@ -448,13 +477,17 @@ script_start4(#opts{vts = true, config = Config, event_handlers = EvHandlers,
end, [], Config),
vts:init_data(ConfigFiles, EvHandlers, ?abs(LogDir), Tests);
-script_start4(#opts{label = Label, shell = true, config = Config,
+script_start4(#opts{label = Label, profile = Profile,
+ shell = true, config = Config,
event_handlers = EvHandlers,
ct_hooks = CTHooks,
logdir = LogDir, testspecs = Specs}, _Args) ->
%% label - used by ct_logs
application:set_env(common_test, test_label, Label),
+ %% profile - used in ct_util
+ application:set_env(common_test, profile, Profile),
+
InstallOpts = [{config,Config},{event_handler,EvHandlers},
{ct_hooks, CTHooks}],
if Config == [] ->
@@ -649,6 +682,10 @@ run_test1(StartOpts) ->
Label = get_start_opt(label, fun(Lbl) when is_list(Lbl) -> Lbl;
(Lbl) when is_atom(Lbl) -> atom_to_list(Lbl)
end, StartOpts),
+ %% profile
+ Profile = get_start_opt(profile, fun(Prof) when is_list(Prof) -> Prof;
+ (Prof) when is_atom(Prof) -> atom_to_list(Prof)
+ end, StartOpts),
%% logdir
LogDir = get_start_opt(logdir, fun(LD) when is_list(LD) -> LD end,
StartOpts),
@@ -750,7 +787,7 @@ run_test1(StartOpts) ->
%% stepped execution
Step = get_start_opt(step, value, StartOpts),
- Opts = #opts{label = Label,
+ Opts = #opts{label = Label, profile = Profile,
cover = Cover, step = Step, logdir = LogDir, config = CfgFiles,
event_handlers = EvHandlers,
ct_hooks = CTHooks,
@@ -792,6 +829,8 @@ run_spec_file(Relaxed,
SpecOpts = get_data_for_node(TS, node()),
Label = choose_val(Opts#opts.label,
SpecOpts#opts.label),
+ Profile = choose_val(Opts#opts.profile,
+ SpecOpts#opts.profile),
LogDir = choose_val(Opts#opts.logdir,
SpecOpts#opts.logdir),
AllConfig = merge_vals([CfgFiles, SpecOpts#opts.config]),
@@ -817,6 +856,7 @@ run_spec_file(Relaxed,
AllCTHooks) of
ok ->
Opts1 = Opts#opts{label = Label,
+ profile = Profile,
cover = Cover,
logdir = which(logdir, LogDir),
config = AllConfig,
@@ -899,67 +939,99 @@ run_dir(Opts = #opts{logdir = LogDir,
ok -> ok;
{error,IReason} -> exit(IReason)
end,
- case lists:keysearch(dir, 1, StartOpts) of
- {value,{_,Dirs=[Dir|_]}} when not is_integer(Dir),
- length(Dirs)>1 ->
- %% multiple dirs (no suite)
- reformat_result(catch do_run(tests(Dirs), [], Opts1, StartOpts));
- false -> % no dir
- %% fun for converting suite name to {Dir,Mod} tuple
- S2M = fun(S) when is_list(S) ->
- {filename:dirname(S),
- list_to_atom(filename:rootname(filename:basename(S)))};
- (A) ->
- {".",A}
- end,
- case lists:keysearch(suite, 1, StartOpts) of
- {value,{_,Suite}} when is_integer(hd(Suite)) ; is_atom(Suite) ->
- {Dir,Mod} = S2M(Suite),
- case groups_and_cases(proplists:get_value(group, StartOpts),
- proplists:get_value(testcase, StartOpts)) of
- Error = {error,_} ->
- exit(Error);
+ case {proplists:get_value(dir, StartOpts),
+ proplists:get_value(suite, StartOpts),
+ groups_and_cases(proplists:get_value(group, StartOpts),
+ proplists:get_value(testcase, StartOpts))} of
+ %% flag specified without data
+ {_,_,Error={error,_}} ->
+ Error;
+ {_,[],_} ->
+ {error,no_suite_specified};
+ {[],_,_} ->
+ {error,no_dir_specified};
+
+ {Dirs=[Hd|_],undefined,[]} when is_list(Dirs), not is_integer(Hd) ->
+ Dirs1 = [if is_atom(D) -> atom_to_list(D);
+ true -> D end || D <- Dirs],
+ reformat_result(catch do_run(tests(Dirs1), [], Opts1, StartOpts));
+
+ {Dir=[Hd|_],undefined,[]} when is_list(Dir) and is_integer(Hd) ->
+ reformat_result(catch do_run(tests(Dir), [], Opts1, StartOpts));
+
+ {Dir,undefined,[]} when is_atom(Dir) ->
+ reformat_result(catch do_run(tests(atom_to_list(Dir)),
+ [], Opts1, StartOpts));
+
+ {undefined,Suites=[Hd|_],[]} when not is_integer(Hd) ->
+ Suites1 = [suite_to_test(S) || S <- Suites],
+ reformat_result(catch do_run(tests(Suites1), [], Opts1, StartOpts));
+
+ {undefined,Suite,[]} when is_atom(Suite) and
+ (Suite /= undefined) ->
+ {Dir,Mod} = suite_to_test(Suite),
+ reformat_result(catch do_run(tests(Dir, Mod), [], Opts1, StartOpts));
+
+ {undefined,Suite,GsAndCs} when is_atom(Suite) and
+ (Suite /= undefined) ->
+ {Dir,Mod} = suite_to_test(Suite),
+ reformat_result(catch do_run(tests(Dir, Mod, GsAndCs),
+ [], Opts1, StartOpts));
+
+ {undefined,[Hd,_|_],_GsAndCs} when not is_integer(Hd) ->
+ exit(multiple_suites_and_cases);
+
+ {undefined,Suite=[Hd|Tl],GsAndCs} when is_integer(Hd) ;
+ (is_list(Hd) and (Tl == [])) ;
+ (is_atom(Hd) and (Tl == [])) ->
+ {Dir,Mod} = suite_to_test(Suite),
+ reformat_result(catch do_run(tests(Dir, Mod, GsAndCs),
+ [], Opts1, StartOpts));
+
+ {[Hd,_|_],_Suites,[]} when is_list(Hd) ; not is_integer(Hd) ->
+ exit(multiple_dirs_and_suites);
+
+ {undefined,undefined,GsAndCs} when GsAndCs /= [] ->
+ exit(incorrect_start_options);
+
+ {Dir,Suite,GsAndCs} when is_integer(hd(Dir)) ;
+ (is_atom(Dir) and (Dir /= undefined)) ;
+ ((length(Dir) == 1) and is_atom(hd(Dir))) ;
+ ((length(Dir) == 1) and is_list(hd(Dir))) ->
+ Dir1 = if is_atom(Dir) -> atom_to_list(Dir);
+ true -> Dir end,
+ if Suite == undefined ->
+ exit(incorrect_start_options);
+
+ is_integer(hd(Suite)) ;
+ (is_atom(Suite) and (Suite /= undefined)) ;
+ ((length(Suite) == 1) and is_atom(hd(Suite))) ;
+ ((length(Suite) == 1) and is_list(hd(Suite))) ->
+ {Dir2,Mod} = suite_to_test(Dir1, Suite),
+ case GsAndCs of
[] ->
- reformat_result(catch do_run(tests(Dir, listify(Mod)),
+ reformat_result(catch do_run(tests(Dir2, Mod),
[], Opts1, StartOpts));
- GsAndCs ->
- reformat_result(catch do_run(tests(Dir, Mod, GsAndCs),
+ _ ->
+ reformat_result(catch do_run(tests(Dir2, Mod, GsAndCs),
[], Opts1, StartOpts))
end;
- {value,{_,Suites}} ->
- reformat_result(catch do_run(tests(lists:map(S2M, Suites)),
- [], Opts1, StartOpts));
- _ ->
- exit(no_tests_specified)
- end;
- {value,{_,Dir}} ->
- case lists:keysearch(suite, 1, StartOpts) of
- {value,{_,Suite}} when is_integer(hd(Suite)) ; is_atom(Suite) ->
- Mod = if is_atom(Suite) -> Suite;
- true -> list_to_atom(Suite)
- end,
- case groups_and_cases(proplists:get_value(group, StartOpts),
- proplists:get_value(testcase, StartOpts)) of
- Error = {error,_} ->
- exit(Error);
- [] ->
- reformat_result(catch do_run(tests(Dir, listify(Mod)),
+
+ is_list(Suite) -> % multiple suites
+ case [suite_to_test(Dir1, S) || S <- Suite] of
+ [_,_|_] when GsAndCs /= [] ->
+ exit(multiple_suites_and_cases);
+ [{Dir2,Mod}] when GsAndCs /= [] ->
+ reformat_result(catch do_run(tests(Dir2, Mod, GsAndCs),
[], Opts1, StartOpts));
- GsAndCs ->
- reformat_result(catch do_run(tests(Dir, Mod, GsAndCs),
+ DirMods ->
+ reformat_result(catch do_run(tests(DirMods),
[], Opts1, StartOpts))
- end;
- {value,{_,Suites=[Suite|_]}} when is_list(Suite) ->
- Mods = lists:map(fun(Str) -> list_to_atom(Str) end, Suites),
- reformat_result(catch do_run(tests(delistify(Dir), Mods),
- [], Opts1, StartOpts));
- {value,{_,Suites}} ->
- reformat_result(catch do_run(tests(delistify(Dir), Suites),
- [], Opts1, StartOpts));
- false -> % no suite, only dir
- reformat_result(catch do_run(tests(listify(Dir)),
- [], Opts1, StartOpts))
- end
+ end
+ end;
+
+ {Dir,Suite,GsAndCs} ->
+ exit({incorrect_start_options,{Dir,Suite,GsAndCs}})
end.
%%%-----------------------------------------------------------------
@@ -1014,6 +1086,7 @@ run_testspec1(TestSpec) ->
end.
get_data_for_node(#testspec{label = Labels,
+ profile = Profiles,
logdir = LogDirs,
cover = CoverFs,
config = Cfgs,
@@ -1024,6 +1097,7 @@ get_data_for_node(#testspec{label = Labels,
multiply_timetraps = MTs,
scale_timetraps = STs}, Node) ->
Label = proplists:get_value(Node, Labels),
+ Profile = proplists:get_value(Node, Profiles),
LogDir = case proplists:get_value(Node, LogDirs) of
undefined -> ".";
Dir -> Dir
@@ -1037,6 +1111,7 @@ get_data_for_node(#testspec{label = Labels,
FiltCTHooks = [Hook || {N,Hook} <- CTHooks, N==Node],
Include = [I || {N,I} <- Incl, N==Node],
#opts{label = Label,
+ profile = Profile,
logdir = LogDir,
cover = Cover,
config = ConfigFiles,
@@ -1118,8 +1193,24 @@ reformat_result({user_error,Reason}) ->
reformat_result(Result) ->
Result.
-suite_to_test(Suite) ->
- {filename:dirname(Suite),list_to_atom(filename:rootname(filename:basename(Suite)))}.
+suite_to_test(Suite) when is_atom(Suite) ->
+ suite_to_test(atom_to_list(Suite));
+
+suite_to_test(Suite) when is_list(Suite) ->
+ {filename:dirname(Suite),
+ list_to_atom(filename:rootname(filename:basename(Suite)))}.
+
+suite_to_test(Dir, Suite) when is_atom(Suite) ->
+ suite_to_test(Dir, atom_to_list(Suite));
+
+suite_to_test(Dir, Suite) when is_list(Suite) ->
+ case filename:dirname(Suite) of
+ "." ->
+ {Dir,list_to_atom(filename:rootname(Suite))};
+ DirName -> % ignore Dir
+ File = filename:basename(Suite),
+ {DirName,list_to_atom(filename:rootname(File))}
+ end.
groups_and_cases(Gs, Cs) when ((Gs == undefined) or (Gs == [])) and
((Cs == undefined) or (Cs == [])) ->
@@ -1173,7 +1264,7 @@ do_run(Tests, Misc, LogDir) when is_list(Misc) ->
do_run(Tests, [], Opts1#opts{logdir = LogDir}, []).
do_run(Tests, Skip, Opts, Args) ->
- #opts{label = Label, cover = Cover} = Opts,
+ #opts{label = Label, profile = Profile, cover = Cover} = Opts,
%% label - used by ct_logs
TestLabel =
@@ -1184,6 +1275,15 @@ do_run(Tests, Skip, Opts, Args) ->
end,
application:set_env(common_test, test_label, TestLabel),
+ %% profile - used in ct_util
+ TestProfile =
+ if Profile == undefined -> undefined;
+ is_atom(Profile) -> atom_to_list(Profile);
+ is_list(Profile) -> Profile;
+ true -> undefined
+ end,
+ application:set_env(common_test, profile, TestProfile),
+
case code:which(test_server) of
non_existing ->
exit({error,no_path_to_test_server});
diff --git a/lib/common_test/src/ct_util.erl b/lib/common_test/src/ct_util.erl
index b3e345b4e5..ef94c25364 100644
--- a/lib/common_test/src/ct_util.erl
+++ b/lib/common_test/src/ct_util.erl
@@ -47,7 +47,7 @@
-export([get_mode/0, create_table/3, read_opts/0]).
--export([set_cwd/1, reset_cwd/0]).
+-export([set_cwd/1, reset_cwd/0, get_start_dir/0]).
-export([parse_table/1]).
@@ -61,6 +61,9 @@
-export([warn_duplicates/1]).
+-export([get_profile_data/0, get_profile_data/1,
+ get_profile_data/2, open_url/3]).
+
-include("ct_event.hrl").
-include("ct_util.hrl").
@@ -243,6 +246,9 @@ set_cwd(Dir) ->
reset_cwd() ->
call(reset_cwd).
+get_start_dir() ->
+ call(get_start_dir).
+
loop(Mode,TestData,StartDir) ->
receive
{update_last_run_index,From} ->
@@ -319,6 +325,9 @@ loop(Mode,TestData,StartDir) ->
{reset_cwd,From} ->
return(From,file:set_cwd(StartDir)),
loop(From,TestData,StartDir);
+ {get_start_dir,From} ->
+ return(From,StartDir),
+ loop(From,TestData,StartDir);
{{stop,Info},From} ->
Time = calendar:local_time(),
ct_event:sync_notify(#event{name=test_done,
@@ -332,7 +341,7 @@ loop(Mode,TestData,StartDir) ->
ets:delete(?conn_table),
ets:delete(?board_table),
ets:delete(?suite_table),
- ct_logs:close(Info),
+ ct_logs:close(Info, StartDir),
ct_event:stop(),
ct_config:stop(),
file:set_cwd(StartDir),
@@ -727,6 +736,79 @@ warn_duplicates(Suites) ->
lists:foreach(Warn, Suites),
ok.
+%%%-----------------------------------------------------------------
+%%% @spec
+%%%
+%%% @doc
+get_profile_data() ->
+ get_profile_data(all).
+
+get_profile_data(KeyOrStartDir) ->
+ if is_atom(KeyOrStartDir) ->
+ get_profile_data(KeyOrStartDir, get_start_dir());
+ is_list(KeyOrStartDir) ->
+ get_profile_data(all, KeyOrStartDir)
+ end.
+
+get_profile_data(Key, StartDir) ->
+ Profile = case application:get_env(common_test, profile) of
+ {ok,undefined} -> default;
+ {ok,Prof} -> Prof;
+ _ -> default
+ end,
+ get_profile_data(Profile, Key, StartDir).
+
+get_profile_data(Profile, Key, StartDir) ->
+ File = case Profile of
+ default ->
+ ?ct_profile_file;
+ _ when is_list(Profile) ->
+ ?ct_profile_file ++ "." ++ Profile;
+ _ when is_atom(Profile) ->
+ ?ct_profile_file ++ "." ++ atom_to_list(Profile)
+ end,
+ FullNameWD = filename:join(StartDir, File),
+ {WhichFile,Result} =
+ case file:consult(FullNameWD) of
+ {error,enoent} ->
+ case init:get_argument(home) of
+ {ok,[[HomeDir]]} ->
+ FullNameHome = filename:join(HomeDir, File),
+ {FullNameHome,file:consult(FullNameHome)};
+ _ ->
+ {File,{error,enoent}}
+ end;
+ Consulted ->
+ {FullNameWD,Consulted}
+ end,
+ case Result of
+ {error,enoent} when Profile /= default ->
+ io:format(user, "~nERROR! Missing profile file ~p~n", [File]),
+ undefined;
+ {error,enoent} when Profile == default ->
+ undefined;
+ {error,Reason} ->
+ io:format(user,"~nERROR! Error in profile file ~p: ~p~n",
+ [WhichFile,Reason]),
+ undefined;
+ {ok,Data} ->
+ Data1 = case Data of
+ [List] when is_list(List) ->
+ List;
+ _ when is_list(Data) ->
+ Data;
+ _ ->
+ io:format(user,
+ "~nERROR! Invalid profile data in ~p~n",
+ [WhichFile]),
+ []
+ end,
+ if Key == all ->
+ Data1;
+ true ->
+ proplists:get_value(Key, Data)
+ end
+ end.
%%%-----------------------------------------------------------------
%%% Internal functions
@@ -799,3 +881,28 @@ abs_name2([H|T],Acc) ->
abs_name2(T,[H|Acc]);
abs_name2([],Acc) ->
filename:join(lists:reverse(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
+ {ok, Paths} ->
+ Path = proplists:get_value(default, Paths),
+ [Cmd | _] = string:tokens(Path, "%"),
+ Cmd1 = Cmd ++ " " ++ Args ++ " " ++ URL,
+ io:format(user, "~nOpening ~s with command:~n ~s~n", [URL,Cmd1]),
+ open_port({spawn,Cmd1}, []);
+ _ ->
+ io:format("~nNo path to iexplore.exe~n",[])
+ end,
+ win32reg:close(R),
+ ok;
+
+open_url(Prog, Args, URL) ->
+ ProgStr = if is_atom(Prog) -> atom_to_list(Prog);
+ is_list(Prog) -> Prog
+ end,
+ Cmd = ProgStr ++ " " ++ Args ++ " " ++ URL,
+ io:format(user, "~nOpening ~s with command:~n ~s~n", [URL,Cmd]),
+ open_port({spawn,Cmd},[]),
+ ok.
diff --git a/lib/common_test/src/ct_util.hrl b/lib/common_test/src/ct_util.hrl
index 556f88c84d..09060f3e8b 100644
--- a/lib/common_test/src/ct_util.hrl
+++ b/lib/common_test/src/ct_util.hrl
@@ -31,6 +31,7 @@
nodes=[],
init=[],
label=[],
+ profile=[],
logdir=["."],
cover=[],
config=[],
@@ -58,3 +59,5 @@
-define(missing_suites_info, "missing_suites.info").
-define(ct_config_txt, ct_config_plain).
+
+-define(ct_profile_file, ".common_test").