From 0075b97214d6c037eca3888bca29d68c9b5fbb74 Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Fri, 8 Jul 2011 20:46:17 +0200 Subject: 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) --- lib/common_test/src/ct_logs.erl | 21 ++- lib/common_test/src/ct_make.erl | 2 +- lib/common_test/src/ct_run.erl | 296 +++++++++++++++++++++++++++------------- lib/common_test/src/ct_util.erl | 111 ++++++++++++++- lib/common_test/src/ct_util.hrl | 3 + 5 files changed, 329 insertions(+), 104 deletions(-) (limited to 'lib') 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"). -- cgit v1.2.3 From e0440ea67e0b1ce05ca2305f7f4b52e4e23ce493 Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Wed, 13 Jul 2011 10:45:39 +0200 Subject: Fix error with test_server not releasing SASL TTY handlers OTP-9311 --- lib/test_server/src/test_server_ctrl.erl | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/test_server/src/test_server_ctrl.erl b/lib/test_server/src/test_server_ctrl.erl index f3445b742b..24069946ef 100644 --- a/lib/test_server/src/test_server_ctrl.erl +++ b/lib/test_server/src/test_server_ctrl.erl @@ -1297,6 +1297,7 @@ terminate(_Reason, State) -> end, kill_all_jobs(State#state.jobs), test_server_node:stop(State#state.target_info), + test_server_h:restore(), ok. kill_all_jobs([{_Name,JobPid}|Jobs]) -> -- cgit v1.2.3 From d3b636f97ce36e106ac53beb4cba0db13cd5656f Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Wed, 13 Jul 2011 17:20:45 +0200 Subject: Fix problem with automatically generated init & end-config functions for groups OTP-9369 --- lib/common_test/src/ct_framework.erl | 2 + lib/test_server/src/test_server_ctrl.erl | 78 +++++++++++++++++--------------- 2 files changed, 43 insertions(+), 37 deletions(-) (limited to 'lib') diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl index 2ebc6c311a..4f57736591 100644 --- a/lib/common_test/src/ct_framework.erl +++ b/lib/common_test/src/ct_framework.erl @@ -1159,12 +1159,14 @@ error_in_suite(Config) -> %% if the group config functions are missing in the suite, %% use these instead ct_init_per_group(GroupName, Config) -> + ct:comment(io_lib:format("start of ~p", [GroupName])), ct_logs:log("WARNING", "init_per_group/2 for ~w missing " "in suite, using default.", [GroupName]), Config. ct_end_per_group(GroupName, _) -> + ct:comment(io_lib:format("end of ~p", [GroupName])), ct_logs:log("WARNING", "end_per_group/2 for ~w missing " "in suite, using default.", [GroupName]), diff --git a/lib/test_server/src/test_server_ctrl.erl b/lib/test_server/src/test_server_ctrl.erl index 24069946ef..85686217f7 100644 --- a/lib/test_server/src/test_server_ctrl.erl +++ b/lib/test_server/src/test_server_ctrl.erl @@ -1665,6 +1665,11 @@ do_test_cases(TopCases, SkipCases, Config, TimetrapData) when is_list(TopCases), is_tuple(TimetrapData) -> start_log_file(), + FwMod = + case os:getenv("TEST_SERVER_FRAMEWORK") of + FW when FW =:= false; FW =:= "undefined" -> ?MODULE; + FW -> list_to_atom(FW) + end, case collect_all_cases(TopCases, SkipCases) of {error,Why} -> print(1, "Error starting: ~p", [Why]), @@ -1677,11 +1682,11 @@ do_test_cases(TopCases, SkipCases, put(test_server_cases, N), put(test_server_case_num, 0), TestSpec = - add_init_and_end_per_suite(TestSpec0, undefined, undefined), - + add_init_and_end_per_suite(TestSpec0, undefined, undefined, FwMod), TI = get_target_info(), - print(1, "Starting test~s", [print_if_known(N, {", ~w test cases",[N]}, - {" (with repeated test cases)",[]})]), + print(1, "Starting test~s", + [print_if_known(N, {", ~w test cases",[N]}, + {" (with repeated test cases)",[]})]), Test = get(test_server_name), test_server_sup:framework_call(report, [tests_start,{Test,N}]), @@ -1710,13 +1715,12 @@ do_test_cases(TopCases, SkipCases, print(html, "
Used Erlang ~s in ~s.\n", [erlang:system_info(version), code:root_dir()]), - case os:getenv("TEST_SERVER_FRAMEWORK") of - FW when FW =:= false; FW =:= "undefined" -> + if FwMod == ?MODULE -> print(html, "

Target:
\n"), print_who(TI#target_info.host, TI#target_info.username), print(html, "
Used Erlang ~s in ~s.\n", [TI#target_info.version, TI#target_info.root_dir]); - _ -> + true -> case test_server_sup:framework_call(target_info, []) of TargetInfo when is_list(TargetInfo), length(TargetInfo) > 0 -> @@ -2006,54 +2010,54 @@ copy_html_file(Src, DestDir) -> end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% add_init_and_end_per_suite(TestSpec, Mod, Ref) -> NewTestSpec +%% add_init_and_end_per_suite(TestSpec, Mod, Ref, FwMod) -> NewTestSpec %% %% Expands TestSpec with an initial init_per_suite, and a final %% end_per_suite element, per each discovered suite in the list. -add_init_and_end_per_suite([{make,_,_}=Case|Cases], LastMod, LastRef) -> - [Case|add_init_and_end_per_suite(Cases, LastMod, LastRef)]; -add_init_and_end_per_suite([{skip_case,{{Mod,all},_}}=Case|Cases], LastMod, LastRef) - when Mod =/= LastMod -> +add_init_and_end_per_suite([{make,_,_}=Case|Cases], LastMod, LastRef, FwMod) -> + [Case|add_init_and_end_per_suite(Cases, LastMod, LastRef, FwMod)]; +add_init_and_end_per_suite([{skip_case,{{Mod,all},_}}=Case|Cases], LastMod, + LastRef, FwMod) when Mod =/= LastMod -> {PreCases, NextMod, NextRef} = do_add_end_per_suite_and_skip(LastMod, LastRef, Mod), - PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef)]; -add_init_and_end_per_suite([{skip_case,{{Mod,_},_}}=Case|Cases], LastMod, LastRef) - when Mod =/= LastMod -> + PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef, FwMod)]; +add_init_and_end_per_suite([{skip_case,{{Mod,_},_}}=Case|Cases], LastMod, + LastRef, FwMod) when Mod =/= LastMod -> {PreCases, NextMod, NextRef} = do_add_init_and_end_per_suite(LastMod, LastRef, Mod), - PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef)]; -add_init_and_end_per_suite([{skip_case,{conf,_,{Mod,_},_}}=Case|Cases], LastMod, LastRef) - when Mod =/= LastMod -> + PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef, FwMod)]; +add_init_and_end_per_suite([{skip_case,{conf,_,{Mod,_},_}}=Case|Cases], LastMod, + LastRef, FwMod) when Mod =/= LastMod -> {PreCases, NextMod, NextRef} = do_add_init_and_end_per_suite(LastMod, LastRef, Mod), - PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef)]; -add_init_and_end_per_suite([{skip_case,_}=Case|Cases], LastMod, LastRef) -> - [Case|add_init_and_end_per_suite(Cases, LastMod, LastRef)]; -add_init_and_end_per_suite([{conf,_,_,{Mod,_}}=Case|Cases], LastMod, LastRef) - when Mod =/= LastMod -> + PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef, FwMod)]; +add_init_and_end_per_suite([{skip_case,_}=Case|Cases], LastMod, LastRef, FwMod) -> + [Case|add_init_and_end_per_suite(Cases, LastMod, LastRef, FwMod)]; +add_init_and_end_per_suite([{conf,_,_,{Mod,_}}=Case|Cases], LastMod, + LastRef, FwMod) when Mod =/= LastMod, Mod =/= FwMod -> {PreCases, NextMod, NextRef} = do_add_init_and_end_per_suite(LastMod, LastRef, Mod), - PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef)]; -add_init_and_end_per_suite([{conf,_,_,_}=Case|Cases], LastMod, LastRef) -> - [Case|add_init_and_end_per_suite(Cases, LastMod, LastRef)]; -add_init_and_end_per_suite([{Mod,_}=Case|Cases], LastMod, LastRef) - when Mod =/= LastMod -> + PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef, FwMod)]; +add_init_and_end_per_suite([{conf,_,_,_}=Case|Cases], LastMod, LastRef, FwMod) -> + [Case|add_init_and_end_per_suite(Cases, LastMod, LastRef, FwMod)]; +add_init_and_end_per_suite([{Mod,_}=Case|Cases], LastMod, LastRef, FwMod) + when Mod =/= LastMod, Mod =/= FwMod -> {PreCases, NextMod, NextRef} = do_add_init_and_end_per_suite(LastMod, LastRef, Mod), - PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef)]; -add_init_and_end_per_suite([{Mod,_,_}=Case|Cases], LastMod, LastRef) - when Mod =/= LastMod -> + PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef, FwMod)]; +add_init_and_end_per_suite([{Mod,_,_}=Case|Cases], LastMod, LastRef, FwMod) + when Mod =/= LastMod, Mod =/= FwMod -> {PreCases, NextMod, NextRef} = do_add_init_and_end_per_suite(LastMod, LastRef, Mod), - PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef)]; -add_init_and_end_per_suite([Case|Cases], LastMod, LastRef)-> - [Case|add_init_and_end_per_suite(Cases, LastMod, LastRef)]; -add_init_and_end_per_suite([], _LastMod, undefined) -> + PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef, FwMod)]; +add_init_and_end_per_suite([Case|Cases], LastMod, LastRef, FwMod)-> + [Case|add_init_and_end_per_suite(Cases, LastMod, LastRef, FwMod)]; +add_init_and_end_per_suite([], _LastMod, undefined, _FwMod) -> []; -add_init_and_end_per_suite([], _LastMod, skipped_suite) -> +add_init_and_end_per_suite([], _LastMod, skipped_suite, _FwMod) -> []; -add_init_and_end_per_suite([], LastMod, LastRef) -> +add_init_and_end_per_suite([], LastMod, LastRef, _FwMod) -> [{conf,LastRef,[],{LastMod,end_per_suite}}]. do_add_init_and_end_per_suite(LastMod, LastRef, Mod) -> -- cgit v1.2.3 From f703d6512219431fa7fe61e5ddd1a9ed32506daa Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Wed, 13 Jul 2011 18:17:36 +0200 Subject: Fix problem with logdir string and some other minor bugs OTP-9370: Fix problem with crash if logdir contains multiple dirs OTP-9155: Fix some minor remaining bugs --- lib/common_test/src/ct_logs.erl | 40 ++++++++++++++++++++-------------------- lib/common_test/src/ct_run.erl | 13 +++++++++++++ 2 files changed, 33 insertions(+), 20 deletions(-) (limited to 'lib') diff --git a/lib/common_test/src/ct_logs.erl b/lib/common_test/src/ct_logs.erl index 5c4eb88c1f..761b906392 100644 --- a/lib/common_test/src/ct_logs.erl +++ b/lib/common_test/src/ct_logs.erl @@ -124,27 +124,27 @@ close(Info, StartDir) -> ok; Error -> io:format("Warning! Cleanup failed: ~p~n", [Error]) - end; + end, + make_all_suites_index(stop), + make_all_runs_index(stop); true -> - file:set_cwd("..") - end, - - 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 + file:set_cwd(".."), + 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 end, ok. diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl index 00b5a53cf4..418e212fd1 100644 --- a/lib/common_test/src/ct_run.erl +++ b/lib/common_test/src/ct_run.erl @@ -157,6 +157,7 @@ script_start(Args) -> end, stop_trace(Tracing), timer:sleep(1000), + io:nl(), Res. script_start1(Parent, Args) -> @@ -2155,6 +2156,18 @@ get_start_opt(Key, IfExists, Args) -> get_start_opt(Key, IfExists, undefined, Args). get_start_opt(Key, IfExists, IfNotExists, Args) -> + try try_get_start_opt(Key, IfExists, IfNotExists, Args) of + Result -> + Result + catch + error:_ -> + exit({user_error,{bad_argument,Key}}) + end. + +try_get_start_opt(Key, IfExists, Args) -> + try_get_start_opt(Key, IfExists, undefined, Args). + +try_get_start_opt(Key, IfExists, IfNotExists, Args) -> case lists:keysearch(Key, 1, Args) of {value,{Key,Val}} when is_function(IfExists) -> IfExists(Val); -- cgit v1.2.3 From 021b0dcb2a3a86ec0e07b0de8dc7cde9be0924ba Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Thu, 14 Jul 2011 14:18:57 +0200 Subject: Introduce new 'logopts' flag Introduce new 'logopts' flag and make it possible to modify the default logging behaviour OTP-9372 OTP-9396 --- lib/common_test/src/ct.erl | 4 ++- lib/common_test/src/ct_framework.erl | 12 ++++++- lib/common_test/src/ct_run.erl | 61 ++++++++++++++++++++++++-------- lib/common_test/src/ct_testspec.erl | 22 ++++++++++++ lib/common_test/src/ct_util.hrl | 1 + lib/common_test/src/vts.erl | 18 +++++----- lib/test_server/src/test_server_ctrl.erl | 34 +++++++++++++----- 7 files changed, 119 insertions(+), 33 deletions(-) (limited to 'lib') diff --git a/lib/common_test/src/ct.erl b/lib/common_test/src/ct.erl index 66da3ef742..4c215d1b1e 100644 --- a/lib/common_test/src/ct.erl +++ b/lib/common_test/src/ct.erl @@ -148,7 +148,7 @@ run(TestDirs) -> %%% {auto_compile,Bool} | {multiply_timetraps,M} | {scale_timetraps,Bool} | %%% {repeat,N} | {duration,DurTime} | {until,StopTime} | %%% {force_stop,Bool} | {decrypt,DecryptKeyOrFile} | -%%% {refresh_logs,LogDir} | {basic_html,Bool} | +%%% {refresh_logs,LogDir} | {logopts,LogOpts} | {basic_html,Bool} | %%% {ct_hooks, CTHs} %%% TestDirs = [string()] | string() %%% Suites = [string()] | string() @@ -177,6 +177,8 @@ run(TestDirs) -> %%% DecryptKeyOrFile = {key,DecryptKey} | {file,DecryptFile} %%% DecryptKey = string() %%% DecryptFile = string() +%%% LogOpts = [LogOpt] +%%% LogOpt = no_nl | no_src %%% CTHs = [CTHModule | {CTHModule, CTHInitArgs}] %%% CTHModule = atom() %%% CTHInitArgs = term() diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl index 4f57736591..0910b39b72 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, report/2, warn/1]). -export([error_notification/4]). --export([overview_html_header/1]). +-export([get_logopts/0, overview_html_header/1]). -export([error_in_suite/1, ct_init_per_group/2, ct_end_per_group/2]). @@ -1333,6 +1333,16 @@ add_data_dir(File,Config) when is_list(File) -> File end. +%%%----------------------------------------------------------------- +%%% @spec get_logopts +get_logopts() -> + case ct_util:get_testdata(logopts) of + undefined -> + []; + LogOpts -> + LogOpts + end. + %%%----------------------------------------------------------------- %%% @spec overview_html_header(TestName) -> Header overview_html_header(TestName) -> diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl index 418e212fd1..4bb555bb9e 100644 --- a/lib/common_test/src/ct_run.erl +++ b/lib/common_test/src/ct_run.erl @@ -33,7 +33,7 @@ %% Exported for VTS --export([run_make/3,do_run/3,tests/1,tests/2,tests/3]). +-export([run_make/3,do_run/4,tests/1,tests/2,tests/3]). %% Misc internal functions @@ -53,6 +53,7 @@ coverspec, step, logdir, + logopts = [], config = [], event_handlers = [], ct_hooks = [], @@ -168,6 +169,8 @@ script_start1(Parent, Args) -> Shell = get_start_opt(shell, true, Args), Cover = get_start_opt(cover, fun([CoverFile]) -> ?abs(CoverFile) end, Args), LogDir = get_start_opt(logdir, fun([LogD]) -> LogD end, Args), + LogOpts = get_start_opt(logopts, fun(Os) -> [list_to_atom(O) || O <- Os] end, + [], Args), MultTT = get_start_opt(multiply_timetraps, fun([MT]) -> list_to_integer(MT) end, 1, Args), ScaleTT = get_start_opt(scale_timetraps, @@ -239,7 +242,8 @@ script_start1(Parent, Args) -> StartOpts = #opts{label = Label, profile = Profile, vts = Vts, shell = Shell, cover = Cover, - logdir = LogDir, event_handlers = EvHandlers, + logdir = LogDir, logopts = LogOpts, + event_handlers = EvHandlers, ct_hooks = CTHooks, include = IncludeDirs, silent_connections = SilentConns, @@ -307,6 +311,9 @@ script_start2(StartOpts = #opts{vts = undefined, LogDir = choose_val(StartOpts#opts.logdir, SpecStartOpts#opts.logdir), + AllLogOpts = merge_vals([StartOpts#opts.logopts, + SpecStartOpts#opts.logopts]), + Cover = choose_val(StartOpts#opts.cover, SpecStartOpts#opts.cover), MultTT = choose_val(StartOpts#opts.multiply_timetraps, @@ -328,6 +335,7 @@ script_start2(StartOpts = #opts{vts = undefined, testspecs = Specs, cover = Cover, logdir = LogDir, + logopts = AllLogOpts, config = SpecStartOpts#opts.config, event_handlers = AllEvHs, ct_hooks = AllCTHooks, @@ -465,7 +473,7 @@ script_start3(StartOpts, Args) -> end. script_start4(#opts{vts = true, config = Config, event_handlers = EvHandlers, - tests = Tests, logdir = LogDir}, _Args) -> + tests = Tests, logdir = LogDir, logopts = LogOpts}, _Args) -> ConfigFiles = lists:foldl(fun({ct_config_plain,CfgFiles}, AllFiles) when is_list(hd(CfgFiles)) -> @@ -476,13 +484,15 @@ script_start4(#opts{vts = true, config = Config, event_handlers = EvHandlers, (_, AllFiles) -> AllFiles end, [], Config), - vts:init_data(ConfigFiles, EvHandlers, ?abs(LogDir), Tests); + vts:init_data(ConfigFiles, EvHandlers, ?abs(LogDir), LogOpts, Tests); script_start4(#opts{label = Label, profile = Profile, shell = true, config = Config, event_handlers = EvHandlers, ct_hooks = CTHooks, - logdir = LogDir, testspecs = Specs}, _Args) -> + logdir = LogDir, + logopts = LogOpts, + testspecs = Specs}, _Args) -> %% label - used by ct_logs application:set_env(common_test, test_label, Label), @@ -499,6 +509,7 @@ script_start4(#opts{label = Label, profile = Profile, case install(InstallOpts) of ok -> ct_util:start(interactive, LogDir), + ct_util:set_testdata(logopts, LogOpts), log_ts_names(Specs), io:nl(), ok; @@ -539,6 +550,7 @@ script_usage() -> "\n\t[-decrypt_key Key] | [-decrypt_file KeyFile]" "\n\t[-dir TestDir1 TestDir2 .. TestDirN] |" "\n\t[-suite Suite [-case Case]]" + "\n\t[-logopts LogOpt1 LogOpt2 .. LogOptN]" "\n\t[-include InclDir1 InclDir2 .. InclDirN]" "\n\t[-no_auto_compile]" "\n\t[-multiply_timetraps N]" @@ -555,8 +567,9 @@ script_usage() -> "\n\t[-silent_connections [ConnType1 ConnType2 .. ConnTypeN]]" "\n\t[-stylesheet CSSFile]" "\n\t[-cover CoverCfgFile]" - "\n\t[-event_handler EvHandler1 and EvHandler2 .. EvHandlerN]" - "\n\t[-ct_hooks CTHook1 and CTHook2 .. CTHookN]" + "\n\t[-event_handler EvHandler1 EvHandler2 .. EvHandlerN]" + "\n\t[-logopts LogOpt1 LogOpt2 .. LogOptN]" + "\n\t[-ct_hooks CTHook1 CTHook2 .. CTHookN]" "\n\t[-include InclDir1 InclDir2 .. InclDirN]" "\n\t[-no_auto_compile]" "\n\t[-multiply_timetraps N]" @@ -574,8 +587,9 @@ script_usage() -> "\n\t[-silent_connections [ConnType1 ConnType2 .. ConnTypeN]]" "\n\t[-stylesheet CSSFile]" "\n\t[-cover CoverCfgFile]" - "\n\t[-event_handler EvHandler1 and EvHandler2 .. EvHandlerN]" - "\n\t[-ct_hooks CTHook1 and CTHook2 .. CTHookN]" + "\n\t[-event_handler EvHandler1 EvHandler2 .. EvHandlerN]" + "\n\t[-logopts LogOpt1 LogOpt2 .. LogOptN]" + "\n\t[-ct_hooks CTHook1 CTHook2 .. CTHookN]" "\n\t[-include InclDir1 InclDir2 .. InclDirN]" "\n\t[-no_auto_compile]" "\n\t[-multiply_timetraps N]" @@ -690,6 +704,9 @@ run_test1(StartOpts) -> %% logdir LogDir = get_start_opt(logdir, fun(LD) when is_list(LD) -> LD end, StartOpts), + %% logopts + LogOpts = get_start_opt(logopts, value, [], StartOpts), + %% config & userconfig CfgFiles = ct_config:get_config_file_list(StartOpts), @@ -789,7 +806,8 @@ run_test1(StartOpts) -> Step = get_start_opt(step, value, StartOpts), Opts = #opts{label = Label, profile = Profile, - cover = Cover, step = Step, logdir = LogDir, config = CfgFiles, + cover = Cover, step = Step, logdir = LogDir, + logopts = LogOpts, config = CfgFiles, event_handlers = EvHandlers, ct_hooks = CTHooks, include = Include, @@ -834,6 +852,8 @@ run_spec_file(Relaxed, SpecOpts#opts.profile), LogDir = choose_val(Opts#opts.logdir, SpecOpts#opts.logdir), + AllLogOpts = merge_vals([Opts#opts.logopts, + SpecOpts#opts.logopts]), AllConfig = merge_vals([CfgFiles, SpecOpts#opts.config]), Cover = choose_val(Opts#opts.cover, SpecOpts#opts.cover), @@ -860,6 +880,7 @@ run_spec_file(Relaxed, profile = Profile, cover = Cover, logdir = which(logdir, LogDir), + logopts = AllLogOpts, config = AllConfig, event_handlers = AllEvHs, include = AllInclude, @@ -1089,6 +1110,7 @@ run_testspec1(TestSpec) -> get_data_for_node(#testspec{label = Labels, profile = Profiles, logdir = LogDirs, + logopts = LogOptsList, cover = CoverFs, config = Cfgs, userconfig = UsrCfgs, @@ -1103,6 +1125,10 @@ get_data_for_node(#testspec{label = Labels, undefined -> "."; Dir -> Dir end, + LogOpts = case proplists:get_value(Node, LogOptsList) of + undefined -> []; + LOs -> LOs + end, Cover = proplists:get_value(Node, CoverFs), MT = proplists:get_value(Node, MTs), ST = proplists:get_value(Node, STs), @@ -1114,6 +1140,7 @@ get_data_for_node(#testspec{label = Labels, #opts{label = Label, profile = Profile, logdir = LogDir, + logopts = LogOpts, cover = Cover, config = ConfigFiles, event_handlers = EvHandlers, @@ -1245,9 +1272,11 @@ tests(TestDirs) when is_list(TestDirs), is_list(hd(TestDirs)) -> [{?testdir(TestDir,all),all,all} || TestDir <- TestDirs]. do_run(Tests, Misc) when is_list(Misc) -> - do_run(Tests, Misc, "."). + do_run(Tests, Misc, ".", []). -do_run(Tests, Misc, LogDir) when is_list(Misc) -> +do_run(Tests, Misc, LogDir, LogOpts) when is_list(Misc), + is_list(LogDir), + is_list(LogOpts) -> Opts = case proplists:get_value(step, Misc) of undefined -> @@ -1262,9 +1291,9 @@ do_run(Tests, Misc, LogDir) when is_list(Misc) -> CoverFile -> Opts#opts{cover = CoverFile} end, - do_run(Tests, [], Opts1#opts{logdir = LogDir}, []). + do_run(Tests, [], Opts1#opts{logdir = LogDir}, []); -do_run(Tests, Skip, Opts, Args) -> +do_run(Tests, Skip, Opts, Args) when is_record(Opts, opts) -> #opts{label = Label, profile = Profile, cover = Cover} = Opts, %% label - used by ct_logs @@ -1319,6 +1348,8 @@ do_run(Tests, Skip, Opts, Args) -> _Pid -> %% save stylesheet info ct_util:set_testdata({stylesheet,Opts#opts.stylesheet}), + %% save logopts + ct_util:set_testdata({logopts,Opts#opts.logopts}), %% enable silent connections case Opts#opts.silent_connections of [] -> @@ -2339,6 +2370,8 @@ opts2args(EnvStartOpts) -> end, EHs), [_LastAnd|StrsR] = lists:reverse(lists:flatten(Strs)), [{event_handler_init,lists:reverse(StrsR)}]; + ({logopts,LOs}) when is_list(LOs) -> + [{logopts,[atom_to_list(LO) || LO <- LOs]}]; ({ct_hooks,[]}) -> []; ({ct_hooks,CTHs}) when is_list(CTHs) -> diff --git a/lib/common_test/src/ct_testspec.erl b/lib/common_test/src/ct_testspec.erl index d845358bb2..bf1dfa24ea 100644 --- a/lib/common_test/src/ct_testspec.erl +++ b/lib/common_test/src/ct_testspec.erl @@ -481,6 +481,26 @@ add_tests([{logdir,Node,Dir}|Ts],Spec) -> add_tests([{logdir,Dir}|Ts],Spec) -> add_tests([{logdir,all_nodes,Dir}|Ts],Spec); +%% --- logopts --- +add_tests([{logopts,all_nodes,Opts}|Ts],Spec) -> + LogOpts = Spec#testspec.logopts, + Tests = [{logopts,N,Opts} || + N <- list_nodes(Spec), + lists:keymember(ref2node(N,Spec#testspec.nodes),1, + LogOpts) == false], + add_tests(Tests++Ts,Spec); +add_tests([{logopts,Nodes,Opts}|Ts],Spec) when is_list(Nodes) -> + Ts1 = separate(Nodes,logopts,[Opts],Ts,Spec#testspec.nodes), + add_tests(Ts1,Spec); +add_tests([{logopts,Node,Opts}|Ts],Spec) -> + LogOpts = Spec#testspec.logopts, + LogOpts1 = [{ref2node(Node,Spec#testspec.nodes),Opts} | + lists:keydelete(ref2node(Node,Spec#testspec.nodes), + 1,LogOpts)], + add_tests(Ts,Spec#testspec{logopts=LogOpts1}); +add_tests([{logopts,Opts}|Ts],Spec) -> + add_tests([{logopts,all_nodes,Opts}|Ts],Spec); + %% --- label --- add_tests([{label,all_nodes,Lbl}|Ts],Spec) -> Labels = Spec#testspec.label, @@ -1097,6 +1117,8 @@ valid_terms() -> {merge_tests,1}, {logdir,2}, {logdir,3}, + {logopts,2}, + {logopts,3}, {label,2}, {label,3}, {event_handler,2}, diff --git a/lib/common_test/src/ct_util.hrl b/lib/common_test/src/ct_util.hrl index 09060f3e8b..73898fe371 100644 --- a/lib/common_test/src/ct_util.hrl +++ b/lib/common_test/src/ct_util.hrl @@ -33,6 +33,7 @@ label=[], profile=[], logdir=["."], + logopts=[], cover=[], config=[], userconfig=[], diff --git a/lib/common_test/src/vts.erl b/lib/common_test/src/vts.erl index f0bf090804..9eb11c23cc 100644 --- a/lib/common_test/src/vts.erl +++ b/lib/common_test/src/vts.erl @@ -20,7 +20,7 @@ -module(vts). -export([start/0, - init_data/4, + init_data/5, stop/0, report/2]). @@ -56,7 +56,7 @@ -record(state,{tests=[],config=[],event_handler=[],test_runner, running=0,reload_results=false,start_dir,current_log_dir, - total=0,ok=0,fail=0,skip=0,testruns=[]}). + logopts=[],total=0,ok=0,fail=0,skip=0,testruns=[]}). %%%----------------------------------------------------------------- @@ -65,8 +65,8 @@ start() -> webtool:start(), webtool:start_tools([],"app=vts"). -init_data(ConfigFiles,EvHandlers,LogDir,Tests) -> - call({init_data,ConfigFiles,EvHandlers,LogDir,Tests}). +init_data(ConfigFiles,EvHandlers,LogDir,LogOpts,Tests) -> + call({init_data,ConfigFiles,EvHandlers,LogDir,LogOpts,Tests}). stop() -> webtool:stop_tools([],"app=vts"), @@ -160,10 +160,11 @@ init(Parent) -> loop(State) -> receive - {{init_data,Config,EvHandlers,LogDir,Tests},From} -> + {{init_data,Config,EvHandlers,LogDir,LogOpts,Tests},From} -> %% ct:pal("State#state.current_log_dir=~p", [State#state.current_log_dir]), NewState = State#state{config=Config,event_handler=EvHandlers, - current_log_dir=LogDir,tests=Tests}, + current_log_dir=LogDir, + logopts=LogOpts,tests=Tests}, ct_install(NewState), return(From,ok), loop(NewState); @@ -270,10 +271,11 @@ return({To,Ref},Result) -> To ! {Ref, Result}. -run_test1(State=#state{tests=Tests,current_log_dir=LogDir}) -> +run_test1(State=#state{tests=Tests,current_log_dir=LogDir, + logopts=LogOpts}) -> Self=self(), RunTest = fun() -> - case ct_run:do_run(Tests,[],LogDir) of + case ct_run:do_run(Tests,[],LogDir,LogOpts) of {error,_Reason} -> aborted(); _ -> diff --git a/lib/test_server/src/test_server_ctrl.erl b/lib/test_server/src/test_server_ctrl.erl index 85686217f7..b7b25fcf72 100644 --- a/lib/test_server/src/test_server_ctrl.erl +++ b/lib/test_server/src/test_server_ctrl.erl @@ -1350,6 +1350,10 @@ init_tester(Mod, Func, Args, Dir, Name, {SumLev,MajLev,MinLev}, put(test_server_minor_level, MinLev), put(test_server_random_seed, proplists:get_value(random_seed, ExtraTools)), put(test_server_testcase_callback, TCCallback), + %% before first print, read and set logging options + LogOpts = test_server_sup:framework_call(get_logopts, [], []), + put(test_server_logopts, LogOpts), + put(test_server_log_nl, not lists:member(no_nl, LogOpts)), StartedExtraTools = start_extra_tools(ExtraTools), {TimeMy,Result} = ts_tc(Mod, Func, Args), put(test_server_common_io_handler, undefined), @@ -1889,11 +1893,12 @@ start_minor_log_file1(Mod, Func, LogDir, AbsName) -> []), SrcListing = downcase(cast_to_list(Mod)) ++ ?src_listing_ext, - case filelib:is_file(filename:join(LogDir, SrcListing)) of - true -> + case {filelib:is_file(filename:join(LogDir, SrcListing)), + lists:member(no_src, get(test_server_logopts))} of + {true,false} -> print(Lev, "source code for ~p:~p/1\n", [SrcListing,Func,Mod,Func]); - false -> ok + _ -> ok end, io:fwrite(Fd, "

\n", []),
@@ -2106,7 +2111,12 @@ run_test_cases(TestSpec, Config, TimetrapData) ->
 
     maybe_open_job_sock(),
 
-    html_convert_modules(TestSpec, Config),
+    case lists:member(no_src, get(test_server_logopts)) of
+	true ->
+	    ok;
+	false ->
+	    html_convert_modules(TestSpec, Config)
+    end,
 
     run_test_cases_loop(TestSpec, [Config], TimetrapData, [], []),
 
@@ -2315,7 +2325,8 @@ run_test_cases_loop([{auto_skip_case,{Type,Ref,Case,Comment},SkipMode}|Cases],
 		    handle_test_case_io_and_status(),
 		    set_io_buffering(undefined),
 		    {Mod,Func} = skip_case(auto, Ref, 0, Case, Comment, false, SkipMode),
-		    test_server_sup:framework_call(report, [tc_auto_skip,{?pl2a(Mod),Func,Comment}]),
+		    test_server_sup:framework_call(report, [tc_auto_skip,
+							    {?pl2a(Mod),Func,Comment}]),
 		    run_test_cases_loop(Cases, Config, TimetrapData, ParentMode,
 					delete_status(Ref, Status));
 		_ ->
@@ -2323,7 +2334,8 @@ run_test_cases_loop([{auto_skip_case,{Type,Ref,Case,Comment},SkipMode}|Cases],
 		    %% parallel group (io buffering is active)
 		    wait_for_cases(Ref),
 		    {Mod,Func} = skip_case(auto, Ref, 0, Case, Comment, true, SkipMode),
-		    test_server_sup:framework_call(report, [tc_auto_skip,{?pl2a(Mod),Func,Comment}]),
+		    test_server_sup:framework_call(report, [tc_auto_skip,
+							    {?pl2a(Mod),Func,Comment}]),
 		    case CurrIOHandler of
 			{Ref,_} ->
 			    %% current_io_handler was set by start conf of this
@@ -4350,14 +4362,18 @@ output_to_fd(Fd, [$=|Msg], internal) ->
     io:put_chars(Fd, [$=]),
     io:put_chars(Fd, Msg),
     io:put_chars(Fd, "\n");
+
 output_to_fd(Fd, Msg, internal) ->
     io:put_chars(Fd, [$=,$=,$=,$ ]),
     io:put_chars(Fd, Msg),
     io:put_chars(Fd, "\n");
+
 output_to_fd(Fd, Msg, _Sender) ->
     io:put_chars(Fd, Msg),
-    io:put_chars(Fd, "\n").
-
+    case get(test_server_log_nl) of
+	false -> ok;
+	_     -> io:put_chars(Fd, "\n")
+    end.
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %% timestamp_filename_get(Leader) -> string()
@@ -4670,7 +4686,7 @@ collect_case_invoke(Mod, Case, MFA, St) ->
 		    collect_subcases(Mod, Case, MFA, St, Suite)
 	    end;
 	_ ->
-	    Suite = test_server_sup:framework_call(get_suite, [?pl2a(Mod),Case],[]),
+	    Suite = test_server_sup:framework_call(get_suite, [?pl2a(Mod),Case], []),
 	    collect_subcases(Mod, Case, MFA, St, Suite)
     end.
 
-- 
cgit v1.2.3


From 8618bb8eab726ab5652b40751bdca928b49eca7f Mon Sep 17 00:00:00 2001
From: Peter Andersson 
Date: Thu, 14 Jul 2011 16:10:31 +0200
Subject: Fix incorrect module name arg to FW:end_tc/3

OTP-9379
---
 lib/common_test/src/ct_run.erl          | 3 ---
 lib/test_server/src/test_server.erl     | 4 ++--
 lib/test_server/src/test_server_sup.erl | 2 +-
 lib/test_server/src/ts_erl_config.erl   | 5 -----
 4 files changed, 3 insertions(+), 11 deletions(-)

(limited to 'lib')

diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl
index 4bb555bb9e..c3b0348b26 100644
--- a/lib/common_test/src/ct_run.erl
+++ b/lib/common_test/src/ct_run.erl
@@ -2195,9 +2195,6 @@ get_start_opt(Key, IfExists, IfNotExists, Args) ->
 	    exit({user_error,{bad_argument,Key}})
     end.
 
-try_get_start_opt(Key, IfExists, Args) ->
-    try_get_start_opt(Key, IfExists, undefined, Args).
-
 try_get_start_opt(Key, IfExists, IfNotExists, Args) ->
     case lists:keysearch(Key, 1, Args) of
 	{value,{Key,Val}} when is_function(IfExists) ->
diff --git a/lib/test_server/src/test_server.erl b/lib/test_server/src/test_server.erl
index 591329b361..d3fa3c8b87 100644
--- a/lib/test_server/src/test_server.erl
+++ b/lib/test_server/src/test_server.erl
@@ -1218,8 +1218,8 @@ do_end_tc_call(M,F,Res,Return) ->
 		    NewReturn
 	    end;
 	Other ->
-	    case test_server_sup:framework_call(
-		   end_tc, [Other,F,Res], Ref) of
+	    case test_server_sup:framework_call(Other, end_tc,
+						[?pl2a(M),F,Res], Ref) of
 		{fail,FWReason} ->
 		    {failed,FWReason};
 		_Else ->
diff --git a/lib/test_server/src/test_server_sup.erl b/lib/test_server/src/test_server_sup.erl
index 53dfb45e3a..e846a4c14a 100644
--- a/lib/test_server/src/test_server_sup.erl
+++ b/lib/test_server/src/test_server_sup.erl
@@ -26,7 +26,7 @@
 	 cleanup_crash_dumps/0, crash_dump_dir/0, tar_crash_dumps/0,
 	 get_username/0, get_os_family/0, 
 	 hostatom/0, hostatom/1, hoststr/0, hoststr/1,
-	 framework_call/2,framework_call/3,
+	 framework_call/2,framework_call/3,framework_call/4,
 	 format_loc/1, package_str/1, package_atom/1,
 	 call_trace/1]).
 -include("test_server_internal.hrl").
diff --git a/lib/test_server/src/ts_erl_config.erl b/lib/test_server/src/ts_erl_config.erl
index 640c8ddc9f..3b41f90d55 100644
--- a/lib/test_server/src/ts_erl_config.erl
+++ b/lib/test_server/src/ts_erl_config.erl
@@ -222,7 +222,6 @@ erl_interface(Vars,OsType) ->
 		end,
     CrossCompile = case OsType of
 		       vxworks -> "true";
-		       ose ->     "true";
 		       _ ->       "false"
 		   end,
     [{erl_interface_libpath, filename:nativename(LibPath)},
@@ -329,8 +328,6 @@ sock_libraries({win32, _}) ->
 sock_libraries({unix, _}) ->
     "";	% Included in general libraries if needed.
 sock_libraries(vxworks) ->
-    "";
-sock_libraries(ose) ->
     "".
 
 link_library(LibName,{win32, _}) ->
@@ -339,8 +336,6 @@ link_library(LibName,{unix, _}) ->
     "lib" ++ LibName ++ ".a";
 link_library(LibName,vxworks) ->
     "lib" ++ LibName ++ ".a";
-link_library(_LibName,ose) ->
-    "";
 link_library(_LibName,_Other) ->
     exit({link_library, not_supported}).
 
-- 
cgit v1.2.3


From bd56af6214c451b9c7d0ab455b2597021299ecaa Mon Sep 17 00:00:00 2001
From: Peter Andersson 
Date: Thu, 14 Jul 2011 16:56:36 +0200
Subject: Introduce new framework callback function to read info about color of
 comments

OTP-9237
---
 lib/common_test/src/ct_framework.erl     | 9 +++++++--
 lib/test_server/src/test_server.erl      | 9 ++++++---
 lib/test_server/src/test_server_ctrl.erl | 7 +++++--
 3 files changed, 18 insertions(+), 7 deletions(-)

(limited to 'lib')

diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl
index 0910b39b72..a683822977 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, report/2, warn/1]).
 -export([error_notification/4]).
 
--export([get_logopts/0, overview_html_header/1]).
+-export([get_logopts/0, format_comment/1, overview_html_header/1]).
 
 -export([error_in_suite/1, ct_init_per_group/2, ct_end_per_group/2]).
 
@@ -1334,7 +1334,7 @@ add_data_dir(File,Config) when is_list(File) ->
     end.
 
 %%%-----------------------------------------------------------------
-%%% @spec get_logopts
+%%% @spec get_logopts() -> [LogOpt]
 get_logopts() ->
     case ct_util:get_testdata(logopts) of
 	undefined ->
@@ -1343,6 +1343,11 @@ get_logopts() ->
 	    LogOpts
     end.
 
+%%%-----------------------------------------------------------------
+%%% @spec format_comment(Comment) -> HtmlComment
+format_comment(Comment) ->
+    "" ++ Comment ++ "".
+
 %%%-----------------------------------------------------------------
 %%% @spec overview_html_header(TestName) -> Header
 overview_html_header(TestName) ->
diff --git a/lib/test_server/src/test_server.erl b/lib/test_server/src/test_server.erl
index d3fa3c8b87..f5f795e082 100644
--- a/lib/test_server/src/test_server.erl
+++ b/lib/test_server/src/test_server.erl
@@ -733,14 +733,18 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) ->
 	    print(Detail,Format,Args),
 	    run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
 	{comment,NewComment} ->
+	    NewComment1 = test_server_ctrl:to_string(NewComment),
+	    NewComment2 = test_server_sup:framework_call(format_comment,
+							 [NewComment1],
+							 NewComment1),
 	    Terminate1 =
 		case Terminate of
 		    {true,{Time,Value,Loc,Opts,_OldComment}} ->
-			{true,{Time,Value,mod_loc(Loc),Opts,NewComment}};
+			{true,{Time,Value,mod_loc(Loc),Opts,NewComment2}};
 		    Other ->
 			Other
 		end,
-	    run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate1,NewComment,CurrConf);
+	    run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate1,NewComment2,CurrConf);
 	{set_curr_conf,NewCurrConf} ->
 	    run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,NewCurrConf);
 	{'EXIT',Pid,{Ref,Time,Value,Loc,Opts}} ->
@@ -2283,7 +2287,6 @@ comment(String) ->
     group_leader() ! {comment,String},
     ok.
 
-
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %% os_type() -> OsType
 %%
diff --git a/lib/test_server/src/test_server_ctrl.erl b/lib/test_server/src/test_server_ctrl.erl
index b7b25fcf72..7554a31530 100644
--- a/lib/test_server/src/test_server_ctrl.erl
+++ b/lib/test_server/src/test_server_ctrl.erl
@@ -173,7 +173,7 @@
 %%% TEST_SERVER INTERFACE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 -export([output/2, print/2, print/3, print_timestamp/2]).
 -export([start_node/3, stop_node/1, wait_for_node/1, is_release_available/1]).
--export([format/1, format/2, format/3]).
+-export([format/1, format/2, format/3, to_string/1]).
 -export([get_target_info/0]).
 -export([get_hosts/0]).
 -export([get_target_os_type/0]).
@@ -3976,8 +3976,11 @@ progress(ok, _CaseNum, Mod, Func, _Loc, RetVal, Time,
 	case RetVal of
 	    {comment,RetComment} ->
 		String = to_string(RetComment),
+		HtmlCmt = test_server_sup:framework_call(format_comment,
+							 [String],
+							 String),
 		print(major, "=result        ok: ~s", [String]),
-		"" ++ String ++ "";
+		"" ++ HtmlCmt ++ "";
 	    _ ->
 		print(major, "=result        ok", []),
 		case Comment0 of
-- 
cgit v1.2.3


From f7ed0bf5212de281c4456f8ec7735ff22a06c371 Mon Sep 17 00:00:00 2001
From: Peter Andersson 
Date: Thu, 14 Jul 2011 17:55:53 +0200
Subject: Fix error with incorrect test case status when end_per_testcase times
 out

OTP-9397
---
 lib/test_server/src/test_server.erl | 117 +++++++++++++++++++++---------------
 1 file changed, 67 insertions(+), 50 deletions(-)

(limited to 'lib')

diff --git a/lib/test_server/src/test_server.erl b/lib/test_server/src/test_server.erl
index f5f795e082..52fb4fba6b 100644
--- a/lib/test_server/src/test_server.erl
+++ b/lib/test_server/src/test_server.erl
@@ -757,7 +757,7 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) ->
 		    case mod_loc(Loc) of
 			{FwMod,FwFunc,framework} ->
 			    %% timout during framework call
-			    spawn_fw_call(FwMod,FwFunc,Pid,
+			    spawn_fw_call(FwMod,FwFunc,CurrConf,Pid,
 					  {framework_error,{timetrap,TVal}},
 					  unknown,self(),Comment),
 			    run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,
@@ -783,7 +783,8 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) ->
 					%% group leader process or io will cause deadlock,
 					%% so we spawn a dedicated process for the operation
 					%% and let the group leader go back to handle io.
-					spawn_fw_call(Mod,Func,Pid,{timetrap_timeout,TVal},
+					spawn_fw_call(Mod,Func,CurrConf,Pid,
+						      {timetrap_timeout,TVal},
 						      Loc1,self(),Comment),
 					undefined
 				end,
@@ -794,12 +795,13 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) ->
 		    case mod_loc(Loc) of
 			{FwMod,FwFunc,framework} ->
 			    %% timout during framework call
-			    spawn_fw_call(FwMod,FwFunc,Pid,
+			    spawn_fw_call(FwMod,FwFunc,CurrConf,Pid,
 					  {framework_error,{timetrap,TVal}},
 					  unknown,self(),Comment);
 			Loc1 ->
 			    {Mod,_Func} = get_mf(Loc1),
-			    spawn_fw_call(Mod,InitOrEnd,Pid,{timetrap_timeout,TVal},
+			    spawn_fw_call(Mod,InitOrEnd,CurrConf,Pid,
+					  {timetrap_timeout,TVal},
 					  Loc1,self(),Comment)
 		    end,
 		    run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
@@ -808,7 +810,7 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) ->
 		    case mod_loc(AbortLoc) of
 			{FwMod,FwFunc,framework} ->
 			    %% abort during framework call
-			    spawn_fw_call(FwMod,FwFunc,Pid,
+			    spawn_fw_call(FwMod,FwFunc,CurrConf,Pid,
 					  {framework_error,ErrorMsg},
 					  unknown,self(),Comment),
 			    run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,
@@ -832,7 +834,7 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) ->
 							  TVal),
 					{EndConfPid,{Mod,Func},Conf};
 				    _ ->
-					spawn_fw_call(Mod,Func,Pid,ErrorMsg,
+					spawn_fw_call(Mod,Func,CurrConf,Pid,ErrorMsg,
 						      Loc1,self(),Comment),
 					undefined
 				end,
@@ -843,17 +845,18 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) ->
 		    %% result of an exit(TestCase,kill) call, which is the
 		    %% only way to abort a testcase process that traps exits
 		    %% (see abort_current_testcase)
-		    spawn_fw_call(undefined,undefined,Pid,testcase_aborted_or_killed,
+		    spawn_fw_call(undefined,undefined,CurrConf,Pid,
+				  testcase_aborted_or_killed,
 				  unknown,self(),Comment),
 		    run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
 		{fw_error,{FwMod,FwFunc,FwError}} ->
-		    spawn_fw_call(FwMod,FwFunc,Pid,{framework_error,FwError},
+		    spawn_fw_call(FwMod,FwFunc,CurrConf,Pid,{framework_error,FwError},
 				  unknown,self(),Comment),
 		    run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
 		_Other ->
 		    %% the testcase has terminated because of Reason (e.g. an exit
 		    %% because a linked process failed)
-		    spawn_fw_call(undefined,undefined,Pid,Reason,
+		    spawn_fw_call(undefined,undefined,CurrConf,Pid,Reason,
 				  unknown,self(),Comment),
 		    run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf)
 	    end;
@@ -861,7 +864,7 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) ->
 	    case CurrConf of
 		{EndConfPid,{Mod,Func},_Conf} ->
 		    {_Mod,_Func,TCPid,TCExitReason,Loc} = Data,
-		    spawn_fw_call(Mod,Func,TCPid,TCExitReason,Loc,self(),Comment),
+		    spawn_fw_call(Mod,Func,CurrConf,TCPid,TCExitReason,Loc,self(),Comment),
 		    run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,undefined);
 		_ ->
 		    run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf)
@@ -932,7 +935,7 @@ call_end_conf(Mod,Func,TCPid,TCExitReason,Loc,Conf,TVal) ->
 				    ok
 			    end,
 			    Supervisor ! {self(),end_conf}
-		       end,
+		    end,
 		Pid = spawn_link(EndConfApply),
 		receive
 		    {Pid,end_conf} ->
@@ -945,50 +948,59 @@ call_end_conf(Mod,Func,TCPid,TCExitReason,Loc,Conf,TVal) ->
 	end,
     spawn_link(EndConfProc).
 
-spawn_fw_call(Mod,{init_per_testcase,Func},Pid,{timetrap_timeout,TVal}=Why,
+spawn_fw_call(Mod,{init_per_testcase,Func},_,Pid,{timetrap_timeout,TVal}=Why,
 	      Loc,SendTo,Comment) ->
     FwCall =
 	fun() ->
-	    Skip = {skip,{failed,{Mod,init_per_testcase,Why}}},
-	    %% if init_per_testcase fails, the test case
-	    %% should be skipped
-	    case catch do_end_tc_call(Mod,Func,{Pid,Skip,[[]]},Why) of
-		{'EXIT',FwEndTCErr} ->
-		    exit({fw_notify_done,end_tc,FwEndTCErr});
-		_ ->
-		    ok
-	    end,
-	    %% finished, report back
-	    SendTo ! {self(),fw_notify_done,
-		      {TVal/1000,Skip,Loc,[],Comment}}
+		Skip = {skip,{failed,{Mod,init_per_testcase,Why}}},
+		%% if init_per_testcase fails, the test case
+		%% should be skipped
+		case catch do_end_tc_call(Mod,Func,{Pid,Skip,[[]]},Why) of
+		    {'EXIT',FwEndTCErr} ->
+			exit({fw_notify_done,end_tc,FwEndTCErr});
+		    _ ->
+			ok
+		end,
+		%% finished, report back
+		SendTo ! {self(),fw_notify_done,
+			  {TVal/1000,Skip,Loc,[],Comment}}
 	end,
     spawn_link(FwCall);
 
-spawn_fw_call(Mod,{end_per_testcase,Func},Pid,{timetrap_timeout,TVal}=Why,
-	      Loc,SendTo,_Comment) ->
+spawn_fw_call(Mod,{end_per_testcase,Func},EndConf,Pid,
+	      {timetrap_timeout,TVal}=Why,_Loc,SendTo,Comment) ->
     FwCall =
 	fun() ->
-	    Conf = [{tc_status,ok}],
-	    %% if end_per_testcase fails, the test case should be
-	    %% reported successful with a warning printed as comment
-	    case catch do_end_tc_call(Mod,Func,{Pid,
-						{failed,{Mod,end_per_testcase,Why}},
-						[Conf]}, Why) of
-		{'EXIT',FwEndTCErr} ->
-		    exit({fw_notify_done,end_tc,FwEndTCErr});
-		_ ->
-		    ok
-	    end,
-	    %% finished, report back
-	    SendTo ! {self(),fw_notify_done,
-		      {TVal/1000,{error,{Mod,end_per_testcase,Why}},Loc,[],
-		       [""
-			"WARNING: end_per_testcase timed out!"
-			""]}}
+		%% if end_per_testcase fails a warning should be
+		%% printed as comment
+		case catch do_end_tc_call(Mod,Func,{Pid,
+						    {failed,{Mod,
+							     end_per_testcase,
+							     Why}},
+						    [EndConf]}, Why) of
+		    {'EXIT',FwEndTCErr} ->
+			exit({fw_notify_done,end_tc,FwEndTCErr});
+		    _ ->
+			ok
+		end,
+		RetVal = case proplists:get_value(tc_status, EndConf) of
+			     undefined -> {failed,{Mod,end_per_testcase,Why}};
+			     Result -> Result
+			 end,
+		FailLoc = proplists:get_value(tc_fail_loc, EndConf),
+		Comment1 = if Comment == "" -> "";
+			      true -> Comment ++ "
" + end, + %% finished, report back + SendTo ! {self(),fw_notify_done, + {TVal/1000,RetVal,FailLoc,[], + [Comment1,"" + "WARNING: end_per_testcase timed out!" + ""]}} end, spawn_link(FwCall); -spawn_fw_call(FwMod,FwFunc,_Pid,{framework_error,FwError},_,SendTo,_Comment) -> +spawn_fw_call(FwMod,FwFunc,_,_Pid,{framework_error,FwError},_,SendTo,_Comment) -> FwCall = fun() -> test_server_sup:framework_call(report, [framework_error, @@ -1003,7 +1015,7 @@ spawn_fw_call(FwMod,FwFunc,_Pid,{framework_error,FwError},_,SendTo,_Comment) -> end, spawn_link(FwCall); -spawn_fw_call(Mod,Func,Pid,Error,Loc,SendTo,Comment) -> +spawn_fw_call(Mod,Func,_,Pid,Error,Loc,SendTo,Comment) -> FwCall = fun() -> case catch fw_error_notify(Mod,Func,[], @@ -1140,25 +1152,28 @@ run_test_case_eval1(Mod, Func, Args, Name, RunInit, TCCallback) -> {EndConf,TSReturn,FWReturn} = case Return of {E,TCError} when E=='EXIT' ; E==failed -> + ModLoc = mod_loc(Loc), fw_error_notify(Mod, Func, NewConf1, - TCError, mod_loc(Loc)), - {[{tc_status,{failed,TCError}}|NewConf1], + TCError, ModLoc), + {[{tc_status,{failed,TCError}}, + {tc_fail_loc,ModLoc}|NewConf1], Return,{error,TCError}}; SaveCfg={save_config,_} -> {[{tc_status,ok},SaveCfg|NewConf1],Return,ok}; {skip_and_save,Why,SaveCfg} -> Skip = {skip,Why}, - {[{tc_status,{skipped,Why}},{save_config,SaveCfg}|NewConf1], + {[{tc_status,{skipped,Why}}, + {save_config,SaveCfg}|NewConf1], Skip,Skip}; {skip,Why} -> {[{tc_status,{skipped,Why}}|NewConf1],Return,Return}; _ -> {[{tc_status,ok}|NewConf1],Return,ok} end, - %% clear current state in controller loop - group_leader() ! {set_curr_conf,undefined}, %% call user callback function if defined EndConf1 = user_callback(TCCallback, Mod, Func, 'end', EndConf), + %% update current state in controller loop + group_leader() ! {set_curr_conf,EndConf1}, {FWReturn1,TSReturn1,EndConf2} = case end_per_testcase(Mod, Func, EndConf1) of SaveCfg1={save_config,_} -> @@ -1172,6 +1187,8 @@ run_test_case_eval1(Mod, Func, Args, Name, RunInit, TCCallback) -> _ -> {FWReturn,TSReturn,EndConf1} end, + %% clear current state in controller loop + group_leader() ! {set_curr_conf,undefined}, put(test_server_init_or_end_conf,undefined), case do_end_tc_call(Mod, Func, {FWReturn1,[EndConf2]}, TSReturn1) of {failed,Reason} = NewReturn -> -- cgit v1.2.3 From 16eaecc29b5f314fbc8f60880688049bcf074896 Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Fri, 15 Jul 2011 00:41:43 +0200 Subject: Fix problem with end_tc being called with incorrect Suite argument OTP-9398: Fix error with end_tc being called with incorrect Suite argument after timeout in lib function OTP-9397: Fix problem with true error not reported to FW --- lib/common_test/src/ct_framework.erl | 3 + lib/test_server/src/test_server.erl | 118 +++++++++++++++++++++++------------ 2 files changed, 80 insertions(+), 41 deletions(-) (limited to 'lib') diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl index a683822977..375e2875e0 100644 --- a/lib/common_test/src/ct_framework.erl +++ b/lib/common_test/src/ct_framework.erl @@ -452,6 +452,9 @@ end_tc(Mod,Func,TCPid,Result,Args,Return) -> false -> ok end, +%%! --- Thu Jul 14 23:45:00 2011 --- peppe was here! + io:format(user, "MOD:FUNC = ~p:~p = ~p~n", [Mod,Func,Result]), + %% save the testcase process pid so that it can be used %% to look up the attached trace window later case ct_util:get_testdata(interpret) of diff --git a/lib/test_server/src/test_server.erl b/lib/test_server/src/test_server.erl index 52fb4fba6b..337bc1d6d7 100644 --- a/lib/test_server/src/test_server.erl +++ b/lib/test_server/src/test_server.erl @@ -955,7 +955,7 @@ spawn_fw_call(Mod,{init_per_testcase,Func},_,Pid,{timetrap_timeout,TVal}=Why, Skip = {skip,{failed,{Mod,init_per_testcase,Why}}}, %% if init_per_testcase fails, the test case %% should be skipped - case catch do_end_tc_call(Mod,Func,{Pid,Skip,[[]]},Why) of + case catch do_end_tc_call(Mod,Func, Loc, {Pid,Skip,[[]]}, Why) of {'EXIT',FwEndTCErr} -> exit({fw_notify_done,end_tc,FwEndTCErr}); _ -> @@ -971,23 +971,26 @@ spawn_fw_call(Mod,{end_per_testcase,Func},EndConf,Pid, {timetrap_timeout,TVal}=Why,_Loc,SendTo,Comment) -> FwCall = fun() -> - %% if end_per_testcase fails a warning should be - %% printed as comment - case catch do_end_tc_call(Mod,Func,{Pid, - {failed,{Mod, - end_per_testcase, - Why}}, - [EndConf]}, Why) of + {RetVal,Report} = + case proplists:get_value(tc_status, EndConf) of + undefined -> + E = {failed,{Mod,end_per_testcase,Why}}, + {E,E}; + E = {failed,Reason} -> + {E,{error,Reason}}; + Result -> + {Result,Result} + end, + FailLoc = proplists:get_value(tc_fail_loc, EndConf), + case catch do_end_tc_call(Mod,Func, FailLoc, + {Pid,Report,[EndConf]}, Why) of {'EXIT',FwEndTCErr} -> exit({fw_notify_done,end_tc,FwEndTCErr}); _ -> ok end, - RetVal = case proplists:get_value(tc_status, EndConf) of - undefined -> {failed,{Mod,end_per_testcase,Why}}; - Result -> Result - end, - FailLoc = proplists:get_value(tc_fail_loc, EndConf), + %% if end_per_testcase fails a warning should be + %% printed as comment Comment1 = if Comment == "" -> ""; true -> Comment ++ "
" end, @@ -1027,7 +1030,8 @@ spawn_fw_call(Mod,Func,_,Pid,Error,Loc,SendTo,Comment) -> ok end, Conf = [{tc_status,{failed,timetrap_timeout}}], - case catch do_end_tc_call(Mod,Func,{Pid,Error,[Conf]},Error) of + case catch do_end_tc_call(Mod,Func, Loc, + {Pid,Error,[Conf]},Error) of {'EXIT',FwEndTCErr} -> exit({fw_notify_done,end_tc,FwEndTCErr}); _ -> @@ -1097,22 +1101,26 @@ run_test_case_eval(Mod, Func, Args0, Name, Ref, RunInit, {ok,Args} -> run_test_case_eval1(Mod, Func, Args, Name, RunInit, TCCallback); Error = {error,_Reason} -> - NewResult = do_end_tc_call(Mod,Func,{Error,Args0}, + Where = {Mod,Func}, + NewResult = do_end_tc_call(Mod,Func, Where, {Error,Args0}, {skip,{failed,Error}}), - {{0,NewResult},{Mod,Func},[]}; + {{0,NewResult},Where,[]}; {fail,Reason} -> Conf = [{tc_status,{failed,Reason}} | hd(Args0)], + Where = {Mod,Func}, fw_error_notify(Mod, Func, Conf, Reason), - NewResult = do_end_tc_call(Mod,Func, {{error,Reason},[Conf]}, + NewResult = do_end_tc_call(Mod,Func, Where, {{error,Reason},[Conf]}, {fail,Reason}), - {{0,NewResult},{Mod,Func},[]}; + {{0,NewResult},Where,[]}; Skip = {skip,_Reason} -> - NewResult = do_end_tc_call(Mod,Func,{Skip,Args0},Skip), - {{0,NewResult},{Mod,Func},[]}; + Where = {Mod,Func}, + NewResult = do_end_tc_call(Mod,Func, Where, {Skip,Args0}, Skip), + {{0,NewResult},Where,[]}; {auto_skip,Reason} -> - NewResult = do_end_tc_call(Mod, Func, {{skip,Reason},Args0}, + Where = {Mod,Func}, + NewResult = do_end_tc_call(Mod,Func, Where, {{skip,Reason},Args0}, {skip,{fw_auto_skip,Reason}}), - {{0,NewResult},{Mod,Func},[]} + {{0,NewResult},Where,[]} end, exit({Ref,Time,Value,Loc,Opts}). @@ -1126,18 +1134,19 @@ run_test_case_eval1(Mod, Func, Args, Name, RunInit, TCCallback) -> Skip = {skip,Reason} -> Line = get_loc(), Conf = [{tc_status,{skipped,Reason}}], - NewRes = do_end_tc_call(Mod,Func,{Skip,[Conf]}, Skip), + NewRes = do_end_tc_call(Mod,Func, Line, {Skip,[Conf]}, Skip), {{0,NewRes},Line,[]}; {skip_and_save,Reason,SaveCfg} -> Line = get_loc(), Conf = [{tc_status,{skipped,Reason}},{save_config,SaveCfg}], - NewRes = do_end_tc_call(Mod, Func, {{skip,Reason},[Conf]}, - {skip, Reason}), + NewRes = do_end_tc_call(Mod,Func, Line, {{skip,Reason},[Conf]}, + {skip,Reason}), {{0,NewRes},Line,[]}; FailTC = {fail,Reason} -> % user fails the testcase EndConf = [{tc_status,{failed,Reason}} | hd(Args)], fw_error_notify(Mod, Func, EndConf, Reason), - NewRes = do_end_tc_call(Mod, Func, {{error,Reason},[EndConf]}, + NewRes = do_end_tc_call(Mod,Func, {Mod,Func}, + {{error,Reason},[EndConf]}, FailTC), {{0,NewRes},{Mod,Func},[]}; {ok,NewConf} -> @@ -1190,7 +1199,8 @@ run_test_case_eval1(Mod, Func, Args, Name, RunInit, TCCallback) -> %% clear current state in controller loop group_leader() ! {set_curr_conf,undefined}, put(test_server_init_or_end_conf,undefined), - case do_end_tc_call(Mod, Func, {FWReturn1,[EndConf2]}, TSReturn1) of + case do_end_tc_call(Mod,Func, Loc, + {FWReturn1,[EndConf2]}, TSReturn1) of {failed,Reason} = NewReturn -> fw_error_notify(Mod,Func,EndConf2, Reason), {{T,NewReturn},{Mod,Func},[]}; @@ -1218,14 +1228,39 @@ run_test_case_eval1(Mod, Func, Args, Name, RunInit, TCCallback) -> {{T,Return2},Loc,Opts} end. -do_end_tc_call(M,F,Res,Return) -> +do_end_tc_call(M,F, Loc, Res, Return) -> + FwMod = os:getenv("TEST_SERVER_FRAMEWORK"), + {Mod,Func} = + if FwMod == M ; FwMod == "undefined"; FwMod == false -> + {M,F}; + is_list(Loc) and (length(Loc)>1) -> + %% If failure in other module (M) than suite, try locate + %% suite name in Loc list and call end_tc with Suite:TestCase + %% instead of M:F. + GetSuite = fun(S,TC) -> + case lists:reverse(atom_to_list(S)) of + [$E,$T,$I,$U,$S,$_|_] -> [{S,TC}]; + _ -> [] + end + end, + case lists:flatmap(fun({S,TC,_}) -> GetSuite(S,TC); + ({{S,TC},_}) -> GetSuite(S,TC); + ({S,TC}) -> GetSuite(S,TC); + (_) -> [] + end, Loc) of + [] -> + {M,F}; + [FoundSuite|_] -> + FoundSuite + end; + true -> + {M,F} + end, + Ref = make_ref(), - case os:getenv("TEST_SERVER_FRAMEWORK") of - FW when FW == "ct_framework"; - FW == "undefined"; - FW == false -> + if FwMod == "ct_framework" ; FwMod == "undefined"; FwMod == false -> case test_server_sup:framework_call( - end_tc, [?pl2a(M),F,Res, Return], ok) of + end_tc, [?pl2a(Mod),Func,Res, Return], ok) of {fail,FWReason} -> {failed,FWReason}; ok -> @@ -1238,9 +1273,9 @@ do_end_tc_call(M,F,Res,Return) -> NewReturn -> NewReturn end; - Other -> - case test_server_sup:framework_call(Other, end_tc, - [?pl2a(M),F,Res], Ref) of + true -> + case test_server_sup:framework_call(FwMod, end_tc, + [?pl2a(Mod),Func,Res], Ref) of {fail,FWReason} -> {failed,FWReason}; _Else -> @@ -1263,7 +1298,7 @@ process_return_val([Return], M,F,A, Loc, Final) when is_list(Return) -> true -> % must be return value from end conf case process_return_val1(Return, M,F,A, Loc, Final, []); false -> % must be Config value from init conf case - case do_end_tc_call(M,F,{ok,A}, Return) of + case do_end_tc_call(M, F, Loc, {ok,A}, Return) of {failed, FWReason} = Failed -> fw_error_notify(M,F,A, FWReason), {Failed, []}; @@ -1280,8 +1315,9 @@ process_return_val1([Failed={E,TCError}|_], M,F,A=[Args], Loc, _, SaveOpts) when E=='EXIT'; E==failed -> fw_error_notify(M,F,A, TCError, mod_loc(Loc)), - case do_end_tc_call(M,F,{{error,TCError}, - [[{tc_status,{failed,TCError}}|Args]]}, Failed) of + case do_end_tc_call(M,F, Loc, {{error,TCError}, + [[{tc_status,{failed,TCError}}|Args]]}, + Failed) of {failed,FWReason} -> {{failed,FWReason},SaveOpts}; NewReturn -> @@ -1298,8 +1334,8 @@ process_return_val1([RetVal={Tag,_}|Opts], M,F,A, Loc, _, SaveOpts) when Tag==sk process_return_val1(Opts, M,F,A, Loc, RetVal, SaveOpts); process_return_val1([_|Opts], M,F,A, Loc, Final, SaveOpts) -> process_return_val1(Opts, M,F,A, Loc, Final, SaveOpts); -process_return_val1([], M,F,A, _Loc, Final, SaveOpts) -> - case do_end_tc_call(M,F,{Final,A}, Final) of +process_return_val1([], M,F,A, Loc, Final, SaveOpts) -> + case do_end_tc_call(M,F, Loc, {Final,A}, Final) of {failed,FWReason} -> {{failed,FWReason},SaveOpts}; NewReturn -> -- cgit v1.2.3 From 8d9b760e7fafec40787be6de5994240f1540d12a Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Fri, 15 Jul 2011 14:38:51 +0200 Subject: Fix problem with incorrect src links OTP-9396 --- lib/common_test/src/ct_framework.erl | 4 ---- lib/test_server/src/test_server_sup.erl | 10 ++++++---- 2 files changed, 6 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl index 375e2875e0..b730f1e46e 100644 --- a/lib/common_test/src/ct_framework.erl +++ b/lib/common_test/src/ct_framework.erl @@ -451,10 +451,6 @@ end_tc(Mod,Func,TCPid,Result,Args,Return) -> {value,{watchdog,Dog}} -> test_server:timetrap_cancel(Dog); false -> ok end, - -%%! --- Thu Jul 14 23:45:00 2011 --- peppe was here! - io:format(user, "MOD:FUNC = ~p:~p = ~p~n", [Mod,Func,Result]), - %% save the testcase process pid so that it can be used %% to look up the attached trace window later case ct_util:get_testdata(interpret) of diff --git a/lib/test_server/src/test_server_sup.erl b/lib/test_server/src/test_server_sup.erl index e846a4c14a..77d364d5cb 100644 --- a/lib/test_server/src/test_server_sup.erl +++ b/lib/test_server/src/test_server_sup.erl @@ -540,8 +540,9 @@ format_loc({Mod,Func}) when is_atom(Func) -> format_loc({Mod,Line}) when is_integer(Line) -> %% ?line macro is used ModStr = package_str(Mod), - case lists:reverse(ModStr) of - [$E,$T,$I,$U,$S,$_|_] -> + case {lists:member(no_src, get(test_server_logopts)), + lists:reverse(ModStr)} of + {false,[$E,$T,$I,$U,$S,$_|_]} -> io_lib:format("{~s,~w}", [ModStr,downcase(ModStr),?src_listing_ext, round_to_10(Line),Line]); @@ -557,8 +558,9 @@ format_loc1([{Mod,Func,Line}|Rest]) -> [" ",format_loc1({Mod,Func,Line}),",\n"|format_loc1(Rest)]; format_loc1({Mod,Func,Line}) -> ModStr = package_str(Mod), - case lists:reverse(ModStr) of - [$E,$T,$I,$U,$S,$_|_] -> + case {lists:member(no_src, get(test_server_logopts)), + lists:reverse(ModStr)} of + {false,[$E,$T,$I,$U,$S,$_|_]} -> io_lib:format("{~s,~w,~w}", [ModStr,Func,downcase(ModStr),?src_listing_ext, round_to_10(Line),Line]); -- cgit v1.2.3 From 6668a91b365b8390d8eb369f7d6c6294711a1fef Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Thu, 1 Sep 2011 16:32:36 +0200 Subject: Various corrections and updates to improve error handling and reporting OTP-8933 --- lib/common_test/doc/src/config_file_chapter.xml | 6 +-- lib/common_test/src/ct_config.erl | 40 ++++++++--------- lib/common_test/src/ct_config_plain.erl | 24 ++++++----- lib/common_test/src/ct_config_xml.erl | 48 ++++++++++----------- lib/common_test/src/ct_framework.erl | 19 ++++++++- lib/common_test/src/ct_logs.erl | 4 +- lib/common_test/src/ct_run.erl | 57 +++++++++++++++++++------ lib/common_test/src/ct_testspec.erl | 8 +++- lib/common_test/src/ct_util.erl | 24 ++++++++--- 9 files changed, 148 insertions(+), 82 deletions(-) (limited to 'lib') diff --git a/lib/common_test/doc/src/config_file_chapter.xml b/lib/common_test/doc/src/config_file_chapter.xml index 59151a73ec..6fc6638bf7 100644 --- a/lib/common_test/doc/src/config_file_chapter.xml +++ b/lib/common_test/doc/src/config_file_chapter.xml @@ -285,7 +285,7 @@ {ok, Config} - if the configuration variables are read successfully, - {error, Error, ErrorDetails} - if the callback module fails to + {error, {Error, ErrorDetails}} - if the callback module fails to proceed with the given configuration parameters. @@ -422,14 +422,14 @@ stop()-> call(Client, Request)-> case whereis(?REGISTERED_NAME) of undefined-> - {error, not_started, Request}; + {error, {not_started, Request}}; Pid-> Pid ! {Client, Request}, receive Reply-> {ok, Reply} after 4000-> - {error, timeout, Request} + {error, {timeout, Request}} end end. diff --git a/lib/common_test/src/ct_config.erl b/lib/common_test/src/ct_config.erl index 6b75937668..fc51aea7f3 100644 --- a/lib/common_test/src/ct_config.erl +++ b/lib/common_test/src/ct_config.erl @@ -204,9 +204,9 @@ get_config_file_list(Opts) -> DefaultConfigs = process_default_configs(Opts), CfgFiles = if - DefaultConfigs == []-> + DefaultConfigs == [] -> []; - true-> + true -> [{?ct_config_txt, DefaultConfigs}] end ++ process_user_configs(Opts, []), @@ -240,12 +240,12 @@ read_config_files(Opts) -> end, ConfigFiles = case lists:keyfind(config, 1, Opts) of - {config,ConfigLists}-> + {config,ConfigLists} -> lists:foldr(fun({Callback,Files}, Acc) -> AddCallback(Callback,Files) ++ Acc end,[],ConfigLists); - false-> + false -> [] end, read_config_files_int(ConfigFiles, fun store_config/3). @@ -255,7 +255,9 @@ read_config_files_int([{Callback, File}|Files], FunToSave) -> {ok, Config} -> FunToSave(Config, Callback, File), read_config_files_int(Files, FunToSave); - {error, ErrorName, ErrorDetail}-> + {error, {ErrorName, ErrorDetail}} -> + {user_error, {ErrorName, File, ErrorDetail}}; + {error, ErrorName, ErrorDetail} -> {user_error, {ErrorName, File, ErrorDetail}} end; read_config_files_int([], _FunToSave) -> @@ -283,7 +285,7 @@ rewrite_config(Config, Callback, File) -> config=File,_='_'}), Updater = fun({Key, Value}) -> case keyfindall(Key, #ct_conf.key, OldRows) of - []-> + [] -> ets:insert(?attr_table, #ct_conf{key=Key, value=Value, @@ -453,9 +455,9 @@ update_conf(Name, NewConfig) -> reload_conf(KeyOrName) -> case lookup_handler_for_config(KeyOrName) of - []-> + [] -> undefined; - HandlerList-> + HandlerList -> HandlerList2 = lists:usort(HandlerList), read_config_files_int(HandlerList2, fun rewrite_config/3), get_config(KeyOrName) @@ -711,13 +713,13 @@ random_bytes_1(N, Acc) -> random_bytes_1(N-1, [random:uniform(255)|Acc]). check_callback_load(Callback) -> case code:is_loaded(Callback) of - {file, _Filename}-> + {file, _Filename} -> check_exports(Callback); - false-> + false -> case code:load_file(Callback) of - {module, Callback}-> + {module, Callback} -> check_exports(Callback); - {error, Error}-> + {error, Error} -> {error, Error} end end. @@ -745,14 +747,14 @@ check_config_files(Configs) -> end, Files) end; - {error, Why}-> + {error, Why} -> {error, {callback, {Callback,Why}}} end; ({Callback, []}) -> case check_callback_load(Callback) of - {ok, Callback}-> + {ok, Callback} -> Callback:check_parameter([]); - {error, Why}-> + {error, Why} -> {error, {callback, {Callback,Why}}} end end, @@ -773,15 +775,15 @@ prepare_user_configs([], Acc, _) -> prepare_config_list(Args) -> ConfigFiles = case lists:keysearch(ct_config, 1, Args) of - {value,{ct_config,Files}}-> + {value,{ct_config,Files}} -> [{?ct_config_txt,[filename:absname(F) || F <- Files]}]; - false-> + false -> [] end, UserConfigs = case lists:keysearch(userconfig, 1, Args) of - {value,{userconfig,UserConfigFiles}}-> + {value,{userconfig,UserConfigFiles}} -> prepare_user_configs(UserConfigFiles, [], new); - false-> + false -> [] end, ConfigFiles ++ UserConfigs. diff --git a/lib/common_test/src/ct_config_plain.erl b/lib/common_test/src/ct_config_plain.erl index 3fbc8af9fb..6698332379 100644 --- a/lib/common_test/src/ct_config_plain.erl +++ b/lib/common_test/src/ct_config_plain.erl @@ -29,7 +29,7 @@ read_config(ConfigFile) -> {ok,Config} -> {ok, Config}; {error,enoent} -> - {error, config_file_error, enoent}; + {error,{config_file_error,file:format_error(enoent)}}; {error,Reason} -> Key = case application:get_env(common_test, decrypt) of @@ -45,23 +45,27 @@ read_config(ConfigFile) -> end, case Key of {error,no_crypt_file} -> - {error, config_file_error, Reason}; + {error,{config_file_error, + lists:flatten( + io_lib:format("~s",[file:format_error(Reason)]))}}; {error,CryptError} -> - {error, decrypt_file_error, CryptError}; + {error,{decrypt_file_error,CryptError}}; _ when is_list(Key) -> - case ct_config:decrypt_config_file(ConfigFile, undefined, {key,Key}) of + case ct_config:decrypt_config_file(ConfigFile, + undefined, + {key,Key}) of {ok,CfgBin} -> case read_config_terms(CfgBin) of {error,ReadFail} -> - {error, config_file_error, ReadFail}; + {error,{config_file_error,ReadFail}}; Config -> - {ok, Config} + {ok,Config} end; {error,DecryptFail} -> - {error, decrypt_config_error, DecryptFail} + {error,{decrypt_config_error,DecryptFail}} end; _ -> - {error, bad_decrypt_key, Key} + {error,{bad_decrypt_key,Key}} end end. @@ -69,9 +73,9 @@ read_config(ConfigFile) -> check_parameter(File)-> case filelib:is_file(File) of true-> - {ok, {file, File}}; + {ok,{file,File}}; false-> - {error, {nofile, File}} + {error,{nofile,File}} end. read_config_terms(Bin) when is_binary(Bin) -> diff --git a/lib/common_test/src/ct_config_xml.erl b/lib/common_test/src/ct_config_xml.erl index 8a6e75e635..794174e663 100644 --- a/lib/common_test/src/ct_config_xml.erl +++ b/lib/common_test/src/ct_config_xml.erl @@ -27,30 +27,30 @@ % read config file read_config(ConfigFile) -> case catch do_read_xml_config(ConfigFile) of - {ok, Config}-> - {ok, Config}; - {error, Error, ErroneousString}-> - {error, Error, ErroneousString} + {ok,Config} -> + {ok,Config}; + Error = {error,_} -> + Error end. % check file exists -check_parameter(File)-> +check_parameter(File) -> case filelib:is_file(File) of - true-> - {ok, {file, File}}; - false-> - {error, {nofile, File}} + true -> + {ok,{file,File}}; + false -> + {error,{nofile,File}} end. % actual reading of the config -do_read_xml_config(ConfigFile)-> +do_read_xml_config(ConfigFile) -> case catch xmerl_sax_parser:file(ConfigFile, - [{event_fun, fun event/3}, - {event_state, []}]) of - {ok, EntityList, _}-> - {ok, lists:reverse(transform_entity_list(EntityList))}; - Oops-> - {error, parsing_failed, Oops} + [{event_fun,fun event/3}, + {event_state,[]}]) of + {ok,EntityList,_} -> + {ok,lists:reverse(transform_entity_list(EntityList))}; + Oops -> + {error,{parsing_failed,Oops}} end. % event callback for xmerl_sax_parser @@ -92,18 +92,18 @@ tag(_El, State) -> State. % transform of the ugly deeply nested entity list to the key-value "tree" -transform_entity_list(EntityList)-> +transform_entity_list(EntityList) -> lists:map(fun transform_entity/1, EntityList). % transform entity from {list(), list()} to {atom(), term()} transform_entity({Tag, [Value|Rest]}) when - is_tuple(Value)-> + is_tuple(Value) -> {list_to_atom(Tag), transform_entity_list(lists:reverse([Value|Rest]))}; -transform_entity({Tag, String})-> +transform_entity({Tag, String}) -> case list_to_term(String) of - {ok, Value}-> + {ok, Value} -> {list_to_atom(Tag), Value}; - Error-> + Error -> throw(Error) end. @@ -111,8 +111,8 @@ transform_entity({Tag, String})-> list_to_term(String) -> {ok, T, _} = erl_scan:string(String++"."), case catch erl_parse:parse_term(T) of - {ok, Term} -> - {ok, Term}; + {ok,Term} -> + {ok,Term}; Error -> - {error, Error, String} + {error,{Error,String}} end. diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl index b730f1e46e..29caa27d94 100644 --- a/lib/common_test/src/ct_framework.erl +++ b/lib/common_test/src/ct_framework.erl @@ -245,7 +245,12 @@ add_defaults(Mod,Func,FuncInfo,DoInit) -> Error = {error,_} -> {SuiteInfo,Error}; MergedInfo -> {SuiteInfo,MergedInfo} end; - {'EXIT',Reason} -> + {'EXIT',Reason} -> + ErrStr = io_lib:format("~n*** ERROR *** " + "~w:suite/0 failed: ~p~n", + [Mod,Reason]), + io:format(ErrStr, []), + io:format(user, ErrStr, []), {suite0_failed,{exited,Reason}}; SuiteInfo when is_list(SuiteInfo) -> case lists:all(fun(E) when is_tuple(E) -> true; @@ -261,9 +266,19 @@ add_defaults(Mod,Func,FuncInfo,DoInit) -> MergedInfo -> {SuiteInfo1,MergedInfo} end; false -> + ErrStr = io_lib:format("~n*** ERROR *** " + "Invalid return value from " + "~w:suite/0: ~p~n", [Mod,SuiteInfo]), + io:format(ErrStr, []), + io:format(user, ErrStr, []), {suite0_failed,bad_return_value} end; - _ -> + SuiteInfo -> + ErrStr = io_lib:format("~n*** ERROR *** " + "Invalid return value from " + "~w:suite/0: ~p~n", [Mod,SuiteInfo]), + io:format(ErrStr, []), + io:format(user, ErrStr, []), {suite0_failed,bad_return_value} end. diff --git a/lib/common_test/src/ct_logs.erl b/lib/common_test/src/ct_logs.erl index 761b906392..f34eb83afa 100644 --- a/lib/common_test/src/ct_logs.erl +++ b/lib/common_test/src/ct_logs.erl @@ -484,8 +484,8 @@ logger_loop(State) -> [Str,Args]), %% stop the testcase, we need %% to see the fault - exit(Pid,logging_failed), - ok; + exit(Pid,{log_printout_error,Str,Args}), + []; IoStr when IoList == [] -> [IoStr]; IoStr -> diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl index c3b0348b26..4ff062c2fa 100644 --- a/lib/common_test/src/ct_run.erl +++ b/lib/common_test/src/ct_run.erl @@ -667,6 +667,16 @@ run_test(StartOpt) when is_tuple(StartOpt) -> run_test([StartOpt]); run_test(StartOpts) when is_list(StartOpts) -> + CTPid = spawn(fun() -> run_test1(StartOpts) end), + Ref = monitor(process, CTPid), + receive + {'DOWN',Ref,process,CTPid,{user_error,Error}} -> + Error; + {'DOWN',Ref,process,CTPid,Other} -> + Other + end. + +run_test1(StartOpts) when is_list(StartOpts) -> case proplists:get_value(refresh_logs, StartOpts) of undefined -> Tracing = start_trace(StartOpts), @@ -675,7 +685,7 @@ run_test(StartOpts) when is_list(StartOpts) -> Res = case ct_repeat:loop_test(func, StartOpts) of false -> - case catch run_test1(StartOpts) of + case catch run_test2(StartOpts) of {'EXIT',Reason} -> file:set_cwd(Cwd), {error,Reason}; @@ -686,13 +696,13 @@ run_test(StartOpts) when is_list(StartOpts) -> Result end, stop_trace(Tracing), - Res; + exit(Res); RefreshDir -> refresh_logs(?abs(RefreshDir)), - ok + exit(done) end. -run_test1(StartOpts) -> +run_test2(StartOpts) -> %% label Label = get_start_opt(label, fun(Lbl) when is_list(Lbl) -> Lbl; (Lbl) when is_atom(Lbl) -> atom_to_list(Lbl) @@ -981,7 +991,7 @@ run_dir(Opts = #opts{logdir = LogDir, {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) -> + {Dir,undefined,[]} when is_atom(Dir) and (Dir /= undefined) -> reformat_result(catch do_run(tests(atom_to_list(Dir)), [], Opts1, StartOpts)); @@ -1052,6 +1062,9 @@ run_dir(Opts = #opts{logdir = LogDir, end end; + {undefined,undefined,[]} -> + exit(no_test_specified); + {Dir,Suite,GsAndCs} -> exit({incorrect_start_options,{Dir,Suite,GsAndCs}}) end. @@ -1064,19 +1077,38 @@ run_dir(Opts = #opts{logdir = LogDir, %%% the same as those used in test specification files. %%% @equiv ct:run_testspec/1 %%%----------------------------------------------------------------- - run_testspec(TestSpec) -> + CTPid = spawn(fun() -> run_testspec1(TestSpec) end), + Ref = monitor(process, CTPid), + receive + {'DOWN',Ref,process,CTPid,{user_error,Error}} -> + Error; + {'DOWN',Ref,process,CTPid,Other} -> + Other + end. + +run_testspec1(TestSpec) -> {ok,Cwd} = file:get_cwd(), io:format("~nCommon Test starting (cwd is ~s)~n~n", [Cwd]), - case catch run_testspec1(TestSpec) of + case catch run_testspec2(TestSpec) of {'EXIT',Reason} -> file:set_cwd(Cwd), - {error,Reason}; + exit({error,Reason}); Result -> - Result + exit(Result) end. -run_testspec1(TestSpec) -> +run_testspec2(File) when is_list(File), is_integer(hd(File)) -> + case file:read_file_info(File) of + {ok,_} -> + exit("Bad argument, " + "use ct:run_test([{spec," ++ File ++ "}])"); + _ -> + exit("Bad argument, list of tuples expected, " + "use ct:run_test/1 for test specification files") + end; + +run_testspec2(TestSpec) -> case catch ct_testspec:collect_tests_from_list(TestSpec, false) of {E,CTReason} when E == error ; E == 'EXIT' -> exit(CTReason); @@ -1295,7 +1327,6 @@ do_run(Tests, Misc, LogDir, LogOpts) when is_list(Misc), do_run(Tests, Skip, Opts, Args) when is_record(Opts, opts) -> #opts{label = Label, profile = Profile, cover = Cover} = Opts, - %% label - used by ct_logs TestLabel = if Label == undefined -> undefined; @@ -2478,8 +2509,8 @@ start_trace(Args) -> false end; {_,Error} -> - io:format("Warning! Tracing not started. Reason: ~p~n~n", - [Error]), + io:format("Warning! Tracing not started. Reason: ~s~n~n", + [file:format_error(Error)]), false end; false -> diff --git a/lib/common_test/src/ct_testspec.erl b/lib/common_test/src/ct_testspec.erl index bf1dfa24ea..2cba1d8410 100644 --- a/lib/common_test/src/ct_testspec.erl +++ b/lib/common_test/src/ct_testspec.erl @@ -249,11 +249,15 @@ collect_tests_from_file1([Spec|Specs],TestSpec,Relaxed) -> SpecDir = filename:dirname(filename:absname(Spec)), case file:consult(Spec) of {ok,Terms} -> - TestSpec1 = collect_tests(Terms,TestSpec#testspec{spec_dir=SpecDir}, + TestSpec1 = collect_tests(Terms, + TestSpec#testspec{spec_dir=SpecDir}, Relaxed), collect_tests_from_file1(Specs,TestSpec1,Relaxed); {error,Reason} -> - throw({error,{Spec,Reason}}) + ReasonStr = + lists:flatten(io_lib:format("~s", + [file:format_error(Reason)])), + throw({error,{Spec,ReasonStr}}) end; collect_tests_from_file1([],TS=#testspec{config=Cfgs,event_handler=EvHs, include=Incl,tests=Tests},_) -> diff --git a/lib/common_test/src/ct_util.erl b/lib/common_test/src/ct_util.erl index ef94c25364..f393ea103d 100644 --- a/lib/common_test/src/ct_util.erl +++ b/lib/common_test/src/ct_util.erl @@ -124,13 +124,15 @@ do_start(Parent,Mode,LogDir) -> ok -> ok; E -> exit(E) end, + DoExit = fun(Reason) -> file:set_cwd(StartDir), exit(Reason) end, Opts = case read_opts() of {ok,Opts1} -> Opts1; Error -> Parent ! {self(),Error}, - exit(Error) + DoExit(Error) end, + %% start an event manager (if not already started by master) case ct_event:start_link() of {error,{already_started,_}} -> @@ -143,16 +145,23 @@ do_start(Parent,Mode,LogDir) -> ct_event:add_handler([{vts,VtsPid}]) end end, + %% start ct_config server - ct_config:start(Mode), + try ct_config:start(Mode) of + _ -> ok + catch + _Class:CfgError -> + DoExit(CfgError) + end, + %% add user event handlers 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 ok -> ok; - {'EXIT',Why} -> exit(Why); - Other -> exit({event_handler,Other}) + {'EXIT',Why} -> DoExit(Why); + Other -> DoExit({event_handler,Other}) end end, case catch lists:foreach(Add,Handlers) of @@ -171,10 +180,11 @@ do_start(Parent,Mode,LogDir) -> data={StartTime, lists:flatten(TestLogDir)}}), %% Initialize ct_hooks - case catch ct_hooks:init(Opts) of + try ct_hooks:init(Opts) of ok -> - Parent ! {self(),started}; - {_,CTHReason} -> + Parent ! {self(),started} + catch + _:CTHReason -> ct_logs:tc_print('Suite Callback',CTHReason,[]), self() ! {{stop,{self(),{user_error,CTHReason}}}, {Parent,make_ref()}} -- cgit v1.2.3 From e91ba727f534553a34c05ad54247a0485e2429ff Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Mon, 5 Sep 2011 19:51:59 +0200 Subject: Implement support for running suites with test case groups through the debugger OTP-9518 --- lib/common_test/doc/src/run_test_chapter.xml | 5 +- lib/common_test/src/ct_framework.erl | 35 ++++++++++++- lib/common_test/src/ct_run.erl | 75 +++++++++++++++++----------- 3 files changed, 81 insertions(+), 34 deletions(-) (limited to 'lib') diff --git a/lib/common_test/doc/src/run_test_chapter.xml b/lib/common_test/doc/src/run_test_chapter.xml index e668568795..e944f215f6 100644 --- a/lib/common_test/doc/src/run_test_chapter.xml +++ b/lib/common_test/doc/src/run_test_chapter.xml @@ -322,8 +322,9 @@ are to be executed by Common Test, and those functions only. If the step option config is specified, breakpoints will also be initially set on the configuration functions in the suite, i.e. - init_per_suite/1, end_per_suite/1, init_per_testcase/2 - and end_per_testcase/2.

+ init_per_suite/1, end_per_suite/1, + init_per_group/2, end_per_group/2, + init_per_testcase/2 and end_per_testcase/2.

Common Test enables the Debugger auto attach feature, which means that for every new interpreted test case function that starts to execute, a new trace window will automatically pop up. (This is because each test diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl index 29caa27d94..089d5be871 100644 --- a/lib/common_test/src/ct_framework.erl +++ b/lib/common_test/src/ct_framework.erl @@ -24,8 +24,8 @@ -module(ct_framework). --export([init_tc/3, end_tc/3, end_tc/4, get_suite/2, report/2, warn/1]). --export([error_notification/4]). +-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]). @@ -781,6 +781,37 @@ get_suite(Mod, Name) -> %%%----------------------------------------------------------------- +get_all_cases(Suite) -> + case get_suite(Suite, all) of + [{?MODULE,error_in_suite,[[{error,_}=Error]]}] -> + Error; + [{?MODULE,error_in_suite,[[Error]]}] -> + {error,Error}; + Tests -> + Cases = get_all_cases1(Suite, Tests), + lists:reverse( + lists:foldl(fun(TC, TCs) -> + case lists:member(TC, TCs) of + true -> TCs; + false -> [TC | TCs] + end + end, [], Cases)) + end. + +get_all_cases1(Suite, [{conf,_Props,_Init,GrTests,_End} | Tests]) -> + get_all_cases1(Suite, GrTests) ++ get_all_cases1(Suite, Tests); + +get_all_cases1(Suite, [Test | Tests]) when is_atom(Test) -> + [{Suite,Test} | get_all_cases1(Suite, Tests)]; + +get_all_cases1(Suite, [Test | Tests]) -> + [Test | get_all_cases1(Suite, Tests)]; + +get_all_cases1(_, []) -> + []. + +%%%----------------------------------------------------------------- + find_groups(Mod, Name, TCs, GroupDefs) -> Found = find(Mod, Name, TCs, GroupDefs, [], GroupDefs, false), trim(Found). diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl index 4ff062c2fa..2dd6ba08aa 100644 --- a/lib/common_test/src/ct_run.erl +++ b/lib/common_test/src/ct_run.erl @@ -2148,7 +2148,14 @@ maybe_interpret1(Suite, Cases, StepOpts) when is_list(Cases) -> maybe_interpret2(Suite, Cases, StepOpts) -> set_break_on_config(Suite, StepOpts), - [i:ib(Suite, Case, 1) || Case <- Cases], + [begin try i:ib(Suite, Case, 1) of + _ -> ok + catch + _:_Error -> + io:format(user, "Invalid breakpoint: ~w:~w/1~n", + [Suite,Case]) + end + end || Case <- Cases, is_atom(Case)], test_server_ctrl:multiply_timetraps(infinity), WinOp = case lists:member(keep_inactive, ensure_atom(StepOpts)) of true -> no_kill; @@ -2161,10 +2168,18 @@ maybe_interpret2(Suite, Cases, StepOpts) -> set_break_on_config(Suite, StepOpts) -> case lists:member(config, ensure_atom(StepOpts)) of true -> - i:ib(Suite, init_per_suite, 1), - i:ib(Suite, init_per_testcase, 2), - i:ib(Suite, end_per_testcase, 2), - i:ib(Suite, end_per_suite, 1); + SetBPIfExists = fun(F,A) -> + case erlang:function_exported(Suite, F, A) of + true -> i:ib(Suite, F, A); + false -> ok + end + end, + SetBPIfExists(init_per_suite, 1), + SetBPIfExists(init_per_group, 2), + SetBPIfExists(init_per_testcase, 2), + SetBPIfExists(end_per_testcase, 2), + SetBPIfExists(end_per_group, 2), + SetBPIfExists(end_per_suite, 1); false -> ok end. @@ -2463,32 +2478,32 @@ is_suite(ModOrFile) when is_list(ModOrFile) -> end. get_all_testcases(Suite) -> - %%! this needs to be updated to handle testcase groups later!! - case catch Suite:all() of - {'EXIT',Why} -> - {error,Why}; - {skip,_} -> - []; - Cases -> - AllCases = - lists:foldl(fun({sequence,SeqName}, All) -> - case catch Suite:sequences() of - {'EXIT',_} -> - All; - Seqs -> - case proplists:get_value(SeqName, Seqs) of - undefined -> - All; - SeqCases -> - lists:reverse(SeqCases) ++ All - end - end; - (Case,All) -> - [Case|All] - end, [], Cases), - lists:reverse(AllCases) + try ct_framework:get_all_cases(Suite) of + {error,_Reason} = Error -> + Error; + SuiteCases -> + Cases = [C || {_S,C} <- SuiteCases], + Cases1 = + try Suite:sequences() of + [] -> + Cases; + Seqs -> + TCs1 = lists:flatten([TCs || {_,TCs} <- Seqs]), + lists:reverse( + lists:foldl(fun(TC, Acc) -> + case lists:member(TC, Acc) of + true -> Acc; + false -> [TC | Acc] + end + end, [], Cases ++ TCs1)) + catch + _:_ -> + Cases + end + catch + _:Error -> + {error,Error} end. - %% Internal tracing support. If {ct_trace,TraceSpec} is present, the %% TraceSpec file will be consulted and dbg used to trace function -- cgit v1.2.3 From 36f1e1898a2ea08d591739cc2e9ff8e7fbb0ea6b Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Tue, 6 Sep 2011 23:33:43 +0200 Subject: Repair and improve the vts mode OTP-9429 --- lib/common_test/src/ct_run.erl | 33 ++++++------ lib/common_test/src/vts.erl | 115 ++++++++++++++++++++++++++--------------- 2 files changed, 89 insertions(+), 59 deletions(-) (limited to 'lib') diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl index 2dd6ba08aa..4ec3ac589d 100644 --- a/lib/common_test/src/ct_run.erl +++ b/lib/common_test/src/ct_run.erl @@ -2483,23 +2483,22 @@ get_all_testcases(Suite) -> Error; SuiteCases -> Cases = [C || {_S,C} <- SuiteCases], - Cases1 = - try Suite:sequences() of - [] -> - Cases; - Seqs -> - TCs1 = lists:flatten([TCs || {_,TCs} <- Seqs]), - lists:reverse( - lists:foldl(fun(TC, Acc) -> - case lists:member(TC, Acc) of - true -> Acc; - false -> [TC | Acc] - end - end, [], Cases ++ TCs1)) - catch - _:_ -> - Cases - end + try Suite:sequences() of + [] -> + Cases; + Seqs -> + TCs1 = lists:flatten([TCs || {_,TCs} <- Seqs]), + lists:reverse( + lists:foldl(fun(TC, Acc) -> + case lists:member(TC, Acc) of + true -> Acc; + false -> [TC | Acc] + end + end, [], Cases ++ TCs1)) + catch + _:_ -> + Cases + end catch _:Error -> {error,Error} diff --git a/lib/common_test/src/vts.erl b/lib/common_test/src/vts.erl index 9eb11c23cc..cc8a932887 100644 --- a/lib/common_test/src/vts.erl +++ b/lib/common_test/src/vts.erl @@ -32,6 +32,7 @@ menu_frame/2, welcome_frame/2, config_frame/2, + browse_config_file/2, add_config_file/2, remove_config_file/2, run_frame/2, @@ -119,6 +120,8 @@ menu_frame(_Env,_Input) -> call(menu_frame). config_frame(_Env,_Input) -> call(config_frame). +browse_config_file(_Env,Input) -> + call({browse_config_file,Input}). add_config_file(_Env,Input) -> call({add_config_file,Input}). remove_config_file(_Env,Input) -> @@ -183,6 +186,9 @@ loop(State) -> {config_frame,From} -> return(From,config_frame1(State)), loop(State); + {{browse_config_file,_Input},From} -> + return(From,ok), + loop(State); {{add_config_file,Input},From} -> {Return,State1} = add_config_file1(Input,State), ct_install(State1), @@ -242,10 +248,12 @@ loop(State) -> return(From,ok); {'EXIT',Pid,Reason} -> case State#state.test_runner of - Pid -> io:format("ERROR: test runner crashed: ~p\n",[Reason]); - _ -> ignore - end, - loop(State); + Pid -> + io:format("Test run error: ~p\n",[Reason]), + loop(State); + _ -> + loop(State) + end; {{test_info,_Type,_Data},From} -> return(From,ok), loop(State) @@ -284,17 +292,18 @@ run_test1(State=#state{tests=Tests,current_log_dir=LogDir, unlink(Self) end, Pid = spawn_link(RunTest), - Total = + {Total,Tests1} = receive {{test_info,start_info,{_,_,Cases}},From} -> return(From,ok), - Cases; + {Cases,Tests}; EXIT = {'EXIT',_,_} -> - self() ! EXIT + self() ! EXIT, + {0,[]} after 30000 -> - 0 + {0,[]} end, - State#state{test_runner=Pid,running=length(Tests), + State#state{test_runner=Pid,running=length(Tests1), total=Total,ok=0,fail=0,skip=0,testruns=[]}. @@ -358,22 +367,32 @@ config_frame1(State) -> config_body(State) -> Entry = [input("TYPE=file NAME=browse SIZE=40"), input("TYPE=hidden NAME=file")], + BrowseForm = + form( + "NAME=read_file_form METHOD=post ACTION=\"./browse_config_file\"", + table( + "BORDER=0", + [tr(td("1. Locate config file")), + tr(td(Entry))])), AddForm = form( - "NAME=read_file_form METHOD=post ACTION=\"./add_config_file\"", + "NAME=add_file_form METHOD=post ACTION=\"./add_config_file\"", table( "BORDER=0", - [tr( - [td(Entry), + [tr(td("2. Paste full config file name here")), + tr( + [td(input("TYPE=text NAME=file SIZE=40")), td("ALIGN=center", input("TYPE=submit onClick=\"file.value=browse.value;\"" " VALUE=\"Add\""))])])), + {Text,RemoveForm} = case State#state.config of [] -> - T = "To be able to run any tests, one or more configuration " - "files must be added. Enter the name of the configuration " - "file below and click the \"Add\" button.", + T = "Before running the tests, one or more configuration " + "files may be added. Locate the config file, copy its " + "full name, paste this into the text field below, then " + "click the \"Add\" button.", R = "", {T,R}; Files -> @@ -396,20 +415,24 @@ config_body(State) -> input("TYPE=submit VALUE=\"Remove\"")))])), {T,R} end, - + [h1("ALIGN=center","Config"), table( - "WIDTH=600 ALIGN=center CELLPADDING=5", + "WIDTH=450 ALIGN=center CELLPADDING=5", [tr(td(["BGCOLOR=",?INFO_BG_COLOR],Text)), - tr(td("ALIGN=center",AddForm)), - tr(td("ALIGN=center",RemoveForm))])]. - + tr(td("")), + tr(td("")), + tr(td("ALIGN=left",BrowseForm)), + tr(td("ALIGN=left",AddForm)), + tr(td("ALIGN=left",RemoveForm))])]. add_config_file1(Input,State) -> State1 = case get_input_data(Input,"file") of - "" -> State; - File -> State#state{config=[File|State#state.config]} + "" -> + State; + File -> + State#state{config=[File|State#state.config]} end, Return = config_frame1(State1), {Return,State1}. @@ -429,10 +452,17 @@ run_body(#state{running=Running}) when Running>0 -> [h1("ALIGN=center","Run Test"), p(["Test are ongoing: ",href("./result_frameset","Results")])]; run_body(State) -> - ConfigList = ul([li(File) || File <- State#state.config]), + ConfigList = + case State#state.config of + [] -> + ul(["none"]); + CfgFiles -> + ul([li(File) || File <- CfgFiles]) + end, ConfigFiles = [h3("Config Files"), ConfigList], - + {ok,CWD} = file:get_cwd(), + CurrWD = [h3("Current Working Directory"), ul(CWD)], AddDirForm = form( "NAME=add_dir_form METHOD=post ACTION=\"./add_test_dir\"", @@ -444,7 +474,6 @@ run_body(State) -> td("ALIGN=center", input("TYPE=submit onClick=\"dir.value=browse.value;\"" " VALUE=\"Add Test Dir\""))])])), - {LoadedTestsTable,Submit} = case create_testdir_entries(State#state.tests,1) of [] -> {"",""}; @@ -456,22 +485,20 @@ run_body(State) -> {table("CELLPADDING=5",[Heading,TestDirs]), submit_button()} end, - - %% It should be ok to have no config-file! Body = - %% case State#state.config of %% [] -> %% p("ALIGN=center", - %% href("./config_frame","Please select one or - %% more config files")); %% _ -> table( - "WIDTH=100%", - [tr(td(ConfigFiles)), + "WIDTH=450 ALIGN=center", + [tr(td("")), + tr(td("")), + tr(td(ConfigFiles)), + tr(td("")), + tr(td(CurrWD)), tr(td("")), tr(td(AddDirForm)), tr(td("")), tr(td(LoadedTestsTable)), - tr(td(Submit))]), - %% end, - + tr(td(Submit)) + ]), [h1("ALIGN=center","Run Test"), Body]. create_testdir_entries([{Dir,Suite,Case}|Tests],N) -> @@ -558,18 +585,17 @@ options([Element|Elements],Selected,N,Func) -> options([],_Selected,_N,_Func) -> []. -add_test_dir1(Input,State) -> +add_test_dir1(Input, State) -> State1 = case get_input_data(Input,"dir") of "" -> State; Dir0 -> Dir = case ct_util:is_test_dir(Dir0) of - true -> - Dir0; - false -> filename:join(Dir0,"test") + true -> Dir0; + false -> ct_util:get_testdir(Dir0, all) end, case filelib:is_dir(Dir) of - true -> + true -> Test = ct_run:tests(Dir), State#state{tests=State#state.tests++Test}; false -> @@ -579,8 +605,6 @@ add_test_dir1(Input,State) -> Return = run_frame1(State1), {Return,State1}. - - remove_test_dir1(Input,State) -> N = list_to_integer(get_input_data(Input,"dir")), State1 = State#state{tests=delete_test(N,State#state.tests)}, @@ -643,6 +667,9 @@ result_frameset2(State) -> "./redirect_to_result_log_frame"; {_Dir,0} -> filename:join(["/log_dir","index.html"]); + {_Dir,_} when State#state.testruns == [] -> + %% crash before first test + "./no_result_log_frame"; {_Dir,_} -> {_,CurrentLog} = hd(State#state.testruns), CurrentLog @@ -751,6 +778,8 @@ report1(tc_done,{_Suite,_Case,{skipped,_Reason}},State) -> State#state{skip=State#state.skip+1}; report1(tc_user_skip,{_Suite,_Case,_Reason},State) -> State#state{skip=State#state.skip+1}; +report1(tc_auto_skip,{_Suite,_Case,_Reason},State) -> + State#state{skip=State#state.skip+1}; report1(loginfo,_,State) -> State. @@ -852,6 +881,8 @@ h2(Text) -> ["

",Text,"

\n"]. h3(Text) -> ["

",Text,"

\n"]. +%%h4(Text) -> +%% ["

",Text,"

\n"]. font(Args,Text) -> ["\n",Text,"\n\n"]. p(Text) -> -- cgit v1.2.3 From b21b1f63bce0ad705671e0f7622d017be464ed67 Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Fri, 16 Sep 2011 23:37:29 +0200 Subject: Implement support for MFA and Fun as timetrap value OTP-9501 --- lib/test_server/src/test_server.erl | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'lib') diff --git a/lib/test_server/src/test_server.erl b/lib/test_server/src/test_server.erl index 337bc1d6d7..039ea720a8 100644 --- a/lib/test_server/src/test_server.erl +++ b/lib/test_server/src/test_server.erl @@ -1905,8 +1905,28 @@ time_ms({Other,_N}) -> exit({invalid_time_spec,Other}); time_ms(Ms) when is_integer(Ms) -> Ms; time_ms(infinity) -> infinity; +time_ms(Fun) when is_function(Fun) -> + try Fun() of + Val -> time_ms1(Val) + catch + _:Error -> + exit({timetrap_error,Error}) + end; +time_ms({M,F,A}) when is_atom(M), is_atom(F), is_list(A) -> + try apply(M, F, A) of + Val -> time_ms1(Val) + catch + _:Error -> + exit({timetrap_error,Error}) + end; time_ms(Other) -> exit({invalid_time_spec,Other}). +time_ms1(MFA = {M,F,A}) when is_atom(M), is_atom(F), is_list(A) -> + exit({invalid_time_spec,MFA}); +time_ms1(Fun) when is_function(Fun) -> + exit({invalid_time_spec,Fun}); +time_ms1(Other) -> + time_ms(Other). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% timetrap_cancel(Handle) -> ok -- cgit v1.2.3 From 8d051d91b86f08877038af1983c8eb5f3f9a7ddb Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Mon, 19 Sep 2011 17:50:29 +0200 Subject: Improve test suite --- lib/test_server/test/test_server_SUITE.erl | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'lib') diff --git a/lib/test_server/test/test_server_SUITE.erl b/lib/test_server/test/test_server_SUITE.erl index 4c344717f0..a8532b08ab 100644 --- a/lib/test_server/test/test_server_SUITE.erl +++ b/lib/test_server/test/test_server_SUITE.erl @@ -119,6 +119,11 @@ test_server_conf02_SUITE(Config) -> run_test_server_tests(SuiteName, NCases, NFail, NExpected, NSucc, NUsrSkip, NAutoSkip, NActualSkip, NActualFail, NActualSucc, Config) -> + + ct:log("See test case log files under:~n~p~n", + [filename:join([proplists:get_value(priv_dir, Config), + SuiteName++".logs"])]), + Node = proplists:get_value(node, Config), {ok,_Pid} = rpc:call(Node,test_server_ctrl, start, []), rpc:call(Node, @@ -132,6 +137,7 @@ run_test_server_tests(SuiteName, NCases, NFail, NExpected, NSucc, end), rpc:call(Node,test_server_ctrl, stop, []), + {ok,#suite{ n_cases = NCases, n_cases_failed = NFail, n_cases_expected = NExpected, -- cgit v1.2.3 From 4c8664f1983a57c8d71ada937381b5fc5791446d Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Tue, 20 Sep 2011 16:26:49 +0200 Subject: Fix incorrect call to end_tc when tc_status=ok and end_per_testcase times out OTP-9397 --- lib/common_test/test/ct_error_SUITE.erl | 24 ++++++++++++------------ lib/common_test/test/ct_repeat_1_SUITE.erl | 2 +- lib/common_test/test/ct_skip_SUITE.erl | 2 +- lib/test_server/src/test_server.erl | 11 +++++++---- 4 files changed, 21 insertions(+), 18 deletions(-) (limited to 'lib') diff --git a/lib/common_test/test/ct_error_SUITE.erl b/lib/common_test/test/ct_error_SUITE.erl index 6867e59b60..6231e27644 100644 --- a/lib/common_test/test/ct_error_SUITE.erl +++ b/lib/common_test/test/ct_error_SUITE.erl @@ -285,7 +285,7 @@ test_events(cfg_error) -> {test_server,my_apply,3}, {test_server,ts_tc,3}, {test_server,run_test_case_eval1,6}, - {test_server,run_test_case_eval,8}]}}}}}, + {test_server,run_test_case_eval,9}]}}}}}, {?eh,tc_auto_skip, {cfg_error_2_SUITE,tc1, {failed,{cfg_error_2_SUITE,init_per_suite, @@ -294,7 +294,7 @@ test_events(cfg_error) -> {test_server,my_apply,3}, {test_server,ts_tc,3}, {test_server,run_test_case_eval1,6}, - {test_server,run_test_case_eval,8}]}}}}}}, + {test_server,run_test_case_eval,9}]}}}}}}, {?eh,test_stats,{0,0,{0,3}}}, {?eh,tc_auto_skip, {cfg_error_2_SUITE,tc2, @@ -304,7 +304,7 @@ test_events(cfg_error) -> {test_server,my_apply,3}, {test_server,ts_tc,3}, {test_server,run_test_case_eval1,6}, - {test_server,run_test_case_eval,8}]}}}}}}, + {test_server,run_test_case_eval,9}]}}}}}}, {?eh,test_stats,{0,0,{0,4}}}, {?eh,tc_auto_skip, {cfg_error_2_SUITE,end_per_suite, @@ -314,7 +314,7 @@ test_events(cfg_error) -> {test_server,my_apply,3}, {test_server,ts_tc,3}, {test_server,run_test_case_eval1,6}, - {test_server,run_test_case_eval,8}]}}}}}}, + {test_server,run_test_case_eval,9}]}}}}}}, {?eh,tc_start,{cfg_error_3_SUITE,init_per_suite}}, {?eh,tc_done, @@ -378,7 +378,7 @@ test_events(cfg_error) -> {test_server,my_apply,3}, {test_server,ts_tc,3}, {test_server,run_test_case_eval1,6}, - {test_server,run_test_case_eval,8}]}}}}}, + {test_server,run_test_case_eval,9}]}}}}}, {?eh,tc_start,{cfg_error_7_SUITE,init_per_suite}}, {?eh,tc_done,{cfg_error_7_SUITE,init_per_suite,ok}}, @@ -432,7 +432,7 @@ test_events(cfg_error) -> {test_server,my_apply,3}, {test_server,ts_tc,3}, {test_server,run_test_case_eval1,6}, - {test_server,run_test_case_eval,8}]}}}}}, + {test_server,run_test_case_eval,9}]}}}}}, {?eh,tc_auto_skip, {cfg_error_8_SUITE,tc1, {failed,{cfg_error_8_SUITE,init_per_group, @@ -441,7 +441,7 @@ test_events(cfg_error) -> {test_server,my_apply,3}, {test_server,ts_tc,3}, {test_server,run_test_case_eval1,6}, - {test_server,run_test_case_eval,8}]}}}}}}, + {test_server,run_test_case_eval,9}]}}}}}}, {?eh,test_stats,{4,0,{0,13}}}, {?eh,tc_auto_skip, {cfg_error_8_SUITE,end_per_group, @@ -451,7 +451,7 @@ test_events(cfg_error) -> {test_server,my_apply,3}, {test_server,ts_tc,3}, {test_server,run_test_case_eval1,6}, - {test_server,run_test_case_eval,8}]}}}}}}], + {test_server,run_test_case_eval,9}]}}}}}}], [{?eh,tc_start,{cfg_error_8_SUITE,{init_per_group,g4,[]}}}, {?eh,tc_done,{cfg_error_8_SUITE,{init_per_group,g4,[]},ok}}, @@ -525,7 +525,7 @@ test_events(cfg_error) -> {test_server,my_apply,3}, {test_server,init_per_testcase,3}, {test_server,run_test_case_eval1,6}, - {test_server,run_test_case_eval,8}]}}}}}}, + {test_server,run_test_case_eval,9}]}}}}}}, {?eh,test_stats,{9,0,{0,17}}}, {?eh,tc_start,{cfg_error_9_SUITE,tc4}}, {?eh,tc_done, @@ -562,7 +562,7 @@ test_events(cfg_error) -> {test_server,my_apply,3}, {test_server,do_end_per_testcase,4}, {test_server,run_test_case_eval1,6}, - {test_server,run_test_case_eval,8}]}}}}}}, + {test_server,run_test_case_eval,9}]}}}}}}, {?eh,test_stats,{12,3,{0,18}}}, {?eh,tc_start,{cfg_error_9_SUITE,tc14}}, {?eh,tc_done, @@ -646,7 +646,7 @@ test_events(lib_error) -> {test_server,my_apply,3}, {test_server,ts_tc,3}, {test_server,run_test_case_eval1,6}, - {test_server,run_test_case_eval,8}]}}}}}, + {test_server,run_test_case_eval,9}]}}}}}, {?eh,test_stats,{0,1,{0,0}}}, {?eh,tc_start,{lib_error_1_SUITE,lines_exit}}, {?eh,tc_done, @@ -671,7 +671,7 @@ test_events(lib_error) -> {test_server,my_apply,3}, {test_server,ts_tc,3}, {test_server,run_test_case_eval1,6}, - {test_server,run_test_case_eval,8}]}}}}}, + {test_server,run_test_case_eval,9}]}}}}}, {?eh,test_stats,{0,5,{0,0}}}, {?eh,tc_start,{lib_error_1_SUITE,no_lines_exit}}, {?eh,tc_done, diff --git a/lib/common_test/test/ct_repeat_1_SUITE.erl b/lib/common_test/test/ct_repeat_1_SUITE.erl index 4e842bd6d6..99e3b83ea9 100644 --- a/lib/common_test/test/ct_repeat_1_SUITE.erl +++ b/lib/common_test/test/ct_repeat_1_SUITE.erl @@ -565,7 +565,7 @@ test_events(repeat_cs_until_any_fail) -> {test_server,my_apply,3}, {test_server,ts_tc,3}, {test_server,run_test_case_eval1,6}, - {test_server,run_test_case_eval,8}]}}}}}, + {test_server,run_test_case_eval,9}]}}}}}, {?eh,test_stats,{5,2,{0,0}}}, {?eh,tc_start,{repeat_1_SUITE,tc_fail_2}}, {?eh,tc_done, diff --git a/lib/common_test/test/ct_skip_SUITE.erl b/lib/common_test/test/ct_skip_SUITE.erl index 4ba4479208..6a8c57a6bd 100644 --- a/lib/common_test/test/ct_skip_SUITE.erl +++ b/lib/common_test/test/ct_skip_SUITE.erl @@ -369,7 +369,7 @@ test_events(auto_skip) -> {test_server,my_apply,3}, {test_server,init_per_testcase,3}, {test_server,run_test_case_eval1,6}, - {test_server,run_test_case_eval,8}]}}}}}}, + {test_server,run_test_case_eval,9}]}}}}}}, {?eh,tc_start, {auto_skip_9_SUITE,{end_per_group,g5,[parallel]}}}, {?eh,tc_done, diff --git a/lib/test_server/src/test_server.erl b/lib/test_server/src/test_server.erl index 039ea720a8..ea55b22603 100644 --- a/lib/test_server/src/test_server.erl +++ b/lib/test_server/src/test_server.erl @@ -612,6 +612,7 @@ do_run_test_case_apply(Mod, Func, Args, Name, RunInit, TimetrapData) -> print(minor, "Current directory is ~p\n", [Cwd]), print_timestamp(minor,"Started at "), TCCallback = get(test_server_testcase_callback), + LogOpts = get(test_server_logopts), Ref = make_ref(), OldGLeader = group_leader(), %% Set ourself to group leader for the spawned process @@ -621,7 +622,7 @@ do_run_test_case_apply(Mod, Func, Args, Name, RunInit, TimetrapData) -> fun() -> run_test_case_eval(Mod, Func, Args, Name, Ref, RunInit, TimetrapData, - TCCallback) + LogOpts, TCCallback) end), group_leader(OldGLeader, self()), put(test_server_detected_fail, []), @@ -979,7 +980,8 @@ spawn_fw_call(Mod,{end_per_testcase,Func},EndConf,Pid, E = {failed,Reason} -> {E,{error,Reason}}; Result -> - {Result,Result} + E = {failed,{Mod,end_per_testcase,Why}}, + {Result,E} end, FailLoc = proplists:get_value(tc_fail_loc, EndConf), case catch do_end_tc_call(Mod,Func, FailLoc, @@ -1092,8 +1094,9 @@ job_proxy_msgloop() -> %% or sends a message {failed, File, Line} to it's group_leader run_test_case_eval(Mod, Func, Args0, Name, Ref, RunInit, - TimetrapData, TCCallback) -> - put(test_server_multiply_timetraps,TimetrapData), + TimetrapData, LogOpts, TCCallback) -> + put(test_server_multiply_timetraps, TimetrapData), + put(test_server_logopts, LogOpts), {{Time,Value},Loc,Opts} = case test_server_sup:framework_call(init_tc,[?pl2a(Mod),Func,Args0], -- cgit v1.2.3 From 942e776f874a5eecf392c917ce6e847a7bef9c85 Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Wed, 21 Sep 2011 17:17:31 +0200 Subject: Add cases to check test case status versus end_per_testcase failure --- .../error/test/cfg_error_9_SUITE.erl | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_9_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_9_SUITE.erl index c4e0d72948..f292985c0c 100644 --- a/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_9_SUITE.erl +++ b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_9_SUITE.erl @@ -76,7 +76,7 @@ init_per_testcase(tc1, Config) -> Config; init_per_testcase(tc2, Config) -> ct:comment("init_per_testcase(tc2) timeout"), - timer:sleep(5000), + ct:sleep(5000), Config; init_per_testcase(tc3, Config) -> badmatch = ?config(void, Config), @@ -96,22 +96,20 @@ init_per_testcase(_, Config) -> %%-------------------------------------------------------------------- end_per_testcase(tc11, _Config) -> ct:comment("A warning should be printed"), - exit(warning_should_be_printed), - done; + exit(warning_should_be_printed); end_per_testcase(tc12, _Config) -> ct:comment("A warning should be printed"), - timer:sleep(5000), - done; + ct:sleep(5000); end_per_testcase(tc13, Config) -> ct:comment("A warning should be printed"), - badmatch = ?config(void, Config), - done; + badmatch = ?config(void, Config); end_per_testcase(tc14, Config) -> ok = ?config(tc_status, Config), {fail,tc14_should_be_failed}; end_per_testcase(tc15, Config) -> - {failed,byebye} = ?config(tc_status, Config), - ok; + exit(kaboom); +end_per_testcase(tc16, Config) -> + ct:sleep(5000); end_per_testcase(_TestCase, _Config) -> done. @@ -139,7 +137,7 @@ groups() -> %%-------------------------------------------------------------------- all() -> [tc1,tc2,tc3,tc4,tc5,tc6,tc7, - tc11,tc12,tc13,tc14]. + tc11,tc12,tc13,tc14,tc15,tc16]. tc1(_) -> fini. @@ -189,4 +187,6 @@ tc14(_) -> ct:comment("This one should be failed by eptc"), yes. tc15(_) -> - exit(byebye). + exit(this_error_must_show). +tc16(_) -> + exit(this_error_must_show). -- cgit v1.2.3 From d7391d973f453de4749857291680380b60330bc7 Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Wed, 21 Sep 2011 23:14:34 +0200 Subject: Fix problem with error message not being printed correctly --- lib/test_server/src/test_server.erl | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/test_server/src/test_server.erl b/lib/test_server/src/test_server.erl index ea55b22603..ae54925c2e 100644 --- a/lib/test_server/src/test_server.erl +++ b/lib/test_server/src/test_server.erl @@ -746,6 +746,9 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) -> Other end, run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate1,NewComment2,CurrConf); + {read_comment,From} -> + From ! {self(),read_comment,Comment}, + run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf); {set_curr_conf,NewCurrConf} -> run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,NewCurrConf); {'EXIT',Pid,{Ref,Time,Value,Loc,Opts}} -> @@ -1443,9 +1446,13 @@ do_end_per_testcase(Mod,EndFunc,Func,Conf) -> {'$test_server_ok',_} -> ok; {'EXIT',Reason} = Why -> - comment(io_lib:format("" + Comment0 = case read_comment() of + "" -> ""; + Cmt -> Cmt ++ "
" + end, + comment(io_lib:format("~s" "WARNING: ~w crashed!" - "\n",[EndFunc])), + "
\n",[Comment0,EndFunc])), group_leader() ! {printout,12, "WARNING: ~w crashed!\n" "Reason: ~p\n" @@ -1455,9 +1462,13 @@ do_end_per_testcase(Mod,EndFunc,Func,Conf) -> mod_loc(get_loc()))]}, {failed,{Mod,end_per_testcase,Why}}; Other -> - comment(io_lib:format("" + Comment0 = case read_comment() of + "" -> ""; + Cmt -> Cmt ++ "
" + end, + comment(io_lib:format("~s" "WARNING: ~w thrown!" - "\n",[EndFunc])), + "
\n",[Comment0,EndFunc])), group_leader() ! {printout,12, "WARNING: ~w thrown!\n" "Reason: ~p\n" @@ -2363,6 +2374,22 @@ comment(String) -> group_leader() ! {comment,String}, ok. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% read_comment() -> string() +%% +%% Read the current comment string stored in +%% state during test case execution. +read_comment() -> + MsgLooper = group_leader(), + MsgLooper ! {read_comment,self()}, + receive + {MsgLooper,read_comment,Comment} -> + Comment + after + 5000 -> + "" + end. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% os_type() -> OsType %% -- cgit v1.2.3 From 11107d76a34667ec87668b2624a0f3df43dea655 Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Thu, 22 Sep 2011 12:46:12 +0200 Subject: Fix error with incorrect notification after end_per_testcase craches --- lib/common_test/test/ct_error_SUITE.erl | 29 +++++++++++++++++------------ lib/test_server/src/test_server.erl | 9 +++++++-- 2 files changed, 24 insertions(+), 14 deletions(-) (limited to 'lib') diff --git a/lib/common_test/test/ct_error_SUITE.erl b/lib/common_test/test/ct_error_SUITE.erl index 6231e27644..c3c77d17cd 100644 --- a/lib/common_test/test/ct_error_SUITE.erl +++ b/lib/common_test/test/ct_error_SUITE.erl @@ -260,7 +260,7 @@ test_events(cfg_error) -> [ {?eh,start_logging,{'DEF','RUNDIR'}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, - {?eh,start_info,{14,14,43}}, + {?eh,start_info,{14,14,45}}, {?eh,tc_start,{cfg_error_1_SUITE,init_per_suite}}, {?eh,tc_done, @@ -567,8 +567,13 @@ test_events(cfg_error) -> {?eh,tc_start,{cfg_error_9_SUITE,tc14}}, {?eh,tc_done, {cfg_error_9_SUITE,tc14,{failed,{error,tc14_should_be_failed}}}}, - {?eh,test_stats,{12,4,{0,18}}}, - + {?eh,tc_start,{cfg_error_9_SUITE,tc15}}, + {?eh,tc_done, + {cfg_error_9_SUITE,tc15,{failed,{error,this_error_must_show}}}}, + {?eh,tc_start,{cfg_error_9_SUITE,tc16}}, + {?eh,tc_done, + {cfg_error_9_SUITE,tc16,{failed,{error,this_error_must_show}}}}, + {?eh,test_stats,{12,6,{0,18}}}, {?eh,tc_start,{cfg_error_9_SUITE,end_per_suite}}, {?eh,tc_done,{cfg_error_9_SUITE,end_per_suite,ok}}, @@ -578,7 +583,7 @@ test_events(cfg_error) -> {?eh,tc_auto_skip,{cfg_error_10_SUITE,tc1, {failed,{cfg_error_10_SUITE,init_per_suite, {failed,fail_init_per_suite}}}}}, - {?eh,test_stats,{12,4,{0,19}}}, + {?eh,test_stats,{12,6,{0,19}}}, {?eh,tc_auto_skip,{cfg_error_10_SUITE,end_per_suite, {failed,{cfg_error_10_SUITE,init_per_suite, {failed,fail_init_per_suite}}}}}, @@ -587,40 +592,40 @@ test_events(cfg_error) -> {?eh,tc_start,{cfg_error_11_SUITE,tc1}}, {?eh,tc_done,{cfg_error_11_SUITE,tc1, {skipped,{config_name_already_in_use,[dummy0]}}}}, - {?eh,test_stats,{12,4,{1,19}}}, + {?eh,test_stats,{12,6,{1,19}}}, {?eh,tc_start,{cfg_error_11_SUITE,tc2}}, {?eh,tc_done,{cfg_error_11_SUITE,tc2,ok}}, - {?eh,test_stats,{13,4,{1,19}}}, + {?eh,test_stats,{13,6,{1,19}}}, {?eh,tc_start,{cfg_error_11_SUITE,end_per_suite}}, {?eh,tc_done,{cfg_error_11_SUITE,end_per_suite,ok}}, {?eh,tc_start,{cfg_error_12_SUITE,tc1}}, {?eh,tc_done,{cfg_error_12_SUITE,tc1,{failed,{timetrap_timeout,500}}}}, - {?eh,test_stats,{13,5,{1,19}}}, + {?eh,test_stats,{13,7,{1,19}}}, {?eh,tc_start,{cfg_error_12_SUITE,tc2}}, {?eh,tc_done,{cfg_error_12_SUITE,tc2,{failed, {cfg_error_12_SUITE,end_per_testcase, {timetrap_timeout,500}}}}}, - {?eh,test_stats,{14,5,{1,19}}}, + {?eh,test_stats,{14,7,{1,19}}}, {?eh,tc_start,{cfg_error_12_SUITE,tc3}}, {?eh,tc_done,{cfg_error_12_SUITE,tc3,ok}}, - {?eh,test_stats,{15,5,{1,19}}}, + {?eh,test_stats,{15,7,{1,19}}}, {?eh,tc_start,{cfg_error_12_SUITE,tc4}}, {?eh,tc_done,{cfg_error_12_SUITE,tc4,{failed, {cfg_error_12_SUITE,end_per_testcase, {timetrap_timeout,500}}}}}, - {?eh,test_stats,{16,5,{1,19}}}, + {?eh,test_stats,{16,7,{1,19}}}, {?eh,tc_start,{cfg_error_13_SUITE,init_per_suite}}, {?eh,tc_done,{cfg_error_13_SUITE,init_per_suite,ok}}, {?eh,tc_start,{cfg_error_13_SUITE,tc1}}, {?eh,tc_done,{cfg_error_13_SUITE,tc1,ok}}, - {?eh,test_stats,{17,5,{1,19}}}, + {?eh,test_stats,{17,7,{1,19}}}, {?eh,tc_start,{cfg_error_13_SUITE,end_per_suite}}, {?eh,tc_done,{cfg_error_13_SUITE,end_per_suite,ok}}, {?eh,tc_start,{cfg_error_14_SUITE,init_per_suite}}, {?eh,tc_done,{cfg_error_14_SUITE,init_per_suite,ok}}, {?eh,tc_start,{cfg_error_14_SUITE,tc1}}, {?eh,tc_done,{cfg_error_14_SUITE,tc1,ok}}, - {?eh,test_stats,{18,5,{1,19}}}, + {?eh,test_stats,{18,7,{1,19}}}, {?eh,tc_start,{cfg_error_14_SUITE,end_per_suite}}, {?eh,tc_done,{cfg_error_14_SUITE,end_per_suite, {comment, diff --git a/lib/test_server/src/test_server.erl b/lib/test_server/src/test_server.erl index ae54925c2e..303ee3ae95 100644 --- a/lib/test_server/src/test_server.erl +++ b/lib/test_server/src/test_server.erl @@ -1194,12 +1194,17 @@ run_test_case_eval1(Mod, Func, Args, Name, RunInit, TCCallback) -> SaveCfg1={save_config,_} -> {FWReturn,TSReturn,[SaveCfg1|lists:keydelete(save_config,1, EndConf1)]}; - {fail,ReasonToFail} -> % user has failed the testcase + {fail,ReasonToFail} -> + %% user has failed the testcase fw_error_notify(Mod, Func, EndConf1, ReasonToFail), {{error,ReasonToFail},{failed,ReasonToFail},EndConf1}; - {failed,{_,end_per_testcase,_}} = Failure -> % unexpected termination + {failed,{_,end_per_testcase,_}} = Failure when FWReturn == ok -> + %% unexpected termination in end_per_testcase + %% report this as the result to the framework {Failure,TSReturn,EndConf1}; _ -> + %% test case result should be reported to framework + %% no matter the status of end_per_testcase {FWReturn,TSReturn,EndConf1} end, %% clear current state in controller loop -- cgit v1.2.3 From 57a84ad4a044a74b19d8b956121feb943bbd5b3a Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Thu, 22 Sep 2011 13:01:31 +0200 Subject: Correct error in test suite --- lib/common_test/test/ct_error_SUITE.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/common_test/test/ct_error_SUITE.erl b/lib/common_test/test/ct_error_SUITE.erl index c3c77d17cd..ebbf6f3bf3 100644 --- a/lib/common_test/test/ct_error_SUITE.erl +++ b/lib/common_test/test/ct_error_SUITE.erl @@ -659,7 +659,7 @@ test_events(lib_error) -> {?eh,test_stats,{0,2,{0,0}}}, {?eh,tc_start,{lib_error_1_SUITE,lines_hang}}, {?eh,tc_done, - {lib_lines,do_hang,{failed,{timetrap_timeout,3000}}}}, + {lib_error_1_SUITE,lines_hang,{failed,{timetrap_timeout,3000}}}}, {?eh,test_stats,{0,3,{0,0}}}, {?eh,tc_start,{lib_error_1_SUITE,lines_throw}}, {?eh,tc_done, -- cgit v1.2.3 From 178940b2184bb3cdaa79d9d51b09c54fbfe68300 Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Thu, 22 Sep 2011 16:40:52 +0200 Subject: Fix crash when CTHook init fails --- lib/common_test/src/ct_util.erl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/common_test/src/ct_util.erl b/lib/common_test/src/ct_util.erl index f393ea103d..3b6ad6f98d 100644 --- a/lib/common_test/src/ct_util.erl +++ b/lib/common_test/src/ct_util.erl @@ -182,7 +182,11 @@ do_start(Parent,Mode,LogDir) -> %% Initialize ct_hooks try ct_hooks:init(Opts) of ok -> - Parent ! {self(),started} + Parent ! {self(),started}; + {fail,CTHReason} -> + ct_logs:tc_print('Suite Callback',CTHReason,[]), + self() ! {{stop,{self(),{user_error,CTHReason}}}, + {Parent,make_ref()}} catch _:CTHReason -> ct_logs:tc_print('Suite Callback',CTHReason,[]), -- cgit v1.2.3 From c7d6fa638a635a9abc7c2f10071f755032ba3617 Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Thu, 22 Sep 2011 18:48:56 +0200 Subject: Fix problem with location value when init config func calls help func --- .../test_server_if/test/ts_if_1_SUITE.erl | 2 +- lib/test_server/src/test_server.erl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_1_SUITE.erl b/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_1_SUITE.erl index 47cea190dd..bda7d91161 100644 --- a/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_1_SUITE.erl +++ b/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_1_SUITE.erl @@ -143,7 +143,7 @@ tc1(_) -> exit(should_have_been_skipped). tc2(_) -> - exit(should_have_been_skipped). + timeout_in_end_per_testcase. tc3(_) -> timer:sleep(5000). diff --git a/lib/test_server/src/test_server.erl b/lib/test_server/src/test_server.erl index 303ee3ae95..e1a139af6f 100644 --- a/lib/test_server/src/test_server.erl +++ b/lib/test_server/src/test_server.erl @@ -1235,7 +1235,7 @@ run_test_case_eval1(Mod, Func, Args, Name, RunInit, TCCallback) -> %% call user callback function if defined Return1 = user_callback(TCCallback, Mod, Func, 'end', Return), {Return2,Opts} = process_return_val([Return1], Mod, Func, - Args1, Loc, Return1), + Args1, {Mod,Func}, Return1), {{T,Return2},Loc,Opts} end. -- cgit v1.2.3 From 18a662a84f65ffd9e8bea60a2948d9b42c3c81f7 Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Thu, 22 Sep 2011 18:50:19 +0200 Subject: Add link to last executed test suite on index page OTP-9520 --- lib/common_test/src/ct_logs.erl | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/common_test/src/ct_logs.erl b/lib/common_test/src/ct_logs.erl index f34eb83afa..0580a814c4 100644 --- a/lib/common_test/src/ct_logs.erl +++ b/lib/common_test/src/ct_logs.erl @@ -509,6 +509,7 @@ logger_loop(State) -> print_style(GL, State#logger_state.stylesheet), set_evmgr_gl(GL), TCGLs = add_tc_gl(TCPid,GL,State), + make_last_run_index(State#logger_state.start_time), return(From,ok), logger_loop(State#logger_state{tc_groupleaders=TCGLs}); {{end_tc,TCPid},From} -> -- cgit v1.2.3 From 22feee99b91818456ee2fcb70fb065b4dee0536e Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Thu, 22 Sep 2011 22:24:20 +0200 Subject: Change order of include files --- lib/common_test/test/ct_test_support.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/common_test/test/ct_test_support.erl b/lib/common_test/test/ct_test_support.erl index 31381abc40..a396a9fad8 100644 --- a/lib/common_test/test/ct_test_support.erl +++ b/lib/common_test/test/ct_test_support.erl @@ -23,8 +23,8 @@ %%% -module(ct_test_support). --include_lib("test_server/include/test_server.hrl"). -include_lib("common_test/include/ct_event.hrl"). +-include_lib("common_test/include/ct.hrl"). -export([init_per_suite/1, init_per_suite/2, end_per_suite/1, init_per_testcase/2, end_per_testcase/2, -- cgit v1.2.3 From b2a37fbc00f29ee6208b0f02b36e9d2f919ecef7 Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Fri, 23 Sep 2011 17:14:03 +0200 Subject: Enhance logging performance OTP-9575 --- lib/common_test/src/ct_framework.erl | 13 ++++++++----- lib/common_test/src/ct_logs.erl | 17 ++++++++++------- 2 files changed, 18 insertions(+), 12 deletions(-) (limited to 'lib') diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl index 089d5be871..63a7c37fa6 100644 --- a/lib/common_test/src/ct_framework.erl +++ b/lib/common_test/src/ct_framework.erl @@ -116,7 +116,7 @@ init_tc1(Mod,Func,[Config0],DoInit) when is_list(Config0) -> Config = lists:keydelete(watchdog,1,Config1), if Func /= init_per_suite, DoInit /= true -> ok; - true -> + true -> %% delete all default values used in previous suite ct_config:delete_default_config(suite), %% release all name -> key bindings (once per suite) @@ -133,7 +133,7 @@ init_tc1(Mod,Func,[Config0],DoInit) when is_list(Config0) -> ct_config:delete_default_config(testcase), case add_defaults(Mod,Func,TestCaseInfo,DoInit) of Error = {suite0_failed,_} -> - ct_logs:init_tc(), + ct_logs:init_tc(false), FuncSpec = group_or_func(Func,Config0), ct_event:notify(#event{name=tc_start, node=node(), @@ -143,7 +143,7 @@ init_tc1(Mod,Func,[Config0],DoInit) when is_list(Config0) -> {SuiteInfo,MergeResult} -> case MergeResult of {error,Reason} when DoInit == false -> - ct_logs:init_tc(), + ct_logs:init_tc(false), FuncSpec = group_or_func(Func,Config0), ct_event:notify(#event{name=tc_start, node=node(), @@ -194,8 +194,11 @@ init_tc2(Mod,Func,SuiteInfo,MergeResult,Config,DoInit) -> Conns -> ct_util:silence_connections(Conns) end, - - ct_logs:init_tc(), + if Func /= init_per_suite, DoInit /= true -> + ct_logs:init_tc(false); + true -> + ct_logs:init_tc(true) + end, FuncSpec = group_or_func(Func,Config), ct_event:notify(#event{name=tc_start, node=node(), diff --git a/lib/common_test/src/ct_logs.erl b/lib/common_test/src/ct_logs.erl index 0580a814c4..3798f26f7b 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/2,init_tc/0,end_tc/1]). +-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([set_stylesheet/2,clear_stylesheet/1]). -export([add_external_logs/1,add_link/3]). @@ -197,15 +197,14 @@ cast(Msg) -> ?MODULE ! Msg end. - %%%----------------------------------------------------------------- -%%% @spec init_tc() -> ok +%%% @spec init_tc(RefreshLog) -> ok %%% %%% @doc Test case initiation (tool-internal use only). %%% %%%

This function is called by ct_framework:init_tc/3

-init_tc() -> - call({init_tc,self(),group_leader()}), +init_tc(RefreshLog) -> + call({init_tc,self(),group_leader(),RefreshLog}), ok. %%%----------------------------------------------------------------- @@ -505,11 +504,15 @@ logger_loop(State) -> [begin io:format(Fd,Str,Args),io:nl(Fd) end || {Str,Args} <- List], logger_loop(State#logger_state{tc_groupleaders=TCGLs}) end; - {{init_tc,TCPid,GL},From} -> + {{init_tc,TCPid,GL,RefreshLog},From} -> print_style(GL, State#logger_state.stylesheet), set_evmgr_gl(GL), TCGLs = add_tc_gl(TCPid,GL,State), - make_last_run_index(State#logger_state.start_time), + if not RefreshLog -> + ok; + true -> + make_last_run_index(State#logger_state.start_time) + end, return(From,ok), logger_loop(State#logger_state{tc_groupleaders=TCGLs}); {{end_tc,TCPid},From} -> -- cgit v1.2.3 From cf69b30f660149c0f39e9cc22b00fb3a90c613b8 Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Fri, 23 Sep 2011 17:15:42 +0200 Subject: Update vsn.mk for common_test and test_server --- lib/common_test/vsn.mk | 2 +- lib/test_server/vsn.mk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/common_test/vsn.mk b/lib/common_test/vsn.mk index f77629b4d1..4782a32933 100644 --- a/lib/common_test/vsn.mk +++ b/lib/common_test/vsn.mk @@ -1,3 +1,3 @@ -COMMON_TEST_VSN = 1.5.4 +COMMON_TEST_VSN = 1.5.5 diff --git a/lib/test_server/vsn.mk b/lib/test_server/vsn.mk index 1dd4a84ce9..563c1b6db6 100644 --- a/lib/test_server/vsn.mk +++ b/lib/test_server/vsn.mk @@ -1,2 +1,2 @@ -TEST_SERVER_VSN = 3.4.4 +TEST_SERVER_VSN = 3.4.5 -- cgit v1.2.3 From 5891e32d8fe1b7ad05e9bca4f37bad746ee64c21 Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Mon, 26 Sep 2011 12:00:26 +0200 Subject: Improve info in CT framework log --- lib/common_test/src/ct_framework.erl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl index 63a7c37fa6..02a5d60445 100644 --- a/lib/common_test/src/ct_framework.erl +++ b/lib/common_test/src/ct_framework.erl @@ -1031,6 +1031,10 @@ make_conf(Mod, Name, Props, TestSpec) -> true -> {{Mod,init_per_group},{Mod,end_per_group}}; false -> + ct_logs:log("TEST INFO", "init_per_group/2 and " + "end_per_group/2 missing for group " + "~p in ~p, using default.", + [Name,Mod]), {{?MODULE,ct_init_per_group}, {?MODULE,ct_end_per_group}} end, @@ -1208,14 +1212,14 @@ error_in_suite(Config) -> %% use these instead ct_init_per_group(GroupName, Config) -> ct:comment(io_lib:format("start of ~p", [GroupName])), - ct_logs:log("WARNING", "init_per_group/2 for ~w missing " + ct_logs:log("TEST INFO", "init_per_group/2 for ~w missing " "in suite, using default.", [GroupName]), Config. ct_end_per_group(GroupName, _) -> ct:comment(io_lib:format("end of ~p", [GroupName])), - ct_logs:log("WARNING", "end_per_group/2 for ~w missing " + ct_logs:log("TEST INFO", "end_per_group/2 for ~w missing " "in suite, using default.", [GroupName]), ok. -- cgit v1.2.3 From 26550631bf825d738bd8c20c9fdb600e9867d81f Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Tue, 27 Sep 2011 01:24:12 +0200 Subject: Fix problem with test_server_ctrl creating invalid conf test OTP-9584 --- lib/common_test/src/ct_framework.erl | 10 +++++----- lib/test_server/src/test_server_ctrl.erl | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl index 02a5d60445..fb89685b7b 100644 --- a/lib/common_test/src/ct_framework.erl +++ b/lib/common_test/src/ct_framework.erl @@ -478,7 +478,6 @@ end_tc(Mod,Func,TCPid,Result,Args,Return) -> _ -> ok end, - ct_util:delete_testdata(comment), ct_util:delete_suite_data(last_saved_config), FuncSpec = @@ -1026,19 +1025,20 @@ make_conf(Mod, Name, Props, TestSpec) -> _ -> ok end, - {InitConf,EndConf} = + {InitConf,EndConf,ExtraProps} = case erlang:function_exported(Mod,init_per_group,2) of true -> - {{Mod,init_per_group},{Mod,end_per_group}}; + {{Mod,init_per_group},{Mod,end_per_group},[]}; false -> ct_logs:log("TEST INFO", "init_per_group/2 and " "end_per_group/2 missing for group " "~p in ~p, using default.", [Name,Mod]), {{?MODULE,ct_init_per_group}, - {?MODULE,ct_end_per_group}} + {?MODULE,ct_end_per_group}, + [{suite,Mod}]} end, - {conf,[{name,Name}|Props],InitConf,TestSpec,EndConf}. + {conf,[{name,Name}|Props++ExtraProps],InitConf,TestSpec,EndConf}. %%%----------------------------------------------------------------- diff --git a/lib/test_server/src/test_server_ctrl.erl b/lib/test_server/src/test_server_ctrl.erl index 7554a31530..4fad86d16d 100644 --- a/lib/test_server/src/test_server_ctrl.erl +++ b/lib/test_server/src/test_server_ctrl.erl @@ -2039,6 +2039,21 @@ add_init_and_end_per_suite([{skip_case,{conf,_,{Mod,_},_}}=Case|Cases], LastMod, PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef, FwMod)]; add_init_and_end_per_suite([{skip_case,_}=Case|Cases], LastMod, LastRef, FwMod) -> [Case|add_init_and_end_per_suite(Cases, LastMod, LastRef, FwMod)]; +add_init_and_end_per_suite([{conf,Ref,Props,{FwMod,Func}}=Case|Cases], LastMod, + LastRef, FwMod) -> + %% if Mod == FwMod, this conf test is (probably) a test case group where + %% the init- and end-functions are missing in the suite, and if so, + %% the suite name should be stored as {suite,Suite} in Props + case proplists:get_value(suite, Props) of + Suite when Suite =/= undefined, Suite =/= LastMod -> + {PreCases, NextMod, NextRef} = + do_add_init_and_end_per_suite(LastMod, LastRef, Suite), + Case1 = {conf,Ref,proplists:delete(suite,Props),{FwMod,Func}}, + PreCases ++ [Case1|add_init_and_end_per_suite(Cases, NextMod, + NextRef, FwMod)]; + _ -> + [Case|add_init_and_end_per_suite(Cases, LastMod, LastRef, FwMod)] + end; add_init_and_end_per_suite([{conf,_,_,{Mod,_}}=Case|Cases], LastMod, LastRef, FwMod) when Mod =/= LastMod, Mod =/= FwMod -> {PreCases, NextMod, NextRef} = -- cgit v1.2.3 From 3c6e2ebefc49b08532e532ef33b6ae0db4b4a981 Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Tue, 27 Sep 2011 01:47:41 +0200 Subject: Fix invalid call to undefined function OTP-9585 --- lib/common_test/src/ct_run.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl index 4ec3ac589d..26ca4f3cb4 100644 --- a/lib/common_test/src/ct_run.erl +++ b/lib/common_test/src/ct_run.erl @@ -509,7 +509,7 @@ script_start4(#opts{label = Label, profile = Profile, case install(InstallOpts) of ok -> ct_util:start(interactive, LogDir), - ct_util:set_testdata(logopts, LogOpts), + ct_util:set_testdata({logopts, LogOpts}), log_ts_names(Specs), io:nl(), ok; -- cgit v1.2.3 From 021b96da72cb7be9c65296016cd8a1eb8c6fc604 Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Tue, 27 Sep 2011 01:55:58 +0200 Subject: Fix errors in test suites --- lib/common_test/test/ct_groups_test_2_SUITE.erl | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/common_test/test/ct_groups_test_2_SUITE.erl b/lib/common_test/test/ct_groups_test_2_SUITE.erl index f33be8a9d4..940d791b15 100644 --- a/lib/common_test/test/ct_groups_test_2_SUITE.erl +++ b/lib/common_test/test/ct_groups_test_2_SUITE.erl @@ -173,16 +173,14 @@ test_events(missing_conf) -> {?eh,start_info,{1,1,2}}, {?eh,tc_start,{ct_framework,ct_init_per_group}}, {?eh,tc_done,{ct_framework,ct_init_per_group,ok}}, - {?eh,test_stats,{1,0,{0,0}}}, {?eh,tc_start,{missing_conf_SUITE,tc1}}, {?eh,tc_done,{missing_conf_SUITE,tc1,ok}}, - {?eh,test_stats,{2,0,{0,0}}}, + {?eh,test_stats,{1,0,{0,0}}}, {?eh,tc_start,{missing_conf_SUITE,tc2}}, {?eh,tc_done,{missing_conf_SUITE,tc2,ok}}, - {?eh,test_stats,{3,0,{0,0}}}, + {?eh,test_stats,{2,0,{0,0}}}, {?eh,tc_start,{ct_framework,ct_end_per_group}}, {?eh,tc_done,{ct_framework,ct_end_per_group,ok}}, - {?eh,test_stats,{4,0,{0,0}}}, {?eh,test_done,{'DEF','STOP_TIME'}}, {?eh,stop_logging,[]} ]; -- cgit v1.2.3 From 001f0a4baa95ccc6eb553cad9e4551b4e520dc8b Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Tue, 27 Sep 2011 13:24:23 +0200 Subject: Solve problem with ct_init/end_per_group being counted as test cases --- lib/common_test/src/ct_framework.erl | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib') diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl index fb89685b7b..37ecf4f928 100644 --- a/lib/common_test/src/ct_framework.erl +++ b/lib/common_test/src/ct_framework.erl @@ -1296,6 +1296,10 @@ report(What,Data) -> ok; {end_per_group,_} -> ok; + {ct_init_per_group,_} -> + ok; + {ct_end_per_group,_} -> + ok; {_,ok} -> add_to_stats(ok); {_,{skipped,{failed,{_,init_per_testcase,_}}}} -> -- cgit v1.2.3 From b7f1a0861daa57db115b358927293d98e1630810 Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Wed, 28 Sep 2011 17:43:26 +0200 Subject: Add missing tests for timetrap handling and fix remaining errors OTP-9593 --- lib/common_test/src/ct_framework.erl | 8 +- lib/common_test/test/ct_error_SUITE.erl | 113 ++++++++++++++- .../error/test/timetrap_3_SUITE.erl | 146 +++++++++++++++++++ .../error/test/timetrap_4_SUITE.erl | 135 ++++++++++++++++++ .../error/test/timetrap_5_SUITE.erl | 155 +++++++++++++++++++++ .../error/test/timetrap_6_SUITE.erl | 114 +++++++++++++++ .../error/test/timetrap_7_SUITE.erl | 137 ++++++++++++++++++ .../error/test/timetrap_utils.erl | 43 ++++++ lib/test_server/src/test_server.erl | 61 +++++--- 9 files changed, 888 insertions(+), 24 deletions(-) create mode 100644 lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_3_SUITE.erl create mode 100644 lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_4_SUITE.erl create mode 100644 lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_5_SUITE.erl create mode 100644 lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_6_SUITE.erl create mode 100644 lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_7_SUITE.erl create mode 100644 lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_utils.erl (limited to 'lib') diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl index 37ecf4f928..482c5242ce 100644 --- a/lib/common_test/src/ct_framework.erl +++ b/lib/common_test/src/ct_framework.erl @@ -204,12 +204,14 @@ init_tc2(Mod,Func,SuiteInfo,MergeResult,Config,DoInit) -> node=node(), data={Mod,FuncSpec}}), - case configure(MergedInfo1,MergedInfo1,SuiteInfo,{Func,DoInit},Config) of + case catch configure(MergedInfo1,MergedInfo1,SuiteInfo,{Func,DoInit},Config) of {suite0_failed,Reason} -> ct_util:set_testdata({curr_tc,{Mod,{suite0_failed,{require,Reason}}}}), {skip,{require_failed_in_suite0,Reason}}; {error,Reason} -> {auto_skip,{require_failed,Reason}}; + {'EXIT',Reason} -> + {auto_skip,Reason}; {ok, FinalConfig} -> case MergeResult of {error,Reason} -> @@ -1306,6 +1308,10 @@ report(What,Data) -> add_to_stats(auto_skipped); {_,{skipped,{require_failed,_}}} -> add_to_stats(auto_skipped); + {_,{skipped,{timetrap_error,_}}} -> + add_to_stats(auto_skipped); + {_,{skipped,{invalid_time_format,_}}} -> + add_to_stats(auto_skipped); {_,{skipped,_}} -> add_to_stats(user_skipped); {_,{SkipOrFail,_Reason}} -> diff --git a/lib/common_test/test/ct_error_SUITE.erl b/lib/common_test/test/ct_error_SUITE.erl index ebbf6f3bf3..d6ee8eed10 100644 --- a/lib/common_test/test/ct_error_SUITE.erl +++ b/lib/common_test/test/ct_error_SUITE.erl @@ -60,7 +60,8 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [cfg_error, lib_error, no_compile, timetrap_end_conf, - timetrap_normal, timetrap_extended]. + timetrap_normal, timetrap_extended, timetrap_parallel, + timetrap_fun]. groups() -> []. @@ -227,6 +228,28 @@ timetrap_parallel(Config) when is_list(Config) -> TestEvents = events_to_check(timetrap_parallel), ok = ct_test_support:verify_events(TestEvents, Events, Config). +%%%----------------------------------------------------------------- +%%% +timetrap_fun(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + Join = fun(D, S) -> filename:join(D, "error/test/"++S) end, + Suites = [Join(DataDir, "timetrap_4_SUITE"), + Join(DataDir, "timetrap_5_SUITE"), + Join(DataDir, "timetrap_6_SUITE"), + Join(DataDir, "timetrap_7_SUITE")], + {Opts,ERPid} = setup([{suite,Suites}], Config), + ok = ct_test_support:run(Opts, Config), + Events = ct_test_support:get_events(ERPid, Config), + + ct_test_support:log_events(timetrap_fun, + reformat(Events, ?eh), + ?config(priv_dir, Config), + Opts), + + TestEvents = events_to_check(timetrap_fun), + ok = ct_test_support:verify_events(TestEvents, Events, Config). + + %%%----------------------------------------------------------------- %%% HELP FUNCTIONS %%%----------------------------------------------------------------- @@ -814,7 +837,7 @@ test_events(timetrap_parallel) -> [ {?eh,start_logging,{'DEF','RUNDIR'}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, - {?eh,start_info,{1,1,7}}, + {?eh,start_info,{1,1,8}}, {?eh,tc_done,{timetrap_3_SUITE,init_per_suite,ok}}, {parallel, [{?eh,tc_start, @@ -826,8 +849,11 @@ test_events(timetrap_parallel) -> {?eh,tc_start,{timetrap_3_SUITE,tc2}}, {?eh,tc_start,{timetrap_3_SUITE,tc3}}, {?eh,tc_start,{timetrap_3_SUITE,tc4}}, + {?eh,tc_start,{timetrap_3_SUITE,tc5}}, {?eh,tc_start,{timetrap_3_SUITE,tc6}}, {?eh,tc_start,{timetrap_3_SUITE,tc7}}, + {?eh,tc_done, + {timetrap_3_SUITE,tc5,ok}}, {?eh,tc_done, {timetrap_3_SUITE,tc1,{failed,{timetrap_timeout,500}}}}, {?eh,tc_done, @@ -842,11 +868,90 @@ test_events(timetrap_parallel) -> {timetrap_3_SUITE,tc4,{failed,{timetrap_timeout,2000}}}}, {?eh,tc_done, {timetrap_3_SUITE,tc3,{failed,{timetrap_timeout,3000}}}}, - {?eh,test_stats,{0,7,{0,0}}}, + {?eh,test_stats,{1,7,{0,0}}}, {?eh,tc_start, {timetrap_3_SUITE,{end_per_group,g1,[parallel]}}}, {?eh,tc_done, {timetrap_3_SUITE,{end_per_group,g1,[parallel]},ok}}]}, {?eh,tc_done,{timetrap_3_SUITE,end_per_suite,ok}}, {?eh,test_done,{'DEF','STOP_TIME'}}, - {?eh,stop_logging,[]}]. + {?eh,stop_logging,[]}]; + +test_events(timetrap_fun) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,start_info,{4,4,17}}, + {?eh,tc_done,{timetrap_4_SUITE,init_per_suite,ok}}, + {?eh,tc_start,{timetrap_4_SUITE,tc0}}, + {?eh,tc_done, + {timetrap_4_SUITE,tc0,{failed,{timetrap_timeout,1000}}}}, + {?eh,tc_start,{timetrap_4_SUITE,tc1}}, + {?eh,tc_done, + {timetrap_4_SUITE,tc1,{failed,{timetrap_timeout,2000}}}}, + {?eh,tc_start,{timetrap_4_SUITE,tc2}}, + {?eh,tc_done, + {timetrap_4_SUITE,tc2,{failed,{timetrap_timeout,500}}}}, + {?eh,tc_start,{timetrap_4_SUITE,tc3}}, + {?eh,tc_done, + {timetrap_4_SUITE,tc3,{failed,{timetrap_timeout,1000}}}}, + {?eh,test_stats,{0,4,{0,0}}}, + {?eh,tc_done,{timetrap_4_SUITE,end_per_suite,ok}}, + + {?eh,tc_done,{timetrap_5_SUITE,init_per_suite,ok}}, + {?eh,tc_start,{timetrap_5_SUITE,tc0}}, + {?eh,tc_done, + {timetrap_5_SUITE,tc0,{failed,{timetrap_timeout,1000}}}}, + {?eh,test_stats,{0,5,{0,0}}}, + {?eh,tc_start,{timetrap_5_SUITE,tc1}}, + {?eh,tc_done, + {timetrap_5_SUITE,tc1,{skipped,{timetrap_error,kaboom}}}}, + {?eh,tc_start,{timetrap_5_SUITE,tc2}}, + {?eh,tc_done, + {timetrap_5_SUITE,tc2,{skipped,{timetrap_error,kaboom}}}}, + {?eh,tc_start,{timetrap_5_SUITE,tc3}}, + {?eh,tc_done, + {timetrap_5_SUITE,tc3, + {skipped,{invalid_time_format,{timetrap_utils,timetrap_val,[5000]}}}}}, + {?eh,tc_start,{timetrap_5_SUITE,tc4}}, + {?eh,tc_done, + {timetrap_5_SUITE,tc4,{skipped,{invalid_time_format,'_'}}}}, + {?eh,test_stats,{0,5,{0,4}}}, + {?eh,tc_start,{timetrap_5_SUITE,tc5}}, + {?eh,tc_done, + {timetrap_5_SUITE,tc5,{failed,{timetrap_timeout,1000}}}}, + {?eh,tc_start,{timetrap_5_SUITE,tc6}}, + {?eh,tc_done, + {timetrap_5_SUITE,tc6,{failed,{timetrap_timeout,1000}}}}, + {?eh,tc_start,{timetrap_5_SUITE,tc7}}, + {?eh,tc_done, + {timetrap_5_SUITE,tc7,{failed,{timetrap_timeout,1000}}}}, + {?eh,test_stats,{0,8,{0,4}}}, + {?eh,tc_done,{timetrap_5_SUITE,end_per_suite,ok}}, + + {?eh,tc_start,{timetrap_6_SUITE,init_per_suite}}, + {?eh,tc_done, + {timetrap_6_SUITE,init_per_suite,{skipped,{timetrap_error,kaboom}}}}, + {?eh,tc_auto_skip, + {timetrap_6_SUITE,tc0,{fw_auto_skip,{timetrap_error,kaboom}}}}, + {?eh,test_stats,{0,8,{0,5}}}, + {?eh,tc_auto_skip, + {timetrap_6_SUITE,end_per_suite,{fw_auto_skip,{timetrap_error,kaboom}}}}, + + {?eh,tc_done,{timetrap_7_SUITE,init_per_suite,ok}}, + {?eh,tc_start,{timetrap_7_SUITE,tc0}}, + {?eh,tc_done, + {timetrap_7_SUITE,tc0,{failed,{timetrap_timeout,1000}}}}, + {?eh,tc_start,{timetrap_7_SUITE,tc1}}, + {?eh,tc_done, + {timetrap_7_SUITE,tc1,{failed,{timetrap_timeout,2000}}}}, + {?eh,tc_start,{timetrap_7_SUITE,tc2}}, + {?eh,tc_done, + {timetrap_7_SUITE,tc2,{failed,{timetrap_timeout,500}}}}, + {?eh,tc_start,{timetrap_7_SUITE,tc3}}, + {?eh,tc_done, + {timetrap_7_SUITE,tc3,{failed,{timetrap_timeout,1000}}}}, + {?eh,test_stats,{0,12,{0,5}}}, + {?eh,tc_done,{timetrap_7_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]. diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_3_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_3_SUITE.erl new file mode 100644 index 0000000000..8271b23afe --- /dev/null +++ b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_3_SUITE.erl @@ -0,0 +1,146 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010-2011. 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 +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +-module(timetrap_3_SUITE). + +-compile(export_all). + +-include_lib("common_test/include/ct.hrl"). + +-define(TO, 3). + +%%-------------------------------------------------------------------- +%% Function: suite() -> Info +%% Info = [tuple()] +%%-------------------------------------------------------------------- +suite() -> + [{timetrap,{seconds,?TO}}]. + +%%-------------------------------------------------------------------- +%% Function: init_per_suite(Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_suite(Config0) -> void() | {save_config,Config1} +%% Config0 = Config1 = [tuple()] +%%-------------------------------------------------------------------- +end_per_suite(_Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Function: init_per_group(GroupName, Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% GroupName = atom() +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%%-------------------------------------------------------------------- +init_per_group(_GroupName, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_group(GroupName, Config0) -> +%% void() | {save_config,Config1} +%% GroupName = atom() +%% Config0 = Config1 = [tuple()] +%%-------------------------------------------------------------------- +end_per_group(_GroupName, _Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Function: groups() -> [Group] +%% Group = {GroupName,Properties,GroupsAndTestCases} +%% GroupName = atom() +%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}] +%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase] +%% TestCase = atom() +%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}} +%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail | +%% repeat_until_any_ok | repeat_until_any_fail +%% N = integer() | forever +%%-------------------------------------------------------------------- +groups() -> + [{g1,[parallel],[tc0,tc1,tc2,tc3,tc4,tc5,tc6,tc7]}]. + +%%-------------------------------------------------------------------- +%% Function: all() -> GroupsAndTestCases | {skip,Reason} +%% GroupsAndTestCases = [{group,GroupName} | TestCase] +%% GroupName = atom() +%% TestCase = atom() +%% Reason = term() +%%-------------------------------------------------------------------- +all() -> + [{group,g1}]. + +tc0() -> + [{timetrap,2000}]. +tc0(_) -> + ct:comment("TO after 2 sec"), + ct:sleep({seconds,5}), + ok. + +tc1() -> + [{timetrap,500}]. +tc1(_) -> + ct:comment("TO after 1/2 sec"), + ct:sleep({seconds,5}), + ok. + +tc2() -> + [{timetrap,1000}]. +tc2(_) -> + ct:comment("TO after 1 sec"), + ct:sleep({seconds,5}), + ok. + +tc3(_) -> + ct:comment(io_lib:format("TO after ~w sec", [?TO])), + ct:sleep({seconds,5}), + ok. + +tc4() -> + [{timetrap,2000}]. +tc4(_) -> + ct:comment(io_lib:format("TO after 2 sec", [])), + ct:sleep({seconds,5}), + ok. + +tc5() -> + [{timetrap,2000}]. +tc5(_) -> + ct:comment("No timeout"), + ct:sleep({seconds,1}), + ok. + +tc6() -> + [{timetrap,1000}]. +tc6(_) -> + ct:comment("TO after 1 sec"), + ct:sleep({seconds,5}), + ok. + +tc7() -> + [{timetrap,1500}]. +tc7(_) -> + ct:comment("TO after 1 1/2 sec"), + ct:sleep({seconds,5}), + ok. diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_4_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_4_SUITE.erl new file mode 100644 index 0000000000..d902454f09 --- /dev/null +++ b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_4_SUITE.erl @@ -0,0 +1,135 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010-2011. 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 +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +-module(timetrap_4_SUITE). + +-compile(export_all). + +-include_lib("common_test/include/ct.hrl"). + +-define(TO, 1). + +%%-------------------------------------------------------------------- +%% Function: suite() -> Info +%% Info = [tuple()] +%%-------------------------------------------------------------------- +suite() -> + [{timetrap,{timetrap_utils,timetrap_val,[{seconds,?TO}]}}]. + +%%-------------------------------------------------------------------- +%% Function: init_per_suite(Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_suite(Config0) -> void() | {save_config,Config1} +%% Config0 = Config1 = [tuple()] +%%-------------------------------------------------------------------- +end_per_suite(_Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Function: init_per_group(GroupName, Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% GroupName = atom() +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%%-------------------------------------------------------------------- +init_per_group(_GroupName, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_group(GroupName, Config0) -> +%% void() | {save_config,Config1} +%% GroupName = atom() +%% Config0 = Config1 = [tuple()] +%%-------------------------------------------------------------------- +end_per_group(_GroupName, _Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Function: init_per_testcase(TestCase, Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% TestCase = atom() +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%%-------------------------------------------------------------------- +init_per_testcase(_, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_testcase(TestCase, Config0) -> +%% void() | {save_config,Config1} +%% TestCase = atom() +%% Config0 = Config1 = [tuple()] +%%-------------------------------------------------------------------- +end_per_testcase(_, _Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Function: groups() -> [Group] +%% Group = {GroupName,Properties,GroupsAndTestCases} +%% GroupName = atom() +%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}] +%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase] +%% TestCase = atom() +%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}} +%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail | +%% repeat_until_any_ok | repeat_until_any_fail +%% N = integer() | forever +%%-------------------------------------------------------------------- +groups() -> + []. + +%%-------------------------------------------------------------------- +%% Function: all() -> GroupsAndTestCases | {skip,Reason} +%% GroupsAndTestCases = [{group,GroupName} | TestCase] +%% GroupName = atom() +%% TestCase = atom() +%% Reason = term() +%%-------------------------------------------------------------------- +all() -> + [tc0,tc1,tc2,tc3]. + +tc0(_) -> + ct:comment(io_lib:format("TO after ~w sec", [?TO])), + ct:sleep({seconds,5}), + ok. + +tc1() -> + [{timetrap,{timetrap_utils,timetrap_val,[2000]}}]. +tc1(_) -> + ct:comment("TO after 2 sec"), + ct:sleep({seconds,5}), + ok. + +tc2() -> + [{timetrap,fun() -> timetrap_utils:timetrap_val(500) end}]. +tc2(_) -> + ct:comment("TO after 0.5 sec"), + ct:sleep(1000), + ok. + +tc3(_) -> + ct:comment(io_lib:format("TO after ~w sec", [?TO])), + ct:sleep({seconds,5}), + ok. diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_5_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_5_SUITE.erl new file mode 100644 index 0000000000..c5d4b5062e --- /dev/null +++ b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_5_SUITE.erl @@ -0,0 +1,155 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010-2011. 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 +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +-module(timetrap_5_SUITE). + +-compile(export_all). + +-include_lib("common_test/include/ct.hrl"). + +-define(TO, 1). + +%%-------------------------------------------------------------------- +%% Function: suite() -> Info +%% Info = [tuple()] +%%-------------------------------------------------------------------- +suite() -> + [{timetrap, fun() -> timetrap_utils:timetrap_val({seconds,?TO}) end}]. + +%%-------------------------------------------------------------------- +%% Function: init_per_suite(Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_suite(Config0) -> void() | {save_config,Config1} +%% Config0 = Config1 = [tuple()] +%%-------------------------------------------------------------------- +end_per_suite(_Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Function: init_per_group(GroupName, Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% GroupName = atom() +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%%-------------------------------------------------------------------- +init_per_group(_GroupName, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_group(GroupName, Config0) -> +%% void() | {save_config,Config1} +%% GroupName = atom() +%% Config0 = Config1 = [tuple()] +%%-------------------------------------------------------------------- +end_per_group(_GroupName, _Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Function: init_per_testcase(TestCase, Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% TestCase = atom() +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%%-------------------------------------------------------------------- +init_per_testcase(_, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_testcase(TestCase, Config0) -> +%% void() | {save_config,Config1} +%% TestCase = atom() +%% Config0 = Config1 = [tuple()] +%%-------------------------------------------------------------------- +end_per_testcase(_, _Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Function: groups() -> [Group] +%% Group = {GroupName,Properties,GroupsAndTestCases} +%% GroupName = atom() +%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}] +%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase] +%% TestCase = atom() +%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}} +%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail | +%% repeat_until_any_ok | repeat_until_any_fail +%% N = integer() | forever +%%-------------------------------------------------------------------- +groups() -> + []. + +%%-------------------------------------------------------------------- +%% Function: all() -> GroupsAndTestCases | {skip,Reason} +%% GroupsAndTestCases = [{group,GroupName} | TestCase] +%% GroupName = atom() +%% TestCase = atom() +%% Reason = term() +%%-------------------------------------------------------------------- +all() -> + [tc0,tc1,tc2,tc3,tc4,tc5,tc6,tc7]. + +tc0(_) -> + ct:comment(io_lib:format("TO after ~w sec", [?TO])), + ct:sleep({seconds,5}), + ok. + +tc1() -> + [{timetrap,{timetrap_utils,timetrap_exit,[kaboom]}}]. +tc1(_) -> + exit(this_should_not_execute). + +tc2() -> + [{timetrap,fun() -> exit(kaboom) end}]. +tc2(_) -> + exit(this_should_not_execute). + +tc3() -> + [{timetrap,{timetrap_utils,timetrap_err_mfa,[]}}]. +tc3(_) -> + exit(this_should_not_execute). + +tc4() -> + [{timetrap,fun() -> timetrap_utils:timetrap_err_fun() end}]. +tc4(_) -> + exit(this_should_not_execute). + +tc5() -> + [{timetrap,{timetrap_utils,timetrap_timeout,[{seconds,40}, + {seconds,1}]}}]. +tc5(_) -> + ct:comment("TO after 40+1 sec"), + ct:sleep({seconds,42}), + ok. + +tc6() -> + [{timetrap,fun() -> ct:sleep(6000), 1000 end}]. +tc6(_) -> + ct:comment("TO after 6+1 sec"), + ct:sleep({seconds,10}). + +tc7(_) -> + ct:comment(io_lib:format("TO after ~w sec", [?TO])), + ct:sleep({seconds,5}), + ok. diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_6_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_6_SUITE.erl new file mode 100644 index 0000000000..90467ff752 --- /dev/null +++ b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_6_SUITE.erl @@ -0,0 +1,114 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010-2011. 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 +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +-module(timetrap_6_SUITE). + +-compile(export_all). + +-include_lib("common_test/include/ct.hrl"). + +-define(TO, 1). + +%%-------------------------------------------------------------------- +%% Function: suite() -> Info +%% Info = [tuple()] +%%-------------------------------------------------------------------- +suite() -> + [{timetrap, fun() -> exit(kaboom) end}]. + +%%-------------------------------------------------------------------- +%% Function: init_per_suite(Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_suite(Config0) -> void() | {save_config,Config1} +%% Config0 = Config1 = [tuple()] +%%-------------------------------------------------------------------- +end_per_suite(_Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Function: init_per_group(GroupName, Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% GroupName = atom() +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%%-------------------------------------------------------------------- +init_per_group(_GroupName, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_group(GroupName, Config0) -> +%% void() | {save_config,Config1} +%% GroupName = atom() +%% Config0 = Config1 = [tuple()] +%%-------------------------------------------------------------------- +end_per_group(_GroupName, _Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Function: init_per_testcase(TestCase, Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% TestCase = atom() +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%%-------------------------------------------------------------------- +init_per_testcase(_, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_testcase(TestCase, Config0) -> +%% void() | {save_config,Config1} +%% TestCase = atom() +%% Config0 = Config1 = [tuple()] +%%-------------------------------------------------------------------- +end_per_testcase(_, _Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Function: groups() -> [Group] +%% Group = {GroupName,Properties,GroupsAndTestCases} +%% GroupName = atom() +%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}] +%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase] +%% TestCase = atom() +%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}} +%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail | +%% repeat_until_any_ok | repeat_until_any_fail +%% N = integer() | forever +%%-------------------------------------------------------------------- +groups() -> + []. + +%%-------------------------------------------------------------------- +%% Function: all() -> GroupsAndTestCases | {skip,Reason} +%% GroupsAndTestCases = [{group,GroupName} | TestCase] +%% GroupName = atom() +%% TestCase = atom() +%% Reason = term() +%%-------------------------------------------------------------------- +all() -> + [tc0]. + +tc0(_) -> + ok. diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_7_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_7_SUITE.erl new file mode 100644 index 0000000000..b25b7770a7 --- /dev/null +++ b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_7_SUITE.erl @@ -0,0 +1,137 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010-2011. 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 +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +-module(timetrap_7_SUITE). + +-compile(export_all). + +-include_lib("common_test/include/ct.hrl"). + +-define(TO, 1). +-define(HANG, 6). + +%%-------------------------------------------------------------------- +%% Function: suite() -> Info +%% Info = [tuple()] +%%-------------------------------------------------------------------- +suite() -> + [{timetrap,{timetrap_utils,timetrap_timeout,[{seconds,?HANG}, + {seconds,?TO}]}}]. + +%%-------------------------------------------------------------------- +%% Function: init_per_suite(Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_suite(Config0) -> void() | {save_config,Config1} +%% Config0 = Config1 = [tuple()] +%%-------------------------------------------------------------------- +end_per_suite(_Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Function: init_per_group(GroupName, Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% GroupName = atom() +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%%-------------------------------------------------------------------- +init_per_group(_GroupName, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_group(GroupName, Config0) -> +%% void() | {save_config,Config1} +%% GroupName = atom() +%% Config0 = Config1 = [tuple()] +%%-------------------------------------------------------------------- +end_per_group(_GroupName, _Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Function: init_per_testcase(TestCase, Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% TestCase = atom() +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%%-------------------------------------------------------------------- +init_per_testcase(_, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_testcase(TestCase, Config0) -> +%% void() | {save_config,Config1} +%% TestCase = atom() +%% Config0 = Config1 = [tuple()] +%%-------------------------------------------------------------------- +end_per_testcase(_, _Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Function: groups() -> [Group] +%% Group = {GroupName,Properties,GroupsAndTestCases} +%% GroupName = atom() +%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}] +%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase] +%% TestCase = atom() +%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}} +%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail | +%% repeat_until_any_ok | repeat_until_any_fail +%% N = integer() | forever +%%-------------------------------------------------------------------- +groups() -> + []. + +%%-------------------------------------------------------------------- +%% Function: all() -> GroupsAndTestCases | {skip,Reason} +%% GroupsAndTestCases = [{group,GroupName} | TestCase] +%% GroupName = atom() +%% TestCase = atom() +%% Reason = term() +%%-------------------------------------------------------------------- +all() -> + [tc0,tc1,tc2,tc3]. + +tc0(_) -> + ct:comment(io_lib:format("TO after ~w+~w sec", [?HANG,?TO])), + ct:sleep({seconds,5}), + ok. + +tc1() -> + [{timetrap,{timetrap_utils,timetrap_val,[2000]}}]. +tc1(_) -> + ct:comment("TO after 2 sec"), + ct:sleep({seconds,5}), + ok. + +tc2() -> + [{timetrap,fun() -> timetrap_utils:timetrap_val(500) end}]. +tc2(_) -> + ct:comment("TO after 0.5 sec"), + ct:sleep(1000), + ok. + +tc3(_) -> + ct:comment(io_lib:format("TO after ~w+~w sec", [?HANG,?TO])), + ct:sleep({seconds,5}), + ok. diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_utils.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_utils.erl new file mode 100644 index 0000000000..fcde6cd701 --- /dev/null +++ b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_utils.erl @@ -0,0 +1,43 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009-2011. 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 +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(timetrap_utils). + +-export([timetrap_val/1, + timetrap_err_fun/0, + timetrap_err_mfa/0, + timetrap_exit/1, + timetrap_timeout/2]). + +timetrap_val(Val) -> + Val. + +timetrap_err_fun() -> + fun() -> 5000 end. + +timetrap_err_mfa() -> + {?MODULE,timetrap_val,[5000]}. + +timetrap_exit(Reason) -> + exit(Reason). + +timetrap_timeout(Sleep, Val) -> + ct:sleep(Sleep), + Val. + diff --git a/lib/test_server/src/test_server.erl b/lib/test_server/src/test_server.erl index e1a139af6f..12625e3c00 100644 --- a/lib/test_server/src/test_server.erl +++ b/lib/test_server/src/test_server.erl @@ -1921,30 +1921,53 @@ time_ms({seconds,N}) -> seconds(N); time_ms({Other,_N}) -> format("=== ERROR: Invalid time specification: ~p. " "Should be seconds, minutes, or hours.~n", [Other]), - exit({invalid_time_spec,Other}); + exit({invalid_time_format,Other}); time_ms(Ms) when is_integer(Ms) -> Ms; time_ms(infinity) -> infinity; time_ms(Fun) when is_function(Fun) -> - try Fun() of - Val -> time_ms1(Val) - catch - _:Error -> - exit({timetrap_error,Error}) - end; -time_ms({M,F,A}) when is_atom(M), is_atom(F), is_list(A) -> - try apply(M, F, A) of - Val -> time_ms1(Val) - catch - _:Error -> + time_ms_apply(Fun); +time_ms({M,F,A}=MFA) when is_atom(M), is_atom(F), is_list(A) -> + time_ms_apply(MFA); +time_ms(Other) -> exit({invalid_time_format,Other}). + +time_ms_apply(Func) -> + time_ms_apply(Func, [5000,30000,60000,infinity]). + +time_ms_apply(Func, TOs) -> + Apply = fun() -> + case Func of + {M,F,A} -> + exit({self(),apply(M, F, A)}); + Fun -> + exit({self(),Fun()}) + end + end, + Pid = spawn(Apply), + Ref = monitor(process, Pid), + time_ms_wait(Func, Pid, Ref, TOs). + +time_ms_wait(Func, Pid, Ref, [TO|TOs]) -> + receive + {'DOWN',Ref,process,Pid,{Pid,Result}} -> + time_ms_check(Result); + {'DOWN',Ref,process,Pid,Error} -> exit({timetrap_error,Error}) + after + TO -> + format("=== WARNING: No return from timetrap function ~p~n", [Func]), + time_ms_wait(Func, Pid, Ref, TOs) end; -time_ms(Other) -> exit({invalid_time_spec,Other}). - -time_ms1(MFA = {M,F,A}) when is_atom(M), is_atom(F), is_list(A) -> - exit({invalid_time_spec,MFA}); -time_ms1(Fun) when is_function(Fun) -> - exit({invalid_time_spec,Fun}); -time_ms1(Other) -> +%% this clause will never execute if 'infinity' is in TOs list, that's ok! +time_ms_wait(Func, Pid, Ref, []) -> + demonitor(Ref), + exit(Pid, kill), + exit({timetrap_error,{no_return_from_timetrap_function,Func}}). + +time_ms_check(MFA = {M,F,A}) when is_atom(M), is_atom(F), is_list(A) -> + exit({invalid_time_format,MFA}); +time_ms_check(Fun) when is_function(Fun) -> + exit({invalid_time_format,Fun}); +time_ms_check(Other) -> time_ms(Other). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -- cgit v1.2.3 From e78be5c09eda6a8738d07d801dd8935f3eaa5400 Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Thu, 29 Sep 2011 00:21:27 +0200 Subject: Add documentation on timetraps and start flags --- lib/common_test/doc/src/common_test_app.xml | 32 +++++++++++++++++++------- lib/common_test/doc/src/write_test_chapter.xml | 14 +++++++---- lib/common_test/src/ct.erl | 2 +- 3 files changed, 35 insertions(+), 13 deletions(-) (limited to 'lib') diff --git a/lib/common_test/doc/src/common_test_app.xml b/lib/common_test/doc/src/common_test_app.xml index 57b032b3fd..f58b2ab0a9 100644 --- a/lib/common_test/doc/src/common_test_app.xml +++ b/lib/common_test/doc/src/common_test_app.xml @@ -133,9 +133,15 @@ {require,Name,Required} | {userdata,UserData} | {silent_connections,Conns} | {stylesheet,CSSFile} | {ct_hooks, CTHs} - Time = MilliSec | {seconds,integer()} | {minutes,integer()} - | {hours,integer()} + Time = TimeVal | TimeFunc + TimeVal = MilliSec | {seconds,integer()} | {minutes,integer()} | + {hours,integer()} + TimeFunc = {Mod,Func,Args} | Fun MilliSec = integer() + Mod = atom() + Func = atom() + Args = list() + Fun = fun() Required = Key | {Key,SubKeys} Key = atom() SubKeys = SubKey | [SubKey] @@ -161,7 +167,9 @@ test case is allowed to take (including init_per_testcase/2 and end_per_testcase/2). If the timetrap time is exceeded, the test case fails with reason - timetrap_timeout.

+ timetrap_timeout. If a TimeFunc function is specified, + it will be called initially and must return a value on + TimeVal format.

The require tag specifies configuration variables that are required by test cases in the suite. If the required @@ -248,7 +256,7 @@ -

MANDATORY (only if one or more groups are defined)

+

OPTIONAL

This function is called before execution of a test case group. It typically contains initialization which is common for @@ -279,7 +287,7 @@ -

MANDATORY (only if one or more groups are defined)

+

OPTIONAL

This function is called after the execution of a test case group is finished. It is meant to be used for cleaning up after init_per_group/2. @@ -353,9 +361,15 @@ Info = {timetrap,Time} | {require,Required} | {require,Name,Required} | {userdata,UserData} | {silent_connections,Conns} - Time = MilliSec | {seconds,integer()} | {minutes,integer()} - | {hours,integer()} + Time = TimeVal | TimeFunc + TimeVal = MilliSec | {seconds,integer()} | {minutes,integer()} | + {hours,integer()} + TimeFunc = {Mod,Func,Args} | Fun MilliSec = integer() + Mod = atom() + Func = atom() + Args = list() + Fun = fun() Required = Key | {Key,SubKeys} Key = atom() SubKeys = SubKey | [SubKey] @@ -378,7 +392,9 @@ exceeded, the test case fails with reason timetrap_timeout. init_per_testcase/2 and end_per_testcase/2 are included in the - timetrap time.

+ timetrap time. If a TimeFunc function is specified, + it will be called before the test case (or init_per_testcase/2) + and must return a value on TimeVal format.

The require tag specifies configuration variables that are required by the test case. If the required diff --git a/lib/common_test/doc/src/write_test_chapter.xml b/lib/common_test/doc/src/write_test_chapter.xml index 3f9fdb7121..e35888e68f 100644 --- a/lib/common_test/doc/src/write_test_chapter.xml +++ b/lib/common_test/doc/src/write_test_chapter.xml @@ -280,6 +280,8 @@ the timetrap time is exceeded, the test case fails with reason timetrap_timeout. Note that init_per_testcase and end_per_testcase are included in the timetrap time. + Please see the Timetrap + section for more details.

userdata @@ -699,8 +701,8 @@
- Timetrap timeouts + Timetrap timeouts

The default time limit for a test case is 30 minutes, unless a timetrap is specified either by the suite info function or a test case info function. The timetrap timeout value defined @@ -723,6 +725,13 @@ multipled by multiply_timetraps, and possibly scaled up if scale_timetraps is enabled, the function ct:sleep/1 may be called.

+

A function (fun or MFA) may be specified as timetrap value + in the suite- and test case info function, e.g:

+

{timetrap,{test_utils,get_timetrap_value,[?MODULE,system_start]}}

+

The function will be called initially by Common Test (before execution + of the suite or the test case) and must return a time value such as an + integer (millisec), or a {SecMinOrHourTag,Time} tuple. More + information can be found in the common_test reference manual.

@@ -818,6 +827,3 @@
- - - diff --git a/lib/common_test/src/ct.erl b/lib/common_test/src/ct.erl index 4c215d1b1e..f3c2029734 100644 --- a/lib/common_test/src/ct.erl +++ b/lib/common_test/src/ct.erl @@ -151,7 +151,7 @@ run(TestDirs) -> %%% {refresh_logs,LogDir} | {logopts,LogOpts} | {basic_html,Bool} | %%% {ct_hooks, CTHs} %%% TestDirs = [string()] | string() -%%% Suites = [string()] | string() +%%% Suites = [string()] | [atom()] | string() | atom() %%% Cases = [atom()] | atom() %%% Groups = [atom()] | atom() %%% TestSpecs = [string()] | string() -- cgit v1.2.3 From 5f04095f2c991a1d2e2c40bfa609342ac9ff9ebe Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Thu, 29 Sep 2011 15:17:37 +0200 Subject: Correct "Missing Suites" link OTP-9592 --- lib/common_test/src/ct_logs.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/common_test/src/ct_logs.erl b/lib/common_test/src/ct_logs.erl index 3798f26f7b..faec461775 100644 --- a/lib/common_test/src/ct_logs.erl +++ b/lib/common_test/src/ct_logs.erl @@ -838,6 +838,7 @@ make_one_index_entry1(SuiteName, Link, Label, Success, Fail, UserSkip, AutoSkip, "" end end, + CtRunDir = filename:dirname(filename:dirname(Link)), {Lbl,Timestamp,Node,AllInfo} = case All of {true,OldRuns} -> @@ -847,7 +848,6 @@ make_one_index_entry1(SuiteName, Link, Label, Success, Fail, UserSkip, AutoSkip, _ -> NodeOrDate end, N = ["",Node1,"\n"], - CtRunDir = filename:dirname(filename:dirname(Link)), L = ["",Label,"\n"], T = ["",timestamp(CtRunDir),"\n"], CtLogFile = filename:join(CtRunDir,?ct_log_name), @@ -866,7 +866,7 @@ make_one_index_entry1(SuiteName, Link, Label, Success, Fail, UserSkip, AutoSkip, if NotBuilt == 0 -> ["",integer_to_list(NotBuilt),"\n"]; true -> - ["", + ["", integer_to_list(NotBuilt),"\n"] end, FailStr = -- cgit v1.2.3 From 345992c1e82eb2e876139248cc50eb4df029a5f5 Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Thu, 29 Sep 2011 17:06:25 +0200 Subject: Create temporary fix for problem with parallel test cases OTP-9600 --- lib/test_server/src/test_server.erl | 40 ++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/test_server/src/test_server.erl b/lib/test_server/src/test_server.erl index 12625e3c00..244207e140 100644 --- a/lib/test_server/src/test_server.erl +++ b/lib/test_server/src/test_server.erl @@ -749,7 +749,8 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) -> {read_comment,From} -> From ! {self(),read_comment,Comment}, run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf); - {set_curr_conf,NewCurrConf} -> + {set_curr_conf,From,NewCurrConf} -> + From ! {self(),set_curr_conf,ok}, run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,NewCurrConf); {'EXIT',Pid,{Ref,Time,Value,Loc,Opts}} -> RetVal = {Time/1000000,Value,mod_loc(Loc),Opts,Comment}, @@ -973,10 +974,19 @@ spawn_fw_call(Mod,{init_per_testcase,Func},_,Pid,{timetrap_timeout,TVal}=Why, spawn_fw_call(Mod,{end_per_testcase,Func},EndConf,Pid, {timetrap_timeout,TVal}=Why,_Loc,SendTo,Comment) -> + %%! This is a temporary fix that keeps Test Server alive during + %%! execution of a parallel test case group, when sometimes + %%! this clause gets called with EndConf == undefined. See OTP-9594 + %%! for more info. + EndConf1 = if EndConf == undefined -> + [{tc_status,{failed,{Mod,end_per_testcase,Why}}}]; + true -> + EndConf + end, FwCall = fun() -> {RetVal,Report} = - case proplists:get_value(tc_status, EndConf) of + case proplists:get_value(tc_status, EndConf1) of undefined -> E = {failed,{Mod,end_per_testcase,Why}}, {E,E}; @@ -986,9 +996,9 @@ spawn_fw_call(Mod,{end_per_testcase,Func},EndConf,Pid, E = {failed,{Mod,end_per_testcase,Why}}, {Result,E} end, - FailLoc = proplists:get_value(tc_fail_loc, EndConf), + FailLoc = proplists:get_value(tc_fail_loc, EndConf1), case catch do_end_tc_call(Mod,Func, FailLoc, - {Pid,Report,[EndConf]}, Why) of + {Pid,Report,[EndConf1]}, Why) of {'EXIT',FwEndTCErr} -> exit({fw_notify_done,end_tc,FwEndTCErr}); _ -> @@ -1160,7 +1170,8 @@ run_test_case_eval1(Mod, Func, Args, Name, RunInit, TCCallback) -> %% call user callback function if defined NewConf1 = user_callback(TCCallback, Mod, Func, init, NewConf), %% save current state in controller loop - group_leader() ! {set_curr_conf,{{Mod,Func},NewConf1}}, + sync_send(group_leader(),set_curr_conf,{{Mod,Func},NewConf1}, + 5000, fun() -> exit(no_answer_from_group_leader) end), put(test_server_loc, {Mod,Func}), %% execute the test case {{T,Return},Loc} = {ts_tc(Mod, Func, [NewConf1]),get_loc()}, @@ -1188,7 +1199,8 @@ run_test_case_eval1(Mod, Func, Args, Name, RunInit, TCCallback) -> %% call user callback function if defined EndConf1 = user_callback(TCCallback, Mod, Func, 'end', EndConf), %% update current state in controller loop - group_leader() ! {set_curr_conf,EndConf1}, + sync_send(group_leader(),set_curr_conf,EndConf1, + 5000, fun() -> exit(no_answer_from_group_leader) end), {FWReturn1,TSReturn1,EndConf2} = case end_per_testcase(Mod, Func, EndConf1) of SaveCfg1={save_config,_} -> @@ -1208,7 +1220,8 @@ run_test_case_eval1(Mod, Func, Args, Name, RunInit, TCCallback) -> {FWReturn,TSReturn,EndConf1} end, %% clear current state in controller loop - group_leader() ! {set_curr_conf,undefined}, + sync_send(group_leader(),set_curr_conf,undefined, + 5000, fun() -> exit(no_answer_from_group_leader) end), put(test_server_init_or_end_conf,undefined), case do_end_tc_call(Mod,Func, Loc, {FWReturn1,[EndConf2]}, TSReturn1) of @@ -2016,6 +2029,19 @@ hours(N) -> trunc(N * 1000 * 60 * 60). minutes(N) -> trunc(N * 1000 * 60). seconds(N) -> trunc(N * 1000). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% sync_send(Pid,Tag,Msg,Timeout,DoAfter) -> Result +%% +sync_send(Pid,Tag,Msg,Timeout,DoAfter) -> + Pid ! {Tag,self(),Msg}, + receive + {Pid,Tag,Result} -> + Result + after Timeout -> + DoAfter() + end. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% timecall(M,F,A) -> {Time,Val} %% Time = float() -- cgit v1.2.3 From ff916887efb0db7b4c093f768e5240d879fa85c9 Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Fri, 30 Sep 2011 11:01:20 +0200 Subject: Rid ct_telnet of doc build warnings OTP-9572 --- lib/common_test/src/ct_telnet.erl | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/common_test/src/ct_telnet.erl b/lib/common_test/src/ct_telnet.erl index c6f5fd7df4..71a784870c 100644 --- a/lib/common_test/src/ct_telnet.erl +++ b/lib/common_test/src/ct_telnet.erl @@ -245,7 +245,6 @@ cmdf(Connection,CmdFormat,Args) -> %%% Data = [string()] %%% @doc Send a telnet command and wait for prompt %%% (uses a format string and list of arguments to build the command). -%%%----------------------------------------------------------------- cmdf(Connection,CmdFormat,Args,Timeout) when is_list(Args) -> Cmd = lists:flatten(io_lib:format(CmdFormat,Args)), cmd(Connection,Cmd,Timeout). @@ -360,15 +359,15 @@ expect(Connection,Patterns) -> %%% will also be a HaltReason returned.

%%% %%%

Examples:
-%%% expect(Connection,[{abc,"ABC"},{xyz,"XYZ"}], -%%% [sequence,{halt,[{nnn,"NNN"}]}]).
will try to match +%%% expect(Connection,[{abc,"ABC"},{xyz,"XYZ"}], +%%% [sequence,{halt,[{nnn,"NNN"}]}]).
will try to match %%% "ABC" first and then "XYZ", but if "NNN" appears the function will %%% return {error,{nnn,["NNN"]}}. If both "ABC" and "XYZ" %%% are matched, the function will return %%% {ok,[AbcMatch,XyzMatch]}.

%%% -%%%

expect(Connection,[{abc,"ABC"},{xyz,"XYZ"}], -%%% [{repeat,2},{halt,[{nnn,"NNN"}]}]).
will try to match +%%%

expect(Connection,[{abc,"ABC"},{xyz,"XYZ"}], +%%% [{repeat,2},{halt,[{nnn,"NNN"}]}]).
will try to match %%% "ABC" or "XYZ" twice. If "NNN" appears the function will return %%% with HaltReason = {nnn,["NNN"]}.

%%% -- cgit v1.2.3 From 09fbbccd5a8638601e44c605cd887f90b85d7d60 Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Fri, 30 Sep 2011 13:26:59 +0200 Subject: Update documentation OTP-9396 OTP-9372 OTP-9155 --- lib/common_test/doc/src/ct_run.xml | 7 ++++-- lib/common_test/doc/src/run_test_chapter.xml | 35 ++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/common_test/doc/src/ct_run.xml b/lib/common_test/doc/src/ct_run.xml index 1ab563d74f..9045646733 100644 --- a/lib/common_test/doc/src/ct_run.xml +++ b/lib/common_test/doc/src/ct_run.xml @@ -83,7 +83,7 @@ Run tests from command line
 	ct_run [-dir TestDir1 TestDir2 .. TestDirN] |
-	[-suite Suite1 Suite2 .. SuiteN
+	[[-dir TestDir] -suite Suite1 Suite2 .. SuiteN
 	 [[-group Group1 Group2 .. GroupN] [-case Case1 Case2 .. CaseN]]]
 	[-step [config | keep_inactive]]
 	[-config ConfigFile1 ConfigFile2 .. ConfigFileN]
@@ -92,6 +92,7 @@
 	[-decrypt_key Key] | [-decrypt_file KeyFile]
 	[-label Label]
 	[-logdir LogDir]
+	[-logopts LogOpts]
 	[-silent_connections [ConnType1 ConnType2 .. ConnTypeN]]
 	[-stylesheet CSSFile]
 	[-cover CoverCfgFile]
@@ -117,6 +118,7 @@
 	[-decrypt_key Key] | [-decrypt_file KeyFile]
 	[-label Label]
 	[-logdir LogDir]
+	[-logopts LogOpts]
 	[-allow_user_terms]
 	[-silent_connections [ConnType1 ConnType2 .. ConnTypeN]]
 	[-stylesheet CSSFile]
@@ -138,10 +140,11 @@
     
         ct_run -vts [-browser Browser]
         [-dir TestDir1 TestDir2 .. TestDirN] |
-        [-suite Suite [[-group Group] [-case Case]]]
+        [[dir TestDir] -suite Suite [[-group Group] [-case Case]]]
 	[-config ConfigFile1 ConfigFile2 .. ConfigFileN]
 	[-userconfig CallbackModule1 ConfigString1 and CallbackModule2
          ConfigString2 and .. and CallbackModuleN ConfigStringN]
+	[-logopts LogOpts]
 	[-decrypt_key Key] | [-decrypt_file KeyFile]
 	[-include InclDir1 InclDir2 .. InclDirN]
 	[-no_auto_compile]
diff --git a/lib/common_test/doc/src/run_test_chapter.xml b/lib/common_test/doc/src/run_test_chapter.xml
index e944f215f6..d3c6847d85 100644
--- a/lib/common_test/doc/src/run_test_chapter.xml
+++ b/lib/common_test/doc/src/run_test_chapter.xml
@@ -128,6 +128,15 @@
     

$ ct_run -suite $SYS1_TEST/setup_SUITE -case start stop

$ ct_run -suite $SYS1_TEST/setup_SUITE -group installation -case start stop

+

It is also possible to combine the dir, suite and group/case flags. E.g, to run + x_SUITE and y_SUITE in directory testdir:

+ +

$ ct_run -dir ./testdir -suite x_SUITE y_SUITE

+ +

This has the same effect as calling:

+ +

$ ct_run -suite ./testdir/x_SUITE ./testdir/y_SUITE

+

Other flags that may be used with ct_run:

]]>, specifies where the HTML log files are to be written. @@ -165,6 +174,8 @@ ]]>, points out a file containing a decryption key for encrypted configuration files. , switches off html enhancements that might not be compatible with older browsers. + ]]>, makes it possible to modify aspects of the logging behaviour, see + Log options below.

Directories passed to Common Test may have either relative or absolute paths.

@@ -645,6 +656,30 @@ to follow test progress simply by refreshing pages in the HTML browser. Statistics totals are not presented until a test is complete however.

+
+ + Log options +

With the logopts start flag, it's possible to specify + options that modify some aspects of the logging behaviour. + Currently, the following options are available:

+ + no_src + no_nl + +

With no_src, the html version of the test suite source + code will not be generated during the test run (and consequently + not be available in the log file system).

+

With no_nl, Common Test will not add a newline character + (\n) to the end of an output string that it receives from a call to e.g. + io:format/2, and which it prints to the test case log.

+

For example, if a test is started with:

+

$ ct_run -suite my_SUITE -logopts no_src

+

then printouts during the test made by successive calls to io:format("x"), + will appear in the test case log as:

+

xxx

+

instead of each x printed on a new line, which is the default behaviour.

+
+
-- cgit v1.2.3 From b6dc1a844eab061d0a7153d46e7e68296f15a504 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Tue, 4 Oct 2011 12:06:58 +0200 Subject: Prepare release --- lib/asn1/doc/src/notes.xml | 19 +++ lib/asn1/vsn.mk | 2 +- lib/common_test/doc/src/notes.xml | 223 ++++++++++++++++++++++++++++++++++ lib/compiler/doc/src/notes.xml | 28 +++++ lib/compiler/vsn.mk | 2 +- lib/cosFileTransfer/doc/src/notes.xml | 16 ++- lib/cosFileTransfer/vsn.mk | 2 +- lib/crypto/doc/src/notes.xml | 25 ++++ lib/crypto/vsn.mk | 2 +- lib/dialyzer/doc/src/notes.xml | 109 +++++++++++++++++ lib/dialyzer/vsn.mk | 2 +- lib/diameter/doc/src/notes.xml | 129 ++++++++++++++++++++ lib/docbuilder/doc/src/notes.xml | 16 +++ lib/edoc/doc/src/notes.xml | 51 ++++++++ lib/erl_docgen/doc/src/notes.xml | 46 ++++++- lib/erl_docgen/vsn.mk | 2 +- lib/erl_interface/doc/src/notes.xml | 47 +++++++ lib/erl_interface/vsn.mk | 2 +- lib/et/doc/src/notes.xml | 14 +++ lib/et/vsn.mk | 2 +- lib/eunit/doc/src/notes.xml | 57 +++++++++ lib/eunit/vsn.mk | 2 +- lib/gs/doc/src/notes.xml | 16 ++- lib/gs/vsn.mk | 2 +- lib/hipe/doc/src/notes.xml | 63 ++++++++++ lib/hipe/vsn.mk | 2 +- lib/kernel/doc/src/notes.xml | 56 +++++++++ lib/mnesia/doc/src/notes.xml | 45 ++++++- lib/observer/doc/src/notes.xml | 16 +++ lib/observer/vsn.mk | 2 +- lib/odbc/doc/src/notes.xml | 44 ++++++- lib/orber/doc/src/notes.xml | 16 ++- lib/orber/vsn.mk | 2 +- lib/os_mon/doc/src/notes.xml | 14 +++ lib/os_mon/vsn.mk | 2 +- lib/parsetools/doc/src/notes.xml | 46 +++++++ lib/parsetools/vsn.mk | 2 +- lib/percept/doc/src/notes.xml | 26 ++++ lib/percept/vsn.mk | 2 +- lib/public_key/doc/src/notes.xml | 17 +++ lib/public_key/vsn.mk | 2 +- lib/reltool/doc/src/notes.xml | 30 ++++- lib/reltool/vsn.mk | 2 +- lib/runtime_tools/doc/src/notes.xml | 17 +++ lib/runtime_tools/vsn.mk | 2 +- lib/sasl/doc/src/notes.xml | 98 +++++++++++++++ lib/sasl/vsn.mk | 2 +- lib/ssl/doc/src/notes.xml | 54 +++++++- lib/stdlib/doc/src/notes.xml | 162 ++++++++++++++++++++++++ lib/test_server/doc/src/notes.xml | 144 ++++++++++++++++++++++ lib/toolbar/doc/src/notes.xml | 16 +++ lib/toolbar/vsn.mk | 2 +- lib/tools/doc/src/notes.xml | 38 ++++++ lib/tools/vsn.mk | 2 +- lib/typer/vsn.mk | 2 +- lib/webtool/doc/src/notes.xml | 16 +++ lib/webtool/vsn.mk | 2 +- lib/wx/doc/src/notes.xml | 33 +++++ lib/wx/vsn.mk | 2 +- lib/xmerl/doc/src/notes.xml | 57 +++++++++ lib/xmerl/vsn.mk | 2 +- 61 files changed, 1822 insertions(+), 34 deletions(-) (limited to 'lib') diff --git a/lib/asn1/doc/src/notes.xml b/lib/asn1/doc/src/notes.xml index 5e221c03e9..52d770c9f6 100644 --- a/lib/asn1/doc/src/notes.xml +++ b/lib/asn1/doc/src/notes.xml @@ -31,6 +31,25 @@

This document describes the changes made to the asn1 application.

+
Asn1 1.6.18 + +
Fixed Bugs and Malfunctions + + +

+ Implement or fix -Werror option

+

+ If -Werror is enabled and there are warnings no output + file is written. Also make sure that error/warning + reporting is consistent. (Thanks to Tuncer Ayaz)

+

+ Own Id: OTP-9536

+
+
+
+ +
+
Asn1 1.6.17
Fixed Bugs and Malfunctions diff --git a/lib/asn1/vsn.mk b/lib/asn1/vsn.mk index 36e082c8ba..b1132155e6 100644 --- a/lib/asn1/vsn.mk +++ b/lib/asn1/vsn.mk @@ -1,2 +1,2 @@ #next version number to use is 1.6.15 | 1.7 | 2.0 -ASN1_VSN = 1.6.17 +ASN1_VSN = 1.6.18 diff --git a/lib/common_test/doc/src/notes.xml b/lib/common_test/doc/src/notes.xml index 826b3c598d..af96ef621f 100644 --- a/lib/common_test/doc/src/notes.xml +++ b/lib/common_test/doc/src/notes.xml @@ -32,6 +32,229 @@ notes.xml +
Common_Test 1.5.5 + +
Fixed Bugs and Malfunctions + + +

+ An error in how comments are colored in the test suite + overview html log file has been corrected. As result, a + new framework callback function, format_comment/1, has + been introduced.

+

+ Own Id: OTP-9237

+
+ +

+ Automatically generated init- and end-configuration + functions for test case groups caused incorrect execution + order of test cases. This has been corrected.

+

+ Own Id: OTP-9369

+
+ +

+ If multiple directories were specified with the 'logdir' + flag/option, Common Test would crash. This has been fixed + so that an error is properly reported instead.

+

+ Own Id: OTP-9370

+
+ +

+ If ct:log/2 was called with bad arguments, this could + cause the Common Test IO handling process to crash. This + fault has been corrected.

+

+ Own Id: OTP-9371 Aux Id: OTP-8933

+
+ +

+ A bug has been fixed that made Test Server call the + end_tc/3 framework function with an incorrect module name + as first argument.

+

+ Own Id: OTP-9379 Aux Id: seq11863

+
+ +

+ If a timetrap timeout occured during execution of of a + function in a lib module (i.e. a function called directly + or indirectly from a test case), the Suite argument in + the end_tc/3 framework callback function would not + correctly contain the name of the test suite, but the lib + module. (This would only happen if the lib module was + compiled with ct.hrl included). This error has been + solved.

+

+ Own Id: OTP-9398

+
+ +

+ Corrections of the vts mode. It will now report errors + (about e.g. incorrect config files) instead of crashing + or hanging. Furthermore, the requirement that the test + directory name must have a "_test" suffix has been + removed. Also, a workaround has been implemented for the + limitation that the file browser (in many web browsers) + will only return the basic file name, not the full + directory path (which made it impossible to have config + files in other directories than the main test directory).

+

+ Own Id: OTP-9429

+
+ +

+ Add a proplist() type

+

+ Recently I was adding specs to an API and found that + there is no canonical proplist() type defined. (Thanks to + Ryan Zezeski)

+

+ Own Id: OTP-9499

+
+ +

+ It is now possible to use the 'step' flag/option to run + the debugger for test suites that contain test case + groups. This previously caused Common Test to crash. If + 'step config' is specified, breakpoints are now also + automatically set on init_per_group and end_per_group. + Note that breakpoints are always set automatically on + test case functions and this is true also for grouped + cases.

+

+ Own Id: OTP-9518 Aux Id: OTP-8933

+
+ +

+ The test index page was not refreshed at the start of + each test suite which made it impossible to follow test + execution by means of refreshing the browser window (no + links to follow). This has been fixed.

+

+ Own Id: OTP-9520 Aux Id: OTP-8933

+
+ +

+ If a test suite would start with a test case group + defined without the init_per_group/2 and end_per_group/2 + function, init_per_suite/1 would not execute initially + and logging of the test run would fail. This error has + been fixed.

+

+ Own Id: OTP-9584

+
+ +

+ The "Missing Suites" link from the top level index page + was incorrect and has been fixed.

+

+ Own Id: OTP-9592

+
+
+
+ + +
Improvements and New Features + + +

+ Various corrections and updates to improve the handling + and reporting of errors.

+

+ Own Id: OTP-8933

+
+ +

+ The dir and suite start option can now be used in + combination. E.g. executing my_SUITE in directory + my_tests can either be specified as "ct_run -suite + my_tests/my_SUITE" or as "ct_run -dir my_tests -suite + my_SUITE". Furthermore, the specification: + ct:run_test([{suite,["./my_SUITE"]},{testcase,t1}]) is + now interpreted as + ct:run_test([{suite,"./my_SUITE"},{testcase,t1}]), i.e. + only testcase t1 in test suite my_SUITE - not all cases - + will be executed.

+

+ Own Id: OTP-9155

+
+ +

+ A new option, 'logopts', has been introduced, to make it + possible to modify some aspects of the logging behaviour + in Common Test (or Test Server). For example, whenever an + io printout is made, test_server adds newline (\n) to the + end of the output string. This may not always be a + preferred action and can therefore be disabled by means + of "ct_run ... -logopts no_nl" (or ct:run_test([..., + {logopts,[no_nl]}])). A new framework callback function, + get_logopts/0, has been introduced (see the ct_framework + module for details).

+

+ Own Id: OTP-9372 Aux Id: OTP-9396

+
+ +

+ A new option, 'logopts', has been introduced, to make it + possible to modify some aspects of the logging behaviour + in Common Test (or Test Server). For example, if the html + version of the test suite source code should not be + generated during the test run (and consequently be + unavailable in the log file system), the feature may be + disabled by means of "ct_run ... -logopts no_src" (or + ct:run_test([..., {logopts,[no_src]}])). A new framework + callback function, get_logopts/0, has been introduced + (see the ct_framework module for details).

+

+ Own Id: OTP-9396 Aux Id: seq11869, OTP-9372

+
+ +

+ CT Hooks can now be assigned a priority. The priority of + a CTH determines when it should execute in relation to + other CTHs. The CTH with the lowest priority will be + executed first, CTHs with equal priority will be executed + in the order which they were installed.

+

+ Own Id: OTP-9445

+
+ +

+ It is now possible to use a tuple {M,F,A}, or a fun, as + timetrap specification in the suite info function or test + case info functions. The function must return a valid + timeout value, as documented in the common_test man page + and in the User's Guide.

+

+ Own Id: OTP-9501 Aux Id: seq11894

+
+ +

+ A new built-in common test hook has been added which + captures error_logger and SASL event and prints them in + the testcase log. To disable this (and any other built-in + hooks) pass 'enable_builtin_hooks false' to common test.

+

+ Own Id: OTP-9543

+
+ +

+ Common Test now has the possibility to have built-in + hooks which are started by default when any test is run. + To disable built-in hooks pass 'enable_builtin_hooks + false' to common test. See the common test hooks + documentation for more details.

+

+ Own Id: OTP-9564

+
+
+
+ +
+
Common_Test 1.5.4
Fixed Bugs and Malfunctions diff --git a/lib/compiler/doc/src/notes.xml b/lib/compiler/doc/src/notes.xml index dd29323787..740cbcf8eb 100644 --- a/lib/compiler/doc/src/notes.xml +++ b/lib/compiler/doc/src/notes.xml @@ -31,6 +31,34 @@

This document describes the changes made to the Compiler application.

+
Compiler 4.7.5 + +
Fixed Bugs and Malfunctions + + +

+ Compiler options given in the source code using a + -compile() attribute used to be included twice in + Mod:module_info(compile). They are now only + included once at the beginning of the list of options.

+

+ Own Id: OTP-9534

+
+ +

+ beam_disasm: Handle stripped BEAM files

+

+ beam_disasm:file/1 would crash if asked to disassemble a + stripped BEAM file without an "Attr" chunk. (Thanks to + Haitao Li)

+

+ Own Id: OTP-9571

+
+
+
+ +
+
Compiler 4.7.4
Fixed Bugs and Malfunctions diff --git a/lib/compiler/vsn.mk b/lib/compiler/vsn.mk index 5863842f5b..04290c0a7f 100644 --- a/lib/compiler/vsn.mk +++ b/lib/compiler/vsn.mk @@ -1 +1 @@ -COMPILER_VSN = 4.7.4 +COMPILER_VSN = 4.7.5 diff --git a/lib/cosFileTransfer/doc/src/notes.xml b/lib/cosFileTransfer/doc/src/notes.xml index 53c207db2f..c7a4fd4504 100644 --- a/lib/cosFileTransfer/doc/src/notes.xml +++ b/lib/cosFileTransfer/doc/src/notes.xml @@ -30,7 +30,21 @@ notes.xml -
+
cosFileTransfer 1.1.12 + +
Fixed Bugs and Malfunctions + + +

XML files have been corrected.

+

+ Own Id: OTP-9550 Aux Id: OTP-9541

+
+
+
+ +
+ +
cosFileTransfer 1.1.11
diff --git a/lib/cosFileTransfer/vsn.mk b/lib/cosFileTransfer/vsn.mk index 9d68ab2720..fe0226e3b3 100644 --- a/lib/cosFileTransfer/vsn.mk +++ b/lib/cosFileTransfer/vsn.mk @@ -1 +1 @@ -COSFILETRANSFER_VSN = 1.1.11 +COSFILETRANSFER_VSN = 1.1.12 diff --git a/lib/crypto/doc/src/notes.xml b/lib/crypto/doc/src/notes.xml index a5434ebd68..763f79e02d 100644 --- a/lib/crypto/doc/src/notes.xml +++ b/lib/crypto/doc/src/notes.xml @@ -30,6 +30,31 @@

This document describes the changes made to the Crypto application.

+
Crypto 2.0.4 + +
Fixed Bugs and Malfunctions + + +

+ crypto:rand_uniform works correctly for negative + integers. Fails with badarg exception for invalid + ranges (when Hi =< Lo) instead of returning + incorrect output.

+

+ Own Id: OTP-9526

+
+ +

+ Fix win32 OpenSSL static linking (Thanks to Dave + Cottlehuber)

+

+ Own Id: OTP-9532

+
+
+
+ +
+
Crypto 2.0.3
Fixed Bugs and Malfunctions diff --git a/lib/crypto/vsn.mk b/lib/crypto/vsn.mk index e754aabc44..33fa9b1ec3 100644 --- a/lib/crypto/vsn.mk +++ b/lib/crypto/vsn.mk @@ -1 +1 @@ -CRYPTO_VSN = 2.0.3 +CRYPTO_VSN = 2.0.4 diff --git a/lib/dialyzer/doc/src/notes.xml b/lib/dialyzer/doc/src/notes.xml index 81622a3854..17291b24f7 100755 --- a/lib/dialyzer/doc/src/notes.xml +++ b/lib/dialyzer/doc/src/notes.xml @@ -31,6 +31,115 @@

This document describes the changes made to the Dialyzer application.

+
Dialyzer 2.4.4 + +
Fixed Bugs and Malfunctions + + +

+ Update results of race_SUITE/extract_translations Update + results of small_SUITE/flatten Add codec_can and + list_to_bitstring tests Fix bug when reporting unused + functions Update Dialyzer r9c_suite results Fix dialyzer + warning on default clause for binary comprehension + (Thanks to Ivan Dubrov)

+

+ Own Id: OTP-9483

+
+ +

+ Fix server loop detection

+

+ Dialyzer does not normally emit warnings for functions + that implement non-terminating server loops. This + detection failed when some of the elements in an SCC + terminated normally (being for example list + comprehensions or other generic anonymous functions that + were included in the SCC). This patch fixes that.

+

+ Own Id: OTP-9489

+
+ +

+ Add a proplist() type

+

+ Recently I was adding specs to an API and found that + there is no canonical proplist() type defined. (Thanks to + Ryan Zezeski)

+

+ Own Id: OTP-9499

+
+ +

+ Suppress some warnings about generation of non-returning + funs

+

+ No warnings are emitted for funs that are non-returning + when the function that generates them has a contract that + specifies that it will return such a non-returning fun.

+

+ Enhance Dialyzer's inference on comparisons

+

+ This patch makes Dialyzer aware of Erlang's total + ordering of terms, enabling discrepancy detection in + cases where e.g. integer() < tuple() is treated as a + comparison that might also return false (when it is + certain to always return true).

+

+ Minor fix in dead code

+

+ Fix infinite loop in dataflow

+

+ Update r9c/{inets,mnesia} results in dialyzer's test + suite

+

+ Add origin information to #fun_var closures

+

+ (Thanks to Tuncer Ayaz and Maria Christakis)

+

+ Own Id: OTP-9529

+
+ +

+ Quote atoms if necessary in types

+

+ Atoms in some occurrences were not correctly quoted when + formatted to strings, for instance by the typer program + (Thanks to Tomas Abrahamsson)

+

+ Update Dialyzer's reference results

+

+ Own Id: OTP-9560

+
+ +

+ Fix typer's crash for nonexisting files Remove unused + macro Fix bug in dataflow Decrease tuple arity limit This + fixes a memory related crash.

+

+ Own Id: OTP-9597

+
+
+
+ + +
Improvements and New Features + + +

+ Types for several BIFs have been extended/corrected. Also + the types for types for lists:keyfind/3, + lists:keysearch/3, and lists:keyemember/3 + have been corrected. The incorrect/incomplete types could + cause false dialyzer warnings.

+

+ Own Id: OTP-9496

+
+
+
+ +
+
Dialyzer 2.4.3
Fixed Bugs and Malfunctions diff --git a/lib/dialyzer/vsn.mk b/lib/dialyzer/vsn.mk index 10de07dfbb..a7e82b54ce 100644 --- a/lib/dialyzer/vsn.mk +++ b/lib/dialyzer/vsn.mk @@ -1 +1 @@ -DIALYZER_VSN = 2.4.3 +DIALYZER_VSN = 2.4.4 diff --git a/lib/diameter/doc/src/notes.xml b/lib/diameter/doc/src/notes.xml index eafddd7d1e..e2723f3e99 100644 --- a/lib/diameter/doc/src/notes.xml +++ b/lib/diameter/doc/src/notes.xml @@ -36,6 +36,135 @@ first.

+
Diameter 0.10 + +
Fixed Bugs and Malfunctions + + +

+ Handle #sctp_paddr_change and #sctp_pdapi_event from + gen_sctp.

+

+ The events are enabled by default but diameter_sctp + neither disabled nor dealt with them. Reception of such + an event caused a transport process to crash.

+

+ Own Id: OTP-9538

+
+ +

+ Fix header folding bug.

+

+ A prepare_request callback from diameter can return a + diameter_header record in order to set values in the + header of an outgoing request. A fault in + diameter_lib:fold_tuple/3 caused the subsequent encode of + the outgoing request to fail.

+

+ Own Id: OTP-9577

+
+ +

+ Fix bugs in sending of answer-message replies.

+

+ 3001 (DIAMETER_COMMAND_UNSUPPORTED) was not sent since + the decode placed the AVP list in the wrong field of the + diameter_packet, causing the subsequent encode to fail. + Session-Id was also set improperly, causing encode to + fail even in this case.

+

+ Own Id: OTP-9578

+
+ +

+ Fix improper use of error_logger:info_report/2.

+

+ Function doesn't take a format string and arguments as it + was called. Instead use error_logger:info_report/1 and + use the same report format as used for warning and error + reports.

+

+ Own Id: OTP-9579

+
+ +

+ Fix and clarify semantics of peer filters.

+

+ An eval filter returning a non-true value caused the call + process to fail and the doc was vague on how an exception + was treated. Clarify that the non-tuple host/realm + filters assume messages of a certain form.

+

+ Own Id: OTP-9580

+
+ +

+ Fix and clarify relay behaviour.

+

+ Implicit filtering of the sending peer in relaying a + request could cause loop detection to be preempted in a + manner not specified by RFC3588. Reply with 3002 + (DIAMETER_UNABLE_TO_DELIVER) on anything but an answer to + a relayed request.

+

+ Own Id: OTP-9583

+
+
+
+ + +
Improvements and New Features + + +

+ @id required in dictionary files only when @messages is + specified.

+

+ @id defines an application identifier and this is used + only when sending or receiving messages. A dictionary can + define only AVP's however, to be included by other + dictionaries using @inherits, in which case it makes no + sense to require @id.

+

+ Note that message definitions are not inherited with + @inherits, only AVP's

+

+ Own Id: OTP-9467

+
+ +

+ Allow @enum when AVP is defined in an inherited + dictionary.

+

+ 3GPP standards (for one) extend the values allowed for + RFC 3588 AVP's of type Enumerated. Previously, extending + an AVP was only possible by completely redefining the + AVP.

+

+ Own Id: OTP-9469

+
+ +

+ Migrate testsuites to pure common test and add both + suites and testcases.

+

+ Own Id: OTP-9553

+
+ +

+ Requests of arbitrary form.

+

+ diameter:call/4 can be passed anything, as long as the + subsequent prepare_request callback returns a term that + can be encoded.

+

+ Own Id: OTP-9581

+
+
+
+ +
+
diameter 0.9 diff --git a/lib/docbuilder/doc/src/notes.xml b/lib/docbuilder/doc/src/notes.xml index ef6523889d..95f24ea9ca 100644 --- a/lib/docbuilder/doc/src/notes.xml +++ b/lib/docbuilder/doc/src/notes.xml @@ -31,6 +31,22 @@

This document describes the changes made to the DocBuilder application.

+
Docbuilder 0.9.8.11 + +
Improvements and New Features + + +

+ The docbuilder application has been deprecated and will + be removed in the R15 release.

+

+ Own Id: OTP-9509

+
+
+
+ +
+
Docbuilder 0.9.8.10
Fixed Bugs and Malfunctions diff --git a/lib/edoc/doc/src/notes.xml b/lib/edoc/doc/src/notes.xml index 31a54788e5..b220067bbe 100644 --- a/lib/edoc/doc/src/notes.xml +++ b/lib/edoc/doc/src/notes.xml @@ -31,6 +31,57 @@

This document describes the changes made to the EDoc application.

+
Edoc 0.7.9 + +
Fixed Bugs and Malfunctions + + +

no_return is a new built-in type.

+

+ Own Id: OTP-9350

+
+ +

+ synchronized with edoc development version

+

+ forgot to ensure that xmerl is found in path for + include_lib to work

+

+ fix -spec declaration that doesn't work in R13B04

+

+ eliminate warnings about unused imports

+

+ removed CVS-keywords from source files (Thanks to Richard + Carlsson )

+

+ Own Id: OTP-9463

+
+ +

+ Add a proplist() type

+

+ Recently I was adding specs to an API and found that + there is no canonical proplist() type defined. (Thanks to + Ryan Zezeski)

+

+ Own Id: OTP-9499

+
+ +

+ Removed some never-matching clauses reported by dialyzer + Fix macro expansion in comments following Erlang types + URI-escape bytes as two hex digits always (reported by + Alfonso De Gregorio) Updated author e-mail Recognize some + more URI schemas in wiki text, in particular https + (Thanks to Richard Carlsson)

+

+ Own Id: OTP-9590

+
+
+
+ +
+
Edoc 0.7.8
Fixed Bugs and Malfunctions diff --git a/lib/erl_docgen/doc/src/notes.xml b/lib/erl_docgen/doc/src/notes.xml index f79639769f..6a0eece56d 100644 --- a/lib/erl_docgen/doc/src/notes.xml +++ b/lib/erl_docgen/doc/src/notes.xml @@ -30,7 +30,51 @@

This document describes the changes made to the erl_docgen application.

-
Erl_Docgen 0.2.5 +
Erl_Docgen 0.2.6 + +
Fixed Bugs and Malfunctions + + +

Bug fixes.

+

+ Own Id: OTP-9360

+
+ +

The manpage generation has been improved.

+

+ Own Id: OTP-9541 Aux Id: OTP-9550

+
+ +

Fix eix file generation for new function spec + references.

+

+ Own Id: OTP-9562

+
+ +

The function signatures in the pdf files was not in a + fixed font.

+

+ Own Id: OTP-9563

+
+ +

The parts level in the system documentation was + missing in the bookmarks menu for the pdf and the + copyright year generation for PDF was not correct.

+

+ Own Id: OTP-9576

+
+ +

The indentation after Warning: and + Note: in manpages has been improved.

+

+ Own Id: OTP-9588

+
+
+
+ +
+ +
Erl_Docgen 0.2.5
Improvements and New Features diff --git a/lib/erl_docgen/vsn.mk b/lib/erl_docgen/vsn.mk index cafb5287de..79c8c570bf 100644 --- a/lib/erl_docgen/vsn.mk +++ b/lib/erl_docgen/vsn.mk @@ -1,2 +1,2 @@ -ERL_DOCGEN_VSN = 0.2.5 +ERL_DOCGEN_VSN = 0.2.6 diff --git a/lib/erl_interface/doc/src/notes.xml b/lib/erl_interface/doc/src/notes.xml index 7055fcd5c9..9a42ebfddf 100644 --- a/lib/erl_interface/doc/src/notes.xml +++ b/lib/erl_interface/doc/src/notes.xml @@ -30,6 +30,53 @@

This document describes the changes made to the Erl_interface application.

+
Erl_Interface 3.7.5 + +
Fixed Bugs and Malfunctions + + +

Align ei buffer according to size of pointers

+

+ Own Id: OTP-9390

+
+ +

XML files have been corrected.

+

+ Own Id: OTP-9550 Aux Id: OTP-9541

+
+ +

+ Make comment and documentation reflect code in + erl_interface/src/misc/ei_decode_term.c (Thanks to Anneli + Cuss)

+

+ Own Id: OTP-9559

+
+
+
+ + +
Improvements and New Features + + +

+ ei: integer overflow in string/atom encoding

+

+ ei_encode_atom() and ei_encode_string() use strlen() to + get the length of the buffer. As strlen() returns an + unsigned long long and both ei functions take a signed + integer, the length fields may overflow.

+

+ Check so that the results of strlen can be held in a + signed integer. (Thanks to Michael Santos)

+

+ Own Id: OTP-9530

+
+
+
+ +
+
Erl_Interface 3.7.4
Fixed Bugs and Malfunctions diff --git a/lib/erl_interface/vsn.mk b/lib/erl_interface/vsn.mk index 75f2b7101b..601958579c 100644 --- a/lib/erl_interface/vsn.mk +++ b/lib/erl_interface/vsn.mk @@ -1 +1 @@ -EI_VSN = 3.7.4 +EI_VSN = 3.7.5 diff --git a/lib/et/doc/src/notes.xml b/lib/et/doc/src/notes.xml index 7082948d94..acc6120fcd 100644 --- a/lib/et/doc/src/notes.xml +++ b/lib/et/doc/src/notes.xml @@ -36,6 +36,20 @@ one section in this document. The title of each section is the version number of Event Tracer (ET).

+
ET 1.4.4 + +
Fixed Bugs and Malfunctions + + +

Dialyzer warnings have been fixed.

+

+ Own Id: OTP-9470

+
+
+
+ +
+
ET 1.4.3
Fixed Bugs and Malfunctions diff --git a/lib/et/vsn.mk b/lib/et/vsn.mk index ea98aeba11..239a72ad73 100644 --- a/lib/et/vsn.mk +++ b/lib/et/vsn.mk @@ -1 +1 @@ -ET_VSN = 1.4.3 +ET_VSN = 1.4.4 diff --git a/lib/eunit/doc/src/notes.xml b/lib/eunit/doc/src/notes.xml index a02d76c5b9..e68330482c 100644 --- a/lib/eunit/doc/src/notes.xml +++ b/lib/eunit/doc/src/notes.xml @@ -32,6 +32,63 @@

This document describes the changes made to the EUnit application.

+
Eunit 2.2.1 + +
Fixed Bugs and Malfunctions + + +

+ Generate separate surefire XMLs for each test suite

+

+ Previously the test cases of all test suites (=modules) + were put in one and the same surefire report XML thereby + breaking the principle of least astonishment and making + post analysis harder. Assume the following layout:

+

+ src/x.erl src/y.erl test/x_tests.erl test/y_tests.erl

+

+ The results for both x_tests and y_tests were written to + only one report grouped under either module x or y + (seemingly randomly).

+

+ Now two reports, one for module x and one for y are + generated. (Thanks to Klas Johansson)

+

+ Own Id: OTP-9465

+
+ +

+ Updated to EUnit version 2.2.0

+

+ New macros assertNotMatch(Guard, Expr), + assertNotEqual(Unexpected, Expr), and + assertNotException(Class, Term, Expr).

+

+ The debugMsg macro now also prints the pid of the current + process.

+

+ When testing all modules in a directory, tests in + Module_tests.erl are no longer executed twice.

+

+ The use of regexp internally has been replaced with re. + (Thanks to Richard Carlsson)

+

+ Own Id: OTP-9505

+
+ +

+ Removed some never-matching clauses reported by dialyzer + Updated author e-mails and homepages Removed cvs keywords + from files Removed files that should not be checked in + (Thanks to Richard Carlsson)

+

+ Own Id: OTP-9591

+
+
+
+ +
+
Eunit 2.1.7
Fixed Bugs and Malfunctions diff --git a/lib/eunit/vsn.mk b/lib/eunit/vsn.mk index d933085bbc..b0a77a225b 100644 --- a/lib/eunit/vsn.mk +++ b/lib/eunit/vsn.mk @@ -1 +1 @@ -EUNIT_VSN = 2.2.0 +EUNIT_VSN = 2.2.1 diff --git a/lib/gs/doc/src/notes.xml b/lib/gs/doc/src/notes.xml index 744efbd4fc..c32db495a1 100644 --- a/lib/gs/doc/src/notes.xml +++ b/lib/gs/doc/src/notes.xml @@ -30,7 +30,21 @@

This document describes the changes made to the GS application.

-
GS 1.5.13 +
GS 1.5.14 + +
Fixed Bugs and Malfunctions + + +

Remove misc. compiler warnings

+

+ Own Id: OTP-9542

+
+
+
+ +
+ +
GS 1.5.13
Improvements and New Features diff --git a/lib/gs/vsn.mk b/lib/gs/vsn.mk index 4c91857572..4894c6c13a 100644 --- a/lib/gs/vsn.mk +++ b/lib/gs/vsn.mk @@ -1,2 +1,2 @@ -GS_VSN = 1.5.13 +GS_VSN = 1.5.14 diff --git a/lib/hipe/doc/src/notes.xml b/lib/hipe/doc/src/notes.xml index 4eb188f76f..6b601e3039 100644 --- a/lib/hipe/doc/src/notes.xml +++ b/lib/hipe/doc/src/notes.xml @@ -30,6 +30,69 @@

This document describes the changes made to HiPE.

+
Hipe 3.8.1 + +
Fixed Bugs and Malfunctions + + +

+ Clean up hipe.hrl.src (Thanks to Tuncer Ayaz)

+

+ Own Id: OTP-9511

+
+ +

+ Fix bug with binary pattern matching of floats of + variable size

+

+ Pattern matching of floats with variable size + (<<F:S/float>>) did always fail. Judging from + similar code for ints, this bug is simply a typo.(Thanks + to Paul Guyot)

+

+ Own Id: OTP-9556

+
+ +

+ Quote atoms if necessary in types

+

+ Atoms in some occurrences were not correctly quoted when + formatted to strings, for instance by the typer program + (Thanks to Tomas Abrahamsson)

+

+ Update Dialyzer's reference results

+

+ Own Id: OTP-9560

+
+ +

+ Fix typer's crash for nonexisting files Remove unused + macro Fix bug in dataflow Decrease tuple arity limit This + fixes a memory related crash.

+

+ Own Id: OTP-9597

+
+
+
+ + +
Improvements and New Features + + +

+ Types for several BIFs have been extended/corrected. Also + the types for types for lists:keyfind/3, + lists:keysearch/3, and lists:keyemember/3 + have been corrected. The incorrect/incomplete types could + cause false dialyzer warnings.

+

+ Own Id: OTP-9496

+
+
+
+ +
+
Hipe 3.8
Fixed Bugs and Malfunctions diff --git a/lib/hipe/vsn.mk b/lib/hipe/vsn.mk index 58ebe68401..65e04ff7fa 100644 --- a/lib/hipe/vsn.mk +++ b/lib/hipe/vsn.mk @@ -1 +1 @@ -HIPE_VSN = 3.8 +HIPE_VSN = 3.8.1 diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml index fc8360b3d1..ec57b03bd9 100644 --- a/lib/kernel/doc/src/notes.xml +++ b/lib/kernel/doc/src/notes.xml @@ -30,6 +30,62 @@

This document describes the changes made to the Kernel application.

+
Kernel 2.14.5 + +
Fixed Bugs and Malfunctions + + +

+ Fix type of Packet arg of gen_tcp:send/2 and + gen_udp:send/4

+

+ The type is marked as a binary() or a string() but in + practice it can be an iodata(). The test suite was + updated to confirm the gen_tcp/2 and gen_udp:send/4 + functions accept iodata() (iolists) packets. (Thanks to + Filipe David Manana)

+

+ Own Id: OTP-9514

+
+ +

XML files have been corrected.

+

+ Own Id: OTP-9550 Aux Id: OTP-9541

+
+
+
+ + +
Improvements and New Features + + +

The types and specifications of the inet modules have + been improved.

+

+ Own Id: OTP-9260

+
+ +

Types and specifications have been added.

+

+ Own Id: OTP-9356

+
+ +

Contracts in STDLIB and Kernel have been improved and + type errors have been corrected.

+

+ Own Id: OTP-9485

+
+ +

Update documentation and specifications of some of + the zlib functions.

+

+ Own Id: OTP-9506

+
+
+
+ +
+
Kernel 2.14.4
Fixed Bugs and Malfunctions diff --git a/lib/mnesia/doc/src/notes.xml b/lib/mnesia/doc/src/notes.xml index 7f50dc049a..8ef573a948 100644 --- a/lib/mnesia/doc/src/notes.xml +++ b/lib/mnesia/doc/src/notes.xml @@ -38,7 +38,50 @@ thus constitutes one section in this document. The title of each section is the version number of Mnesia.

-
Mnesia 4.4.19 +
Mnesia 4.5 + +
Fixed Bugs and Malfunctions + + +

+ Fix protocol issues. Mnesia-4.4.19 could not communicate + with to older nodes.

+

+ Own Id: OTP-9473

+
+ +

XML files have been corrected.

+

+ Own Id: OTP-9550 Aux Id: OTP-9541

+
+
+
+ + +
Improvements and New Features + + +

+ Dump the log even if no transactions have been invoked on + local node, otherwise the log will grow forever with + decisions from the other nodes who have tables on disk. + Thanks Marek Majkowski.

+

+ Own Id: OTP-9551

+
+ +

+ Use dedicated api for clear_table, i.e. instead of + match_delete use delete_all_objects. Thanks KukHyun Lee.

+

+ Own Id: OTP-9558

+
+
+
+ +
+ +
Mnesia 4.4.19
Fixed Bugs and Malfunctions diff --git a/lib/observer/doc/src/notes.xml b/lib/observer/doc/src/notes.xml index 73eb992323..baa1354268 100644 --- a/lib/observer/doc/src/notes.xml +++ b/lib/observer/doc/src/notes.xml @@ -31,6 +31,22 @@

This document describes the changes made to the Observer application.

+
Observer 0.9.10 + +
Fixed Bugs and Malfunctions + + +

+ Do not install *.bat files on non-win32 machines (Thanks + to Hans Ulrich Niedermann)

+

+ Own Id: OTP-9515

+
+
+
+ +
+
Observer 0.9.9
Improvements and New Features diff --git a/lib/observer/vsn.mk b/lib/observer/vsn.mk index 14c8f54ba3..76e2f591fa 100644 --- a/lib/observer/vsn.mk +++ b/lib/observer/vsn.mk @@ -1 +1 @@ -OBSERVER_VSN = 0.9.9 +OBSERVER_VSN = 0.9.10 diff --git a/lib/odbc/doc/src/notes.xml b/lib/odbc/doc/src/notes.xml index e15e7dea7d..9c6ca8a017 100644 --- a/lib/odbc/doc/src/notes.xml +++ b/lib/odbc/doc/src/notes.xml @@ -31,7 +31,49 @@

This document describes the changes made to the odbc application.

-
ODBC 2.10.10 +
ODBC 2.10.11 + +
Fixed Bugs and Malfunctions + + +

+ When using output parameters the internal odbc state was + not correctly cleaned causing the next call to + param_query to misbehave.

+

+ Own Id: OTP-9444

+
+ +

XML files have been corrected.

+

+ Own Id: OTP-9550 Aux Id: OTP-9541

+
+
+
+ + +
Improvements and New Features + + +

+ Add code to handle old ODBC drivers on solaris. Also adds + tests with MySQL.

+

+ Own Id: OTP-8407

+
+ +

+ Odbc now supports SQL_WLONGVARCHAR, thanks to Hanfei Shen + for the patch.

+

+ Own Id: OTP-8493

+
+
+
+ +
+ +
ODBC 2.10.10
Fixed Bugs and Malfunctions diff --git a/lib/orber/doc/src/notes.xml b/lib/orber/doc/src/notes.xml index 231872f958..c8477d9252 100644 --- a/lib/orber/doc/src/notes.xml +++ b/lib/orber/doc/src/notes.xml @@ -32,7 +32,21 @@ notes.xml -
+
Orber 3.6.22 + +
Fixed Bugs and Malfunctions + + +

XML files have been corrected.

+

+ Own Id: OTP-9550 Aux Id: OTP-9541

+
+
+
+ +
+ +
Orber 3.6.21
diff --git a/lib/orber/vsn.mk b/lib/orber/vsn.mk index 35aabd51cd..29b21e8e01 100644 --- a/lib/orber/vsn.mk +++ b/lib/orber/vsn.mk @@ -1,3 +1,3 @@ -ORBER_VSN = 3.6.21 +ORBER_VSN = 3.6.22 diff --git a/lib/os_mon/doc/src/notes.xml b/lib/os_mon/doc/src/notes.xml index 0a088ca8b6..f641bbd828 100644 --- a/lib/os_mon/doc/src/notes.xml +++ b/lib/os_mon/doc/src/notes.xml @@ -30,6 +30,20 @@

This document describes the changes made to the OS_Mon application.

+
Os_Mon 2.2.7 + +
Fixed Bugs and Malfunctions + + +

Remove misc. compiler warnings

+

+ Own Id: OTP-9542

+
+
+
+ +
+
Os_Mon 2.2.6
Fixed Bugs and Malfunctions diff --git a/lib/os_mon/vsn.mk b/lib/os_mon/vsn.mk index 2d583a398b..f000e24a8f 100644 --- a/lib/os_mon/vsn.mk +++ b/lib/os_mon/vsn.mk @@ -1 +1 @@ -OS_MON_VSN = 2.2.6 +OS_MON_VSN = 2.2.7 diff --git a/lib/parsetools/doc/src/notes.xml b/lib/parsetools/doc/src/notes.xml index 77b3a1a657..0c611db1ec 100644 --- a/lib/parsetools/doc/src/notes.xml +++ b/lib/parsetools/doc/src/notes.xml @@ -30,6 +30,52 @@

This document describes the changes made to the Parsetools application.

+
Parsetools 2.0.6 + +
Fixed Bugs and Malfunctions + + +

Dialyzer warnings have been removed.

+

+ Own Id: OTP-8318

+
+ +

+ yecc: add warnings_as_errors option(Thanks to Tuncer + ayaz)

+

+ Own Id: OTP-9376

+
+ +

+ Fix incorrect order of pseudo variables in yecc example

+

+ The example is for converting from infix to prefix. This + change uses to correct ordering of the triplet. (Thanks + to Garret Smith)

+

+ Own Id: OTP-9484

+
+ +

+ Implement or fix -Werror option

+

+ If -Werror is enabled and there are warnings no output + file is written. Also make sure that error/warning + reporting is consistent. (Thanks to Tuncer Ayaz)

+

+ Own Id: OTP-9536

+
+ +

XML files have been corrected.

+

+ Own Id: OTP-9550 Aux Id: OTP-9541

+
+
+
+ +
+
Parsetools 2.0.5
Improvements and New Features diff --git a/lib/parsetools/vsn.mk b/lib/parsetools/vsn.mk index 812bf21f03..093523f0e7 100644 --- a/lib/parsetools/vsn.mk +++ b/lib/parsetools/vsn.mk @@ -1 +1 @@ -PARSETOOLS_VSN = 2.0.5 +PARSETOOLS_VSN = 2.0.6 diff --git a/lib/percept/doc/src/notes.xml b/lib/percept/doc/src/notes.xml index 33bfa7baab..95c2bbda56 100644 --- a/lib/percept/doc/src/notes.xml +++ b/lib/percept/doc/src/notes.xml @@ -32,6 +32,32 @@

This document describes the changes made to the Percept application.

+
Percept 0.8.6 + +
Fixed Bugs and Malfunctions + + +

+ Fix message handling in select requests

+

+ percept_db used to send results in untagged messages, and + use a non selective receive to extract them. When percept + is used from the shell process, this can confuse other + messages with the actual result.

+

+ Add a tag to the message to be {result, Result}. Add + demonitor to avoid keeping DOWN message in the queue fix + one spec in do_start/0

+

+ (Thanks to Ahmed Omar)

+

+ Own Id: OTP-9490

+
+
+
+ +
+
Percept 0.8.5
Fixed Bugs and Malfunctions diff --git a/lib/percept/vsn.mk b/lib/percept/vsn.mk index 2a302991aa..3b4d9bbb64 100644 --- a/lib/percept/vsn.mk +++ b/lib/percept/vsn.mk @@ -1 +1 @@ -PERCEPT_VSN = 0.8.5 +PERCEPT_VSN = 0.8.6 diff --git a/lib/public_key/doc/src/notes.xml b/lib/public_key/doc/src/notes.xml index 9d77750ea2..efd4a37eb9 100644 --- a/lib/public_key/doc/src/notes.xml +++ b/lib/public_key/doc/src/notes.xml @@ -34,6 +34,23 @@ notes.xml +
Public_Key 0.13 + +
Fixed Bugs and Malfunctions + + +

+ replace "a ssl" with "an ssl" reindent + pkix_path_validation/3 Trivial documentation fixes + (Thanks to Christian von Roques )

+

+ Own Id: OTP-9464

+
+
+
+ +
+
Public_Key 0.12
Improvements and New Features diff --git a/lib/public_key/vsn.mk b/lib/public_key/vsn.mk index 3c6b012152..66ac78a65d 100644 --- a/lib/public_key/vsn.mk +++ b/lib/public_key/vsn.mk @@ -1 +1 @@ -PUBLIC_KEY_VSN = 0.12 +PUBLIC_KEY_VSN = 0.13 diff --git a/lib/reltool/doc/src/notes.xml b/lib/reltool/doc/src/notes.xml index 324d69675e..5304b996a4 100644 --- a/lib/reltool/doc/src/notes.xml +++ b/lib/reltool/doc/src/notes.xml @@ -37,7 +37,35 @@ thus constitutes one section in this document. The title of each section is the version number of Reltool.

-
Reltool 0.5.6 +
Reltool 0.5.7 + +
Fixed Bugs and Malfunctions + + +

+ If a module was duplicated in the library directories + visible to reltool, and the configuration did not point + out which file to use, then reltool:start would always + fail. A pop-up is added which asks if you want to + continue with a safe and minimal configuration.

+

+ Own Id: OTP-9383

+
+ +

+ wx would sometimes crash due to an empty radiobox on the + 'releases' tab of the system window. This radiobox is + removed, and replaced by a listbox which will always + contain at least kernel and stdlib applications.

+

+ Own Id: OTP-9384

+
+
+
+ +
+ +
Reltool 0.5.6
Fixed Bugs and Malfunctions diff --git a/lib/reltool/vsn.mk b/lib/reltool/vsn.mk index 227b1c80a2..751f9bb6db 100644 --- a/lib/reltool/vsn.mk +++ b/lib/reltool/vsn.mk @@ -1 +1 @@ -RELTOOL_VSN = 0.5.6 +RELTOOL_VSN = 0.5.7 diff --git a/lib/runtime_tools/doc/src/notes.xml b/lib/runtime_tools/doc/src/notes.xml index 599be62241..0bb76e1ea4 100644 --- a/lib/runtime_tools/doc/src/notes.xml +++ b/lib/runtime_tools/doc/src/notes.xml @@ -31,6 +31,23 @@

This document describes the changes made to the Runtime_Tools application.

+
Runtime_Tools 1.8.6 + +
Improvements and New Features + + +

+ Two new built-in trace pattern aliases have been added: + caller_trace (c) and caller_exception_trace (cx). See the + dbg:ltp/0 documentation for more info.

+

+ Own Id: OTP-9458

+
+
+
+ +
+
Runtime_Tools 1.8.5
Improvements and New Features diff --git a/lib/runtime_tools/vsn.mk b/lib/runtime_tools/vsn.mk index 6ed98f697e..0bcd261861 100644 --- a/lib/runtime_tools/vsn.mk +++ b/lib/runtime_tools/vsn.mk @@ -1 +1 @@ -RUNTIME_TOOLS_VSN = 1.8.5 +RUNTIME_TOOLS_VSN = 1.8.6 diff --git a/lib/sasl/doc/src/notes.xml b/lib/sasl/doc/src/notes.xml index d4460d47b4..01cdc4b29e 100644 --- a/lib/sasl/doc/src/notes.xml +++ b/lib/sasl/doc/src/notes.xml @@ -30,6 +30,104 @@

This document describes the changes made to the SASL application.

+
SASL 2.1.10 + +
Fixed Bugs and Malfunctions + + +

+ The release_handler functionality on windows services was + broken. This has been corrected.

+

+ Own Id: OTP-9306

+
+ +

+ If a new version of an application did not include any + erlang module changes, the code path of the application + was not updated by the release_handler unless a + 'load_object_code' instruction was added for the + application. This would be a problem if e.g. only some + files in the priv dir were changed since calls to + code:lib_dir or code:priv_dir would then point to the old + location of the application. This has been corrected - + now code:replace_path/2 will be called for all + applications that are changed (i.e. when the + application's vsn is changed in the .rel file).

+

+ Own Id: OTP-9402

+
+ +

+ The appup instruction 'delete_module' would cause a crash + during upgrade if the module to be deleted was not + loaded. This has been corrected.

+

+ Own Id: OTP-9417

+
+ +

+ If a path was given as ONLY 'ebin' and not for example + './ebin', then systools:make_tar would fail with a + function_clause exception in filename:join/1. This + has been corrected. (Thanks to Nikola Skoric for + reporting).

+

+ Own Id: OTP-9507

+
+ +

+ Implement or fix -Werror option

+

+ If -Werror is enabled and there are warnings no output + file is written. Also make sure that error/warning + reporting is consistent. (Thanks to Tuncer Ayaz)

+

+ Own Id: OTP-9536

+
+ +

+ Improved error information for timeouts during + release_handler:install_release.

+

+ This patch addresses two cases where a timeout will occur + during upgrade. 1) if a supervisor is suspended (call to + get children from supervisor will hang) 2) if the child + spec for a supervisor incorrectly states that it is a + worker with a dynamic set of modules (call to get modules + from gen_event will hang)

+

+ An error report will now be printed, and the return value + of release_handler:install_release will indicate what + happened. (Thanks to joe williams)

+

+ Own Id: OTP-9546

+
+
+
+ + +
Improvements and New Features + + +

+ release_handler:install_release could be very slow + when there are many processes in the system. Some + optimization work has been done both in erts and in the + release handler in order to improve this.

+

+ A new option, purge, is added to + release_handler:check_install_release which can be + called first in order to speed up the execution of + release_handler:install_release.

+

+ Own Id: OTP-9395

+
+
+
+ +
+
SASL 2.1.9.4
Fixed Bugs and Malfunctions diff --git a/lib/sasl/vsn.mk b/lib/sasl/vsn.mk index 26dc2c1448..2db134af48 100644 --- a/lib/sasl/vsn.mk +++ b/lib/sasl/vsn.mk @@ -1 +1 @@ -SASL_VSN = 2.1.9.4 +SASL_VSN = 2.1.10 diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml index e090b4e1ef..5df2632149 100644 --- a/lib/ssl/doc/src/notes.xml +++ b/lib/ssl/doc/src/notes.xml @@ -30,7 +30,59 @@

This document describes the changes made to the SSL application.

-
+
SSL 4.1.6 + +
Fixed Bugs and Malfunctions + + +

+ replace "a ssl" with "an ssl" reindent + pkix_path_validation/3 Trivial documentation fixes + (Thanks to Christian von Roques )

+

+ Own Id: OTP-9464

+
+
+
+ + +
Improvements and New Features + + +

+ Adds function clause to avoid denial of service attack. + Thanks to Vinod for reporting this vulnerability.

+

+ Own Id: OTP-9364

+
+ +

+ Error handling code now takes care of inet:getopts/2 and + inets:setopts/2 crashes. Thanks to Richard Jones for + reporting this.

+

+ Own Id: OTP-9382

+
+ +

+ Support explicit use of packet option httph and httph_bin

+

+ Own Id: OTP-9461

+
+ +

+ Decoding of hello extensions could fail to come to the + correct conclusion due to an error in a binary match + pattern. Thanks to Ben Murphy.

+

+ Own Id: OTP-9589

+
+
+
+ +
+ +
SSL 4.1.5
Improvements and New Features diff --git a/lib/stdlib/doc/src/notes.xml b/lib/stdlib/doc/src/notes.xml index 36089f2603..d9c220b996 100644 --- a/lib/stdlib/doc/src/notes.xml +++ b/lib/stdlib/doc/src/notes.xml @@ -30,6 +30,168 @@

This document describes the changes made to the STDLIB application.

+
STDLIB 1.17.5 + +
Fixed Bugs and Malfunctions + + +

+ erl_tar:extract failed when executed inside a directory + with some parent directory to which the user has no read + access. This has been corrected.

+

+ Own Id: OTP-9368

+
+ +

A bug in erl_scan:set_attribute/3 has been + fixed.

+

+ Own Id: OTP-9412

+
+ +

The contract of io_lib:fread() has been + corrected.

+

+ Own Id: OTP-9413 Aux Id: seq11873

+
+ +

+ A crash in io_lib:fread/2 when end of input data was + encountered while trying to match literal characters, + which should return {more,_,_,_} but instead crashed, has + been corrected. Reported by Klas Johansson.

+

+ A similar peculiarity for io:fread when encountering end + of file before any field data has also been corrected.

+

+ Own Id: OTP-9439

+
+ +

The contract of timer:now_diff() has been + corrected. (Thanks to Alex Morarash).

+

+ Own Id: OTP-9450

+
+ +

+ Fix minor typo in gen_fsm documentation (Thanks to Haitao + Li)

+

+ Own Id: OTP-9456

+
+ +

The contracts of zip:zip_list_dir/1 and + zip:zip_get/2 have been corrected.

+

+ Own Id: OTP-9471 Aux Id: seq11887, OTP-9472

+
+ +

A bug in zip:zip_open() has been fixed.

+

+ Own Id: OTP-9472 Aux Id: seq11887, OTP-9471

+
+ +

+ Fix trivial documentation errors(Thanks to Matthias Lang)

+

+ Own Id: OTP-9498

+
+ +

+ Add a proplist() type

+

+ Recently I was adding specs to an API and found that + there is no canonical proplist() type defined. (Thanks to + Ryan Zezeski)

+

+ Own Id: OTP-9499

+
+ +

+ fix supervisors restarting temporary children

+

+ In the current implementation of supervisors, temporary + children should never be restarted. However, when a + temporary child is restarted as part of a one_for_all or + rest_for_one strategy where the failing process is not + the temporary child, the supervisor still tries to + restart it.

+

+ Because the supervisor doesn't keep some of the MFA + information of temporary children, this causes the + supervisor to hit its restart limit and crash.

+

+ This patch fixes the behaviour by inserting a clause in + terminate_children/2-3 (private function) that will omit + temporary children when building a list of killed + processes, to avoid having the supervisor trying to + restart them again.

+

+ Only supervisors in need of restarting children used the + list, so the change should be of no impact for the + functions that called terminate_children/2-3 only to kill + all children.

+

+ The documentation has been modified to make this + behaviour more explicit. (Thanks to Fred Hebert)

+

+ Own Id: OTP-9502

+
+ +

+ fix broken edoc annotations (Thanks to Richard Carlsson)

+

+ Own Id: OTP-9516

+
+ +

XML files have been corrected.

+

+ Own Id: OTP-9550 Aux Id: OTP-9541

+
+ +

+ Handle rare race in the crypto key server functionality

+

+ Own Id: OTP-9586

+
+
+
+ + +
Improvements and New Features + + +

Types and specifications have been added.

+

+ Own Id: OTP-9356

+
+ +

The contracts of the queue module have been + modified.

+

+ Own Id: OTP-9418

+
+ +

Contracts in STDLIB and Kernel have been improved and + type errors have been corrected.

+

+ Own Id: OTP-9485

+
+ +

+ Types for several BIFs have been extended/corrected. Also + the types for types for lists:keyfind/3, + lists:keysearch/3, and lists:keyemember/3 + have been corrected. The incorrect/incomplete types could + cause false dialyzer warnings.

+

+ Own Id: OTP-9496

+
+
+
+ +
+
STDLIB 1.17.4
Fixed Bugs and Malfunctions diff --git a/lib/test_server/doc/src/notes.xml b/lib/test_server/doc/src/notes.xml index 50923b1b03..beeff55ffe 100644 --- a/lib/test_server/doc/src/notes.xml +++ b/lib/test_server/doc/src/notes.xml @@ -32,6 +32,150 @@ notes.xml +
Test_Server 3.4.5 + +
Fixed Bugs and Malfunctions + + +

+ An error in how comments are colored in the test suite + overview html log file has been corrected. As result, a + new framework callback function, format_comment/1, has + been introduced.

+

+ Own Id: OTP-9237

+
+ +

+ Test Server did not release SASL TTY handlers + (sasl_report_tty_h and error_logger_tty_h) properly after + each test run. This error has been fixed.

+

+ Own Id: OTP-9311

+
+ +

+ Automatically generated init- and end-configuration + functions for test case groups caused incorrect execution + order of test cases. This has been corrected.

+

+ Own Id: OTP-9369

+
+ +

+ If ct:log/2 was called with bad arguments, this could + cause the Common Test IO handling process to crash. This + fault has been corrected.

+

+ Own Id: OTP-9371 Aux Id: OTP-8933

+
+ +

+ A bug has been fixed that made Test Server call the + end_tc/3 framework function with an incorrect module name + as first argument.

+

+ Own Id: OTP-9379 Aux Id: seq11863

+
+ +

+ If end_per_testcase caused a timetrap timeout, the actual + test case status was discarded and the test case logged + as successful (even if the case had actually failed + before the call to end_per_testcase). This fault has been + fixed.

+

+ Own Id: OTP-9397

+
+ +

+ If a timetrap timeout occured during execution of of a + function in a lib module (i.e. a function called directly + or indirectly from a test case), the Suite argument in + the end_tc/3 framework callback function would not + correctly contain the name of the test suite, but the lib + module. (This would only happen if the lib module was + compiled with ct.hrl included). This error has been + solved.

+

+ Own Id: OTP-9398

+
+ +

+ Add a proplist() type

+

+ Recently I was adding specs to an API and found that + there is no canonical proplist() type defined. (Thanks to + Ryan Zezeski)

+

+ Own Id: OTP-9499

+
+ +

XML files have been corrected.

+

+ Own Id: OTP-9550 Aux Id: OTP-9541

+
+ +

+ If a test suite would start with a test case group + defined without the init_per_group/2 and end_per_group/2 + function, init_per_suite/1 would not execute initially + and logging of the test run would fail. This error has + been fixed.

+

+ Own Id: OTP-9584

+
+
+
+ + +
Improvements and New Features + + +

+ A new option, 'logopts', has been introduced, to make it + possible to modify some aspects of the logging behaviour + in Common Test (or Test Server). For example, whenever an + io printout is made, test_server adds newline (\n) to the + end of the output string. This may not always be a + preferred action and can therefore be disabled by means + of "ct_run ... -logopts no_nl" (or ct:run_test([..., + {logopts,[no_nl]}])). A new framework callback function, + get_logopts/0, has been introduced (see the ct_framework + module for details).

+

+ Own Id: OTP-9372 Aux Id: OTP-9396

+
+ +

+ A new option, 'logopts', has been introduced, to make it + possible to modify some aspects of the logging behaviour + in Common Test (or Test Server). For example, if the html + version of the test suite source code should not be + generated during the test run (and consequently be + unavailable in the log file system), the feature may be + disabled by means of "ct_run ... -logopts no_src" (or + ct:run_test([..., {logopts,[no_src]}])). A new framework + callback function, get_logopts/0, has been introduced + (see the ct_framework module for details).

+

+ Own Id: OTP-9396 Aux Id: seq11869, OTP-9372

+
+ +

+ It is now possible to use a tuple {M,F,A}, or a fun, as + timetrap specification in the suite info function or test + case info functions. The function must return a valid + timeout value, as documented in the common_test man page + and in the User's Guide.

+

+ Own Id: OTP-9501 Aux Id: seq11894

+
+
+
+ +
+
Test_Server 3.4.4
Fixed Bugs and Malfunctions diff --git a/lib/toolbar/doc/src/notes.xml b/lib/toolbar/doc/src/notes.xml index e2a3c22684..ffca2c5fbf 100644 --- a/lib/toolbar/doc/src/notes.xml +++ b/lib/toolbar/doc/src/notes.xml @@ -31,6 +31,22 @@

This document describes the changes made to the Toolbar application.

+
Toolbar 1.4.2 + +
Fixed Bugs and Malfunctions + + +

+ Improve spelling throughout documentation, code comments + and error messages

+

+ Own Id: OTP-9555

+
+
+
+ +
+
Toolbar 1.4.1
Improvements and New Features diff --git a/lib/toolbar/vsn.mk b/lib/toolbar/vsn.mk index 47d18e29f0..105303d785 100644 --- a/lib/toolbar/vsn.mk +++ b/lib/toolbar/vsn.mk @@ -1,4 +1,4 @@ -TOOLBAR_VSN = 1.4.1 +TOOLBAR_VSN = 1.4.2 diff --git a/lib/tools/doc/src/notes.xml b/lib/tools/doc/src/notes.xml index 02d92fc4e7..17506fb6e2 100644 --- a/lib/tools/doc/src/notes.xml +++ b/lib/tools/doc/src/notes.xml @@ -30,6 +30,44 @@

This document describes the changes made to the Tools application.

+
Tools 2.6.6.5 + +
Fixed Bugs and Malfunctions + + +

+ Teach the emacs mode to compile yecc and leex files

+

+ If visiting a .yrl or .xrl file in emacs with + erlang-mode, then the `erlang-compile' function (normally + bound to C-c C-k), now knows how to compile yecc and leex + files, and then, if that compilation succeeds, also + compiles the resulting .erl files.

+

+ Also introduce a `erlang-compile-command-function-alist' + to make it possible to hook in other functions for + computing compilation commands/expressions, depending on + file name. (Thanks to Tomas Abrahamsson )

+

+ Own Id: OTP-9503

+
+
+
+ + +
Improvements and New Features + + +

Bugs in xref(3) have been fixed. (Thanks to Matthias + Lang.)

+

+ Own Id: OTP-9416

+
+
+
+ +
+
Tools 2.6.6.4
Fixed Bugs and Malfunctions diff --git a/lib/tools/vsn.mk b/lib/tools/vsn.mk index 6999c695e6..2d63a33554 100644 --- a/lib/tools/vsn.mk +++ b/lib/tools/vsn.mk @@ -1 +1 @@ -TOOLS_VSN = 2.6.6.4 +TOOLS_VSN = 2.6.6.5 diff --git a/lib/typer/vsn.mk b/lib/typer/vsn.mk index fe8faabdf8..9e73aed286 100644 --- a/lib/typer/vsn.mk +++ b/lib/typer/vsn.mk @@ -1 +1 @@ -TYPER_VSN = 0.9.1 +TYPER_VSN = 0.9.2 diff --git a/lib/webtool/doc/src/notes.xml b/lib/webtool/doc/src/notes.xml index b626ad2178..c58a440937 100644 --- a/lib/webtool/doc/src/notes.xml +++ b/lib/webtool/doc/src/notes.xml @@ -31,6 +31,22 @@

This document describes the changes made to the Webtool application.

+
WebTool 0.8.9 + +
Fixed Bugs and Malfunctions + + +

+ Do not install *.bat files on non-win32 machines (Thanks + to Hans Ulrich Niedermann)

+

+ Own Id: OTP-9515

+
+
+
+ +
+
WebTool 0.8.8
Fixed Bugs and Malfunctions diff --git a/lib/webtool/vsn.mk b/lib/webtool/vsn.mk index d687b4ff81..2643be866e 100644 --- a/lib/webtool/vsn.mk +++ b/lib/webtool/vsn.mk @@ -1 +1 @@ -WEBTOOL_VSN=0.8.8 +WEBTOOL_VSN=0.8.9 diff --git a/lib/wx/doc/src/notes.xml b/lib/wx/doc/src/notes.xml index 26d1f892b2..7bd8d18592 100644 --- a/lib/wx/doc/src/notes.xml +++ b/lib/wx/doc/src/notes.xml @@ -31,6 +31,39 @@

This document describes the changes made to the wxErlang application.

+
Wx 0.99 + +
Fixed Bugs and Malfunctions + + +

+ wx: fix obsolete guard warning (list/1) (Thanks to Tuncer + Ayaz)

+

+ Own Id: OTP-9513

+
+ +

XML files have been corrected.

+

+ Own Id: OTP-9550 Aux Id: OTP-9541

+
+
+
+ + +
Improvements and New Features + + +

+ Support virtual tables in wxListCtrl.

+

+ Own Id: OTP-9415

+
+
+
+ +
+
Wx 0.98.10
Fixed Bugs and Malfunctions diff --git a/lib/wx/vsn.mk b/lib/wx/vsn.mk index 02899f4115..8685c633d4 100644 --- a/lib/wx/vsn.mk +++ b/lib/wx/vsn.mk @@ -1 +1 @@ -WX_VSN = 0.98.10 +WX_VSN = 0.99 diff --git a/lib/xmerl/doc/src/notes.xml b/lib/xmerl/doc/src/notes.xml index 697823eee2..15c42d6f6a 100644 --- a/lib/xmerl/doc/src/notes.xml +++ b/lib/xmerl/doc/src/notes.xml @@ -31,6 +31,63 @@

This document describes the changes made to the Xmerl application.

+
Xmerl 1.2.10 + +
Fixed Bugs and Malfunctions + + +

Fixed a schema search bug in xmerl_xsd.

A + new flag was needed in the xsd_state record so if the + state is saved there is an incompatibility and a state + conversion is needed.

+

+ *** INCOMPATIBILITY with R14B03 ***

+

+ Own Id: OTP-9410

+
+ +

Fixed xmerl_scan problems with entities in attribute + values.

+

+ Own Id: OTP-9411

+
+ +

Streaming bug in xmerl_scan.

If the + continuation_fun runs out of input at the end of an + attribute value then it crashed. (Thanks to Simon + Cornish)

+

+ Own Id: OTP-9457

+
+ +

+ Fixed xmerl_ucs UCS2 little endian en/decoding

+

+ Corrected number of shift bytes in + xmerl_ucs:char_to_ucs2le and recursive call from + from_ucs2le to from_ucs4le. (Thanks to Michal Ptaszek)

+

+ Own Id: OTP-9548

+
+ +

+ Add latin9 (iso-8859-15) support in xmerl_ucs (Thanks to + David Julien)

+

+ Own Id: OTP-9552

+
+ +

+ Improve spelling throughout documentation, code comments + and error messages

+

+ Own Id: OTP-9555

+
+
+
+ +
+
Xmerl 1.2.9
Fixed Bugs and Malfunctions diff --git a/lib/xmerl/vsn.mk b/lib/xmerl/vsn.mk index 965a0ae7b4..82df8fdeef 100644 --- a/lib/xmerl/vsn.mk +++ b/lib/xmerl/vsn.mk @@ -1 +1 @@ -XMERL_VSN = 1.2.9 +XMERL_VSN = 1.2.10 -- cgit v1.2.3