From 9f4d45da9bfa3b1f5d3d345e48447ad89088afc9 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Mon, 20 Sep 2010 15:40:27 +0200 Subject: Update framework callbacks to use end_tc/4 if available. end_tc/4 can return anything which init_tc/3 can, and also modify the COnfig variable when called from init_per_suite and init_per_group --- lib/common_test/src/ct_suite_callback.erl | 92 +++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 lib/common_test/src/ct_suite_callback.erl (limited to 'lib/common_test') diff --git a/lib/common_test/src/ct_suite_callback.erl b/lib/common_test/src/ct_suite_callback.erl new file mode 100644 index 0000000000..db4ac9a4ec --- /dev/null +++ b/lib/common_test/src/ct_suite_callback.erl @@ -0,0 +1,92 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-2010. 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% +%% + +%%% @doc Common Test Framework test execution control module. +%%% +%%%

This module is a proxy for calling and handling suite callbacks.

+ +-module(ct_suite_callback). + +%% API Exports +-export([init/1]). +-export([init_tc/3]). +-export([end_tc/4]). +-export([terminate/2]). + +-type proplist() :: [{atom(),term()}]. + +-define(config_name, suite_callbacks). + +%% API Functions + +%% @doc Called before any suites are started +-spec init(State :: term()) -> ok | + {error, Reason :: term()}. +init(Opts) -> + add_new_callbacks(Opts), + ok. + +%% @doc Called after all suites are done. +-spec terminate(Config :: proplist(),State :: term()) -> + ok. +terminate(Config, State) -> + ok. + +%% @doc Called as each test case is started. This includes all configuration +%% tests. +-spec init_tc(Mod :: atom(), Func :: atom(), Config :: proplist()) -> + {ok, NewConfig :: proplist()} | + {skip, Reason :: term()} | + {auto_skip, Reason :: term()} | + {error, Reason :: term()}. +init_tc(Mod, init_per_suite, Config) -> + add_new_callbacks(Config), + {ok, Config}; +init_tc(Mod, Func, Config) -> + {ok, Config}. + +%% @doc Called as each test case is completed. This includes all configuration +%% tests. +-spec end_tc(Mod :: atom(), + Func :: atom(), + Config :: proplist(), + Result :: term()) -> + {ok, NewConfig :: proplist()} | + {skip, Reason :: term()} | + {auto_skip, Reason :: term()} | + {error, Reason :: term()} | + ok. +end_tc(Mod, Func, Config, Result) -> + {ok, Config}. + + +%% Iternal Functions +add_new_callbacks(Config) -> + NewCBConfs = lists:flatmap(fun({?config_name, CallbackConfigs}) -> + CallbackConfigs; + (_) -> + [] + end, Config), + CBStates = lists:map(fun call_init/1,NewCBConfs), + ct_util:save_suite_data_async(?config_name, CBStates). + +call_init({Mod, Config}) -> + {Mod, Mod:init(Config)}. + + -- cgit v1.2.3 From ec4c840624a9a44d4d7d6b1e51e1f33a291a704b Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Mon, 20 Sep 2010 15:46:12 +0200 Subject: Add support for suite_callback in spec, command_line and interactive. Start work on suite_callback functionality. --- lib/common_test/src/Makefile | 3 +- lib/common_test/src/ct_framework.erl | 36 +++++++++------ lib/common_test/src/ct_run.erl | 75 ++++++++++++++++++++++++------- lib/common_test/src/ct_suite_callback.erl | 73 +++++++++++++++++++++--------- lib/common_test/src/ct_testspec.erl | 16 +++++++ lib/common_test/src/ct_util.erl | 22 ++++++++- lib/common_test/src/ct_util.hrl | 1 + 7 files changed, 174 insertions(+), 52 deletions(-) (limited to 'lib/common_test') diff --git a/lib/common_test/src/Makefile b/lib/common_test/src/Makefile index 027667e6b0..14a0a27051 100644 --- a/lib/common_test/src/Makefile +++ b/lib/common_test/src/Makefile @@ -67,7 +67,8 @@ MODULES= \ ct_config \ ct_config_plain \ ct_config_xml \ - ct_slave + ct_slave \ + ct_suite_callback TARGET_MODULES= $(MODULES:%=$(EBIN)/%) diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl index f2ca023cff..8e6cfb5565 100644 --- a/lib/common_test/src/ct_framework.erl +++ b/lib/common_test/src/ct_framework.erl @@ -24,7 +24,7 @@ -module(ct_framework). --export([init_tc/3, end_tc/3, get_suite/2, report/2, warn/1]). +-export([init_tc/3, end_tc/4, get_suite/2, report/2, warn/1]). -export([error_notification/4]). -export([overview_html_header/1]). @@ -207,7 +207,7 @@ init_tc2(Mod,Func,SuiteInfo,MergeResult,Config,DoInit) -> {skip,{require_failed_in_suite0,Reason}}; {error,Reason} -> {auto_skip,{require_failed,Reason}}; - FinalConfig -> + {ok, FinalConfig} -> case MergeResult of {error,Reason} -> %% suite0 configure finished now, report that @@ -216,13 +216,20 @@ init_tc2(Mod,Func,SuiteInfo,MergeResult,Config,DoInit) -> _ -> case get('$test_server_framework_test') of undefined -> - FinalConfig; + ct_suite_init(Mod, FuncSpec, FinalConfig); Fun -> Fun(init_tc, FinalConfig) end end end. - + +ct_suite_init(Mod, Func, [Config]) when is_list(Config) -> + case ct_suite_callback:init_tc( Mod, Func, Config) of + NewConfig when is_list(NewConfig) -> + {ok, [NewConfig]}; + Else -> + Else + end. add_defaults(Mod,Func,FuncInfo,DoInit) -> case (catch Mod:suite()) of @@ -418,14 +425,14 @@ try_set_default(Name,Key,Info,Where) -> %%% %%% @doc Test server framework callback, called by the test_server %%% when a test case is finished. -end_tc(?MODULE,error_in_suite,_) -> % bad start! +end_tc(?MODULE,error_in_suite,_, _) -> % bad start! ok; -end_tc(Mod,Func,{TCPid,Result,[Args]}) when is_pid(TCPid) -> - end_tc(Mod,Func,TCPid,Result,Args); -end_tc(Mod,Func,{Result,[Args]}) -> - end_tc(Mod,Func,self(),Result,Args). +end_tc(Mod,Func,{TCPid,Result,[Args]}, Return) when is_pid(TCPid) -> + end_tc(Mod,Func,TCPid,Result,Args,Return); +end_tc(Mod,Func,{Result,[Args]}, Return) -> + end_tc(Mod,Func,self(),Result,Args,Return). -end_tc(Mod,Func,TCPid,Result,Args) -> +end_tc(Mod,Func,TCPid,Result,Args,Return) -> case lists:keysearch(watchdog,1,Args) of {value,{watchdog,Dog}} -> test_server:timetrap_cancel(Dog); false -> ok @@ -448,8 +455,10 @@ end_tc(Mod,Func,TCPid,Result,Args) -> {_,GroupName,_Props} = Group -> case lists:keysearch(save_config,1,Args) of {value,{save_config,SaveConfig}} -> - ct_util:save_suite_data(last_saved_config, - {Mod,{group,GroupName}},SaveConfig), + ct_util:save_suite_data( + last_saved_config, + {Mod,{group,GroupName}}, + SaveConfig), Group; false -> Group @@ -492,7 +501,8 @@ end_tc(Mod,Func,TCPid,Result,Args) -> end, case get('$test_server_framework_test') of undefined -> - ok; + ct_suite_callback:end_tc( + Mod, FuncSpec, Args, Return); Fun -> Fun(end_tc, ok) end. diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl index d0e6ba5fa6..df7f21a51f 100644 --- a/lib/common_test/src/ct_run.erl +++ b/lib/common_test/src/ct_run.erl @@ -54,6 +54,7 @@ logdir, config = [], event_handlers = [], + suite_callbacks = [], include = [], silent_connections, stylesheet, @@ -171,6 +172,9 @@ script_start1(Parent, Args) -> ([]) -> true end, false, Args), EvHandlers = event_handler_args2opts(Args), + SuiteCBs = get_start_opt(suite_callback, + fun(CBs) -> [list_to_atom(CB) || CB <- CBs] end, + [], Args), %% check flags and set corresponding application env variables @@ -234,6 +238,7 @@ script_start1(Parent, Args) -> StartOpts = #opts{label = Label, vts = Vts, shell = Shell, cover = Cover, logdir = LogDir, event_handlers = EvHandlers, + suite_callbacks = SuiteCBs, include = IncludeDirs, silent_connections = SilentConns, stylesheet = Stylesheet, @@ -305,6 +310,10 @@ script_start2(StartOpts = #opts{vts = undefined, SpecStartOpts#opts.scale_timetraps), AllEvHs = merge_vals([StartOpts#opts.event_handlers, SpecStartOpts#opts.event_handlers]), + AllSuiteCBs = merge_vals( + [StartOpts#opts.suite_callbacks, + SpecStartOpts#opts.suite_callbacks]), + AllInclude = merge_vals([StartOpts#opts.include, SpecStartOpts#opts.include]), application:set_env(common_test, include, AllInclude), @@ -315,6 +324,7 @@ script_start2(StartOpts = #opts{vts = undefined, logdir = LogDir, config = SpecStartOpts#opts.config, event_handlers = AllEvHs, + suite_callbacks = AllSuiteCBs, include = AllInclude, multiply_timetraps = MultTT, scale_timetraps = ScaleTT}} @@ -332,7 +342,8 @@ script_start2(StartOpts = #opts{vts = undefined, {error,no_testspec_specified}; {undefined,_} -> % no testspec used case check_and_install_configfiles(InitConfig, TheLogDir, - Opts#opts.event_handlers) of + Opts#opts.event_handlers, + Opts#opts.suite_callbacks) of ok -> % go on read tests from start flags script_start3(Opts#opts{config=InitConfig, logdir=TheLogDir}, Args); @@ -343,7 +354,8 @@ script_start2(StartOpts = #opts{vts = undefined, %% merge config from start flags with config from testspec AllConfig = merge_vals([InitConfig, Opts#opts.config]), case check_and_install_configfiles(AllConfig, TheLogDir, - Opts#opts.event_handlers) of + Opts#opts.event_handlers, + Opts#opts.suite_callbacks) of ok -> % read tests from spec {Run,Skip} = ct_testspec:prepare_tests(Terms, node()), do_run(Run, Skip, Opts#opts{config=AllConfig, @@ -358,7 +370,8 @@ script_start2(StartOpts, Args) -> InitConfig = ct_config:prepare_config_list(Args), LogDir = which(logdir, StartOpts#opts.logdir), case check_and_install_configfiles(InitConfig, LogDir, - StartOpts#opts.event_handlers) of + StartOpts#opts.event_handlers, + StartOpts#opts.suite_callbacks) of ok -> % go on read tests from start flags script_start3(StartOpts#opts{config=InitConfig, logdir=LogDir}, Args); @@ -366,11 +379,12 @@ script_start2(StartOpts, Args) -> Error end. -check_and_install_configfiles(Configs, LogDir, EvHandlers) -> +check_and_install_configfiles(Configs, LogDir, EvHandlers, SuiteCBs) -> case ct_config:check_config_files(Configs) of false -> install([{config,Configs}, - {event_handler,EvHandlers}], LogDir); + {event_handler,EvHandlers}, + {suite_callbacks,SuiteCBs}], LogDir); {value,{error,{nofile,File}}} -> {error,{cant_read_config_file,File}}; {value,{error,{wrong_config,Message}}}-> @@ -438,11 +452,13 @@ script_start4(#opts{vts = true, config = Config, event_handlers = EvHandlers, script_start4(#opts{label = Label, shell = true, config = Config, event_handlers = EvHandlers, + suite_callbacks = SuiteCBs, logdir = LogDir, testspecs = Specs}, _Args) -> %% label - used by ct_logs application:set_env(common_test, test_label, Label), - InstallOpts = [{config,Config},{event_handler,EvHandlers}], + InstallOpts = [{config,Config},{event_handler,EvHandlers}, + {suite_callbacks, SuiteCBs}], if Config == [] -> ok; true -> @@ -508,6 +524,7 @@ script_usage() -> "\n\t[-stylesheet CSSFile]" "\n\t[-cover CoverCfgFile]" "\n\t[-event_handler EvHandler1 EvHandler2 .. EvHandlerN]" + "\n\t[-suite_callback SuiteCB1 SuiteCB2 .. SuiteCBN]" "\n\t[-include InclDir1 InclDir2 .. InclDirN]" "\n\t[-no_auto_compile]" "\n\t[-multiply_timetraps N]" @@ -526,6 +543,7 @@ script_usage() -> "\n\t[-stylesheet CSSFile]" "\n\t[-cover CoverCfgFile]" "\n\t[-event_handler EvHandler1 EvHandler2 .. EvHandlerN]" + "\n\t[-suite_callback SuiteCB1 SuiteCB2 .. SuiteCBN]" "\n\t[-include InclDir1 InclDir2 .. InclDirN]" "\n\t[-no_auto_compile]" "\n\t[-multiply_timetraps N]" @@ -664,6 +682,9 @@ run_test1(StartOpts) -> end, Hs)) end, + %% Suite Callbacks + SuiteCBs = get_start_opt(suite_callbacks, value, [], StartOpts), + %% silent connections SilentConns = get_start_opt(silent_connections, fun(all) -> []; @@ -733,7 +754,9 @@ run_test1(StartOpts) -> Opts = #opts{label = Label, cover = Cover, step = Step, logdir = LogDir, config = CfgFiles, - event_handlers = EvHandlers, include = Include, + event_handlers = EvHandlers, + suite_callbacks = SuiteCBs, + include = Include, silent_connections = SilentConns, stylesheet = Stylesheet, multiply_timetraps = MultiplyTT, @@ -784,11 +807,16 @@ run_spec_file(Relaxed, SpecOpts#opts.event_handlers]), AllInclude = merge_vals([Opts#opts.include, SpecOpts#opts.include]), + + AllSuiteCBs = merge_vals([Opts#opts.suite_callbacks, + SpecOpts#opts.suite_callbacks]), + application:set_env(common_test, include, AllInclude), case check_and_install_configfiles(AllConfig, which(logdir,LogDir), - AllEvHs) of + AllEvHs, + AllSuiteCBs) of ok -> Opts1 = Opts#opts{label = Label, cover = Cover, @@ -798,7 +826,8 @@ run_spec_file(Relaxed, include = AllInclude, testspecs = AbsSpecs, multiply_timetraps = MultTT, - scale_timetraps = ScaleTT}, + scale_timetraps = ScaleTT, + suite_callbacks = AllSuiteCBs}, {Run,Skip} = ct_testspec:prepare_tests(TS, node()), reformat_result(catch do_run(Run, Skip, Opts1, StartOpts)); {error,GCFReason} -> @@ -808,10 +837,12 @@ run_spec_file(Relaxed, run_prepared(Run, Skip, Opts = #opts{logdir = LogDir, config = CfgFiles, - event_handlers = EvHandlers}, + event_handlers = EvHandlers, + suite_callbacks = SuiteCBs}, StartOpts) -> LogDir1 = which(logdir, LogDir), - case check_and_install_configfiles(CfgFiles, LogDir1, EvHandlers) of + case check_and_install_configfiles(CfgFiles, LogDir1, + EvHandlers, SuiteCBs) of ok -> reformat_result(catch do_run(Run, Skip, Opts#opts{logdir = LogDir1}, StartOpts)); @@ -842,7 +873,8 @@ check_config_file(Callback, File)-> run_dir(Opts = #opts{logdir = LogDir, config = CfgFiles, - event_handlers = EvHandlers}, StartOpts) -> + event_handlers = EvHandlers, + suite_callbacks = SuiteCB }, StartOpts) -> LogDir1 = which(logdir, LogDir), Opts1 = Opts#opts{logdir = LogDir1}, AbsCfgFiles = @@ -863,7 +895,9 @@ run_dir(Opts = #opts{logdir = LogDir, check_config_file(Callback, File) end, FileList)} end, CfgFiles), - case install([{config,AbsCfgFiles},{event_handler,EvHandlers}], LogDir1) of + case install([{config,AbsCfgFiles}, + {event_handler,EvHandlers}, + {suite_callbacks, SuiteCB}], LogDir1) of ok -> ok; {error,IReason} -> exit(IReason) end, @@ -968,7 +1002,8 @@ run_testspec1(TestSpec) -> application:set_env(common_test, include, AllInclude), LogDir1 = which(logdir,Opts#opts.logdir), case check_and_install_configfiles(Opts#opts.config, LogDir1, - Opts#opts.event_handlers) of + Opts#opts.event_handlers, + Opts#opts.suite_callbacks) of ok -> Opts1 = Opts#opts{testspecs = [], logdir = LogDir1, @@ -986,6 +1021,7 @@ get_data_for_node(#testspec{label = Labels, config = Cfgs, userconfig = UsrCfgs, event_handler = EvHs, + suite_callbacks = SuCBs, include = Incl, multiply_timetraps = MTs, scale_timetraps = STs}, Node) -> @@ -1000,12 +1036,14 @@ get_data_for_node(#testspec{label = Labels, ConfigFiles = [{?ct_config_txt,F} || {N,F} <- Cfgs, N==Node] ++ [CBF || {N,CBF} <- UsrCfgs, N==Node], EvHandlers = [{H,A} || {N,H,A} <- EvHs, N==Node], + SuiteCBs = [CB || {N,CB} <- SuCBs, N==Node], Include = [I || {N,I} <- Incl, N==Node], #opts{label = Label, logdir = LogDir, cover = Cover, config = ConfigFiles, event_handlers = EvHandlers, + suite_callbacks = SuiteCBs, include = Include, multiply_timetraps = MT, scale_timetraps = ST}. @@ -2263,12 +2301,17 @@ do_trace(Terms) -> dbg:tracer(), dbg:p(self(), [sos,call]), lists:foreach(fun({m,M}) -> - case dbg:tpl(M,[{'_',[],[{return_trace}]}]) of + case dbg:tpl(M,x) of + {error,What} -> exit({error,{tracing_failed,What}}); + _ -> ok + end; + ({me,M}) -> + case dbg:tp(M,x) of {error,What} -> exit({error,{tracing_failed,What}}); _ -> ok end; ({f,M,F}) -> - case dbg:tpl(M,F,[{'_',[],[{return_trace}]}]) of + case dbg:tpl(M,F,x) of {error,What} -> exit({error,{tracing_failed,What}}); _ -> ok end; diff --git a/lib/common_test/src/ct_suite_callback.erl b/lib/common_test/src/ct_suite_callback.erl index db4ac9a4ec..52ce5b92d1 100644 --- a/lib/common_test/src/ct_suite_callback.erl +++ b/lib/common_test/src/ct_suite_callback.erl @@ -39,8 +39,8 @@ -spec init(State :: term()) -> ok | {error, Reason :: term()}. init(Opts) -> - add_new_callbacks(Opts), - ok. + call(get_new_callbacks(Opts), fun call_init/2, ok). + %% @doc Called after all suites are done. -spec terminate(Config :: proplist(),State :: term()) -> @@ -51,15 +51,18 @@ terminate(Config, State) -> %% @doc Called as each test case is started. This includes all configuration %% tests. -spec init_tc(Mod :: atom(), Func :: atom(), Config :: proplist()) -> - {ok, NewConfig :: proplist()} | + NewConfig :: proplist() | {skip, Reason :: term()} | {auto_skip, Reason :: term()} | {error, Reason :: term()}. init_tc(Mod, init_per_suite, Config) -> - add_new_callbacks(Config), - {ok, Config}; + NewConfig = call(get_new_callbacks(Config) ++ get_callbacks(), + fun call_init/2, remove(?config_name,Config)), + + Data = ct_util:read_suite_data(?config_name), + [{suitedata, Data} | NewConfig]; init_tc(Mod, Func, Config) -> - {ok, Config}. + Config. %% @doc Called as each test case is completed. This includes all configuration %% tests. @@ -67,26 +70,54 @@ init_tc(Mod, Func, Config) -> Func :: atom(), Config :: proplist(), Result :: term()) -> - {ok, NewConfig :: proplist()} | + NewConfig :: proplist() | {skip, Reason :: term()} | {auto_skip, Reason :: term()} | {error, Reason :: term()} | ok. +end_tc(Mod, init_per_suite, _, Return) -> + NewConfig = call(get_new_callbacks(Return) ++ get_callbacks(), + fun call_init/2, remove(suitedata, remove(?config_name,Return))), + + Data = ct_util:read_suite_data(?config_name), + [{suitedata, Data} | NewConfig]; end_tc(Mod, Func, Config, Result) -> - {ok, Config}. + Result. %% Iternal Functions -add_new_callbacks(Config) -> - NewCBConfs = lists:flatmap(fun({?config_name, CallbackConfigs}) -> - CallbackConfigs; - (_) -> - [] - end, Config), - CBStates = lists:map(fun call_init/1,NewCBConfs), - ct_util:save_suite_data_async(?config_name, CBStates). - -call_init({Mod, Config}) -> - {Mod, Mod:init(Config)}. - - +get_new_callbacks(Config) -> + lists:flatmap(fun({?config_name, CallbackConfigs}) -> + CallbackConfigs; + (_) -> + [] + end, Config). + +get_callbacks() -> + ct_util:read_suite_data(?config_name). + +call_init(Mod, Config) when is_atom(Mod) -> + call_init({Mod, undefined}, Config); +call_init({Mod, State}, Config) -> + {{Mod, running, Mod:init(State)}, Config}; +call_init({Mod, running, State}, Config) -> + {{Mod, running, State}, Config}. + +%% Generic call function +call(Fun, Config) -> + call(get_callbacks(), Fun, Config). + +call(CBs, Fun, Config) -> + call(CBs, Fun, Config, []). + +call([CB | Rest], Fun, Config, NewCBs) -> + {NewCB, NewConf} = Fun(CB,Config), + call(Rest, Fun, NewConf, [NewCB | NewCBs]); +call([], _Fun, Config, NewCBs) -> + ct_util:save_suite_data_async(?config_name, NewCBs), + Config. + + +remove(Key,List) -> + [Conf || Conf <- List, + element(1,Conf) =/= Key]. diff --git a/lib/common_test/src/ct_testspec.erl b/lib/common_test/src/ct_testspec.erl index f5069427a2..942241da6c 100644 --- a/lib/common_test/src/ct_testspec.erl +++ b/lib/common_test/src/ct_testspec.erl @@ -625,6 +625,20 @@ add_tests([{event_handler,Node,H,Args}|Ts],Spec) when is_atom(H) -> Node1 = ref2node(Node,Spec#testspec.nodes), add_tests(Ts,Spec#testspec{event_handler=[{Node1,H,Args}|EvHs]}); +%% --- suite_callbacks -- +add_tests([{suite_callbacks, all_nodes, CBs} | Ts], Spec) -> + Tests = [{suite_callbacks,N,CBs} || N <- list_nodes(Spec)], + add_tests(Tests ++ Ts, Spec); +add_tests([{suite_callbacks, Node, [CB|CBs]}|Ts], Spec) -> + SuiteCbs = Spec#testspec.suite_callbacks, + Node1 = ref2node(Node,Spec#testspec.nodes), + add_tests([{suite_callbacks, Node, CBs} | Ts], + Spec#testspec{suite_callbacks = [{Node1,CB} | SuiteCbs]}); +add_tests([{suite_callbacks, _Node, []}|Ts], Spec) -> + add_tests(Ts, Spec); +add_tests([{suite_callbacks, CBs}|Ts], Spec) -> + add_tests([{suite_callbacks, all_nodes, CBs}|Ts], Spec); + %% --- include --- add_tests([{include,all_nodes,InclDirs}|Ts],Spec) -> Tests = lists:map(fun(N) -> {include,N,InclDirs} end, list_nodes(Spec)), @@ -1051,6 +1065,8 @@ valid_terms() -> {event_handler,2}, {event_handler,3}, {event_handler,4}, + {suite_callbacks,2}, + {suite_callbacks,3}, {multiply_timetraps,2}, {multiply_timetraps,3}, {scale_timetraps,2}, diff --git a/lib/common_test/src/ct_util.erl b/lib/common_test/src/ct_util.erl index b5ab4cbb6e..4696b3c954 100644 --- a/lib/common_test/src/ct_util.erl +++ b/lib/common_test/src/ct_util.erl @@ -32,7 +32,9 @@ -export([close_connections/0]). --export([save_suite_data/3, save_suite_data/2, read_suite_data/1, +-export([save_suite_data/3, save_suite_data/2, + save_suite_data_async/3, save_suite_data_async/2, + read_suite_data/1, delete_suite_data/0, delete_suite_data/1, match_delete_suite_data/1, delete_testdata/0, delete_testdata/1, set_testdata/1, get_testdata/1, update_testdata/2]). @@ -159,6 +161,11 @@ do_start(Parent,Mode,LogDir) -> ok end, {StartTime,TestLogDir} = ct_logs:init(Mode), + + %% Initiate suite_callbacks + ok = ct_suite_callback:init(Opts), + + ct_event:notify(#event{name=test_start, node=node(), data={StartTime, @@ -182,12 +189,19 @@ read_opts() -> {error,{bad_installation,Error}} end. + save_suite_data(Key, Value) -> call({save_suite_data, {Key, undefined, Value}}). save_suite_data(Key, Name, Value) -> call({save_suite_data, {Key, Name, Value}}). +save_suite_data_async(Key, Value) -> + save_suite_data_async(Key, undefined, Value). + +save_suite_data_async(Key, Name, Value) -> + cast({save_suite_data, {Key, Name, Value}}). + read_suite_data(Key) -> call({read_suite_data, Key}). @@ -308,6 +322,9 @@ loop(Mode,TestData,StartDir) -> ct_config:stop(), file:set_cwd(StartDir), return(From,ok); + {Ref, _Msg} when is_reference(Ref) -> + %% This clause is used when doing cast operations. + loop(Mode,TestData,StartDir); {get_mode,From} -> return(From,Mode), loop(Mode,TestData,StartDir); @@ -713,6 +730,9 @@ call(Msg) -> return({To,Ref},Result) -> To ! {Ref, Result}. +cast(Msg) -> + ct_util_server ! {Msg, {ct_util_server, make_ref()}}. + seconds(T) -> test_server:seconds(T). diff --git a/lib/common_test/src/ct_util.hrl b/lib/common_test/src/ct_util.hrl index ee973f6220..99f029bc0e 100644 --- a/lib/common_test/src/ct_util.hrl +++ b/lib/common_test/src/ct_util.hrl @@ -36,6 +36,7 @@ config=[], userconfig=[], event_handler=[], + suite_callbacks=[], include=[], multiply_timetraps=[], scale_timetraps=[], -- cgit v1.2.3 From 19a4512b95ca20d32cf1eff4dc20eed9dc20510a Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Mon, 20 Sep 2010 19:10:21 +0200 Subject: Add so that suite_callcacks can be configures in suite/0 --- lib/common_test/src/ct_framework.erl | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/common_test') diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl index 8e6cfb5565..08ee843597 100644 --- a/lib/common_test/src/ct_framework.erl +++ b/lib/common_test/src/ct_framework.erl @@ -369,6 +369,8 @@ configure([{timetrap,off}|Rest],Info,SuiteInfo,Scope,Config) -> configure([{timetrap,Time}|Rest],Info,SuiteInfo,Scope,Config) -> Dog = test_server:timetrap(Time), configure(Rest,Info,SuiteInfo,Scope,[{watchdog,Dog}|Config]); +configure([{suite_callbacks, CB} | Rest], Info, SuiteInfo, Scope, Config) -> + configure(Rest, Info, SuiteInfo, Scope, [{suite_callbacks, CB} | Config]); configure([_|Rest],Info,SuiteInfo,Scope,Config) -> configure(Rest,Info,SuiteInfo,Scope,Config); configure([],_,_,_,Config) -> -- cgit v1.2.3 From 688e2a2506b16d851d1bbbf4f66eadba1feb1b88 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Mon, 20 Sep 2010 19:11:11 +0200 Subject: Update ct_trace me to include calling functions --- lib/common_test/src/ct_run.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/common_test') diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl index df7f21a51f..7869e385c2 100644 --- a/lib/common_test/src/ct_run.erl +++ b/lib/common_test/src/ct_run.erl @@ -2306,7 +2306,7 @@ do_trace(Terms) -> _ -> ok end; ({me,M}) -> - case dbg:tp(M,x) of + case dbg:tp(M,[{'_',[],[x,{message,{caller}}]}]) of {error,What} -> exit({error,{tracing_failed,What}}); _ -> ok end; -- cgit v1.2.3 From 34a7a606cb09c096623a0fb4237f8c87f307d7ff Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Mon, 20 Sep 2010 19:12:21 +0200 Subject: Add so that suite_callbacks can be added by suite_callbacks. Add support for pre/post_init_suite/2 in suite callback --- lib/common_test/src/ct_suite_callback.erl | 84 +++++++++++++++++++------------ 1 file changed, 52 insertions(+), 32 deletions(-) (limited to 'lib/common_test') diff --git a/lib/common_test/src/ct_suite_callback.erl b/lib/common_test/src/ct_suite_callback.erl index 52ce5b92d1..e14e5f90f3 100644 --- a/lib/common_test/src/ct_suite_callback.erl +++ b/lib/common_test/src/ct_suite_callback.erl @@ -39,7 +39,9 @@ -spec init(State :: term()) -> ok | {error, Reason :: term()}. init(Opts) -> - call(get_new_callbacks(Opts), fun call_init/2, ok). + call([{CB, call_init, undefined} || CB <- get_new_callbacks(Opts)], + ct_suite_callback_init_dummy, []), + ok. %% @doc Called after all suites are done. @@ -56,42 +58,44 @@ terminate(Config, State) -> {auto_skip, Reason :: term()} | {error, Reason :: term()}. init_tc(Mod, init_per_suite, Config) -> - NewConfig = call(get_new_callbacks(Config) ++ get_callbacks(), - fun call_init/2, remove(?config_name,Config)), - - Data = ct_util:read_suite_data(?config_name), - [{suitedata, Data} | NewConfig]; -init_tc(Mod, Func, Config) -> + call(fun call_pre_init_suite/2, Config); +init_tc(_, _, Config) -> Config. %% @doc Called as each test case is completed. This includes all configuration %% tests. -spec end_tc(Mod :: atom(), Func :: atom(), - Config :: proplist(), + CallConfig :: proplist(), Result :: term()) -> NewConfig :: proplist() | {skip, Reason :: term()} | {auto_skip, Reason :: term()} | {error, Reason :: term()} | ok. -end_tc(Mod, init_per_suite, _, Return) -> - NewConfig = call(get_new_callbacks(Return) ++ get_callbacks(), - fun call_init/2, remove(suitedata, remove(?config_name,Return))), +end_tc(Mod, init_per_suite, _, Result) -> - Data = ct_util:read_suite_data(?config_name), - [{suitedata, Data} | NewConfig]; -end_tc(Mod, Func, Config, Result) -> + NewConfig = call(fun call_post_init_suite/2, Result), + + NewConfig; +end_tc(_, _, _, Result) -> Result. %% Iternal Functions -get_new_callbacks(Config) -> +get_new_callbacks(Config, Fun) -> + lists:foldl(fun(NewCB, Acc) -> + [{NewCB, call_init, Fun} | Acc] + end, [], get_new_callbacks(Config)). + +get_new_callbacks(Config) when is_list(Config) -> lists:flatmap(fun({?config_name, CallbackConfigs}) -> CallbackConfigs; (_) -> [] - end, Config). + end, Config); +get_new_callbacks(_Config) -> + []. get_callbacks() -> ct_util:read_suite_data(?config_name). @@ -99,25 +103,41 @@ get_callbacks() -> call_init(Mod, Config) when is_atom(Mod) -> call_init({Mod, undefined}, Config); call_init({Mod, State}, Config) -> - {{Mod, running, Mod:init(State)}, Config}; -call_init({Mod, running, State}, Config) -> - {{Mod, running, State}, Config}. + {Id, NewState} = Mod:init(State), + {Config, {Id, {Mod, NewState}}}. + +call_pre_init_suite({Mod, State}, Config) -> + {NewConf, NewState} = Mod:pre_init_suite(Config, State), + {NewConf, {Mod, NewState}}. +call_post_init_suite({Mod, State}, Config) -> + {NewConf, NewState} = Mod:post_init_suite(Config, State), + {NewConf, {Mod, NewState}}. %% Generic call function call(Fun, Config) -> - call(get_callbacks(), Fun, Config). - -call(CBs, Fun, Config) -> - call(CBs, Fun, Config, []). - -call([CB | Rest], Fun, Config, NewCBs) -> - {NewCB, NewConf} = Fun(CB,Config), - call(Rest, Fun, NewConf, [NewCB | NewCBs]); -call([], _Fun, Config, NewCBs) -> - ct_util:save_suite_data_async(?config_name, NewCBs), + CBs = get_callbacks(), + call([{CBId,Fun} || {CBId, _} <- CBs] ++ get_new_callbacks(Config, Fun), + remove(?config_name,Config), CBs). + +call([{CB, call_init, NextFun} | Rest], Config, CBs) -> + {Config, {NewId, _} = NewCB} = call_init(CB, Config), + {NewCBs, NewRest} = case proplists:get_value(NewId, CBs, NextFun) of + undefined -> {CBs ++ [NewCB],Rest}; + {NewId, _, _} -> {CBs, Rest}; + Fun -> {CBs ++ [NewCB],[{NewId, NextFun} | Rest]} + end, + call(NewRest, Config, NewCBs); +call([{CBId, Fun} | Rest], Config, CBs) -> + {NewConf, NewCBInfo} = Fun(proplists:get_value(CBId, CBs), Config), + NewCalls = get_new_callbacks(NewConf, Fun), + call(NewCalls ++ Rest, remove(?config_name, NewConf), + lists:keyreplace(CBId, 1, CBs, {CBId, NewCBInfo})); +call([], Config, CBs) -> + ct_util:save_suite_data_async(?config_name, CBs), Config. - -remove(Key,List) -> +remove(Key,List) when is_list(List) -> [Conf || Conf <- List, - element(1,Conf) =/= Key]. + element(1, Conf) =/= Key]; +remove(_, Else) -> + Else. -- cgit v1.2.3 From 95b6bdd287c5b7c5d3c70290489576bf48449ac1 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Tue, 21 Sep 2010 12:15:43 +0200 Subject: Add support for all pre/post init/end functions --- lib/common_test/src/ct_suite_callback.erl | 127 +++++++++++++++++------------- 1 file changed, 72 insertions(+), 55 deletions(-) (limited to 'lib/common_test') diff --git a/lib/common_test/src/ct_suite_callback.erl b/lib/common_test/src/ct_suite_callback.erl index e14e5f90f3..fcada641d7 100644 --- a/lib/common_test/src/ct_suite_callback.erl +++ b/lib/common_test/src/ct_suite_callback.erl @@ -33,106 +33,105 @@ -define(config_name, suite_callbacks). +%% ------------------------------------------------------------------------- %% API Functions +%% ------------------------------------------------------------------------- %% @doc Called before any suites are started -spec init(State :: term()) -> ok | {error, Reason :: term()}. init(Opts) -> call([{CB, call_init, undefined} || CB <- get_new_callbacks(Opts)], - ct_suite_callback_init_dummy, []), + ct_suite_callback_init_dummy, undefined, []), ok. %% @doc Called after all suites are done. -spec terminate(Config :: proplist(),State :: term()) -> ok. -terminate(Config, State) -> +terminate(_Config, _State) -> ok. %% @doc Called as each test case is started. This includes all configuration %% tests. --spec init_tc(Mod :: atom(), Func :: atom(), Config :: proplist()) -> +-spec init_tc(Mod :: atom(), Func :: atom(), Args :: list()) -> NewConfig :: proplist() | {skip, Reason :: term()} | {auto_skip, Reason :: term()} | - {error, Reason :: term()}. + {fail, Reason :: term()}. +init_tc(ct_framework, Mod, Args) -> + Args; init_tc(Mod, init_per_suite, Config) -> - call(fun call_pre_init_suite/2, Config); -init_tc(_, _, Config) -> - Config. + call(fun call_generic/3, Config, {pre_init_suite, Mod}); +init_tc(Mod, end_per_suite, Config) -> + call(fun call_generic/3, Config, {pre_end_suite, Mod}); +init_tc(_Mod, {init_per_group, GroupName, _}, Config) -> + call(fun call_generic/3, Config, {pre_init_group, GroupName}); +init_tc(_Mod, {end_per_group, GroupName, _}, Config) -> + call(fun call_generic/3, Config, {pre_end_group, GroupName}); +init_tc(_Mod, TC, Config) -> + call(fun call_generic/3, Config, {pre_init_group, TC}). %% @doc Called as each test case is completed. This includes all configuration %% tests. -spec end_tc(Mod :: atom(), Func :: atom(), - CallConfig :: proplist(), + Args :: list(), Result :: term()) -> NewConfig :: proplist() | {skip, Reason :: term()} | {auto_skip, Reason :: term()} | - {error, Reason :: term()} | + {fail, Reason :: term()} | ok. -end_tc(Mod, init_per_suite, _, Result) -> - - NewConfig = call(fun call_post_init_suite/2, Result), - - NewConfig; -end_tc(_, _, _, Result) -> - Result. - - -%% Iternal Functions -get_new_callbacks(Config, Fun) -> - lists:foldl(fun(NewCB, Acc) -> - [{NewCB, call_init, Fun} | Acc] - end, [], get_new_callbacks(Config)). - -get_new_callbacks(Config) when is_list(Config) -> - lists:flatmap(fun({?config_name, CallbackConfigs}) -> - CallbackConfigs; - (_) -> - [] - end, Config); -get_new_callbacks(_Config) -> - []. - -get_callbacks() -> - ct_util:read_suite_data(?config_name). - -call_init(Mod, Config) when is_atom(Mod) -> - call_init({Mod, undefined}, Config); -call_init({Mod, State}, Config) -> +end_tc(ct_framework, Mod, _Args, Result) -> + Result; +end_tc(Mod, init_per_suite, _Config, Result) -> + call(fun call_generic/3, Result, {post_init_suite, Mod}); +end_tc(Mod, end_per_suite, _Config, Result) -> + call(fun call_generic/3, Result, {post_end_suite, Mod}); +end_tc(_Mod, {init_per_group, GroupName, _}, _Config, Result) -> + call(fun call_generic/3, Result, {post_init_group, GroupName}); +end_tc(_Mod, {end_per_group, GroupName, _}, _Config, Result) -> + call(fun call_generic/3, Result, {post_end_group, GroupName}); +end_tc(_Mod, TC, _Config, Result) -> + call(fun call_generic/3, Result, {post_end_tc, TC}). + +%% ------------------------------------------------------------------------- +%% Internal Functions +%% ------------------------------------------------------------------------- +call_init(Mod, Config, Meta) when is_atom(Mod) -> + call_init({Mod, undefined}, Config, Meta); +call_init({Mod, State}, Config, _) -> {Id, NewState} = Mod:init(State), {Config, {Id, {Mod, NewState}}}. -call_pre_init_suite({Mod, State}, Config) -> - {NewConf, NewState} = Mod:pre_init_suite(Config, State), - {NewConf, {Mod, NewState}}. -call_post_init_suite({Mod, State}, Config) -> - {NewConf, NewState} = Mod:post_init_suite(Config, State), +call_generic({Mod, State}, Config, {Function, undefined}) -> + {NewConf, NewState} = Mod:Function(Config, State), + {NewConf, {Mod, NewState}}; +call_generic({Mod, State}, Config, {Function, Tag}) -> + {NewConf, NewState} = Mod:Function(Tag, Config, State), {NewConf, {Mod, NewState}}. %% Generic call function -call(Fun, Config) -> +call(Fun, Config, Meta) -> CBs = get_callbacks(), call([{CBId,Fun} || {CBId, _} <- CBs] ++ get_new_callbacks(Config, Fun), - remove(?config_name,Config), CBs). - -call([{CB, call_init, NextFun} | Rest], Config, CBs) -> - {Config, {NewId, _} = NewCB} = call_init(CB, Config), + remove(?config_name,Config), Meta, CBs). + +call([{CB, call_init, NextFun} | Rest], Config, Meta, CBs) -> + {Config, {NewId, _} = NewCB} = call_init(CB, Config, Meta), {NewCBs, NewRest} = case proplists:get_value(NewId, CBs, NextFun) of undefined -> {CBs ++ [NewCB],Rest}; - {NewId, _, _} -> {CBs, Rest}; + ExistingCB when is_tuple(ExistingCB) -> {CBs, Rest}; Fun -> {CBs ++ [NewCB],[{NewId, NextFun} | Rest]} end, - call(NewRest, Config, NewCBs); -call([{CBId, Fun} | Rest], Config, CBs) -> - {NewConf, NewCBInfo} = Fun(proplists:get_value(CBId, CBs), Config), + call(NewRest, Config, Meta, NewCBs); +call([{CBId, Fun} | Rest], Config, Meta, CBs) -> + {NewConf, NewCBInfo} = Fun(proplists:get_value(CBId, CBs), Config, Meta), NewCalls = get_new_callbacks(NewConf, Fun), - call(NewCalls ++ Rest, remove(?config_name, NewConf), + call(NewCalls ++ Rest, remove(?config_name, NewConf), Meta, lists:keyreplace(CBId, 1, CBs, {CBId, NewCBInfo})); -call([], Config, CBs) -> +call([], Config, Meta, CBs) -> ct_util:save_suite_data_async(?config_name, CBs), Config. @@ -141,3 +140,21 @@ remove(Key,List) when is_list(List) -> element(1, Conf) =/= Key]; remove(_, Else) -> Else. + +%% Fetch callback functions +get_new_callbacks(Config, Fun) -> + lists:foldl(fun(NewCB, Acc) -> + [{NewCB, call_init, Fun} | Acc] + end, [], get_new_callbacks(Config)). + +get_new_callbacks(Config) when is_list(Config) -> + lists:flatmap(fun({?config_name, CallbackConfigs}) -> + CallbackConfigs; + (_) -> + [] + end, Config); +get_new_callbacks(_Config) -> + []. + +get_callbacks() -> + ct_util:read_suite_data(?config_name). -- cgit v1.2.3 From 587bceba86718fb935e367a558af9f60bcd2bec8 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Mon, 27 Sep 2010 16:25:40 +0200 Subject: Remove some compilation warnings --- lib/common_test/src/ct_suite_callback.erl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib/common_test') diff --git a/lib/common_test/src/ct_suite_callback.erl b/lib/common_test/src/ct_suite_callback.erl index fcada641d7..ab5c005a43 100644 --- a/lib/common_test/src/ct_suite_callback.erl +++ b/lib/common_test/src/ct_suite_callback.erl @@ -59,7 +59,7 @@ terminate(_Config, _State) -> {skip, Reason :: term()} | {auto_skip, Reason :: term()} | {fail, Reason :: term()}. -init_tc(ct_framework, Mod, Args) -> +init_tc(ct_framework, _Func, Args) -> Args; init_tc(Mod, init_per_suite, Config) -> call(fun call_generic/3, Config, {pre_init_suite, Mod}); @@ -83,7 +83,7 @@ init_tc(_Mod, TC, Config) -> {auto_skip, Reason :: term()} | {fail, Reason :: term()} | ok. -end_tc(ct_framework, Mod, _Args, Result) -> +end_tc(ct_framework, _Func, _Args, Result) -> Result; end_tc(Mod, init_per_suite, _Config, Result) -> call(fun call_generic/3, Result, {post_init_suite, Mod}); @@ -123,7 +123,7 @@ call([{CB, call_init, NextFun} | Rest], Config, Meta, CBs) -> {NewCBs, NewRest} = case proplists:get_value(NewId, CBs, NextFun) of undefined -> {CBs ++ [NewCB],Rest}; ExistingCB when is_tuple(ExistingCB) -> {CBs, Rest}; - Fun -> {CBs ++ [NewCB],[{NewId, NextFun} | Rest]} + _ -> {CBs ++ [NewCB],[{NewId, NextFun} | Rest]} end, call(NewRest, Config, Meta, NewCBs); call([{CBId, Fun} | Rest], Config, Meta, CBs) -> @@ -131,7 +131,7 @@ call([{CBId, Fun} | Rest], Config, Meta, CBs) -> NewCalls = get_new_callbacks(NewConf, Fun), call(NewCalls ++ Rest, remove(?config_name, NewConf), Meta, lists:keyreplace(CBId, 1, CBs, {CBId, NewCBInfo})); -call([], Config, Meta, CBs) -> +call([], Config, _Meta, CBs) -> ct_util:save_suite_data_async(?config_name, CBs), Config. -- cgit v1.2.3 From 87a24f6a5c9a032baf64b2a3427c899c5e8632e7 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Wed, 17 Nov 2010 16:55:43 +0100 Subject: Update so that non tuple return values are not filtered out --- lib/common_test/src/ct_suite_callback.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/common_test') diff --git a/lib/common_test/src/ct_suite_callback.erl b/lib/common_test/src/ct_suite_callback.erl index ab5c005a43..124397b222 100644 --- a/lib/common_test/src/ct_suite_callback.erl +++ b/lib/common_test/src/ct_suite_callback.erl @@ -136,8 +136,8 @@ call([], Config, _Meta, CBs) -> Config. remove(Key,List) when is_list(List) -> - [Conf || Conf <- List, - element(1, Conf) =/= Key]; + [Conf || Conf <- List, is_tuple(Conf) =:= false + orelse element(1, Conf) =/= Key]; remove(_, Else) -> Else. -- cgit v1.2.3 From 1ab0779cd90f5b76bf546b5964e8550f1b68f962 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Wed, 17 Nov 2010 16:56:26 +0100 Subject: Expand tracing functions to be more verbose --- lib/common_test/src/ct_run.erl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'lib/common_test') diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl index 7869e385c2..9b4007026b 100644 --- a/lib/common_test/src/ct_run.erl +++ b/lib/common_test/src/ct_run.erl @@ -2306,12 +2306,14 @@ do_trace(Terms) -> _ -> ok end; ({me,M}) -> - case dbg:tp(M,[{'_',[],[x,{message,{caller}}]}]) of + case dbg:tp(M,[{'_',[],[{exception_trace}, + {message,{caller}}]}]) of {error,What} -> exit({error,{tracing_failed,What}}); _ -> ok end; ({f,M,F}) -> - case dbg:tpl(M,F,x) of + case dbg:tpl(M,F,[{'_',[],[{exception_trace}, + {message,{caller}}]}]) of {error,What} -> exit({error,{tracing_failed,What}}); _ -> ok end; -- cgit v1.2.3 From dc20d9d2538b60547c3cbfba1772b500a85302b8 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Wed, 17 Nov 2010 16:59:34 +0100 Subject: Update to be backward compatible with ct framework test funktionality --- lib/common_test/src/ct_framework.erl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'lib/common_test') diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl index 08ee843597..ac10bddefc 100644 --- a/lib/common_test/src/ct_framework.erl +++ b/lib/common_test/src/ct_framework.erl @@ -218,7 +218,12 @@ init_tc2(Mod,Func,SuiteInfo,MergeResult,Config,DoInit) -> undefined -> ct_suite_init(Mod, FuncSpec, FinalConfig); Fun -> - Fun(init_tc, FinalConfig) + case Fun(init_tc, FinalConfig) of + NewConfig when is_list(NewConfig) -> + {ok,NewConfig}; + Else -> + Else + end end end end. -- cgit v1.2.3 From 6c4801696d6a22d61d2e7b145506f2548ea80547 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 18 Nov 2010 14:11:23 +0100 Subject: Update input parameter for suite callbacks to be called suite_callbacks when given from both erlang shell and ct_run command --- lib/common_test/src/ct_run.erl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/common_test') diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl index 9b4007026b..78782d346a 100644 --- a/lib/common_test/src/ct_run.erl +++ b/lib/common_test/src/ct_run.erl @@ -172,7 +172,7 @@ script_start1(Parent, Args) -> ([]) -> true end, false, Args), EvHandlers = event_handler_args2opts(Args), - SuiteCBs = get_start_opt(suite_callback, + SuiteCBs = get_start_opt(suite_callbacks, fun(CBs) -> [list_to_atom(CB) || CB <- CBs] end, [], Args), @@ -524,7 +524,7 @@ script_usage() -> "\n\t[-stylesheet CSSFile]" "\n\t[-cover CoverCfgFile]" "\n\t[-event_handler EvHandler1 EvHandler2 .. EvHandlerN]" - "\n\t[-suite_callback SuiteCB1 SuiteCB2 .. SuiteCBN]" + "\n\t[-suite_callbacks SuiteCB1 SuiteCB2 .. SuiteCBN]" "\n\t[-include InclDir1 InclDir2 .. InclDirN]" "\n\t[-no_auto_compile]" "\n\t[-multiply_timetraps N]" @@ -543,7 +543,7 @@ script_usage() -> "\n\t[-stylesheet CSSFile]" "\n\t[-cover CoverCfgFile]" "\n\t[-event_handler EvHandler1 EvHandler2 .. EvHandlerN]" - "\n\t[-suite_callback SuiteCB1 SuiteCB2 .. SuiteCBN]" + "\n\t[-suite_callbacks SuiteCB1 SuiteCB2 .. SuiteCBN]" "\n\t[-include InclDir1 InclDir2 .. InclDirN]" "\n\t[-no_auto_compile]" "\n\t[-multiply_timetraps N]" -- cgit v1.2.3 From 3bacd0466501e872c69fbb89c7e6600395d7854c Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 18 Nov 2010 14:17:27 +0100 Subject: Rename all callback functions to be more inline with the suite callback functions --- lib/common_test/src/ct_suite_callback.erl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'lib/common_test') diff --git a/lib/common_test/src/ct_suite_callback.erl b/lib/common_test/src/ct_suite_callback.erl index 124397b222..702d9a354c 100644 --- a/lib/common_test/src/ct_suite_callback.erl +++ b/lib/common_test/src/ct_suite_callback.erl @@ -62,15 +62,15 @@ terminate(_Config, _State) -> init_tc(ct_framework, _Func, Args) -> Args; init_tc(Mod, init_per_suite, Config) -> - call(fun call_generic/3, Config, {pre_init_suite, Mod}); + call(fun call_generic/3, Config, {pre_init_per_suite, Mod}); init_tc(Mod, end_per_suite, Config) -> - call(fun call_generic/3, Config, {pre_end_suite, Mod}); + call(fun call_generic/3, Config, {pre_end_per_suite, Mod}); init_tc(_Mod, {init_per_group, GroupName, _}, Config) -> - call(fun call_generic/3, Config, {pre_init_group, GroupName}); + call(fun call_generic/3, Config, {pre_init_per_group, GroupName}); init_tc(_Mod, {end_per_group, GroupName, _}, Config) -> - call(fun call_generic/3, Config, {pre_end_group, GroupName}); + call(fun call_generic/3, Config, {pre_end_per_group, GroupName}); init_tc(_Mod, TC, Config) -> - call(fun call_generic/3, Config, {pre_init_group, TC}). + call(fun call_generic/3, Config, {pre_init_per_testcase, TC}). %% @doc Called as each test case is completed. This includes all configuration %% tests. @@ -86,15 +86,15 @@ init_tc(_Mod, TC, Config) -> end_tc(ct_framework, _Func, _Args, Result) -> Result; end_tc(Mod, init_per_suite, _Config, Result) -> - call(fun call_generic/3, Result, {post_init_suite, Mod}); + call(fun call_generic/3, Result, {post_init_per_suite, Mod}); end_tc(Mod, end_per_suite, _Config, Result) -> - call(fun call_generic/3, Result, {post_end_suite, Mod}); + call(fun call_generic/3, Result, {post_end_per_suite, Mod}); end_tc(_Mod, {init_per_group, GroupName, _}, _Config, Result) -> - call(fun call_generic/3, Result, {post_init_group, GroupName}); + call(fun call_generic/3, Result, {post_init_per_group, GroupName}); end_tc(_Mod, {end_per_group, GroupName, _}, _Config, Result) -> - call(fun call_generic/3, Result, {post_end_group, GroupName}); + call(fun call_generic/3, Result, {post_end_per_group, GroupName}); end_tc(_Mod, TC, _Config, Result) -> - call(fun call_generic/3, Result, {post_end_tc, TC}). + call(fun call_generic/3, Result, {post_end_per_testcase, TC}). %% ------------------------------------------------------------------------- %% Internal Functions -- cgit v1.2.3 From 18b2dba61c4849fd924ace459d169d263e7e6619 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 18 Nov 2010 14:15:50 +0100 Subject: Add terminate SCB functionality --- lib/common_test/src/ct_suite_callback.erl | 13 ++++++++++--- lib/common_test/src/ct_util.erl | 4 ++++ 2 files changed, 14 insertions(+), 3 deletions(-) (limited to 'lib/common_test') diff --git a/lib/common_test/src/ct_suite_callback.erl b/lib/common_test/src/ct_suite_callback.erl index 702d9a354c..44e54f3968 100644 --- a/lib/common_test/src/ct_suite_callback.erl +++ b/lib/common_test/src/ct_suite_callback.erl @@ -27,7 +27,7 @@ -export([init/1]). -export([init_tc/3]). -export([end_tc/4]). --export([terminate/2]). +-export([terminate/1]). -type proplist() :: [{atom(),term()}]. @@ -47,9 +47,12 @@ init(Opts) -> %% @doc Called after all suites are done. --spec terminate(Config :: proplist(),State :: term()) -> +-spec terminate(Callbacks :: term()) -> ok. -terminate(_Config, _State) -> +terminate(Callbacks) -> + io:format("Callbacks: ~p",[Callbacks]), + call([{CBId, fun call_terminate/3} || {CBId,_} <- Callbacks], + ct_suite_callback_init_dummy, undefined, Callbacks), ok. %% @doc Called as each test case is started. This includes all configuration @@ -105,6 +108,10 @@ call_init({Mod, State}, Config, _) -> {Id, NewState} = Mod:init(State), {Config, {Id, {Mod, NewState}}}. +call_terminate({Mod, State}, _, _) -> + Mod:terminate(State), + {[],{Mod,State}}. + call_generic({Mod, State}, Config, {Function, undefined}) -> {NewConf, NewState} = Mod:Function(Config, State), {NewConf, {Mod, NewState}}; diff --git a/lib/common_test/src/ct_util.erl b/lib/common_test/src/ct_util.erl index 4696b3c954..fddeff881e 100644 --- a/lib/common_test/src/ct_util.erl +++ b/lib/common_test/src/ct_util.erl @@ -313,6 +313,10 @@ loop(Mode,TestData,StartDir) -> ct_event:sync_notify(#event{name=test_done, node=node(), data=Time}), + Callbacks = ets:lookup_element(?suite_table, + suite_callbacks, + #suite_data.value), + ct_suite_callback:terminate(Callbacks), close_connections(ets:tab2list(?conn_table)), ets:delete(?conn_table), ets:delete(?board_table), -- cgit v1.2.3 From 9809d4a71dc48fd52ec8b4d3d2002b2facf323e7 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 18 Nov 2010 14:16:53 +0100 Subject: Change default state to [] instead of undefined --- lib/common_test/src/ct_suite_callback.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/common_test') diff --git a/lib/common_test/src/ct_suite_callback.erl b/lib/common_test/src/ct_suite_callback.erl index 44e54f3968..c92de8ea51 100644 --- a/lib/common_test/src/ct_suite_callback.erl +++ b/lib/common_test/src/ct_suite_callback.erl @@ -103,7 +103,7 @@ end_tc(_Mod, TC, _Config, Result) -> %% Internal Functions %% ------------------------------------------------------------------------- call_init(Mod, Config, Meta) when is_atom(Mod) -> - call_init({Mod, undefined}, Config, Meta); + call_init({Mod, []}, Config, Meta); call_init({Mod, State}, Config, _) -> {Id, NewState} = Mod:init(State), {Config, {Id, {Mod, NewState}}}. -- cgit v1.2.3 From 90dac5ad22aefa725731b637e8128474aa6f7bdc Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 18 Nov 2010 14:10:08 +0100 Subject: Move end_tc call to be made before the tc_done event is generated --- lib/common_test/src/ct_framework.erl | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'lib/common_test') diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl index ac10bddefc..54d0433eef 100644 --- a/lib/common_test/src/ct_framework.erl +++ b/lib/common_test/src/ct_framework.erl @@ -482,12 +482,20 @@ end_tc(Mod,Func,TCPid,Result,Args,Return) -> end, ct_util:reset_silent_connections(), + FinalResult = case get('$test_server_framework_test') of + undefined -> + ct_suite_callback:end_tc( + Mod, FuncSpec, Args, Return); + Fun -> + Fun(end_tc, ok) + end, + %% send sync notification so that event handlers may print %% in the log file before it gets closed ct_event:sync_notify(#event{name=tc_done, node=node(), - data={Mod,FuncSpec,tag(Result)}}), - case Result of + data={Mod,FuncSpec,tag(FinalResult)}}), + case FinalResult of {skip,{sequence_failed,_,_}} -> %% ct_logs:init_tc is never called for a skipped test case %% in a failing sequence, so neither should end_tc @@ -505,14 +513,7 @@ end_tc(Mod,Func,TCPid,Result,Args,Return) -> ct_util:match_delete_suite_data({seq,Mod,'_'}); _ -> ok - end, - case get('$test_server_framework_test') of - undefined -> - ct_suite_callback:end_tc( - Mod, FuncSpec, Args, Return); - Fun -> - Fun(end_tc, ok) - end. + end, FinalResult. %% {error,Reason} | {skip,Reason} | {timetrap_timeout,TVal} | %% {testcase_aborted,Reason} | testcase_aborted_or_killed | @@ -525,6 +526,8 @@ tag(E = {ETag,_}) when ETag == error; ETag == 'EXIT'; {failed,E}; tag(E = testcase_aborted_or_killed) -> {failed,E}; +tag(Other) when is_list(Other) -> + ok; tag(Other) -> Other. -- cgit v1.2.3 From 118091a805e98fe3d883595ab943891f43a8f92e Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 18 Nov 2010 14:08:55 +0100 Subject: Add testcase for SCB which does nothing --- lib/common_test/test/Makefile | 3 +- .../ct_error_SUITE_data/error/test/empty_scb.erl | 187 +++++++++++++++++++++ lib/common_test/test/ct_suite_callback_SUITE.erl | 150 +++++++++++++++++ .../scb/tests/ct_scb_empty_SUITE.erl | 110 ++++++++++++ 4 files changed, 449 insertions(+), 1 deletion(-) create mode 100644 lib/common_test/test/ct_error_SUITE_data/error/test/empty_scb.erl create mode 100644 lib/common_test/test/ct_suite_callback_SUITE.erl create mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scb_empty_SUITE.erl (limited to 'lib/common_test') diff --git a/lib/common_test/test/Makefile b/lib/common_test/test/Makefile index f2fe3390cf..28be9f56f1 100644 --- a/lib/common_test/test/Makefile +++ b/lib/common_test/test/Makefile @@ -40,7 +40,8 @@ MODULES= \ ct_test_server_if_1_SUITE \ ct_config_SUITE \ ct_master_SUITE \ - ct_misc_1_SUITE + ct_misc_1_SUITE \ + ct_suite_callback_SUITE ERL_FILES= $(MODULES:%=%.erl) diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/empty_scb.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/empty_scb.erl new file mode 100644 index 0000000000..41808b4f1d --- /dev/null +++ b/lib/common_test/test/ct_error_SUITE_data/error/test/empty_scb.erl @@ -0,0 +1,187 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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% +%% + +%%% @doc Common Test Example Suite Callback module. +%%% +%%%

This module gives an example of a common test SCB (Suite CallBack). +%%% There are many ways to add a SCB to a test run, you can do it either in +%%% the command line using -suite_callback, in a test spec using +%%% {suite_callback,M} or in the suite it self by returning suite_callback +%%% from either suite/0, init_per_suite/1, init_per_group/2 and +%%% init_per_testcase/2. The scope of the SCB is determined by where is it +%%% started. If it is started in the command line or test spec then it will +%%% be stopped at the end of all tests. If it is started in init_per_suite, +%%% it will be stopped after end_per_suite and so on. See terminate +%%% documentation for a table describing the scoping machanics. +%%% +%%% All of callbacks except init/1 in a SCB are optional.

+ +-module(empty_scb). + +%% Suite Callbacks +-export([init/1]). + +-export([pre_init_suite/3]). +-export([post_init_suite/3]). +-export([pre_end_suite/3]). +-export([post_end_suite/3]). + +-export([pre_init_group/3]). +-export([post_init_group/3]). +-export([pre_end_group/3]). +-export([post_end_group/3]). + +-export([pre_init_tc/3]). +-export([post_end_tc/3]). + +-export([on_tc_fail/3]). + +-export([terminate/2]). + +-type proplist() :: list({atom(),term()}). +-type config() :: proplist(). +-type reason() :: term(). +-type skip_or_fail() :: {skip, reason()} | + {auto_skip, reason()} | + {fail, reason()}. + +-record(state, { id = ?MODULE :: term()}). + +%% @doc Always called before any other callback function. Use this to initiate +%% any common state. It should return an ID for this SCB and a state. The ID +%% is used to uniquly identify an SCB instance, if two SCB's return the same +%% ID the seconds SCB is ignored. This function should NOT have any side +%% effects as it might be called multiple times by common test. +-spec init(Opts :: proplist()) -> + {Id :: term(), State :: #state{}}. +init(Opts) -> + {?MODULE, #state{ }}. + +%% @doc Called before init_per_suite is called. Note that this callback is +%% only called if the SCB is added before init_per_suite is run (eg. in a test +%% specification, suite/0 function etc). +%% You can change the config in the this function. +-spec pre_init_suite(Suite :: atom(), + Config :: config(), + State :: #state{}) -> + {config() | skip_or_fail(), NewState :: #state{}}. +pre_init_suite(Suite,Config,State) -> + {Config, State}. + +%% @doc Called after init_per_suite. +%% you can change the config in this function. +-spec post_init_suite(Suite :: atom(), + Config :: config(), + State :: #state{}) -> + {config() | skip_or_fail(), NewState :: #state{}}. +post_init_suite(Suite,Config,State) -> + {Config, State}. + +%% @doc Called before end_per_suite. Note that the config cannot be +%% changed here, only the status of the suite. +-spec pre_end_suite(Suite :: atom(), + Config :: config(), + State :: #state{}) -> + {ok | skip_or_fail(), NewState :: #state{}}. +pre_end_suite(Suite,Config,State) -> {Config, State}. + +%% @doc Called after end_per_suite. Note that the config cannot be +%% changed here, only the status of the suite. +-spec post_end_suite(Suite :: atom(), + Config :: config(), + State :: #state{}) -> + {ok | skip_or_fail(), NewState :: #state{}}. +post_end_suite(Suite,Config,State) -> {Config, State}. + +%% @doc Called before each init_per_group. +%% You can change the config in this function. +-spec pre_init_group(Group :: atom(), + Config :: config(), + State :: #state{}) -> + {config() | skip_or_fail(), NewState :: #state{}}. +pre_init_group(Group,Config,State) -> {Config, State}. + +%% @doc Called after each init_per_group. +%% You can change the config in this function. +-spec post_init_group(Group :: atom(), + Config :: config(), + State :: #state{}) -> + {config() | skip_or_fail(), NewState :: #state{}}. +post_init_group(Group,Config,State) -> {Config, State}. + +%% @doc Called after each end_per_group. Note that the config cannot be +%% changed here, only the status of the group. +-spec pre_end_group(Group :: atom(), + Config :: config(), + State :: #state{}) -> + {ok | skip_or_fail(), NewState :: #state{}}. +pre_end_group(Group,Config,State) -> {Config, State}. + +%% @doc Called after each end_per_group. Note that the config cannot be +%% changed here, only the status of the group. +-spec post_end_group(Group :: atom(), + Config :: config(), + State :: #state{}) -> + {ok | skip_or_fail(), NewState :: #state{}}. +post_end_group(Group,Config,State) -> {Config, State}. + +%% @doc Called before each test case. +%% You can change the config in this function. +-spec pre_init_tc(TC :: atom(), + Config :: config(), + State :: #state{}) -> + {config() | skip_or_fail(), NewState :: #state{}}. +pre_init_tc(TC,Config,State) -> {Config, State}. + +%% @doc Called after each test case. Note that the config cannot be +%% changed here, only the status of the test case. +-spec post_end_tc(TC :: atom(), + Config :: config(), + State :: #state{}) -> + {ok | skip_or_fail(), NewState :: #state{}}. +post_end_tc(TC,Config,State) -> {Config, State}. + +%% @doc Called after post_init_suite, post_end_suite, post_init_group, +%% post_end_group and post_end_tc if the suite, group or test case failed. +%% This function should be used for extra cleanup which might be needed. +%% It is not possible to modify the config or the status of the test run. +-spec on_tc_fail(TC :: init_per_suite | end_per_suite | + init_per_group | end_per_group | atom(), + Config :: config(), State :: #state{}) -> + ok. +on_tc_fail(_TC, _Config, _State) -> + ok. + +%% @doc Called when the scope of the SCB is done, this depends on +%% when the SCB was specified. This translation table describes when this +%% function is called. +%% +%% | Started in | terminate called | +%% |---------------------|-------------------------| +%% | command_line | after all tests are run | +%% | test spec | after all tests are run | +%% | suite/0 | after SUITE is done | +%% | init_per_suite/1 | after SUITE is done | +%% | init_per_group/2 | after group is done | +%% | init_per_testcase/2 | after test case is done | +%% |-----------------------------------------------| +%% +-spec terminate(Config :: proplist(), State :: #state{}) -> + term(). +terminate(Config,State) -> {Config, State}. diff --git a/lib/common_test/test/ct_suite_callback_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE.erl new file mode 100644 index 0000000000..7a8ad9a82e --- /dev/null +++ b/lib/common_test/test/ct_suite_callback_SUITE.erl @@ -0,0 +1,150 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009-2010. 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% +%% + +%%%------------------------------------------------------------------- +%%% File: ct_error_SUITE +%%% +%%% Description: +%%% Test various errors in Common Test suites. +%%% +%%% The suites used for the test are located in the data directory. +%%%------------------------------------------------------------------- +-module(ct_suite_callback_SUITE). + +-compile(export_all). + +-include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + +-define(eh, ct_test_support_eh). + +%%-------------------------------------------------------------------- +%% TEST SERVER CALLBACK FUNCTIONS +%%-------------------------------------------------------------------- + +%%-------------------------------------------------------------------- +%% Description: Since Common Test starts another Test Server +%% instance, the tests need to be performed on a separate node (or +%% there will be clashes with logging processes etc). +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + DataDir = ?config(data_dir, Config), + TestDir = filename:join(DataDir,"scb/tests/"), + SCBs = filelib:wildcard(filename:join(TestDir,"*_scb.erl")), + io:format("SCBs: ~p",[SCBs]), + [io:format("Compiling ~p: ~p", + [FileName,compile:file(FileName,[{outdir,TestDir},debug_info])]) || + FileName <- SCBs], + ct_test_support:init_per_suite([{path_dirs,[TestDir]} | Config]). + +end_per_suite(Config) -> + ct_test_support:end_per_suite(Config). + +init_per_testcase(TestCase, Config) -> + ct_test_support:init_per_testcase(TestCase, Config). + +end_per_testcase(TestCase, Config) -> + ct_test_support:end_per_testcase(TestCase, Config). + + +suite() -> + [{timetrap,{minutes,1}}]. + +all() -> + all(suite). + +all(suite) -> + [ + empty + ]. + + +%%-------------------------------------------------------------------- +%% TEST CASES +%%-------------------------------------------------------------------- + +%%%----------------------------------------------------------------- +%%% +empty(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + Suites = [filename:join(DataDir,"scb/tests/ct_scb_empty_SUITE.erl")], + {Opts,ERPid} = setup([{suite,Suites}, + {suite_callbacks,[empty_scb]}], Config), + ok = ct_test_support:run(Opts, Config), + Events = ct_test_support:get_events(ERPid, Config), + + ct_test_support:log_events(empty_scb, + reformat(Events, ?eh), + ?config(priv_dir, Config)), + + TestEvents = events_to_check(empty), + ok = ct_test_support:verify_events(TestEvents, Events, Config). + +%%%----------------------------------------------------------------- +%%% HELP FUNCTIONS +%%%----------------------------------------------------------------- + +setup(Test, Config) -> + Opts0 = ct_test_support:get_opts(Config), + Level = ?config(trace_level, Config), + EvHArgs = [{cbm,ct_test_support},{trace_level,Level}], + Opts = Opts0 ++ [{event_handler,{?eh,EvHArgs}}|Test], + ERPid = ct_test_support:start_event_receiver(Config), + {Opts,ERPid}. + +reformat(Events, EH) -> + ct_test_support:reformat(Events, EH). +%reformat(Events, _EH) -> +% Events. + +%%%----------------------------------------------------------------- +%%% TEST EVENTS +%%%----------------------------------------------------------------- +events_to_check(Test) -> + %% 2 tests (ct:run_test + script_start) is default + events_to_check(Test, 2). + +events_to_check(_, 0) -> + []; +events_to_check(Test, N) -> + test_events(Test) ++ events_to_check(Test, N-1). + +test_events(empty) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,scb,{empty_scb,init,[[]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, + {?eh,scb,{empty_scb,pre_init_per_suite,[ct_scb_empty_SUITE,[]]}}, + {?eh,scb,{empty_scb,post_init_per_suite,[ct_scb_empty_SUITE,[]]}}, + {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite,ok}}, + + {?eh,tc_start,{ct_scb_empty_SUITE,test_case}}, + {?eh,scb,{empty_scb,pre_init_per_testcase,[test_case,[]]}}, + {?eh,scb,{empty_scb,post_end_per_testcase,[test_case,[]]}}, + {?eh,tc_done,{ct_scb_empty_SUITE,test_case,ok}}, + + {?eh,tc_start,{ct_scb_empty_SUITE,end_per_suite}}, + {?eh,scb,{empty_scb,pre_end_per_suite,[ct_scb_empty_SUITE,[]]}}, + {?eh,scb,{empty_scb,post_end_per_suite,[ct_scb_empty_SUITE,[]]}}, + {?eh,tc_done,{ct_scb_empty_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,scb,{empty_scb,terminate,[[]]}}, + {?eh,stop_logging,[]} + ]. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scb_empty_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scb_empty_SUITE.erl new file mode 100644 index 0000000000..2c62379be3 --- /dev/null +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scb_empty_SUITE.erl @@ -0,0 +1,110 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(ct_scb_empty_SUITE). + +-suite_defaults([{timetrap, {minutes, 10}}]). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-include("ct.hrl"). + +%% Test server callback functions +%%-------------------------------------------------------------------- +%% @doc +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Initiation before the whole suite +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%% +%% @spec init_per_suite(Config) -> Config +%% @end +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + Config. + +%%-------------------------------------------------------------------- +%% @doc +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Cleanup after the whole suite +%% +%% @spec end_per_suite(Config) -> _ +%% @end +%%-------------------------------------------------------------------- +end_per_suite(_Config) -> + ok. + +%%-------------------------------------------------------------------- +%% @doc +%% Case - atom() +%% Name of the test case that is about to be run. +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Initiation before each test case +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%% Initiation before each test case +%% +%% @spec init_per_testcase(TestCase, Config) -> Config +%% @end +%%-------------------------------------------------------------------- +init_per_testcase(_TestCase, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% @doc +%% Case - atom() +%% Name of the test case that is about to be run. +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Cleanup after each test case +%% +%% @spec end_per_testcase(TestCase, Config) -> _ +%% @end +%%-------------------------------------------------------------------- +end_per_testcase(_TestCase, _Config) -> + ok. + +%%-------------------------------------------------------------------- +%% @doc +%% TestCases - [Case] +%% Case - atom() +%% Name of a test case. +%% +%% Returns a list of all test cases in this test suite +%% +%% @spec all() -> TestCases +%% @end +%%-------------------------------------------------------------------- +all() -> + [test_case]. + +%% Test cases starts here. +%%-------------------------------------------------------------------- +test_case(Config) when is_list(Config) -> + ok. -- cgit v1.2.3 From 7456eddb172280e480b27d79d20a0140adb54c40 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 18 Nov 2010 16:29:55 +0100 Subject: Add SCB error handling functionality --- lib/common_test/src/ct_suite_callback.erl | 59 +++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 14 deletions(-) (limited to 'lib/common_test') diff --git a/lib/common_test/src/ct_suite_callback.erl b/lib/common_test/src/ct_suite_callback.erl index c92de8ea51..503d7a6c9c 100644 --- a/lib/common_test/src/ct_suite_callback.erl +++ b/lib/common_test/src/ct_suite_callback.erl @@ -107,16 +107,18 @@ call_init(Mod, Config, Meta) when is_atom(Mod) -> call_init({Mod, State}, Config, _) -> {Id, NewState} = Mod:init(State), {Config, {Id, {Mod, NewState}}}. - + call_terminate({Mod, State}, _, _) -> Mod:terminate(State), {[],{Mod,State}}. call_generic({Mod, State}, Config, {Function, undefined}) -> - {NewConf, NewState} = Mod:Function(Config, State), + {NewConf, NewState} = catch_apply(Mod,Function,[Config, State], + {Config, State}), {NewConf, {Mod, NewState}}; call_generic({Mod, State}, Config, {Function, Tag}) -> - {NewConf, NewState} = Mod:Function(Tag, Config, State), + {NewConf, NewState} = catch_apply(Mod,Function,[Tag, Config, State], + {Config,State}), {NewConf, {Mod, NewState}}. %% Generic call function @@ -126,18 +128,35 @@ call(Fun, Config, Meta) -> remove(?config_name,Config), Meta, CBs). call([{CB, call_init, NextFun} | Rest], Config, Meta, CBs) -> - {Config, {NewId, _} = NewCB} = call_init(CB, Config, Meta), - {NewCBs, NewRest} = case proplists:get_value(NewId, CBs, NextFun) of - undefined -> {CBs ++ [NewCB],Rest}; - ExistingCB when is_tuple(ExistingCB) -> {CBs, Rest}; - _ -> {CBs ++ [NewCB],[{NewId, NextFun} | Rest]} - end, - call(NewRest, Config, Meta, NewCBs); + try + {Config, {NewId, {Mod,_State}} = NewCB} = call_init(CB, Config, Meta), + {NewCBs, NewRest} = case proplists:get_value(NewId, CBs, NextFun) of + undefined -> {CBs ++ [NewCB],Rest}; + ExistingCB when is_tuple(ExistingCB) -> + {CBs, Rest}; + _ -> + {CBs ++ [NewCB],[{NewId, NextFun} | Rest]} + end, + ct_logs:log("Suite Callback","Started a SCB: Mod: ~p, Id: ~p", + [Mod,NewId]), + call(NewRest, Config, Meta, NewCBs) + catch Error:Reason -> + ct_logs:log("Suite Callback","Failed to start a SCB: ~p:~p", + [Error,{Reason,erlang:get_stacktrace()}]), + call(Rest, Config, Meta, CBs) + end; call([{CBId, Fun} | Rest], Config, Meta, CBs) -> - {NewConf, NewCBInfo} = Fun(proplists:get_value(CBId, CBs), Config, Meta), - NewCalls = get_new_callbacks(NewConf, Fun), - call(NewCalls ++ Rest, remove(?config_name, NewConf), Meta, - lists:keyreplace(CBId, 1, CBs, {CBId, NewCBInfo})); + try + {NewConf, NewCBInfo} = Fun(proplists:get_value(CBId, CBs), + Config, Meta), + NewCalls = get_new_callbacks(NewConf, Fun), + call(NewCalls ++ Rest, remove(?config_name, NewConf), Meta, + lists:keyreplace(CBId, 1, CBs, {CBId, NewCBInfo})) + catch Error:Reason -> + ct_logs:log("Suite Callback","Call to SCB failed: ~p:~p", + [Error,{Reason,erlang:get_stacktrace()}]), + call(Rest, Config, Meta, CBs) + end; call([], Config, _Meta, CBs) -> ct_util:save_suite_data_async(?config_name, CBs), Config. @@ -165,3 +184,15 @@ get_new_callbacks(_Config) -> get_callbacks() -> ct_util:read_suite_data(?config_name). + +catch_apply(M,F,A, Default) -> + try + apply(M,F,A) + catch error:undef -> + case erlang:get_stacktrace() of + [{M,F,A}|_] -> + Default; + _Else -> + error(undef,[M,F,A]) + end + end. -- cgit v1.2.3 From 92ad0e04b09ebe755e60fa0828c5799b3ce1f559 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 18 Nov 2010 16:31:04 +0100 Subject: Add testcases for multiple SCBs and unexisting SCBs --- lib/common_test/test/ct_suite_callback_SUITE.erl | 88 +++++++- .../scb/tests/empty_scb.erl | 248 +++++++++++++++++++++ 2 files changed, 324 insertions(+), 12 deletions(-) create mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/empty_scb.erl (limited to 'lib/common_test') diff --git a/lib/common_test/test/ct_suite_callback_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE.erl index 7a8ad9a82e..f8a111d28c 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE.erl @@ -71,7 +71,7 @@ all() -> all(suite) -> [ - empty + one_scb, two_scb, faulty_scb_no_init ]. @@ -81,25 +81,38 @@ all(suite) -> %%%----------------------------------------------------------------- %%% -empty(Config) when is_list(Config) -> +one_scb(Config) when is_list(Config) -> + do_test(one_empty_scb, "ct_scb_empty_SUITE.erl",[empty_scb], Config). + +two_scb(Config) when is_list(Config) -> + do_test(two_empty_scb, "ct_scb_empty_SUITE.erl",[empty_scb,empty_scb], + Config). + +faulty_scb_no_init(Config) when is_list(Config) -> + do_test(faulty_scb_no_init, "ct_scb_empty_SUITE.erl",[askjhdkljashdkaj], + Config). + +%%%----------------------------------------------------------------- +%%% HELP FUNCTIONS +%%%----------------------------------------------------------------- + +do_test(Tag, SuiteWildCard, SCBs, Config) -> + DataDir = ?config(data_dir, Config), - Suites = [filename:join(DataDir,"scb/tests/ct_scb_empty_SUITE.erl")], + Suites = filelib:wildcard( + filename:join([DataDir,"scb/tests",SuiteWildCard])), {Opts,ERPid} = setup([{suite,Suites}, - {suite_callbacks,[empty_scb]}], Config), + {suite_callbacks,SCBs}], Config), ok = ct_test_support:run(Opts, Config), Events = ct_test_support:get_events(ERPid, Config), - ct_test_support:log_events(empty_scb, + ct_test_support:log_events(Tag, reformat(Events, ?eh), ?config(priv_dir, Config)), - TestEvents = events_to_check(empty), + TestEvents = events_to_check(Tag), ok = ct_test_support:verify_events(TestEvents, Events, Config). -%%%----------------------------------------------------------------- -%%% HELP FUNCTIONS -%%%----------------------------------------------------------------- - setup(Test, Config) -> Opts0 = ct_test_support:get_opts(Config), Level = ?config(trace_level, Config), @@ -125,7 +138,7 @@ events_to_check(_, 0) -> events_to_check(Test, N) -> test_events(Test) ++ events_to_check(Test, N-1). -test_events(empty) -> +test_events(one_empty_scb) -> [ {?eh,start_logging,{'DEF','RUNDIR'}}, {?eh,scb,{empty_scb,init,[[]]}}, @@ -147,4 +160,55 @@ test_events(empty) -> {?eh,test_done,{'DEF','STOP_TIME'}}, {?eh,scb,{empty_scb,terminate,[[]]}}, {?eh,stop_logging,[]} - ]. + ]; + +test_events(two_empty_scb) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,scb,{empty_scb,init,[[]]}}, + {?eh,scb,{empty_scb,init,[[]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, + {?eh,scb,{empty_scb,pre_init_per_suite,[ct_scb_empty_SUITE,[]]}}, + {?eh,scb,{empty_scb,pre_init_per_suite,[ct_scb_empty_SUITE,[]]}}, + {?eh,scb,{empty_scb,post_init_per_suite,[ct_scb_empty_SUITE,[]]}}, + {?eh,scb,{empty_scb,post_init_per_suite,[ct_scb_empty_SUITE,[]]}}, + {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite,ok}}, + + {?eh,tc_start,{ct_scb_empty_SUITE,test_case}}, + {?eh,scb,{empty_scb,pre_init_per_testcase,[test_case,[]]}}, + {?eh,scb,{empty_scb,pre_init_per_testcase,[test_case,[]]}}, + {?eh,scb,{empty_scb,post_end_per_testcase,[test_case,[]]}}, + {?eh,scb,{empty_scb,post_end_per_testcase,[test_case,[]]}}, + {?eh,tc_done,{ct_scb_empty_SUITE,test_case,ok}}, + + {?eh,tc_start,{ct_scb_empty_SUITE,end_per_suite}}, + {?eh,scb,{empty_scb,pre_end_per_suite,[ct_scb_empty_SUITE,[]]}}, + {?eh,scb,{empty_scb,pre_end_per_suite,[ct_scb_empty_SUITE,[]]}}, + {?eh,scb,{empty_scb,post_end_per_suite,[ct_scb_empty_SUITE,[]]}}, + {?eh,scb,{empty_scb,post_end_per_suite,[ct_scb_empty_SUITE,[]]}}, + {?eh,tc_done,{ct_scb_empty_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,scb,{empty_scb,terminate,[[]]}}, + {?eh,scb,{empty_scb,terminate,[[]]}}, + {?eh,stop_logging,[]} + ]; + +test_events(faulty_scb_no_init) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, + {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite,ok}}, + + {?eh,tc_start,{ct_scb_empty_SUITE,test_case}}, + {?eh,tc_done,{ct_scb_empty_SUITE,test_case,ok}}, + + {?eh,tc_start,{ct_scb_empty_SUITE,end_per_suite}}, + {?eh,tc_done,{ct_scb_empty_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]; + +test_events(ok) -> + ok. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/empty_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/empty_scb.erl new file mode 100644 index 0000000000..1b8979ee4b --- /dev/null +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/empty_scb.erl @@ -0,0 +1,248 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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% +%% + +%%% @doc Common Test Example Suite Callback module. +%%% +%%%

This module gives an example of a common test SCB (Suite CallBack). +%%% There are many ways to add a SCB to a test run, you can do it either in +%%% the command line using -suite_callback, in a test spec using +%%% {suite_callback,M} or in the suite it self by returning suite_callback +%%% from either suite/0, init_per_suite/1, init_per_group/2 and +%%% init_per_testcase/2. The scope of the SCB is determined by where is it +%%% started. If it is started in the command line or test spec then it will +%%% be stopped at the end of all tests. If it is started in init_per_suite, +%%% it will be stopped after end_per_suite and so on. See terminate +%%% documentation for a table describing the scoping machanics. +%%% +%%% All of callbacks except init/1 in a SCB are optional.

+ +-module(empty_scb). + +%% Suite Callbacks +-export([init/1]). + +-export([pre_init_per_suite/3]). +-export([post_init_per_suite/3]). +-export([pre_end_per_suite/3]). +-export([post_end_per_suite/3]). + +-export([pre_init_per_group/3]). +-export([post_init_per_group/3]). +-export([pre_end_per_group/3]). +-export([post_end_per_group/3]). + +-export([pre_init_per_testcase/3]). +-export([post_end_per_testcase/3]). + +-export([on_tc_fail/3]). + +-export([terminate/1]). + +-include_lib("common_test/src/ct_util.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + +-type proplist() :: list({atom(),term()}). +-type config() :: proplist(). +-type reason() :: term(). +-type skip_or_fail() :: {skip, reason()} | + {auto_skip, reason()} | + {fail, reason()}. + +-record(state, { id = ?MODULE :: term()}). + +%% @doc Always called before any other callback function. Use this to initiate +%% any common state. It should return an ID for this SCB and a state. The ID +%% is used to uniquly identify an SCB instance, if two SCB's return the same +%% ID the seconds SCB is ignored. This function should NOT have any side +%% effects as it might be called multiple times by common test. +-spec init(Opts :: proplist()) -> + {Id :: term(), State :: #state{}}. +init(Opts) -> + gen_event:notify(?CT_EVMGR_REF, #event{ name = scb, node = node(), + data = {?MODULE, init, [Opts]}}), + {now(), Opts}. + +%% @doc Called before init_per_suite is called. Note that this callback is +%% only called if the SCB is added before init_per_suite is run (eg. in a test +%% specification, suite/0 function etc). +%% You can change the config in the this function. +-spec pre_init_per_suite(Suite :: atom(), + Config :: config(), + State :: #state{}) -> + {config() | skip_or_fail(), NewState :: #state{}}. +pre_init_per_suite(Suite,Config,State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = scb, node = node(), + data = {?MODULE, pre_init_per_suite, + [Suite,State]}}), + {Config, State}. + +%% @doc Called after init_per_suite. +%% you can change the config in this function. +-spec post_init_per_suite(Suite :: atom(), + Config :: config(), + State :: #state{}) -> + {config() | skip_or_fail(), NewState :: #state{}}. +post_init_per_suite(Suite,Config,State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = scb, node = node(), + data = {?MODULE, post_init_per_suite, + [Suite,State]}}), + {Config, State}. + +%% @doc Called before end_per_suite. Note that the config cannot be +%% changed here, only the status of the suite. +-spec pre_end_per_suite(Suite :: atom(), + Config :: config(), + State :: #state{}) -> + {ok | skip_or_fail(), NewState :: #state{}}. +pre_end_per_suite(Suite,Config,State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = scb, node = node(), + data = {?MODULE, pre_end_per_suite, + [Suite,State]}}), + {Config, State}. + +%% @doc Called after end_per_suite. Note that the config cannot be +%% changed here, only the status of the suite. +-spec post_end_per_suite(Suite :: atom(), + Config :: config(), + State :: #state{}) -> + {ok | skip_or_fail(), NewState :: #state{}}. +post_end_per_suite(Suite,Config,State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = scb, node = node(), + data = {?MODULE, post_end_per_suite, + [Suite,State]}}), + {Config, State}. + +%% @doc Called before each init_per_group. +%% You can change the config in this function. +-spec pre_init_per_group(Group :: atom(), + Config :: config(), + State :: #state{}) -> + {config() | skip_or_fail(), NewState :: #state{}}. +pre_init_per_group(Group,Config,State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = scb, node = node(), + data = {?MODULE, pre_init_per_group, + [Group,State]}}), + {Config, State}. + +%% @doc Called after each init_per_group. +%% You can change the config in this function. +-spec post_init_per_group(Group :: atom(), + Config :: config(), + State :: #state{}) -> + {config() | skip_or_fail(), NewState :: #state{}}. +post_init_per_group(Group,Config,State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = scb, node = node(), + data = {?MODULE, post_init_per_group, + [Group,State]}}), + {Config, State}. + +%% @doc Called after each end_per_group. Note that the config cannot be +%% changed here, only the status of the group. +-spec pre_end_per_group(Group :: atom(), + Config :: config(), + State :: #state{}) -> + {ok | skip_or_fail(), NewState :: #state{}}. +pre_end_per_group(Group,Config,State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = scb, node = node(), + data = {?MODULE, pre_end_per_group, + [Group,State]}}), + {Config, State}. + +%% @doc Called after each end_per_group. Note that the config cannot be +%% changed here, only the status of the group. +-spec post_end_per_group(Group :: atom(), + Config :: config(), + State :: #state{}) -> + {ok | skip_or_fail(), NewState :: #state{}}. +post_end_per_group(Group,Config,State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = scb, node = node(), + data = {?MODULE, post_end_per_group, + [Group,State]}}), + {Config, State}. + +%% @doc Called before each test case. +%% You can change the config in this function. +-spec pre_init_per_testcase(TC :: atom(), + Config :: config(), + State :: #state{}) -> + {config() | skip_or_fail(), NewState :: #state{}}. +pre_init_per_testcase(TC,Config,State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = scb, node = node(), + data = {?MODULE, pre_init_per_testcase, + [TC,State]}}), + {Config, State}. + +%% @doc Called after each test case. Note that the config cannot be +%% changed here, only the status of the test case. +-spec post_end_per_testcase(TC :: atom(), + Config :: config(), + State :: #state{}) -> + {ok | skip_or_fail(), NewState :: #state{}}. +post_end_per_testcase(TC,Config,State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = scb, node = node(), + data = {?MODULE, post_end_per_testcase, + [TC,State]}}), + {Config, State}. + +%% @doc Called after post_init_per_suite, post_end_per_suite, post_init_per_group, +%% post_end_per_group and post_end_per_tc if the suite, group or test case failed. +%% This function should be used for extra cleanup which might be needed. +%% It is not possible to modify the config or the status of the test run. +-spec on_tc_fail(TC :: init_per_suite | end_per_suite | + init_per_group | end_per_group | atom(), + Config :: config(), State :: #state{}) -> + ok. +on_tc_fail(TC, Config, State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = scb, node = node(), + data = {?MODULE, on_tc_fail, + [TC,State]}}), + ok. + +%% @doc Called when the scope of the SCB is done, this depends on +%% when the SCB was specified. This translation table describes when this +%% function is called. +%% +%% | Started in | terminate called | +%% |---------------------|-------------------------| +%% | command_line | after all tests are run | +%% | test spec | after all tests are run | +%% | suite/0 | after SUITE is done | +%% | init_per_suite/1 | after SUITE is done | +%% | init_per_group/2 | after group is done | +%% | init_per_testcase/2 | after test case is done | +%% |-----------------------------------------------| +%% +-spec terminate(State :: #state{}) -> + term(). +terminate(State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = scb, node = node(), + data = {?MODULE, terminate, [State]}}), + ok. -- cgit v1.2.3 From f736305327fea94f0e014422f18ca8dcceb62389 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 18 Nov 2010 17:28:24 +0100 Subject: Extend SCB error handling printouts Update error behaviour so that a failing SCB callback results in a failing testcase --- lib/common_test/src/ct_suite_callback.erl | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'lib/common_test') diff --git a/lib/common_test/src/ct_suite_callback.erl b/lib/common_test/src/ct_suite_callback.erl index 503d7a6c9c..5b132306a3 100644 --- a/lib/common_test/src/ct_suite_callback.erl +++ b/lib/common_test/src/ct_suite_callback.erl @@ -50,7 +50,6 @@ init(Opts) -> -spec terminate(Callbacks :: term()) -> ok. terminate(Callbacks) -> - io:format("Callbacks: ~p",[Callbacks]), call([{CBId, fun call_terminate/3} || {CBId,_} <- Callbacks], ct_suite_callback_init_dummy, undefined, Callbacks), ok. @@ -109,7 +108,7 @@ call_init({Mod, State}, Config, _) -> {Config, {Id, {Mod, NewState}}}. call_terminate({Mod, State}, _, _) -> - Mod:terminate(State), + catch_apply(Mod,terminate,[State], ok), {[],{Mod,State}}. call_generic({Mod, State}, Config, {Function, undefined}) -> @@ -152,10 +151,8 @@ call([{CBId, Fun} | Rest], Config, Meta, CBs) -> NewCalls = get_new_callbacks(NewConf, Fun), call(NewCalls ++ Rest, remove(?config_name, NewConf), Meta, lists:keyreplace(CBId, 1, CBs, {CBId, NewCBInfo})) - catch Error:Reason -> - ct_logs:log("Suite Callback","Call to SCB failed: ~p:~p", - [Error,{Reason,erlang:get_stacktrace()}]), - call(Rest, Config, Meta, CBs) + catch throw:{error_in_scb_call,Reason} -> + call(Rest, {fail, Reason}, Meta, CBs) end; call([], Config, _Meta, CBs) -> ct_util:save_suite_data_async(?config_name, CBs), @@ -188,11 +185,16 @@ get_callbacks() -> catch_apply(M,F,A, Default) -> try apply(M,F,A) - catch error:undef -> + catch error:Reason -> case erlang:get_stacktrace() of - [{M,F,A}|_] -> + [{M,F,A}|_] when Reason == undef -> Default; - _Else -> - error(undef,[M,F,A]) + Trace -> + ct_logs:log("Suite Callback","Call to SCB failed: ~p:~p", + [error,{Reason,Trace}]), + throw({error_in_scb_call, + lists:flatten( + io_lib:format("~p:~p/~p SCB call failed", + [M,F,length(A)]))}) end end. -- cgit v1.2.3 From 990d7e2914529da5028a07b9f3ed54ab6560fd26 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 18 Nov 2010 17:29:14 +0100 Subject: Add tests for minimal_scb, minimal_and_maximal_scb and faulty_scb_undef --- lib/common_test/test/ct_suite_callback_SUITE.erl | 77 +++++++++++++++++++++- .../scb/tests/minimal_scb.erl | 35 ++++++++++ .../scb/tests/undef_scb.erl | 39 +++++++++++ 3 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/minimal_scb.erl create mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/undef_scb.erl (limited to 'lib/common_test') diff --git a/lib/common_test/test/ct_suite_callback_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE.erl index f8a111d28c..b45d395849 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE.erl @@ -71,7 +71,8 @@ all() -> all(suite) -> [ - one_scb, two_scb, faulty_scb_no_init + one_scb, two_scb, faulty_scb_no_init, minimal_scb, + minimal_and_maximal_scb, faulty_scb_undef ]. @@ -92,6 +93,18 @@ faulty_scb_no_init(Config) when is_list(Config) -> do_test(faulty_scb_no_init, "ct_scb_empty_SUITE.erl",[askjhdkljashdkaj], Config). +minimal_scb(Config) when is_list(Config) -> + do_test(minimal_scb, "ct_scb_empty_SUITE.erl",[minimal_scb],Config). + +minimal_and_maximal_scb(Config) when is_list(Config) -> + do_test(minimal_and_maximal_scb, "ct_scb_empty_SUITE.erl", + [minimal_scb, empty_scb],Config). + +faulty_scb_undef(Config) when is_list(Config) -> + do_test(faulty_scb_undef, "ct_scb_empty_SUITE.erl", + [undef_scb],Config). + + %%%----------------------------------------------------------------- %%% HELP FUNCTIONS %%%----------------------------------------------------------------- @@ -210,5 +223,67 @@ test_events(faulty_scb_no_init) -> {?eh,stop_logging,[]} ]; +test_events(minimal_scb) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,scb,{minimal_scb,init,[[]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, + {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite,ok}}, + + {?eh,tc_start,{ct_scb_empty_SUITE,test_case}}, + {?eh,tc_done,{ct_scb_empty_SUITE,test_case,ok}}, + + {?eh,tc_start,{ct_scb_empty_SUITE,end_per_suite}}, + {?eh,tc_done,{ct_scb_empty_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]; + +test_events(minimal_and_maximal_scb) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,scb,{minimal_scb,init,[[]]}}, + {?eh,scb,{empty_scb,init,[[]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, + {?eh,scb,{empty_scb,pre_init_per_suite,[ct_scb_empty_SUITE,[]]}}, + {?eh,scb,{empty_scb,post_init_per_suite,[ct_scb_empty_SUITE,[]]}}, + {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite,ok}}, + + {?eh,tc_start,{ct_scb_empty_SUITE,test_case}}, + {?eh,scb,{empty_scb,pre_init_per_testcase,[test_case,[]]}}, + {?eh,scb,{empty_scb,post_end_per_testcase,[test_case,[]]}}, + {?eh,tc_done,{ct_scb_empty_SUITE,test_case,ok}}, + + {?eh,tc_start,{ct_scb_empty_SUITE,end_per_suite}}, + {?eh,scb,{empty_scb,pre_end_per_suite,[ct_scb_empty_SUITE,[]]}}, + {?eh,scb,{empty_scb,post_end_per_suite,[ct_scb_empty_SUITE,[]]}}, + {?eh,tc_done,{ct_scb_empty_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,scb,{empty_scb,terminate,[[]]}}, + {?eh,stop_logging,[]} + ]; + +test_events(faulty_scb_undef) -> + FailReasonStr = "undef_scb:pre_init_per_suite/3 SCB call failed", + FailReason = {ct_scb_empty_SUITE,init_per_suite, + {failed,FailReasonStr}}, + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,scb,{undef_scb,init,[[]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, + {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite, + {fail, FailReasonStr}}}, + + {?eh,tc_auto_skip,{ct_scb_empty_SUITE,test_case, + {failed, FailReason}}}, + {?eh,tc_auto_skip,{ct_scb_empty_SUITE,end_per_suite, + {failed, FailReason}}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]; + test_events(ok) -> ok. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/minimal_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/minimal_scb.erl new file mode 100644 index 0000000000..c08f1aba4a --- /dev/null +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/minimal_scb.erl @@ -0,0 +1,35 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(minimal_scb). + + +-include_lib("common_test/src/ct_util.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + + +%% Suite Callbacks +-export([init/1]). + +init(Opts) -> + gen_event:notify(?CT_EVMGR_REF, #event{ name = scb, node = node(), + data = {?MODULE, init, [Opts]}}), + {now(), Opts}. + diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/undef_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/undef_scb.erl new file mode 100644 index 0000000000..cc0651d3dd --- /dev/null +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/undef_scb.erl @@ -0,0 +1,39 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(undef_scb). + + +-include_lib("common_test/src/ct_util.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + + +%% Suite Callbacks +-export([init/1]). +-export([pre_init_per_suite/3]). + +init(Opts) -> + gen_event:notify(?CT_EVMGR_REF, #event{ name = scb, node = node(), + data = {?MODULE, init, [Opts]}}), + {now(), Opts}. + + +pre_init_per_suite(Suite, Config, State) -> + lists:flaten([1,2,[3,4]]). -- cgit v1.2.3 From c9383e50b2df112fc7c5a5e6f4d23ecdc43adfbb Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 18 Nov 2010 18:21:26 +0100 Subject: Add scoping test cases --- lib/common_test/test/ct_suite_callback_SUITE.erl | 220 ++++++++++++++++++++- .../scb/tests/ct_scope_group_scb_SUITE.erl | 120 +++++++++++ .../scb/tests/ct_scope_per_group_scb_SUITE.erl | 120 +++++++++++ .../scb/tests/ct_scope_per_suite_scb_SUITE.erl | 110 +++++++++++ .../scb/tests/ct_scope_per_tc_scb_SUITE.erl | 110 +++++++++++ .../scb/tests/ct_scope_suite_scb_SUITE.erl | 112 +++++++++++ .../scb/tests/ct_scope_tc_scb_SUITE.erl | 110 +++++++++++ 7 files changed, 896 insertions(+), 6 deletions(-) create mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_group_scb_SUITE.erl create mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_group_scb_SUITE.erl create mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_suite_scb_SUITE.erl create mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_tc_scb_SUITE.erl create mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_suite_scb_SUITE.erl create mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_tc_scb_SUITE.erl (limited to 'lib/common_test') diff --git a/lib/common_test/test/ct_suite_callback_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE.erl index b45d395849..4de888a79f 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE.erl @@ -64,17 +64,19 @@ end_per_testcase(TestCase, Config) -> suite() -> - [{timetrap,{minutes,1}}]. + [{timetrap,{seconds,15}}]. all() -> all(suite). all(suite) -> - [ - one_scb, two_scb, faulty_scb_no_init, minimal_scb, - minimal_and_maximal_scb, faulty_scb_undef - ]. - + lists:reverse( + [ + one_scb, two_scb, faulty_scb_no_init, minimal_scb, + minimal_and_maximal_scb, faulty_scb_undef, scope_per_suite_scb, + scope_per_tc_scb, scope_per_group_scb, scope_suite_scb + ]). + %%-------------------------------------------------------------------- %% TEST CASES @@ -104,6 +106,45 @@ faulty_scb_undef(Config) when is_list(Config) -> do_test(faulty_scb_undef, "ct_scb_empty_SUITE.erl", [undef_scb],Config). +scope_per_suite_scb(Config) when is_list(Config) -> + do_test(scope_per_suite_scb, "ct_scope_per_suite_scb_SUITE.erl", + [],Config). + +scope_suite_scb(Config) when is_list(Config) -> + do_test(scope_suite_scb, "ct_scope_suite_scb_SUITE.erl", + [],Config). + +scope_per_tc_scb(Config) when is_list(Config) -> + do_test(scope_per_tc_scb, "ct_scope_per_tc_scb_SUITE.erl", + [],Config). + +scope_per_group_scb(Config) when is_list(Config) -> + do_test(scope_per_group_scb, "ct_scope_per_group_scb_SUITE.erl", + [],Config). + +fail_pre_suite_scb(Config) -> + do_test(fail_pre_suite_scb, "ct_scb_empty_SUITE.erl", + [fail_pre_suite_scb],Config). + +fail_post_suite_scb(Config) -> + do_test(fail_post_suite_scb, "ct_scb_empty_SUITE.erl", + [fail_post_suite_scb],Config). + +skip_pre_suite_scb(Config) -> + do_test(skip_pre_suite_scb, "ct_scb_empty_SUITE.erl", + [skip_pre_suite_scb],Config). + +skip_post_suite_scb(Config) -> + do_test(skip_post_suite_scb, "ct_scb_empty_SUITE.erl", + [skip_post_suite_scb],Config). + +scope_tc_scb(Config) when is_list(Config) -> + do_test(scope_tc_scb, "ct_scope_tc_scb_SUITE.erl", + [],Config). + +scope_group_scb(Config) when is_list(Config) -> + do_test(scope_group_scb, "ct_scope_group_scb_SUITE.erl", + [],Config). %%%----------------------------------------------------------------- %%% HELP FUNCTIONS @@ -285,5 +326,172 @@ test_events(faulty_scb_undef) -> {?eh,stop_logging,[]} ]; +test_events(scope_per_suite_scb) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_scope_per_suite_scb_SUITE,init_per_suite}}, + {?eh,scb,{empty_scb,init,[[]]}}, + {?eh,scb,{empty_scb,post_init_per_suite,[ct_scope_per_suite_scb_SUITE,[]]}}, + {?eh,tc_done,{ct_scope_per_suite_scb_SUITE,init_per_suite,ok}}, + + {?eh,tc_start,{ct_scope_per_suite_scb_SUITE,test_case}}, + {?eh,scb,{empty_scb,pre_init_per_testcase,[test_case,[]]}}, + {?eh,scb,{empty_scb,post_end_per_testcase,[test_case,[]]}}, + {?eh,tc_done,{ct_scope_per_suite_scb_SUITE,test_case,ok}}, + + {?eh,tc_start,{ct_scope_per_suite_scb_SUITE,end_per_suite}}, + {?eh,scb,{empty_scb,pre_end_per_suite,[ct_scope_per_suite_scb_SUITE,[]]}}, + {?eh,scb,{empty_scb,post_end_per_suite,[ct_scope_per_suite_scb_SUITE,[]]}}, + {?eh,scb,{empty_scb,terminate,[[]]}}, + {?eh,tc_done,{ct_scope_per_suite_scb_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]; + +test_events(scope_suite_scb) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_scope_suite_scb_SUITE,init_per_suite}}, + {?eh,scb,{empty_scb,init,[[]]}}, + {?eh,scb,{empty_scb,pre_init_per_suite,[ct_scope_suite_scb_SUITE,[]]}}, + {?eh,scb,{empty_scb,post_init_per_suite,[ct_scope_suite_scb_SUITE,[]]}}, + {?eh,tc_done,{ct_scope_suite_scb_SUITE,init_per_suite,ok}}, + + {?eh,tc_start,{ct_scope_suite_scb_SUITE,test_case}}, + {?eh,scb,{empty_scb,pre_init_per_testcase,[test_case,[]]}}, + {?eh,scb,{empty_scb,post_end_per_testcase,[test_case,[]]}}, + {?eh,tc_done,{ct_scope_suite_scb_SUITE,test_case,ok}}, + + {?eh,tc_start,{ct_scope_suite_scb_SUITE,end_per_suite}}, + {?eh,scb,{empty_scb,pre_end_per_suite,[ct_scope_suite_scb_SUITE,[]]}}, + {?eh,scb,{empty_scb,post_end_per_suite,[ct_scope_suite_scb_SUITE,[]]}}, + {?eh,scb,{empty_scb,terminate,[[]]}}, + {?eh,tc_done,{ct_scope_suite_scb_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]; + +test_events(scope_per_tc_scb) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_scope_per_tc_scb_SUITE,init_per_suite}}, + {?eh,tc_done,{ct_scope_per_tc_scb_SUITE,init_per_suite,ok}}, + + {?eh,tc_start,{ct_scope_per_tc_scb_SUITE,test_case}}, + {?eh,scb,{empty_scb,init,[[]]}}, + {?eh,scb,{empty_scb,post_end_per_testcase,[test_case,[]]}}, + {?eh,scb,{empty_scb,terminate,[[]]}}, + {?eh,tc_done,{ct_scope_per_tc_scb_SUITE,test_case,ok}}, + + {?eh,tc_start,{ct_scope_per_tc_scb_SUITE,end_per_suite}}, + {?eh,tc_done,{ct_scope_per_tc_scb_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]; + +test_events(scope_per_group_scb) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_scope_per_group_scb_SUITE,init_per_suite}}, + {?eh,tc_done,{ct_scope_per_group_scb_SUITE,init_per_suite,ok}}, + + [{?eh,tc_start,{ct_scope_per_group_scb_SUITE,{init_per_group,group1,[]}}}, + {?eh,scb,{empty_scb,init,[[]]}}, + {?eh,scb,{empty_scb,post_init_per_group,[group1,[]]}}, + {?eh,tc_done,{ct_scope_per_group_scb_SUITE,{init_per_group,group1,[]},ok}}, + + {?eh,tc_start,{ct_scope_per_group_scb_SUITE,test_case}}, + {?eh,scb,{empty_scb,pre_init_per_testcase,[test_case,[]]}}, + {?eh,scb,{empty_scb,post_end_per_testcase,[test_case,[]]}}, + {?eh,tc_done,{ct_scope_per_group_scb_SUITE,test_case,ok}}, + + {?eh,tc_start,{ct_scope_per_group_scb_SUITE,{end_per_group,group1,[]}}}, + {?eh,scb,{empty_scb,pre_end_per_group,[group1,[]]}}, + {?eh,scb,{empty_scb,post_end_per_group,[group1,[]]}}, + {?eh,scb,{empty_scb,terminate,[[]]}}, + {?eh,tc_done,{ct_scope_per_group_scb_SUITE,{end_per_group,group1,[]},ok}}], + + {?eh,tc_start,{ct_scope_per_group_scb_SUITE,end_per_suite}}, + {?eh,tc_done,{ct_scope_per_group_scb_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]; + +test_events(fail_pre_suite_scb) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,scb,{fail_pre_suite_scb,init,[[]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, + {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite, + {fail, "Test failure"}}}, + + {?eh,tc_auto_skip,{ct_scb_empty_SUITE,test_case, + {failed, + {ct_scb_empty_SUITE,init_per_suite,{failed,"Test failure"}}}}}, + + {?eh,tc_auto_skip, {ct_scb_empty_SUITE, end_per_suite, + {failed, {ct_scb_empty_SUITE, init_per_suite, {failed, "Test failure"}}}}}, + + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]; + +test_events(fail_post_suite_scb) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,scb,{minimal_scb,init,[[]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, + {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite,ok}}, + + {?eh,tc_start,{ct_scb_empty_SUITE,test_case}}, + {?eh,tc_done,{ct_scb_empty_SUITE,test_case,ok}}, + + {?eh,tc_start,{ct_scb_empty_SUITE,end_per_suite}}, + {?eh,tc_done,{ct_scb_empty_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]; + +test_events(skip_pre_suite_scb) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,scb,{minimal_scb,init,[[]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, + {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite,ok}}, + + {?eh,tc_start,{ct_scb_empty_SUITE,test_case}}, + {?eh,tc_done,{ct_scb_empty_SUITE,test_case,ok}}, + + {?eh,tc_start,{ct_scb_empty_SUITE,end_per_suite}}, + {?eh,tc_done,{ct_scb_empty_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]; + +test_events(skip_post_suite_scb) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,scb,{minimal_scb,init,[[]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, + {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite,ok}}, + + {?eh,tc_start,{ct_scb_empty_SUITE,test_case}}, + {?eh,tc_done,{ct_scb_empty_SUITE,test_case,ok}}, + + {?eh,tc_start,{ct_scb_empty_SUITE,end_per_suite}}, + {?eh,tc_done,{ct_scb_empty_SUITE,end_per_suite,ok}}, + + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]; + test_events(ok) -> ok. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_group_scb_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_group_scb_SUITE.erl new file mode 100644 index 0000000000..70fcea6fea --- /dev/null +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_group_scb_SUITE.erl @@ -0,0 +1,120 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(ct_scope_group_scb_SUITE). + +-suite_defaults([{timetrap, {minutes, 10}}]). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-include("ct.hrl"). + +%% Test server callback functions +%%-------------------------------------------------------------------- +%% @doc +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Initiation before the whole suite +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%% +%% @spec init_per_suite(Config) -> Config +%% @end +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + Config. + +%%-------------------------------------------------------------------- +%% @doc +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Cleanup after the whole suite +%% +%% @spec end_per_suite(Config) -> _ +%% @end +%%-------------------------------------------------------------------- +end_per_suite(_Config) -> + ok. + +%%-------------------------------------------------------------------- +%% @doc +%% Case - atom() +%% Name of the test case that is about to be run. +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Initiation before each test case +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%% Initiation before each test case +%% +%% @spec init_per_testcase(TestCase, Config) -> Config +%% @end +%%-------------------------------------------------------------------- +init_per_testcase(_TestCase, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% @doc +%% Case - atom() +%% Name of the test case that is about to be run. +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Cleanup after each test case +%% +%% @spec end_per_testcase(TestCase, Config) -> _ +%% @end +%%-------------------------------------------------------------------- +end_per_testcase(_TestCase, _Config) -> + ok. + +init_per_group(GroupName, Config) -> + Config. + +end_per_group(GroupName, Config) -> + ok. + +%%-------------------------------------------------------------------- +%% @doc +%% TestCases - [Case] +%% Case - atom() +%% Name of a test case. +%% +%% Returns a list of all test cases in this test suite +%% +%% @spec all() -> TestCases +%% @end +%%-------------------------------------------------------------------- +all() -> + [{group,group1}]. + +groups() -> + [{group1,[],[test_case]}]. + + +%% Test cases starts here. +%%-------------------------------------------------------------------- +test_case(Config) when is_list(Config) -> + ok. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_group_scb_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_group_scb_SUITE.erl new file mode 100644 index 0000000000..cbda931f5e --- /dev/null +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_group_scb_SUITE.erl @@ -0,0 +1,120 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(ct_scope_per_group_scb_SUITE). + +-suite_defaults([{timetrap, {minutes, 10}}]). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-include("ct.hrl"). + +%% Test server callback functions +%%-------------------------------------------------------------------- +%% @doc +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Initiation before the whole suite +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%% +%% @spec init_per_suite(Config) -> Config +%% @end +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + Config. + +%%-------------------------------------------------------------------- +%% @doc +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Cleanup after the whole suite +%% +%% @spec end_per_suite(Config) -> _ +%% @end +%%-------------------------------------------------------------------- +end_per_suite(_Config) -> + ok. + +%%-------------------------------------------------------------------- +%% @doc +%% Case - atom() +%% Name of the test case that is about to be run. +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Initiation before each test case +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%% Initiation before each test case +%% +%% @spec init_per_testcase(TestCase, Config) -> Config +%% @end +%%-------------------------------------------------------------------- +init_per_testcase(_TestCase, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% @doc +%% Case - atom() +%% Name of the test case that is about to be run. +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Cleanup after each test case +%% +%% @spec end_per_testcase(TestCase, Config) -> _ +%% @end +%%-------------------------------------------------------------------- +end_per_testcase(_TestCase, _Config) -> + ok. + +init_per_group(GroupName, Config) -> + [{suite_callbacks,[empty_scb]}|Config]. + +end_per_group(GroupName, Config) -> + ok. + +%%-------------------------------------------------------------------- +%% @doc +%% TestCases - [Case] +%% Case - atom() +%% Name of a test case. +%% +%% Returns a list of all test cases in this test suite +%% +%% @spec all() -> TestCases +%% @end +%%-------------------------------------------------------------------- +all() -> + [{group,group1}]. + +groups() -> + [{group1,[],[test_case]}]. + + +%% Test cases starts here. +%%-------------------------------------------------------------------- +test_case(Config) when is_list(Config) -> + ok. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_suite_scb_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_suite_scb_SUITE.erl new file mode 100644 index 0000000000..fef00ed4f3 --- /dev/null +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_suite_scb_SUITE.erl @@ -0,0 +1,110 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(ct_scope_per_suite_scb_SUITE). + +-suite_defaults([{timetrap, {minutes, 10}}]). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-include("ct.hrl"). + +%% Test server callback functions +%%-------------------------------------------------------------------- +%% @doc +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Initiation before the whole suite +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%% +%% @spec init_per_suite(Config) -> Config +%% @end +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + [{suite_callbacks,[empty_scb]}|Config]. + +%%-------------------------------------------------------------------- +%% @doc +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Cleanup after the whole suite +%% +%% @spec end_per_suite(Config) -> _ +%% @end +%%-------------------------------------------------------------------- +end_per_suite(_Config) -> + ok. + +%%-------------------------------------------------------------------- +%% @doc +%% Case - atom() +%% Name of the test case that is about to be run. +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Initiation before each test case +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%% Initiation before each test case +%% +%% @spec init_per_testcase(TestCase, Config) -> Config +%% @end +%%-------------------------------------------------------------------- +init_per_testcase(_TestCase, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% @doc +%% Case - atom() +%% Name of the test case that is about to be run. +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Cleanup after each test case +%% +%% @spec end_per_testcase(TestCase, Config) -> _ +%% @end +%%-------------------------------------------------------------------- +end_per_testcase(_TestCase, _Config) -> + ok. + +%%-------------------------------------------------------------------- +%% @doc +%% TestCases - [Case] +%% Case - atom() +%% Name of a test case. +%% +%% Returns a list of all test cases in this test suite +%% +%% @spec all() -> TestCases +%% @end +%%-------------------------------------------------------------------- +all() -> + [test_case]. + +%% Test cases starts here. +%%-------------------------------------------------------------------- +test_case(Config) when is_list(Config) -> + ok. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_tc_scb_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_tc_scb_SUITE.erl new file mode 100644 index 0000000000..d99e741553 --- /dev/null +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_tc_scb_SUITE.erl @@ -0,0 +1,110 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(ct_scope_per_tc_scb_SUITE). + +-suite_defaults([{timetrap, {minutes, 10}}]). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-include("ct.hrl"). + +%% Test server callback functions +%%-------------------------------------------------------------------- +%% @doc +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Initiation before the whole suite +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%% +%% @spec init_per_suite(Config) -> Config +%% @end +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + Config. + +%%-------------------------------------------------------------------- +%% @doc +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Cleanup after the whole suite +%% +%% @spec end_per_suite(Config) -> _ +%% @end +%%-------------------------------------------------------------------- +end_per_suite(_Config) -> + ok. + +%%-------------------------------------------------------------------- +%% @doc +%% Case - atom() +%% Name of the test case that is about to be run. +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Initiation before each test case +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%% Initiation before each test case +%% +%% @spec init_per_testcase(TestCase, Config) -> Config +%% @end +%%-------------------------------------------------------------------- +init_per_testcase(_TestCase, Config) -> + [{suite_callbacks,[empty_scb]}|Config]. + +%%-------------------------------------------------------------------- +%% @doc +%% Case - atom() +%% Name of the test case that is about to be run. +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Cleanup after each test case +%% +%% @spec end_per_testcase(TestCase, Config) -> _ +%% @end +%%-------------------------------------------------------------------- +end_per_testcase(_TestCase, _Config) -> + ok. + +%%-------------------------------------------------------------------- +%% @doc +%% TestCases - [Case] +%% Case - atom() +%% Name of a test case. +%% +%% Returns a list of all test cases in this test suite +%% +%% @spec all() -> TestCases +%% @end +%%-------------------------------------------------------------------- +all() -> + [test_case]. + +%% Test cases starts here. +%%-------------------------------------------------------------------- +test_case(Config) when is_list(Config) -> + ok. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_suite_scb_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_suite_scb_SUITE.erl new file mode 100644 index 0000000000..2e32773336 --- /dev/null +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_suite_scb_SUITE.erl @@ -0,0 +1,112 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(ct_scope_suite_scb_SUITE). + +-suite_defaults([{timetrap, {minutes, 10}}]). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-include("ct.hrl"). + +suite() -> + [{suite_callbacks,[empty_scb]}]. +%% Test server callback functions +%%-------------------------------------------------------------------- +%% @doc +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Initiation before the whole suite +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%% +%% @spec init_per_suite(Config) -> Config +%% @end +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + [{suite_callbacks,[empty_scb]}|Config]. + +%%-------------------------------------------------------------------- +%% @doc +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Cleanup after the whole suite +%% +%% @spec end_per_suite(Config) -> _ +%% @end +%%-------------------------------------------------------------------- +end_per_suite(_Config) -> + ok. + +%%-------------------------------------------------------------------- +%% @doc +%% Case - atom() +%% Name of the test case that is about to be run. +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Initiation before each test case +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%% Initiation before each test case +%% +%% @spec init_per_testcase(TestCase, Config) -> Config +%% @end +%%-------------------------------------------------------------------- +init_per_testcase(_TestCase, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% @doc +%% Case - atom() +%% Name of the test case that is about to be run. +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Cleanup after each test case +%% +%% @spec end_per_testcase(TestCase, Config) -> _ +%% @end +%%-------------------------------------------------------------------- +end_per_testcase(_TestCase, _Config) -> + ok. + +%%-------------------------------------------------------------------- +%% @doc +%% TestCases - [Case] +%% Case - atom() +%% Name of a test case. +%% +%% Returns a list of all test cases in this test suite +%% +%% @spec all() -> TestCases +%% @end +%%-------------------------------------------------------------------- +all() -> + [test_case]. + +%% Test cases starts here. +%%-------------------------------------------------------------------- +test_case(Config) when is_list(Config) -> + ok. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_tc_scb_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_tc_scb_SUITE.erl new file mode 100644 index 0000000000..cb894e49e4 --- /dev/null +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_tc_scb_SUITE.erl @@ -0,0 +1,110 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(ct_scope_tc_scb_SUITE). + +-suite_defaults([{timetrap, {minutes, 10}}]). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-include("ct.hrl"). + +%% Test server callback functions +%%-------------------------------------------------------------------- +%% @doc +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Initiation before the whole suite +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%% +%% @spec init_per_suite(Config) -> Config +%% @end +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + Config. + +%%-------------------------------------------------------------------- +%% @doc +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Cleanup after the whole suite +%% +%% @spec end_per_suite(Config) -> _ +%% @end +%%-------------------------------------------------------------------- +end_per_suite(_Config) -> + ok. + +%%-------------------------------------------------------------------- +%% @doc +%% Case - atom() +%% Name of the test case that is about to be run. +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Initiation before each test case +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%% Initiation before each test case +%% +%% @spec init_per_testcase(TestCase, Config) -> Config +%% @end +%%-------------------------------------------------------------------- +init_per_testcase(_TestCase, Config) -> + [{suite_callbacks,[empty_scb]}|Config]. + +%%-------------------------------------------------------------------- +%% @doc +%% Case - atom() +%% Name of the test case that is about to be run. +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Cleanup after each test case +%% +%% @spec end_per_testcase(TestCase, Config) -> _ +%% @end +%%-------------------------------------------------------------------- +end_per_testcase(_TestCase, _Config) -> + ok. + +%%-------------------------------------------------------------------- +%% @doc +%% TestCases - [Case] +%% Case - atom() +%% Name of a test case. +%% +%% Returns a list of all test cases in this test suite +%% +%% @spec all() -> TestCases +%% @end +%%-------------------------------------------------------------------- +all() -> + [test_case]. + +%% Test cases starts here. +%%-------------------------------------------------------------------- +test_case(Config) when is_list(Config) -> + ok. -- cgit v1.2.3 From 65ed50867590df76521b1032b91e35fdbd56f3f5 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Fri, 19 Nov 2010 16:12:07 +0100 Subject: Add scoping for suite and groups --- lib/common_test/src/ct_suite_callback.erl | 57 +++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 14 deletions(-) (limited to 'lib/common_test') diff --git a/lib/common_test/src/ct_suite_callback.erl b/lib/common_test/src/ct_suite_callback.erl index 5b132306a3..e0822308a2 100644 --- a/lib/common_test/src/ct_suite_callback.erl +++ b/lib/common_test/src/ct_suite_callback.erl @@ -42,7 +42,7 @@ {error, Reason :: term()}. init(Opts) -> call([{CB, call_init, undefined} || CB <- get_new_callbacks(Opts)], - ct_suite_callback_init_dummy, undefined, []), + ct_suite_callback_init_dummy, init, []), ok. @@ -50,8 +50,8 @@ init(Opts) -> -spec terminate(Callbacks :: term()) -> ok. terminate(Callbacks) -> - call([{CBId, fun call_terminate/3} || {CBId,_} <- Callbacks], - ct_suite_callback_init_dummy, undefined, Callbacks), + call([{CBId, fun call_terminate/3} || {CBId,_,_} <- Callbacks], + ct_suite_callback_terminate_dummy, terminate, Callbacks), ok. %% @doc Called as each test case is started. This includes all configuration @@ -103,9 +103,9 @@ end_tc(_Mod, TC, _Config, Result) -> %% ------------------------------------------------------------------------- call_init(Mod, Config, Meta) when is_atom(Mod) -> call_init({Mod, []}, Config, Meta); -call_init({Mod, State}, Config, _) -> +call_init({Mod, State}, Config, Scope) -> {Id, NewState} = Mod:init(State), - {Config, {Id, {Mod, NewState}}}. + {Config, {Id, scope(Scope), {Mod, NewState}}}. call_terminate({Mod, State}, _, _) -> catch_apply(Mod,terminate,[State], ok), @@ -123,12 +123,12 @@ call_generic({Mod, State}, Config, {Function, Tag}) -> %% Generic call function call(Fun, Config, Meta) -> CBs = get_callbacks(), - call([{CBId,Fun} || {CBId, _} <- CBs] ++ get_new_callbacks(Config, Fun), + call([{CBId,Fun} || {CBId,_, _} <- CBs] ++ get_new_callbacks(Config, Fun), remove(?config_name,Config), Meta, CBs). call([{CB, call_init, NextFun} | Rest], Config, Meta, CBs) -> try - {Config, {NewId, {Mod,_State}} = NewCB} = call_init(CB, Config, Meta), + {Config, {NewId, _, {Mod,_State}} = NewCB} = call_init(CB, Config, Meta), {NewCBs, NewRest} = case proplists:get_value(NewId, CBs, NextFun) of undefined -> {CBs ++ [NewCB],Rest}; ExistingCB when is_tuple(ExistingCB) -> @@ -146,16 +146,18 @@ call([{CB, call_init, NextFun} | Rest], Config, Meta, CBs) -> end; call([{CBId, Fun} | Rest], Config, Meta, CBs) -> try - {NewConf, NewCBInfo} = Fun(proplists:get_value(CBId, CBs), - Config, Meta), - NewCalls = get_new_callbacks(NewConf, Fun), - call(NewCalls ++ Rest, remove(?config_name, NewConf), Meta, - lists:keyreplace(CBId, 1, CBs, {CBId, NewCBInfo})) + {_,Scope,ModState} = lists:keyfind(CBId, 1, CBs), + {NewConf, NewCBInfo} = Fun(ModState, Config, Meta), + NewCalls = get_new_callbacks(NewConf, Fun), + NewCBs = lists:keyreplace(CBId, 1, CBs, {CBId, Scope, NewCBInfo}), + call(NewCalls ++ Rest, remove(?config_name, NewConf), Meta, + terminate_if_scope_ends(CBId, Meta, NewCBs)) catch throw:{error_in_scb_call,Reason} -> - call(Rest, {fail, Reason}, Meta, CBs) + call(Rest, {fail, Reason}, Meta, + terminate_if_scope_ends(CBId, Meta, CBs)) end; call([], Config, _Meta, CBs) -> - ct_util:save_suite_data_async(?config_name, CBs), + save_suite_data_async(CBs), Config. remove(Key,List) when is_list(List) -> @@ -164,6 +166,29 @@ remove(Key,List) when is_list(List) -> remove(_, Else) -> Else. +%% Translate scopes, i.e. init_per_group,group1 -> end_per_group,group1 etc +scope({pre_init_per_testcase, TC}) -> + {post_end_per_testcase, TC}; +scope({pre_init_per_group, GroupName}) -> + {post_end_per_group, GroupName}; +scope({post_init_per_group, GroupName}) -> + {post_end_per_group, GroupName}; +scope({pre_init_per_suite, SuiteName}) -> + {post_end_per_suite, SuiteName}; +scope({post_init_per_suite, SuiteName}) -> + {post_end_per_suite, SuiteName}; +scope(init) -> + none. + +terminate_if_scope_ends(CBId, Function, CBs) -> + case lists:keyfind(CBId, 1, CBs) of + {CBId, Function, _ModState} = CB -> + terminate([CB]), + lists:keydelete(CBId, 1, CBs); + _ -> + CBs + end. + %% Fetch callback functions get_new_callbacks(Config, Fun) -> lists:foldl(fun(NewCB, Acc) -> @@ -179,6 +204,9 @@ get_new_callbacks(Config) when is_list(Config) -> get_new_callbacks(_Config) -> []. +save_suite_data_async(CBs) -> + ct_util:save_suite_data_async(?config_name, CBs). + get_callbacks() -> ct_util:read_suite_data(?config_name). @@ -187,6 +215,7 @@ catch_apply(M,F,A, Default) -> apply(M,F,A) catch error:Reason -> case erlang:get_stacktrace() of + %% Return the default if it was the SCB module which did not have the function. [{M,F,A}|_] when Reason == undef -> Default; Trace -> -- cgit v1.2.3 From 0655bd3132d42457be62f1f22ba36e9267555047 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Mon, 22 Nov 2010 15:29:09 +0100 Subject: Add on_tc_skip function --- .../scb/tests/empty_scb.erl | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'lib/common_test') diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/empty_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/empty_scb.erl index 1b8979ee4b..0d98a8c55a 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/empty_scb.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/empty_scb.erl @@ -51,6 +51,7 @@ -export([post_end_per_testcase/3]). -export([on_tc_fail/3]). +-export([on_tc_skip/3]). -export([terminate/1]). @@ -216,15 +217,31 @@ post_end_per_testcase(TC,Config,State) -> %% It is not possible to modify the config or the status of the test run. -spec on_tc_fail(TC :: init_per_suite | end_per_suite | init_per_group | end_per_group | atom(), - Config :: config(), State :: #state{}) -> + Reason :: term(), State :: #state{}) -> ok. -on_tc_fail(TC, Config, State) -> +on_tc_fail(TC, Reason, State) -> gen_event:notify( ?CT_EVMGR_REF, #event{ name = scb, node = node(), data = {?MODULE, on_tc_fail, [TC,State]}}), ok. +%% @doc Called when a test case is skipped by either user action +%% or due to an init function failing. Test case can be +%% end_per_suite, init_per_group, end_per_group and the actual test cases. +-spec on_tc_skip(TC :: end_per_suite | + init_per_group | end_per_group | atom(), + {tc_auto_skip, {failed, {Mod :: atom(), Function :: atom(), Reason :: term()}}} | + {tc_user_skip, {skipped, Reason :: term()}}, + State :: #state{}) -> + ok. +on_tc_skip(TC, Reason, State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = scb, node = node(), + data = {?MODULE, on_tc_skip, + [TC,State]}}), + ok. + %% @doc Called when the scope of the SCB is done, this depends on %% when the SCB was specified. This translation table describes when this %% function is called. -- cgit v1.2.3 From 07673c7267b222101ab102112eff9f96049cd308 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Mon, 22 Nov 2010 15:29:41 +0100 Subject: Add tags to tests --- lib/common_test/test/ct_suite_callback_SUITE.erl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'lib/common_test') diff --git a/lib/common_test/test/ct_suite_callback_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE.erl index 4de888a79f..059d76822a 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE.erl @@ -73,8 +73,9 @@ all(suite) -> lists:reverse( [ one_scb, two_scb, faulty_scb_no_init, minimal_scb, - minimal_and_maximal_scb, faulty_scb_undef, scope_per_suite_scb, - scope_per_tc_scb, scope_per_group_scb, scope_suite_scb + minimal_and_maximal_scb, faulty_scb_undef%, scope_per_suite_scb, +% scope_per_tc_scb, scope_per_group_scb, scope_suite_scb, +% fail_pre_suite_scb, fail_post_suite_scb, skip_pre_suite_scb, skip_post_suite_scb ]). @@ -156,7 +157,7 @@ do_test(Tag, SuiteWildCard, SCBs, Config) -> Suites = filelib:wildcard( filename:join([DataDir,"scb/tests",SuiteWildCard])), {Opts,ERPid} = setup([{suite,Suites}, - {suite_callbacks,SCBs}], Config), + {suite_callbacks,SCBs},{label,Tag}], Config), ok = ct_test_support:run(Opts, Config), Events = ct_test_support:get_events(ERPid, Config), @@ -316,7 +317,7 @@ test_events(faulty_scb_undef) -> {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite, - {fail, FailReasonStr}}}, + {failed, {error,FailReasonStr}}}}, {?eh,tc_auto_skip,{ct_scb_empty_SUITE,test_case, {failed, FailReason}}}, @@ -488,7 +489,6 @@ test_events(skip_post_suite_scb) -> {?eh,tc_start,{ct_scb_empty_SUITE,end_per_suite}}, {?eh,tc_done,{ct_scb_empty_SUITE,end_per_suite,ok}}, - {?eh,test_done,{'DEF','STOP_TIME'}}, {?eh,stop_logging,[]} ]; -- cgit v1.2.3 From 25dfebe8122488db306378eefb8d4ede5e4da601 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Mon, 22 Nov 2010 15:30:46 +0100 Subject: Update to be compatible with how common_test tests the ct framework --- lib/common_test/src/ct_framework.erl | 43 ++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 16 deletions(-) (limited to 'lib/common_test') diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl index 54d0433eef..487f093d38 100644 --- a/lib/common_test/src/ct_framework.erl +++ b/lib/common_test/src/ct_framework.erl @@ -482,19 +482,25 @@ end_tc(Mod,Func,TCPid,Result,Args,Return) -> end, ct_util:reset_silent_connections(), - FinalResult = case get('$test_server_framework_test') of - undefined -> - ct_suite_callback:end_tc( - Mod, FuncSpec, Args, Return); - Fun -> - Fun(end_tc, ok) - end, - - %% send sync notification so that event handlers may print - %% in the log file before it gets closed - ct_event:sync_notify(#event{name=tc_done, - node=node(), - data={Mod,FuncSpec,tag(FinalResult)}}), + case get('$test_server_framework_test') of + undefined -> + FinalResult = ct_suite_callback:end_tc( + Mod, FuncSpec, Args, Result), + % send sync notification so that event handlers may print + % in the log file before it gets closed + ct_event:sync_notify(#event{name=tc_done, + node=node(), + data={Mod,FuncSpec,tag(FinalResult)}}); + Fun -> + % send sync notification so that event handlers may print + % in the log file before it gets closed + ct_event:sync_notify(#event{name=tc_done, + node=node(), + data={Mod,FuncSpec,tag(Result)}}), + FinalResult = Fun(end_tc, ok) + end, + + case FinalResult of {skip,{sequence_failed,_,_}} -> %% ct_logs:init_tc is never called for a skipped test case @@ -513,7 +519,14 @@ end_tc(Mod,Func,TCPid,Result,Args,Return) -> ct_util:match_delete_suite_data({seq,Mod,'_'}); _ -> ok - end, FinalResult. + end, + case FinalResult of + Result -> + ok; + _Else -> + FinalResult + end. + %% {error,Reason} | {skip,Reason} | {timetrap_timeout,TVal} | %% {testcase_aborted,Reason} | testcase_aborted_or_killed | @@ -526,8 +539,6 @@ tag(E = {ETag,_}) when ETag == error; ETag == 'EXIT'; {failed,E}; tag(E = testcase_aborted_or_killed) -> {failed,E}; -tag(Other) when is_list(Other) -> - ok; tag(Other) -> Other. -- cgit v1.2.3 From c054d38535e4128e1c5b21980c9e5137a888ec56 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Mon, 22 Nov 2010 16:43:44 +0100 Subject: Add special tagging for scb in order for event generation to be backward compatible --- lib/common_test/src/ct_framework.erl | 20 ++++++++++++++++++-- lib/common_test/src/ct_suite_callback.erl | 27 +++++++++++++++++++-------- 2 files changed, 37 insertions(+), 10 deletions(-) (limited to 'lib/common_test') diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl index 487f093d38..9b749523e8 100644 --- a/lib/common_test/src/ct_framework.erl +++ b/lib/common_test/src/ct_framework.erl @@ -485,12 +485,13 @@ end_tc(Mod,Func,TCPid,Result,Args,Return) -> case get('$test_server_framework_test') of undefined -> FinalResult = ct_suite_callback:end_tc( - Mod, FuncSpec, Args, Result), + Mod, FuncSpec, Args, Result, Return), % send sync notification so that event handlers may print % in the log file before it gets closed ct_event:sync_notify(#event{name=tc_done, node=node(), - data={Mod,FuncSpec,tag(FinalResult)}}); + data={Mod,FuncSpec, + tag_scb(FinalResult)}}); Fun -> % send sync notification so that event handlers may print % in the log file before it gets closed @@ -542,6 +543,21 @@ tag(E = testcase_aborted_or_killed) -> tag(Other) -> Other. +tag_scb({STag,Reason}) when STag == skip; STag == skipped -> + {skipped,Reason}; +tag_scb({fail, Reason}) -> + {failed, Reason}; +tag_scb(E = {ETag,_}) when ETag == error; ETag == 'EXIT'; + ETag == timetrap_timeout; + ETag == testcase_aborted -> + {failed,E}; +tag_scb(E = testcase_aborted_or_killed) -> + {failed,E}; +tag_scb(List) when is_list(List) -> + ok; +tag_scb(Other) -> + Other. + %%%----------------------------------------------------------------- %%% @spec error_notification(Mod,Func,Args,Error) -> ok %%% Mod = atom() diff --git a/lib/common_test/src/ct_suite_callback.erl b/lib/common_test/src/ct_suite_callback.erl index e0822308a2..00fbb425a1 100644 --- a/lib/common_test/src/ct_suite_callback.erl +++ b/lib/common_test/src/ct_suite_callback.erl @@ -26,7 +26,7 @@ %% API Exports -export([init/1]). -export([init_tc/3]). --export([end_tc/4]). +-export([end_tc/5]). -export([terminate/1]). -type proplist() :: [{atom(),term()}]. @@ -79,23 +79,34 @@ init_tc(_Mod, TC, Config) -> -spec end_tc(Mod :: atom(), Func :: atom(), Args :: list(), - Result :: term()) -> + Result :: term(), + Resturn :: term()) -> NewConfig :: proplist() | {skip, Reason :: term()} | {auto_skip, Reason :: term()} | {fail, Reason :: term()} | ok. -end_tc(ct_framework, _Func, _Args, Result) -> +end_tc(ct_framework, _Func, _Args, Result, _Return) -> Result; -end_tc(Mod, init_per_suite, _Config, Result) -> + +end_tc(Mod, init_per_suite, _Config, _Result, Return) when is_list(Return) -> + call(fun call_generic/3, Return, {post_init_per_suite, Mod}); +end_tc(Mod, init_per_suite, _Config, Result, _Return) -> call(fun call_generic/3, Result, {post_init_per_suite, Mod}); -end_tc(Mod, end_per_suite, _Config, Result) -> + +end_tc(Mod, end_per_suite, _Config, Result, _Return) -> call(fun call_generic/3, Result, {post_end_per_suite, Mod}); -end_tc(_Mod, {init_per_group, GroupName, _}, _Config, Result) -> + +end_tc(_Mod, {init_per_group, GroupName, _}, _Config, _Result, Return) + when is_list(Return) -> + call(fun call_generic/3, Return, {post_init_per_group, GroupName}); +end_tc(_Mod, {init_per_group, GroupName, _}, _Config, Result, _Return) -> call(fun call_generic/3, Result, {post_init_per_group, GroupName}); -end_tc(_Mod, {end_per_group, GroupName, _}, _Config, Result) -> + +end_tc(_Mod, {end_per_group, GroupName, _}, _Config, Result, _Return) -> call(fun call_generic/3, Result, {post_end_per_group, GroupName}); -end_tc(_Mod, TC, _Config, Result) -> + +end_tc(_Mod, TC, _Config, Result, _Return) -> call(fun call_generic/3, Result, {post_end_per_testcase, TC}). %% ------------------------------------------------------------------------- -- cgit v1.2.3 From 7a86a1a4802ac7ad596519a22377ed85cecfaaf5 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Mon, 22 Nov 2010 18:21:39 +0100 Subject: Add possibility to use '_' and '$proplist' anywhere in a event spec --- lib/common_test/test/ct_test_support.erl | 36 +++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 12 deletions(-) (limited to 'lib/common_test') diff --git a/lib/common_test/test/ct_test_support.erl b/lib/common_test/test/ct_test_support.erl index 5e9792f02c..d9b9f85ded 100644 --- a/lib/common_test/test/ct_test_support.erl +++ b/lib/common_test/test/ct_test_support.erl @@ -877,21 +877,33 @@ locate({TEH,tc_done,{undefined,undefined,{testcase_aborted, end; %% matches any event of type Name -locate({TEH,Name,Data}, Node, [Ev|Evs], Config) when Data == '_' -> - case Ev of - {TEH,#event{name=Name, node=Node}} -> - {Config,Evs}; - _ -> +locate({TEH,Name,Data}, Node, [{TEH,#event{name=Name, + data = EvData, + node = Node}}|Evs], + Config) -> + try match_data(Data, EvData) of + match -> + {Config,Evs} + catch _:_ -> nomatch end; -locate({TEH,Name,Data}, Node, [Ev|Evs], Config) -> - case Ev of - {TEH,#event{name=Name, node=Node, data=Data}} -> - {Config,Evs}; - _ -> - nomatch - end. +locate({TEH,Name,Data}, Node, [_|Evs], Config) -> + nomatch. + +match_data([H1|MatchT],[H2|ValT]) -> + match_data(H1,H2), + match_data(MatchT,ValT); +match_data(Tuple1,Tuple2) when is_tuple(Tuple1),is_tuple(Tuple2) -> + match_data(tuple_to_list(Tuple1),tuple_to_list(Tuple2)); +match_data(D,D) -> + match; +match_data('_',_) -> + match; +match_data('$proplist',Proplist) -> + lists:foreach(fun({_,_}) -> ok end,Proplist); +match_data([],[]) -> + match. log_events(TC, Events, PrivDir) -> LogFile = filename:join(PrivDir, atom_to_list(TC)++".events"), -- cgit v1.2.3 From eeb9e92f290a8a9d3431c541c2548bff5ad7c98f Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Tue, 23 Nov 2010 17:40:10 +0100 Subject: Refactor tests to use '_' and '$proplist' --- lib/common_test/test/ct_suite_callback_SUITE.erl | 119 +++++++++++---------- .../scb/tests/empty_scb.erl | 33 +++--- .../scb/tests/minimal_scb.erl | 4 +- .../scb/tests/undef_scb.erl | 46 ++++++-- 4 files changed, 120 insertions(+), 82 deletions(-) (limited to 'lib/common_test') diff --git a/lib/common_test/test/ct_suite_callback_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE.erl index 059d76822a..e4bc524162 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE.erl @@ -199,18 +199,21 @@ test_events(one_empty_scb) -> {?eh,scb,{empty_scb,init,[[]]}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, - {?eh,scb,{empty_scb,pre_init_per_suite,[ct_scb_empty_SUITE,[]]}}, - {?eh,scb,{empty_scb,post_init_per_suite,[ct_scb_empty_SUITE,[]]}}, + {?eh,scb,{empty_scb,pre_init_per_suite, + [ct_scb_empty_SUITE,'$proplist',[]]}}, + {?eh,scb,{empty_scb,post_init_per_suite, + [ct_scb_empty_SUITE,'$proplist',[]]}}, {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite,ok}}, {?eh,tc_start,{ct_scb_empty_SUITE,test_case}}, - {?eh,scb,{empty_scb,pre_init_per_testcase,[test_case,[]]}}, - {?eh,scb,{empty_scb,post_end_per_testcase,[test_case,[]]}}, + {?eh,scb,{empty_scb,pre_init_per_testcase,[test_case,'$proplist',[]]}}, + {?eh,scb,{empty_scb,post_end_per_testcase,[test_case,'_',[]]}}, {?eh,tc_done,{ct_scb_empty_SUITE,test_case,ok}}, {?eh,tc_start,{ct_scb_empty_SUITE,end_per_suite}}, - {?eh,scb,{empty_scb,pre_end_per_suite,[ct_scb_empty_SUITE,[]]}}, - {?eh,scb,{empty_scb,post_end_per_suite,[ct_scb_empty_SUITE,[]]}}, + {?eh,scb,{empty_scb,pre_end_per_suite, + [ct_scb_empty_SUITE,'$proplist',[]]}}, + {?eh,scb,{empty_scb,post_end_per_suite,[ct_scb_empty_SUITE,'_',[]]}}, {?eh,tc_done,{ct_scb_empty_SUITE,end_per_suite,ok}}, {?eh,test_done,{'DEF','STOP_TIME'}}, {?eh,scb,{empty_scb,terminate,[[]]}}, @@ -220,32 +223,32 @@ test_events(one_empty_scb) -> test_events(two_empty_scb) -> [ {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{empty_scb,init,[[]]}}, - {?eh,scb,{empty_scb,init,[[]]}}, + {?eh,scb,{'_',init,[[]]}}, + {?eh,scb,{'_',init,[[]]}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, - {?eh,scb,{empty_scb,pre_init_per_suite,[ct_scb_empty_SUITE,[]]}}, - {?eh,scb,{empty_scb,pre_init_per_suite,[ct_scb_empty_SUITE,[]]}}, - {?eh,scb,{empty_scb,post_init_per_suite,[ct_scb_empty_SUITE,[]]}}, - {?eh,scb,{empty_scb,post_init_per_suite,[ct_scb_empty_SUITE,[]]}}, + {?eh,scb,{'_',pre_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, + {?eh,scb,{'_',pre_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, + {?eh,scb,{'_',post_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, + {?eh,scb,{'_',post_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite,ok}}, {?eh,tc_start,{ct_scb_empty_SUITE,test_case}}, - {?eh,scb,{empty_scb,pre_init_per_testcase,[test_case,[]]}}, - {?eh,scb,{empty_scb,pre_init_per_testcase,[test_case,[]]}}, - {?eh,scb,{empty_scb,post_end_per_testcase,[test_case,[]]}}, - {?eh,scb,{empty_scb,post_end_per_testcase,[test_case,[]]}}, + {?eh,scb,{'_',pre_init_per_testcase,[test_case,'$proplist',[]]}}, + {?eh,scb,{'_',pre_init_per_testcase,[test_case,'$proplist',[]]}}, + {?eh,scb,{'_',post_end_per_testcase,[test_case,ok,[]]}}, + {?eh,scb,{'_',post_end_per_testcase,[test_case,ok,[]]}}, {?eh,tc_done,{ct_scb_empty_SUITE,test_case,ok}}, {?eh,tc_start,{ct_scb_empty_SUITE,end_per_suite}}, - {?eh,scb,{empty_scb,pre_end_per_suite,[ct_scb_empty_SUITE,[]]}}, - {?eh,scb,{empty_scb,pre_end_per_suite,[ct_scb_empty_SUITE,[]]}}, - {?eh,scb,{empty_scb,post_end_per_suite,[ct_scb_empty_SUITE,[]]}}, - {?eh,scb,{empty_scb,post_end_per_suite,[ct_scb_empty_SUITE,[]]}}, + {?eh,scb,{'_',pre_end_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, + {?eh,scb,{'_',pre_end_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, + {?eh,scb,{'_',post_end_per_suite,[ct_scb_empty_SUITE,'_',[]]}}, + {?eh,scb,{'_',post_end_per_suite,[ct_scb_empty_SUITE,'_',[]]}}, {?eh,tc_done,{ct_scb_empty_SUITE,end_per_suite,ok}}, {?eh,test_done,{'DEF','STOP_TIME'}}, - {?eh,scb,{empty_scb,terminate,[[]]}}, - {?eh,scb,{empty_scb,terminate,[[]]}}, + {?eh,scb,{'_',terminate,[[]]}}, + {?eh,scb,{'_',terminate,[[]]}}, {?eh,stop_logging,[]} ]; @@ -268,7 +271,7 @@ test_events(faulty_scb_no_init) -> test_events(minimal_scb) -> [ {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{minimal_scb,init,[[]]}}, + {?eh,scb,{'_',init,[[]]}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite,ok}}, @@ -285,25 +288,25 @@ test_events(minimal_scb) -> test_events(minimal_and_maximal_scb) -> [ {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{minimal_scb,init,[[]]}}, - {?eh,scb,{empty_scb,init,[[]]}}, + {?eh,scb,{'_',init,[[]]}}, + {?eh,scb,{'_',init,[[]]}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, - {?eh,scb,{empty_scb,pre_init_per_suite,[ct_scb_empty_SUITE,[]]}}, - {?eh,scb,{empty_scb,post_init_per_suite,[ct_scb_empty_SUITE,[]]}}, + {?eh,scb,{'_',pre_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, + {?eh,scb,{'_',post_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite,ok}}, {?eh,tc_start,{ct_scb_empty_SUITE,test_case}}, - {?eh,scb,{empty_scb,pre_init_per_testcase,[test_case,[]]}}, - {?eh,scb,{empty_scb,post_end_per_testcase,[test_case,[]]}}, + {?eh,scb,{'_',pre_init_per_testcase,[test_case,'$proplist',[]]}}, + {?eh,scb,{'_',post_end_per_testcase,[test_case,ok,[]]}}, {?eh,tc_done,{ct_scb_empty_SUITE,test_case,ok}}, {?eh,tc_start,{ct_scb_empty_SUITE,end_per_suite}}, - {?eh,scb,{empty_scb,pre_end_per_suite,[ct_scb_empty_SUITE,[]]}}, - {?eh,scb,{empty_scb,post_end_per_suite,[ct_scb_empty_SUITE,[]]}}, + {?eh,scb,{'_',pre_end_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, + {?eh,scb,{'_',post_end_per_suite,[ct_scb_empty_SUITE,'_',[]]}}, {?eh,tc_done,{ct_scb_empty_SUITE,end_per_suite,ok}}, {?eh,test_done,{'DEF','STOP_TIME'}}, - {?eh,scb,{empty_scb,terminate,[[]]}}, + {?eh,scb,{'_',terminate,[[]]}}, {?eh,stop_logging,[]} ]; @@ -313,16 +316,21 @@ test_events(faulty_scb_undef) -> {failed,FailReasonStr}}, [ {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{undef_scb,init,[[]]}}, + {?eh,scb,{'_',init,[[]]}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite, {failed, {error,FailReasonStr}}}}, + {?eh,scb,{'_',on_tc_fail,'_'}}, {?eh,tc_auto_skip,{ct_scb_empty_SUITE,test_case, {failed, FailReason}}}, + {?eh,scb,{'_',on_tc_skip,'_'}}, + {?eh,tc_auto_skip,{ct_scb_empty_SUITE,end_per_suite, {failed, FailReason}}}, + {?eh,scb,{'_',on_tc_skip,'_'}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, {?eh,stop_logging,[]} ]; @@ -332,19 +340,20 @@ test_events(scope_per_suite_scb) -> {?eh,start_logging,{'DEF','RUNDIR'}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,tc_start,{ct_scope_per_suite_scb_SUITE,init_per_suite}}, - {?eh,scb,{empty_scb,init,[[]]}}, - {?eh,scb,{empty_scb,post_init_per_suite,[ct_scope_per_suite_scb_SUITE,[]]}}, + {?eh,scb,{'_',init,[[]]}}, + {?eh,scb,{'_',post_init_per_suite,[ct_scope_per_suite_scb_SUITE,'$proplist',[]]}}, {?eh,tc_done,{ct_scope_per_suite_scb_SUITE,init_per_suite,ok}}, {?eh,tc_start,{ct_scope_per_suite_scb_SUITE,test_case}}, - {?eh,scb,{empty_scb,pre_init_per_testcase,[test_case,[]]}}, - {?eh,scb,{empty_scb,post_end_per_testcase,[test_case,[]]}}, + {?eh,scb,{'_',pre_init_per_testcase,[test_case,'$proplist',[]]}}, + {?eh,scb,{'_',post_end_per_testcase,[test_case,ok,[]]}}, {?eh,tc_done,{ct_scope_per_suite_scb_SUITE,test_case,ok}}, {?eh,tc_start,{ct_scope_per_suite_scb_SUITE,end_per_suite}}, - {?eh,scb,{empty_scb,pre_end_per_suite,[ct_scope_per_suite_scb_SUITE,[]]}}, - {?eh,scb,{empty_scb,post_end_per_suite,[ct_scope_per_suite_scb_SUITE,[]]}}, - {?eh,scb,{empty_scb,terminate,[[]]}}, + {?eh,scb,{'_',pre_end_per_suite, + [ct_scope_per_suite_scb_SUITE,'$proplist',[]]}}, + {?eh,scb,{'_',post_end_per_suite,[ct_scope_per_suite_scb_SUITE,'_',[]]}}, + {?eh,scb,{'_',terminate,[[]]}}, {?eh,tc_done,{ct_scope_per_suite_scb_SUITE,end_per_suite,ok}}, {?eh,test_done,{'DEF','STOP_TIME'}}, {?eh,stop_logging,[]} @@ -355,20 +364,20 @@ test_events(scope_suite_scb) -> {?eh,start_logging,{'DEF','RUNDIR'}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,tc_start,{ct_scope_suite_scb_SUITE,init_per_suite}}, - {?eh,scb,{empty_scb,init,[[]]}}, - {?eh,scb,{empty_scb,pre_init_per_suite,[ct_scope_suite_scb_SUITE,[]]}}, - {?eh,scb,{empty_scb,post_init_per_suite,[ct_scope_suite_scb_SUITE,[]]}}, + {?eh,scb,{'_',init,[[]]}}, + {?eh,scb,{'_',pre_init_per_suite,[ct_scope_suite_scb_SUITE,'$proplist',[]]}}, + {?eh,scb,{'_',post_init_per_suite,[ct_scope_suite_scb_SUITE,'$proplist',[]]}}, {?eh,tc_done,{ct_scope_suite_scb_SUITE,init_per_suite,ok}}, {?eh,tc_start,{ct_scope_suite_scb_SUITE,test_case}}, - {?eh,scb,{empty_scb,pre_init_per_testcase,[test_case,[]]}}, - {?eh,scb,{empty_scb,post_end_per_testcase,[test_case,[]]}}, + {?eh,scb,{'_',pre_init_per_testcase,[test_case,'$proplist',[]]}}, + {?eh,scb,{'_',post_end_per_testcase,[test_case,ok,[]]}}, {?eh,tc_done,{ct_scope_suite_scb_SUITE,test_case,ok}}, {?eh,tc_start,{ct_scope_suite_scb_SUITE,end_per_suite}}, - {?eh,scb,{empty_scb,pre_end_per_suite,[ct_scope_suite_scb_SUITE,[]]}}, - {?eh,scb,{empty_scb,post_end_per_suite,[ct_scope_suite_scb_SUITE,[]]}}, - {?eh,scb,{empty_scb,terminate,[[]]}}, + {?eh,scb,{'_',pre_end_per_suite,[ct_scope_suite_scb_SUITE,'$proplist',[]]}}, + {?eh,scb,{'_',post_end_per_suite,[ct_scope_suite_scb_SUITE,'_',[]]}}, + {?eh,scb,{'_',terminate,[[]]}}, {?eh,tc_done,{ct_scope_suite_scb_SUITE,end_per_suite,ok}}, {?eh,test_done,{'DEF','STOP_TIME'}}, {?eh,stop_logging,[]} @@ -401,19 +410,19 @@ test_events(scope_per_group_scb) -> {?eh,tc_done,{ct_scope_per_group_scb_SUITE,init_per_suite,ok}}, [{?eh,tc_start,{ct_scope_per_group_scb_SUITE,{init_per_group,group1,[]}}}, - {?eh,scb,{empty_scb,init,[[]]}}, - {?eh,scb,{empty_scb,post_init_per_group,[group1,[]]}}, + {?eh,scb,{'_',init,[[]]}}, + {?eh,scb,{'_',post_init_per_group,[group1,'$proplist',[]]}}, {?eh,tc_done,{ct_scope_per_group_scb_SUITE,{init_per_group,group1,[]},ok}}, {?eh,tc_start,{ct_scope_per_group_scb_SUITE,test_case}}, - {?eh,scb,{empty_scb,pre_init_per_testcase,[test_case,[]]}}, - {?eh,scb,{empty_scb,post_end_per_testcase,[test_case,[]]}}, + {?eh,scb,{'_',pre_init_per_testcase,[test_case,'$proplist',[]]}}, + {?eh,scb,{'_',post_end_per_testcase,[test_case,ok,[]]}}, {?eh,tc_done,{ct_scope_per_group_scb_SUITE,test_case,ok}}, {?eh,tc_start,{ct_scope_per_group_scb_SUITE,{end_per_group,group1,[]}}}, - {?eh,scb,{empty_scb,pre_end_per_group,[group1,[]]}}, - {?eh,scb,{empty_scb,post_end_per_group,[group1,[]]}}, - {?eh,scb,{empty_scb,terminate,[[]]}}, + {?eh,scb,{'_',pre_end_per_group,[group1,'$proplist',[]]}}, + {?eh,scb,{'_',post_end_per_group,[group1,'_',[]]}}, + {?eh,scb,{'_',terminate,[[]]}}, {?eh,tc_done,{ct_scope_per_group_scb_SUITE,{end_per_group,group1,[]},ok}}], {?eh,tc_start,{ct_scope_per_group_scb_SUITE,end_per_suite}}, diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/empty_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/empty_scb.erl index 0d98a8c55a..05f6563c45 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/empty_scb.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/empty_scb.erl @@ -91,7 +91,7 @@ pre_init_per_suite(Suite,Config,State) -> gen_event:notify( ?CT_EVMGR_REF, #event{ name = scb, node = node(), data = {?MODULE, pre_init_per_suite, - [Suite,State]}}), + [Suite,Config,State]}}), {Config, State}. %% @doc Called after init_per_suite. @@ -104,7 +104,7 @@ post_init_per_suite(Suite,Config,State) -> gen_event:notify( ?CT_EVMGR_REF, #event{ name = scb, node = node(), data = {?MODULE, post_init_per_suite, - [Suite,State]}}), + [Suite,Config,State]}}), {Config, State}. %% @doc Called before end_per_suite. Note that the config cannot be @@ -117,7 +117,7 @@ pre_end_per_suite(Suite,Config,State) -> gen_event:notify( ?CT_EVMGR_REF, #event{ name = scb, node = node(), data = {?MODULE, pre_end_per_suite, - [Suite,State]}}), + [Suite,Config,State]}}), {Config, State}. %% @doc Called after end_per_suite. Note that the config cannot be @@ -130,7 +130,7 @@ post_end_per_suite(Suite,Config,State) -> gen_event:notify( ?CT_EVMGR_REF, #event{ name = scb, node = node(), data = {?MODULE, post_end_per_suite, - [Suite,State]}}), + [Suite,Config,State]}}), {Config, State}. %% @doc Called before each init_per_group. @@ -143,7 +143,7 @@ pre_init_per_group(Group,Config,State) -> gen_event:notify( ?CT_EVMGR_REF, #event{ name = scb, node = node(), data = {?MODULE, pre_init_per_group, - [Group,State]}}), + [Group,Config,State]}}), {Config, State}. %% @doc Called after each init_per_group. @@ -156,7 +156,7 @@ post_init_per_group(Group,Config,State) -> gen_event:notify( ?CT_EVMGR_REF, #event{ name = scb, node = node(), data = {?MODULE, post_init_per_group, - [Group,State]}}), + [Group,Config,State]}}), {Config, State}. %% @doc Called after each end_per_group. Note that the config cannot be @@ -169,7 +169,7 @@ pre_end_per_group(Group,Config,State) -> gen_event:notify( ?CT_EVMGR_REF, #event{ name = scb, node = node(), data = {?MODULE, pre_end_per_group, - [Group,State]}}), + [Group,Config,State]}}), {Config, State}. %% @doc Called after each end_per_group. Note that the config cannot be @@ -182,7 +182,7 @@ post_end_per_group(Group,Config,State) -> gen_event:notify( ?CT_EVMGR_REF, #event{ name = scb, node = node(), data = {?MODULE, post_end_per_group, - [Group,State]}}), + [Group,Config,State]}}), {Config, State}. %% @doc Called before each test case. @@ -195,7 +195,7 @@ pre_init_per_testcase(TC,Config,State) -> gen_event:notify( ?CT_EVMGR_REF, #event{ name = scb, node = node(), data = {?MODULE, pre_init_per_testcase, - [TC,State]}}), + [TC,Config,State]}}), {Config, State}. %% @doc Called after each test case. Note that the config cannot be @@ -208,7 +208,7 @@ post_end_per_testcase(TC,Config,State) -> gen_event:notify( ?CT_EVMGR_REF, #event{ name = scb, node = node(), data = {?MODULE, post_end_per_testcase, - [TC,State]}}), + [TC,Config,State]}}), {Config, State}. %% @doc Called after post_init_per_suite, post_end_per_suite, post_init_per_group, @@ -218,13 +218,13 @@ post_end_per_testcase(TC,Config,State) -> -spec on_tc_fail(TC :: init_per_suite | end_per_suite | init_per_group | end_per_group | atom(), Reason :: term(), State :: #state{}) -> - ok. + NewState :: #state{}. on_tc_fail(TC, Reason, State) -> gen_event:notify( ?CT_EVMGR_REF, #event{ name = scb, node = node(), data = {?MODULE, on_tc_fail, - [TC,State]}}), - ok. + [TC,Reason,State]}}), + State. %% @doc Called when a test case is skipped by either user action %% or due to an init function failing. Test case can be @@ -234,13 +234,13 @@ on_tc_fail(TC, Reason, State) -> {tc_auto_skip, {failed, {Mod :: atom(), Function :: atom(), Reason :: term()}}} | {tc_user_skip, {skipped, Reason :: term()}}, State :: #state{}) -> - ok. + NewState :: #state{}. on_tc_skip(TC, Reason, State) -> gen_event:notify( ?CT_EVMGR_REF, #event{ name = scb, node = node(), data = {?MODULE, on_tc_skip, - [TC,State]}}), - ok. + [TC,Reason,State]}}), + State. %% @doc Called when the scope of the SCB is done, this depends on %% when the SCB was specified. This translation table describes when this @@ -253,7 +253,6 @@ on_tc_skip(TC, Reason, State) -> %% | suite/0 | after SUITE is done | %% | init_per_suite/1 | after SUITE is done | %% | init_per_group/2 | after group is done | -%% | init_per_testcase/2 | after test case is done | %% |-----------------------------------------------| %% -spec terminate(State :: #state{}) -> diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/minimal_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/minimal_scb.erl index c08f1aba4a..e5fdbfb8a0 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/minimal_scb.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/minimal_scb.erl @@ -29,7 +29,5 @@ -export([init/1]). init(Opts) -> - gen_event:notify(?CT_EVMGR_REF, #event{ name = scb, node = node(), - data = {?MODULE, init, [Opts]}}), - {now(), Opts}. + empty_scb:init(Opts). diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/undef_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/undef_scb.erl index cc0651d3dd..80d0f10415 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/undef_scb.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/undef_scb.erl @@ -26,14 +26,46 @@ %% Suite Callbacks --export([init/1]). --export([pre_init_per_suite/3]). +-compile(export_all). init(Opts) -> - gen_event:notify(?CT_EVMGR_REF, #event{ name = scb, node = node(), - data = {?MODULE, init, [Opts]}}), - {now(), Opts}. + empty_scb:init(Opts). - -pre_init_per_suite(Suite, Config, State) -> +pre_init_per_suite(_Suite, _Config, _State) -> lists:flaten([1,2,[3,4]]). + +post_init_per_suite(Suite,Config,State) -> + empty_scb:post_init_per_suite(Suite,Config,State). + +pre_end_per_suite(Suite,Config,State) -> + empty_scb:pre_end_per_suite(Suite,Config,State). + +post_end_per_suite(Suite,Config,State) -> + empty_scb:post_end_per_suite(Suite,Config,State). + +pre_init_per_group(Group,Config,State) -> + empty_scb:pre_init_per_group(Group,Config,State). + +post_init_per_group(Group,Config,State) -> + empty_scb:post_init_per_group(Group,Config,State). + +pre_end_per_group(Group,Config,State) -> + empty_scb:pre_end_per_group(Group,Config,State). + +post_end_per_group(Group,Config,State) -> + empty_scb:post_end_per_group(Group,Config,State). + +pre_init_per_testcase(TC,Config,State) -> + empty_scb:pre_init_per_testcase(TC,Config,State). + +post_end_per_testcase(TC,Config,State) -> + empty_scb:post_end_per_testcase(TC,Config,State). + +on_tc_fail(TC, Reason, State) -> + empty_scb:on_tc_fail(TC,Reason,State). + +on_tc_skip(TC, Reason, State) -> + empty_scb:on_tc_skip(TC,Reason,State). + +terminate(State) -> + empty_scb:terminate(State). -- cgit v1.2.3 From 53196e4720f316800eedaec2ce4792683cb3c80e Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Tue, 23 Nov 2010 17:37:40 +0100 Subject: Remove scope_tc test case as it should not be possble to have this scope --- lib/common_test/test/ct_suite_callback_SUITE.erl | 38 +------ .../scb/tests/ct_scope_tc_scb_SUITE.erl | 110 --------------------- 2 files changed, 4 insertions(+), 144 deletions(-) delete mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_tc_scb_SUITE.erl (limited to 'lib/common_test') diff --git a/lib/common_test/test/ct_suite_callback_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE.erl index e4bc524162..4e5ecfab76 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE.erl @@ -73,9 +73,10 @@ all(suite) -> lists:reverse( [ one_scb, two_scb, faulty_scb_no_init, minimal_scb, - minimal_and_maximal_scb, faulty_scb_undef%, scope_per_suite_scb, -% scope_per_tc_scb, scope_per_group_scb, scope_suite_scb, -% fail_pre_suite_scb, fail_post_suite_scb, skip_pre_suite_scb, skip_post_suite_scb + minimal_and_maximal_scb, faulty_scb_undef, scope_per_suite_scb, + scope_per_group_scb, scope_suite_scb%, +% fail_pre_suite_scb, fail_post_suite_scb, skip_pre_suite_scb, +% skip_post_suite_scb ]). @@ -115,10 +116,6 @@ scope_suite_scb(Config) when is_list(Config) -> do_test(scope_suite_scb, "ct_scope_suite_scb_SUITE.erl", [],Config). -scope_per_tc_scb(Config) when is_list(Config) -> - do_test(scope_per_tc_scb, "ct_scope_per_tc_scb_SUITE.erl", - [],Config). - scope_per_group_scb(Config) when is_list(Config) -> do_test(scope_per_group_scb, "ct_scope_per_group_scb_SUITE.erl", [],Config). @@ -139,14 +136,6 @@ skip_post_suite_scb(Config) -> do_test(skip_post_suite_scb, "ct_scb_empty_SUITE.erl", [skip_post_suite_scb],Config). -scope_tc_scb(Config) when is_list(Config) -> - do_test(scope_tc_scb, "ct_scope_tc_scb_SUITE.erl", - [],Config). - -scope_group_scb(Config) when is_list(Config) -> - do_test(scope_group_scb, "ct_scope_group_scb_SUITE.erl", - [],Config). - %%%----------------------------------------------------------------- %%% HELP FUNCTIONS %%%----------------------------------------------------------------- @@ -383,25 +372,6 @@ test_events(scope_suite_scb) -> {?eh,stop_logging,[]} ]; -test_events(scope_per_tc_scb) -> - [ - {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, - {?eh,tc_start,{ct_scope_per_tc_scb_SUITE,init_per_suite}}, - {?eh,tc_done,{ct_scope_per_tc_scb_SUITE,init_per_suite,ok}}, - - {?eh,tc_start,{ct_scope_per_tc_scb_SUITE,test_case}}, - {?eh,scb,{empty_scb,init,[[]]}}, - {?eh,scb,{empty_scb,post_end_per_testcase,[test_case,[]]}}, - {?eh,scb,{empty_scb,terminate,[[]]}}, - {?eh,tc_done,{ct_scope_per_tc_scb_SUITE,test_case,ok}}, - - {?eh,tc_start,{ct_scope_per_tc_scb_SUITE,end_per_suite}}, - {?eh,tc_done,{ct_scope_per_tc_scb_SUITE,end_per_suite,ok}}, - {?eh,test_done,{'DEF','STOP_TIME'}}, - {?eh,stop_logging,[]} - ]; - test_events(scope_per_group_scb) -> [ {?eh,start_logging,{'DEF','RUNDIR'}}, diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_tc_scb_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_tc_scb_SUITE.erl deleted file mode 100644 index cb894e49e4..0000000000 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_tc_scb_SUITE.erl +++ /dev/null @@ -1,110 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2010. 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(ct_scope_tc_scb_SUITE). - --suite_defaults([{timetrap, {minutes, 10}}]). - -%% Note: This directive should only be used in test suites. --compile(export_all). - --include("ct.hrl"). - -%% Test server callback functions -%%-------------------------------------------------------------------- -%% @doc -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Initiation before the whole suite -%% -%% Note: This function is free to add any key/value pairs to the Config -%% variable, but should NOT alter/remove any existing entries. -%% -%% @spec init_per_suite(Config) -> Config -%% @end -%%-------------------------------------------------------------------- -init_per_suite(Config) -> - Config. - -%%-------------------------------------------------------------------- -%% @doc -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Cleanup after the whole suite -%% -%% @spec end_per_suite(Config) -> _ -%% @end -%%-------------------------------------------------------------------- -end_per_suite(_Config) -> - ok. - -%%-------------------------------------------------------------------- -%% @doc -%% Case - atom() -%% Name of the test case that is about to be run. -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Initiation before each test case -%% -%% Note: This function is free to add any key/value pairs to the Config -%% variable, but should NOT alter/remove any existing entries. -%% Initiation before each test case -%% -%% @spec init_per_testcase(TestCase, Config) -> Config -%% @end -%%-------------------------------------------------------------------- -init_per_testcase(_TestCase, Config) -> - [{suite_callbacks,[empty_scb]}|Config]. - -%%-------------------------------------------------------------------- -%% @doc -%% Case - atom() -%% Name of the test case that is about to be run. -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Cleanup after each test case -%% -%% @spec end_per_testcase(TestCase, Config) -> _ -%% @end -%%-------------------------------------------------------------------- -end_per_testcase(_TestCase, _Config) -> - ok. - -%%-------------------------------------------------------------------- -%% @doc -%% TestCases - [Case] -%% Case - atom() -%% Name of a test case. -%% -%% Returns a list of all test cases in this test suite -%% -%% @spec all() -> TestCases -%% @end -%%-------------------------------------------------------------------- -all() -> - [test_case]. - -%% Test cases starts here. -%%-------------------------------------------------------------------- -test_case(Config) when is_list(Config) -> - ok. -- cgit v1.2.3 From 2f95eaaee45add848df49c84bd449f5c52d63000 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Tue, 23 Nov 2010 17:42:11 +0100 Subject: Add on_tc_fail and on_tc_skip functionality --- lib/common_test/src/ct_framework.erl | 20 +++++++++++++++++--- lib/common_test/src/ct_suite_callback.erl | 13 +++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) (limited to 'lib/common_test') diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl index 9b749523e8..f7c07a5374 100644 --- a/lib/common_test/src/ct_framework.erl +++ b/lib/common_test/src/ct_framework.erl @@ -546,7 +546,7 @@ tag(Other) -> tag_scb({STag,Reason}) when STag == skip; STag == skipped -> {skipped,Reason}; tag_scb({fail, Reason}) -> - {failed, Reason}; + {failed, {error,Reason}}; tag_scb(E = {ETag,_}) when ETag == error; ETag == 'EXIT'; ETag == timetrap_timeout; ETag == testcase_aborted -> @@ -1184,6 +1184,18 @@ report(What,Data) -> ok; tc_done -> {_Suite,Case,Result} = Data, + case Result of + {failed, _} -> + ct_suite_callback:on_tc_fail(What, Data); + {skipped,{failed,{_,init_per_testcase,_}}} -> + ct_suite_callback:on_tc_skip(tc_auto_skip, Data); + {skipped,{require_failed,_}} -> + ct_suite_callback:on_tc_skip(tc_auto_skip, Data); + {skipped,_} -> + ct_suite_callback:on_tc_skip(tc_user_skip, Data); + _Else -> + ok + end, case {Case,Result} of {init_per_suite,_} -> ok; @@ -1201,8 +1213,8 @@ report(What,Data) -> add_to_stats(auto_skipped); {_,{skipped,_}} -> add_to_stats(user_skipped); - {_,{FailOrSkip,_Reason}} -> - add_to_stats(FailOrSkip) + {_,{SkipOrFail,_Reason}} -> + add_to_stats(SkipOrFail) end; tc_user_skip -> %% test case specified as skipped in testspec @@ -1210,6 +1222,7 @@ report(What,Data) -> ct_event:sync_notify(#event{name=tc_user_skip, node=node(), data=Data}), + ct_suite_callback:on_tc_skip(What, Data), add_to_stats(user_skipped); tc_auto_skip -> %% test case skipped because of error in init_per_suite @@ -1222,6 +1235,7 @@ report(What,Data) -> ct_event:sync_notify(#event{name=tc_auto_skip, node=node(), data=Data}), + ct_suite_callback:on_tc_skip(What, Data), if Case /= end_per_suite, Case /= end_per_group -> add_to_stats(auto_skipped); true -> diff --git a/lib/common_test/src/ct_suite_callback.erl b/lib/common_test/src/ct_suite_callback.erl index 00fbb425a1..dd4fc76c8b 100644 --- a/lib/common_test/src/ct_suite_callback.erl +++ b/lib/common_test/src/ct_suite_callback.erl @@ -28,6 +28,8 @@ -export([init_tc/3]). -export([end_tc/5]). -export([terminate/1]). +-export([on_tc_skip/2]). +-export([on_tc_fail/2]). -type proplist() :: [{atom(),term()}]. @@ -109,6 +111,12 @@ end_tc(_Mod, {end_per_group, GroupName, _}, _Config, Result, _Return) -> end_tc(_Mod, TC, _Config, Result, _Return) -> call(fun call_generic/3, Result, {post_end_per_testcase, TC}). +on_tc_skip(How, {_Suite, Case, Reason}) -> + call(fun call_cleanup/3, {How, Reason}, {on_tc_skip, Case}). + +on_tc_fail(How, {_Suite, Case, Reason}) -> + call(fun call_cleanup/3, Reason, {on_tc_fail, Case}). + %% ------------------------------------------------------------------------- %% Internal Functions %% ------------------------------------------------------------------------- @@ -122,6 +130,11 @@ call_terminate({Mod, State}, _, _) -> catch_apply(Mod,terminate,[State], ok), {[],{Mod,State}}. +call_cleanup({Mod, State}, Reason, {Function, Tag}) -> + NewState = catch_apply(Mod,Function,[Tag, Reason, State], + {Reason,State}), + {Reason, {Mod, NewState}}. + call_generic({Mod, State}, Config, {Function, undefined}) -> {NewConf, NewState} = catch_apply(Mod,Function,[Config, State], {Config, State}), -- cgit v1.2.3 From 21a7ce9d0cb2358e74e302123d1cf45bd865224f Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Tue, 23 Nov 2010 17:41:06 +0100 Subject: Add init_per_suite skip and fail test cases --- lib/common_test/test/ct_suite_callback_SUITE.erl | 94 ++++++++++++++++------ .../scb/tests/fail_post_suite_scb.erl | 72 +++++++++++++++++ .../scb/tests/fail_pre_suite_scb.erl | 72 +++++++++++++++++ .../scb/tests/skip_post_suite_scb.erl | 72 +++++++++++++++++ .../scb/tests/skip_pre_suite_scb.erl | 73 +++++++++++++++++ 5 files changed, 357 insertions(+), 26 deletions(-) create mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/fail_post_suite_scb.erl create mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/fail_pre_suite_scb.erl create mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/skip_post_suite_scb.erl create mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/skip_pre_suite_scb.erl (limited to 'lib/common_test') diff --git a/lib/common_test/test/ct_suite_callback_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE.erl index 4e5ecfab76..b6af8e0c2a 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE.erl @@ -74,9 +74,9 @@ all(suite) -> [ one_scb, two_scb, faulty_scb_no_init, minimal_scb, minimal_and_maximal_scb, faulty_scb_undef, scope_per_suite_scb, - scope_per_group_scb, scope_suite_scb%, -% fail_pre_suite_scb, fail_post_suite_scb, skip_pre_suite_scb, -% skip_post_suite_scb + scope_per_group_scb, scope_suite_scb, + fail_pre_suite_scb, fail_post_suite_scb, skip_pre_suite_scb, + skip_post_suite_scb ]). @@ -404,70 +404,112 @@ test_events(scope_per_group_scb) -> test_events(fail_pre_suite_scb) -> [ {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{fail_pre_suite_scb,init,[[]]}}, + {?eh,scb,{'_',init,[[]]}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + + {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, + {?eh,scb,{'_',pre_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, + {?eh,scb,{'_',post_init_per_suite,[ct_scb_empty_SUITE, + {error,"Test failure"},[]]}}, {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite, - {fail, "Test failure"}}}, + {failed, {error,"Test failure"}}}}, + {?eh,scb,{'_',on_tc_fail, + [init_per_suite,{failed,"Test failure"},[]]}}, + {?eh,tc_auto_skip,{ct_scb_empty_SUITE,test_case, - {failed, - {ct_scb_empty_SUITE,init_per_suite,{failed,"Test failure"}}}}}, + {failed,{ct_scb_empty_SUITE,init_per_suite, + {failed,"Test failure"}}}}}, + {?eh,scb,{'_',on_tc_skip, + [test_case, {tc_auto_skip, + {failed, {ct_scb_empty_SUITE, init_per_suite, + {failed, "Test failure"}}}},[]]}}, + {?eh,tc_auto_skip, {ct_scb_empty_SUITE, end_per_suite, - {failed, {ct_scb_empty_SUITE, init_per_suite, {failed, "Test failure"}}}}}, + {failed, {ct_scb_empty_SUITE, init_per_suite, + {failed, "Test failure"}}}}}, + {?eh,scb,{'_',on_tc_skip, + [end_per_suite, {tc_auto_skip, + {failed, {ct_scb_empty_SUITE, init_per_suite, + {failed, "Test failure"}}}},[]]}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,scb, {'_',terminate,[[]]}}, {?eh,stop_logging,[]} ]; test_events(fail_post_suite_scb) -> [ {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{minimal_scb,init,[[]]}}, + {?eh,scb,{'_',init,[[]]}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, - {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite,ok}}, + {?eh,scb,{'_',pre_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, + {?eh,scb,{'_',post_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, + {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite, + {failed,{error,"Test failure"}}}}, + {?eh,scb,{'_',on_tc_fail,[init_per_suite, {failed,"Test failure"}, []]}}, - {?eh,tc_start,{ct_scb_empty_SUITE,test_case}}, - {?eh,tc_done,{ct_scb_empty_SUITE,test_case,ok}}, + {?eh,tc_auto_skip,{ct_scb_empty_SUITE,test_case, + {failed,{ct_scb_empty_SUITE,init_per_suite, + {failed,"Test failure"}}}}}, + {?eh,scb,{'_',on_tc_skip,[test_case,{tc_auto_skip,'_'},[]]}}, - {?eh,tc_start,{ct_scb_empty_SUITE,end_per_suite}}, - {?eh,tc_done,{ct_scb_empty_SUITE,end_per_suite,ok}}, + {?eh,tc_auto_skip, {ct_scb_empty_SUITE, end_per_suite, + {failed, {ct_scb_empty_SUITE, init_per_suite, + {failed, "Test failure"}}}}}, + {?eh,scb,{'_',on_tc_skip,[end_per_suite,{tc_auto_skip,'_'},[]]}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,scb, {'_',terminate,[[]]}}, {?eh,stop_logging,[]} ]; test_events(skip_pre_suite_scb) -> [ {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{minimal_scb,init,[[]]}}, + {?eh,scb,{'_',init,[[]]}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, - {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite,ok}}, + {?eh,scb,{'_',pre_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, + {?eh,scb,{'_',post_init_per_suite,[ct_scb_empty_SUITE,{skip,"Test skip"},[]]}}, + {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite,{skipped,"Test skip"}}}, + {?eh,scb,{'_',on_tc_skip, + [init_per_suite,{tc_user_skip,{skipped,"Test skip"}},[]]}}, - {?eh,tc_start,{ct_scb_empty_SUITE,test_case}}, - {?eh,tc_done,{ct_scb_empty_SUITE,test_case,ok}}, + {?eh,tc_auto_skip,{ct_scb_empty_SUITE,test_case,"Test skip"}}, + {?eh,scb,{'_',on_tc_skip,[test_case,{tc_auto_skip,"Test skip"},[]]}}, - {?eh,tc_start,{ct_scb_empty_SUITE,end_per_suite}}, - {?eh,tc_done,{ct_scb_empty_SUITE,end_per_suite,ok}}, + {?eh,tc_auto_skip, {ct_scb_empty_SUITE, end_per_suite,"Test skip"}}, + {?eh,scb,{'_',on_tc_skip,[end_per_suite,{tc_auto_skip,"Test skip"},[]]}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,scb, {'_',terminate,[[]]}}, {?eh,stop_logging,[]} ]; test_events(skip_post_suite_scb) -> [ {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{minimal_scb,init,[[]]}}, + {?eh,scb,{'_',init,[[]]}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, - {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite,ok}}, + {?eh,scb,{'_',pre_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, + {?eh,scb,{'_',post_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, + {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite,{skipped,"Test skip"}}}, + {?eh,scb,{'_',on_tc_skip, + [init_per_suite,{tc_user_skip,{skipped,"Test skip"}},[]]}}, - {?eh,tc_start,{ct_scb_empty_SUITE,test_case}}, - {?eh,tc_done,{ct_scb_empty_SUITE,test_case,ok}}, + {?eh,tc_auto_skip,{ct_scb_empty_SUITE,test_case,"Test skip"}}, + {?eh,scb,{'_',on_tc_skip,[test_case,{tc_auto_skip,"Test skip"},[]]}}, + + {?eh,tc_auto_skip, {ct_scb_empty_SUITE, end_per_suite,"Test skip"}}, + {?eh,scb,{'_',on_tc_skip,[end_per_suite,{tc_auto_skip,"Test skip"},[]]}}, - {?eh,tc_start,{ct_scb_empty_SUITE,end_per_suite}}, - {?eh,tc_done,{ct_scb_empty_SUITE,end_per_suite,ok}}, {?eh,test_done,{'DEF','STOP_TIME'}}, {?eh,stop_logging,[]} ]; diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/fail_post_suite_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/fail_post_suite_scb.erl new file mode 100644 index 0000000000..2ba5013652 --- /dev/null +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/fail_post_suite_scb.erl @@ -0,0 +1,72 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(fail_post_suite_scb). + + +-include_lib("common_test/src/ct_util.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + + +%% Suite Callbacks +-compile(export_all). + +init(Opts) -> + empty_scb:init(Opts). + +pre_init_per_suite(Suite, Config, State) -> + empty_scb:pre_init_per_suite(Suite,Config,State). + +post_init_per_suite(Suite,Config,State) -> + empty_scb:post_init_per_suite(Suite,Config,State), + {{fail, "Test failure"}, State}. + +pre_end_per_suite(Suite,Config,State) -> + empty_scb:pre_end_per_suite(Suite,Config,State). + +post_end_per_suite(Suite,Config,State) -> + empty_scb:post_end_per_suite(Suite,Config,State). + +pre_init_per_group(Group,Config,State) -> + empty_scb:pre_init_per_group(Group,Config,State). + +post_init_per_group(Group,Config,State) -> + empty_scb:post_init_per_group(Group,Config,State). + +pre_end_per_group(Group,Config,State) -> + empty_scb:pre_end_per_group(Group,Config,State). + +post_end_per_group(Group,Config,State) -> + empty_scb:post_end_per_group(Group,Config,State). + +pre_init_per_testcase(TC,Config,State) -> + empty_scb:pre_init_per_testcase(TC,Config,State). + +post_end_per_testcase(TC,Config,State) -> + empty_scb:post_end_per_testcase(TC,Config,State). + +on_tc_fail(TC, Reason, State) -> + empty_scb:on_tc_fail(TC,Reason,State). + +on_tc_skip(TC, Reason, State) -> + empty_scb:on_tc_skip(TC,Reason,State). + +terminate(State) -> + empty_scb:terminate(State). diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/fail_pre_suite_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/fail_pre_suite_scb.erl new file mode 100644 index 0000000000..f108624836 --- /dev/null +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/fail_pre_suite_scb.erl @@ -0,0 +1,72 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(fail_pre_suite_scb). + + +-include_lib("common_test/src/ct_util.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + + +%% Suite Callbacks +-compile(export_all). + +init(Opts) -> + empty_scb:init(Opts). + +pre_init_per_suite(Suite, Config, State) -> + empty_scb:pre_init_per_suite(Suite,Config,State), + {{fail, "Test failure"}, State}. + +post_init_per_suite(Suite,Config,State) -> + empty_scb:post_init_per_suite(Suite,Config,State). + +pre_end_per_suite(Suite,Config,State) -> + empty_scb:pre_end_per_suite(Suite,Config,State). + +post_end_per_suite(Suite,Config,State) -> + empty_scb:post_end_per_suite(Suite,Config,State). + +pre_init_per_group(Group,Config,State) -> + empty_scb:pre_init_per_group(Group,Config,State). + +post_init_per_group(Group,Config,State) -> + empty_scb:post_init_per_group(Group,Config,State). + +pre_end_per_group(Group,Config,State) -> + empty_scb:pre_end_per_group(Group,Config,State). + +post_end_per_group(Group,Config,State) -> + empty_scb:post_end_per_group(Group,Config,State). + +pre_init_per_testcase(TC,Config,State) -> + empty_scb:pre_init_per_testcase(TC,Config,State). + +post_end_per_testcase(TC,Config,State) -> + empty_scb:post_end_per_testcase(TC,Config,State). + +on_tc_fail(TC, Reason, State) -> + empty_scb:on_tc_fail(TC,Reason,State). + +on_tc_skip(TC, Reason, State) -> + empty_scb:on_tc_skip(TC,Reason,State). + +terminate(State) -> + empty_scb:terminate(State). diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/skip_post_suite_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/skip_post_suite_scb.erl new file mode 100644 index 0000000000..5462e34175 --- /dev/null +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/skip_post_suite_scb.erl @@ -0,0 +1,72 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(skip_post_suite_scb). + + +-include_lib("common_test/src/ct_util.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + + +%% Suite Callbacks +-compile(export_all). + +init(Opts) -> + empty_scb:init(Opts). + +pre_init_per_suite(Suite, Config, State) -> + empty_scb:pre_init_per_suite(Suite,Config,State). + +post_init_per_suite(Suite,Config,State) -> + empty_scb:post_init_per_suite(Suite,Config,State), + {{skip, "Test skip"}, State}. + +pre_end_per_suite(Suite,Config,State) -> + empty_scb:pre_end_per_suite(Suite,Config,State). + +post_end_per_suite(Suite,Config,State) -> + empty_scb:post_end_per_suite(Suite,Config,State). + +pre_init_per_group(Group,Config,State) -> + empty_scb:pre_init_per_group(Group,Config,State). + +post_init_per_group(Group,Config,State) -> + empty_scb:post_init_per_group(Group,Config,State). + +pre_end_per_group(Group,Config,State) -> + empty_scb:pre_end_per_group(Group,Config,State). + +post_end_per_group(Group,Config,State) -> + empty_scb:post_end_per_group(Group,Config,State). + +pre_init_per_testcase(TC,Config,State) -> + empty_scb:pre_init_per_testcase(TC,Config,State). + +post_end_per_testcase(TC,Config,State) -> + empty_scb:post_end_per_testcase(TC,Config,State). + +on_tc_fail(TC, Reason, State) -> + empty_scb:on_tc_fail(TC,Reason,State). + +on_tc_skip(TC, Reason, State) -> + empty_scb:on_tc_skip(TC,Reason,State). + +terminate(State) -> + empty_scb:terminate(State). diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/skip_pre_suite_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/skip_pre_suite_scb.erl new file mode 100644 index 0000000000..006ae4a90f --- /dev/null +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/skip_pre_suite_scb.erl @@ -0,0 +1,73 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(skip_pre_suite_scb). + + +-include_lib("common_test/src/ct_util.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + + +%% Suite Callbacks +-compile(export_all). + +init(Opts) -> + empty_scb:init(Opts). + + +pre_init_per_suite(Suite, Config, State) -> + empty_scb:pre_init_per_suite(Suite,Config,State), + {{skip, "Test skip"}, State}. + +post_init_per_suite(Suite,Config,State) -> + empty_scb:post_init_per_suite(Suite,Config,State). + +pre_end_per_suite(Suite,Config,State) -> + empty_scb:pre_end_per_suite(Suite,Config,State). + +post_end_per_suite(Suite,Config,State) -> + empty_scb:post_end_per_suite(Suite,Config,State). + +pre_init_per_group(Group,Config,State) -> + empty_scb:pre_init_per_group(Group,Config,State). + +post_init_per_group(Group,Config,State) -> + empty_scb:post_init_per_group(Group,Config,State). + +pre_end_per_group(Group,Config,State) -> + empty_scb:pre_end_per_group(Group,Config,State). + +post_end_per_group(Group,Config,State) -> + empty_scb:post_end_per_group(Group,Config,State). + +pre_init_per_testcase(TC,Config,State) -> + empty_scb:pre_init_per_testcase(TC,Config,State). + +post_end_per_testcase(TC,Config,State) -> + empty_scb:post_end_per_testcase(TC,Config,State). + +on_tc_fail(TC, Reason, State) -> + empty_scb:on_tc_fail(TC,Reason,State). + +on_tc_skip(TC, Reason, State) -> + empty_scb:on_tc_skip(TC,Reason,State). + +terminate(State) -> + empty_scb:terminate(State). -- cgit v1.2.3 From e6a27219093c22e6d63025078de9926590816f7c Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Tue, 23 Nov 2010 17:57:07 +0100 Subject: Remove supurflous comments and _SUITE files --- .../scb/tests/ct_scb_empty_SUITE.erl | 63 ----------- .../scb/tests/ct_scope_group_scb_SUITE.erl | 120 --------------------- .../scb/tests/ct_scope_per_group_scb_SUITE.erl | 64 ----------- .../scb/tests/ct_scope_per_suite_scb_SUITE.erl | 63 ----------- .../scb/tests/ct_scope_suite_scb_SUITE.erl | 68 +----------- 5 files changed, 3 insertions(+), 375 deletions(-) delete mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_group_scb_SUITE.erl (limited to 'lib/common_test') diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scb_empty_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scb_empty_SUITE.erl index 2c62379be3..0eb40bce00 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scb_empty_SUITE.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scb_empty_SUITE.erl @@ -27,84 +27,21 @@ -include("ct.hrl"). %% Test server callback functions -%%-------------------------------------------------------------------- -%% @doc -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Initiation before the whole suite -%% -%% Note: This function is free to add any key/value pairs to the Config -%% variable, but should NOT alter/remove any existing entries. -%% -%% @spec init_per_suite(Config) -> Config -%% @end -%%-------------------------------------------------------------------- init_per_suite(Config) -> Config. -%%-------------------------------------------------------------------- -%% @doc -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Cleanup after the whole suite -%% -%% @spec end_per_suite(Config) -> _ -%% @end -%%-------------------------------------------------------------------- end_per_suite(_Config) -> ok. -%%-------------------------------------------------------------------- -%% @doc -%% Case - atom() -%% Name of the test case that is about to be run. -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Initiation before each test case -%% -%% Note: This function is free to add any key/value pairs to the Config -%% variable, but should NOT alter/remove any existing entries. -%% Initiation before each test case -%% -%% @spec init_per_testcase(TestCase, Config) -> Config -%% @end -%%-------------------------------------------------------------------- init_per_testcase(_TestCase, Config) -> Config. -%%-------------------------------------------------------------------- -%% @doc -%% Case - atom() -%% Name of the test case that is about to be run. -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Cleanup after each test case -%% -%% @spec end_per_testcase(TestCase, Config) -> _ -%% @end -%%-------------------------------------------------------------------- end_per_testcase(_TestCase, _Config) -> ok. -%%-------------------------------------------------------------------- -%% @doc -%% TestCases - [Case] -%% Case - atom() -%% Name of a test case. -%% -%% Returns a list of all test cases in this test suite -%% -%% @spec all() -> TestCases -%% @end -%%-------------------------------------------------------------------- all() -> [test_case]. %% Test cases starts here. -%%-------------------------------------------------------------------- test_case(Config) when is_list(Config) -> ok. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_group_scb_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_group_scb_SUITE.erl deleted file mode 100644 index 70fcea6fea..0000000000 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_group_scb_SUITE.erl +++ /dev/null @@ -1,120 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2010. 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(ct_scope_group_scb_SUITE). - --suite_defaults([{timetrap, {minutes, 10}}]). - -%% Note: This directive should only be used in test suites. --compile(export_all). - --include("ct.hrl"). - -%% Test server callback functions -%%-------------------------------------------------------------------- -%% @doc -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Initiation before the whole suite -%% -%% Note: This function is free to add any key/value pairs to the Config -%% variable, but should NOT alter/remove any existing entries. -%% -%% @spec init_per_suite(Config) -> Config -%% @end -%%-------------------------------------------------------------------- -init_per_suite(Config) -> - Config. - -%%-------------------------------------------------------------------- -%% @doc -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Cleanup after the whole suite -%% -%% @spec end_per_suite(Config) -> _ -%% @end -%%-------------------------------------------------------------------- -end_per_suite(_Config) -> - ok. - -%%-------------------------------------------------------------------- -%% @doc -%% Case - atom() -%% Name of the test case that is about to be run. -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Initiation before each test case -%% -%% Note: This function is free to add any key/value pairs to the Config -%% variable, but should NOT alter/remove any existing entries. -%% Initiation before each test case -%% -%% @spec init_per_testcase(TestCase, Config) -> Config -%% @end -%%-------------------------------------------------------------------- -init_per_testcase(_TestCase, Config) -> - Config. - -%%-------------------------------------------------------------------- -%% @doc -%% Case - atom() -%% Name of the test case that is about to be run. -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Cleanup after each test case -%% -%% @spec end_per_testcase(TestCase, Config) -> _ -%% @end -%%-------------------------------------------------------------------- -end_per_testcase(_TestCase, _Config) -> - ok. - -init_per_group(GroupName, Config) -> - Config. - -end_per_group(GroupName, Config) -> - ok. - -%%-------------------------------------------------------------------- -%% @doc -%% TestCases - [Case] -%% Case - atom() -%% Name of a test case. -%% -%% Returns a list of all test cases in this test suite -%% -%% @spec all() -> TestCases -%% @end -%%-------------------------------------------------------------------- -all() -> - [{group,group1}]. - -groups() -> - [{group1,[],[test_case]}]. - - -%% Test cases starts here. -%%-------------------------------------------------------------------- -test_case(Config) when is_list(Config) -> - ok. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_group_scb_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_group_scb_SUITE.erl index cbda931f5e..8df4a6d522 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_group_scb_SUITE.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_group_scb_SUITE.erl @@ -27,66 +27,15 @@ -include("ct.hrl"). %% Test server callback functions -%%-------------------------------------------------------------------- -%% @doc -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Initiation before the whole suite -%% -%% Note: This function is free to add any key/value pairs to the Config -%% variable, but should NOT alter/remove any existing entries. -%% -%% @spec init_per_suite(Config) -> Config -%% @end -%%-------------------------------------------------------------------- init_per_suite(Config) -> Config. -%%-------------------------------------------------------------------- -%% @doc -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Cleanup after the whole suite -%% -%% @spec end_per_suite(Config) -> _ -%% @end -%%-------------------------------------------------------------------- end_per_suite(_Config) -> ok. -%%-------------------------------------------------------------------- -%% @doc -%% Case - atom() -%% Name of the test case that is about to be run. -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Initiation before each test case -%% -%% Note: This function is free to add any key/value pairs to the Config -%% variable, but should NOT alter/remove any existing entries. -%% Initiation before each test case -%% -%% @spec init_per_testcase(TestCase, Config) -> Config -%% @end -%%-------------------------------------------------------------------- init_per_testcase(_TestCase, Config) -> Config. -%%-------------------------------------------------------------------- -%% @doc -%% Case - atom() -%% Name of the test case that is about to be run. -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Cleanup after each test case -%% -%% @spec end_per_testcase(TestCase, Config) -> _ -%% @end -%%-------------------------------------------------------------------- end_per_testcase(_TestCase, _Config) -> ok. @@ -96,25 +45,12 @@ init_per_group(GroupName, Config) -> end_per_group(GroupName, Config) -> ok. -%%-------------------------------------------------------------------- -%% @doc -%% TestCases - [Case] -%% Case - atom() -%% Name of a test case. -%% -%% Returns a list of all test cases in this test suite -%% -%% @spec all() -> TestCases -%% @end -%%-------------------------------------------------------------------- all() -> [{group,group1}]. groups() -> [{group1,[],[test_case]}]. - %% Test cases starts here. -%%-------------------------------------------------------------------- test_case(Config) when is_list(Config) -> ok. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_suite_scb_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_suite_scb_SUITE.erl index fef00ed4f3..5492243b1b 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_suite_scb_SUITE.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_suite_scb_SUITE.erl @@ -27,84 +27,21 @@ -include("ct.hrl"). %% Test server callback functions -%%-------------------------------------------------------------------- -%% @doc -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Initiation before the whole suite -%% -%% Note: This function is free to add any key/value pairs to the Config -%% variable, but should NOT alter/remove any existing entries. -%% -%% @spec init_per_suite(Config) -> Config -%% @end -%%-------------------------------------------------------------------- init_per_suite(Config) -> [{suite_callbacks,[empty_scb]}|Config]. -%%-------------------------------------------------------------------- -%% @doc -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Cleanup after the whole suite -%% -%% @spec end_per_suite(Config) -> _ -%% @end -%%-------------------------------------------------------------------- end_per_suite(_Config) -> ok. -%%-------------------------------------------------------------------- -%% @doc -%% Case - atom() -%% Name of the test case that is about to be run. -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Initiation before each test case -%% -%% Note: This function is free to add any key/value pairs to the Config -%% variable, but should NOT alter/remove any existing entries. -%% Initiation before each test case -%% -%% @spec init_per_testcase(TestCase, Config) -> Config -%% @end -%%-------------------------------------------------------------------- init_per_testcase(_TestCase, Config) -> Config. -%%-------------------------------------------------------------------- -%% @doc -%% Case - atom() -%% Name of the test case that is about to be run. -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Cleanup after each test case -%% -%% @spec end_per_testcase(TestCase, Config) -> _ -%% @end -%%-------------------------------------------------------------------- end_per_testcase(_TestCase, _Config) -> ok. -%%-------------------------------------------------------------------- -%% @doc -%% TestCases - [Case] -%% Case - atom() -%% Name of a test case. -%% -%% Returns a list of all test cases in this test suite -%% -%% @spec all() -> TestCases -%% @end -%%-------------------------------------------------------------------- all() -> [test_case]. %% Test cases starts here. -%%-------------------------------------------------------------------- test_case(Config) when is_list(Config) -> ok. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_suite_scb_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_suite_scb_SUITE.erl index 2e32773336..7598c911b1 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_suite_scb_SUITE.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_suite_scb_SUITE.erl @@ -26,87 +26,25 @@ -include("ct.hrl"). +%% Test server callback functions suite() -> [{suite_callbacks,[empty_scb]}]. -%% Test server callback functions -%%-------------------------------------------------------------------- -%% @doc -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Initiation before the whole suite -%% -%% Note: This function is free to add any key/value pairs to the Config -%% variable, but should NOT alter/remove any existing entries. -%% -%% @spec init_per_suite(Config) -> Config -%% @end -%%-------------------------------------------------------------------- + init_per_suite(Config) -> - [{suite_callbacks,[empty_scb]}|Config]. + Config. -%%-------------------------------------------------------------------- -%% @doc -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Cleanup after the whole suite -%% -%% @spec end_per_suite(Config) -> _ -%% @end -%%-------------------------------------------------------------------- end_per_suite(_Config) -> ok. -%%-------------------------------------------------------------------- -%% @doc -%% Case - atom() -%% Name of the test case that is about to be run. -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Initiation before each test case -%% -%% Note: This function is free to add any key/value pairs to the Config -%% variable, but should NOT alter/remove any existing entries. -%% Initiation before each test case -%% -%% @spec init_per_testcase(TestCase, Config) -> Config -%% @end -%%-------------------------------------------------------------------- init_per_testcase(_TestCase, Config) -> Config. -%%-------------------------------------------------------------------- -%% @doc -%% Case - atom() -%% Name of the test case that is about to be run. -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Cleanup after each test case -%% -%% @spec end_per_testcase(TestCase, Config) -> _ -%% @end -%%-------------------------------------------------------------------- end_per_testcase(_TestCase, _Config) -> ok. -%%-------------------------------------------------------------------- -%% @doc -%% TestCases - [Case] -%% Case - atom() -%% Name of a test case. -%% -%% Returns a list of all test cases in this test suite -%% -%% @spec all() -> TestCases -%% @end -%%-------------------------------------------------------------------- all() -> [test_case]. %% Test cases starts here. -%%-------------------------------------------------------------------- test_case(Config) when is_list(Config) -> ok. -- cgit v1.2.3 From 0908ef629325d2aed93f654ea78949205060a013 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Wed, 24 Nov 2010 14:29:02 +0100 Subject: Update all post_*_per_* to also take the Config argument which the *_per_* was called with as an argument. --- lib/common_test/src/ct_suite_callback.erl | 82 +++++++++++---------- lib/common_test/test/ct_suite_callback_SUITE.erl | 50 ++++++------- .../scb/tests/empty_scb.erl | 83 ++++++++++++---------- .../scb/tests/fail_post_suite_scb.erl | 20 +++--- .../scb/tests/fail_pre_suite_scb.erl | 20 +++--- .../scb/tests/skip_post_suite_scb.erl | 20 +++--- .../scb/tests/skip_pre_suite_scb.erl | 20 +++--- .../scb/tests/undef_scb.erl | 20 +++--- 8 files changed, 159 insertions(+), 156 deletions(-) (limited to 'lib/common_test') diff --git a/lib/common_test/src/ct_suite_callback.erl b/lib/common_test/src/ct_suite_callback.erl index dd4fc76c8b..06c7fc3833 100644 --- a/lib/common_test/src/ct_suite_callback.erl +++ b/lib/common_test/src/ct_suite_callback.erl @@ -66,15 +66,15 @@ terminate(Callbacks) -> init_tc(ct_framework, _Func, Args) -> Args; init_tc(Mod, init_per_suite, Config) -> - call(fun call_generic/3, Config, {pre_init_per_suite, Mod}); + call(fun call_generic/3, Config, [pre_init_per_suite, Mod]); init_tc(Mod, end_per_suite, Config) -> - call(fun call_generic/3, Config, {pre_end_per_suite, Mod}); + call(fun call_generic/3, Config, [pre_end_per_suite, Mod]); init_tc(_Mod, {init_per_group, GroupName, _}, Config) -> - call(fun call_generic/3, Config, {pre_init_per_group, GroupName}); + call(fun call_generic/3, Config, [pre_init_per_group, GroupName]); init_tc(_Mod, {end_per_group, GroupName, _}, Config) -> - call(fun call_generic/3, Config, {pre_end_per_group, GroupName}); + call(fun call_generic/3, Config, [pre_end_per_group, GroupName]); init_tc(_Mod, TC, Config) -> - call(fun call_generic/3, Config, {pre_init_per_testcase, TC}). + call(fun call_generic/3, Config, [pre_init_per_testcase, TC]). %% @doc Called as each test case is completed. This includes all configuration %% tests. @@ -91,31 +91,31 @@ init_tc(_Mod, TC, Config) -> end_tc(ct_framework, _Func, _Args, Result, _Return) -> Result; -end_tc(Mod, init_per_suite, _Config, _Result, Return) when is_list(Return) -> - call(fun call_generic/3, Return, {post_init_per_suite, Mod}); -end_tc(Mod, init_per_suite, _Config, Result, _Return) -> - call(fun call_generic/3, Result, {post_init_per_suite, Mod}); +end_tc(Mod, init_per_suite, Config, _Result, Return) when is_list(Return) -> + call(fun call_generic/3, Return, [post_init_per_suite, Mod, Config]); +end_tc(Mod, init_per_suite, Config, Result, _Return) -> + call(fun call_generic/3, Result, [post_init_per_suite, Mod, Config]); -end_tc(Mod, end_per_suite, _Config, Result, _Return) -> - call(fun call_generic/3, Result, {post_end_per_suite, Mod}); +end_tc(Mod, end_per_suite, Config, Result, _Return) -> + call(fun call_generic/3, Result, [post_end_per_suite, Mod, Config]); -end_tc(_Mod, {init_per_group, GroupName, _}, _Config, _Result, Return) +end_tc(_Mod, {init_per_group, GroupName, _}, Config, _Result, Return) when is_list(Return) -> - call(fun call_generic/3, Return, {post_init_per_group, GroupName}); -end_tc(_Mod, {init_per_group, GroupName, _}, _Config, Result, _Return) -> - call(fun call_generic/3, Result, {post_init_per_group, GroupName}); + call(fun call_generic/3, Return, [post_init_per_group, GroupName, Config]); +end_tc(_Mod, {init_per_group, GroupName, _}, Config, Result, _Return) -> + call(fun call_generic/3, Result, [post_init_per_group, GroupName, Config]); -end_tc(_Mod, {end_per_group, GroupName, _}, _Config, Result, _Return) -> - call(fun call_generic/3, Result, {post_end_per_group, GroupName}); +end_tc(_Mod, {end_per_group, GroupName, _}, Config, Result, _Return) -> + call(fun call_generic/3, Result, [post_end_per_group, GroupName, Config]); -end_tc(_Mod, TC, _Config, Result, _Return) -> - call(fun call_generic/3, Result, {post_end_per_testcase, TC}). +end_tc(_Mod, TC, Config, Result, _Return) -> + call(fun call_generic/3, Result, [post_end_per_testcase, TC, Config]). on_tc_skip(How, {_Suite, Case, Reason}) -> - call(fun call_cleanup/3, {How, Reason}, {on_tc_skip, Case}). + call(fun call_cleanup/3, {How, Reason}, [on_tc_skip, Case]). -on_tc_fail(How, {_Suite, Case, Reason}) -> - call(fun call_cleanup/3, Reason, {on_tc_fail, Case}). +on_tc_fail(_How, {_Suite, Case, Reason}) -> + call(fun call_cleanup/3, Reason, [on_tc_fail, Case]). %% ------------------------------------------------------------------------- %% Internal Functions @@ -130,19 +130,15 @@ call_terminate({Mod, State}, _, _) -> catch_apply(Mod,terminate,[State], ok), {[],{Mod,State}}. -call_cleanup({Mod, State}, Reason, {Function, Tag}) -> - NewState = catch_apply(Mod,Function,[Tag, Reason, State], +call_cleanup({Mod, State}, Reason, [Function | Args]) -> + NewState = catch_apply(Mod,Function, Args ++ [Reason, State], {Reason,State}), {Reason, {Mod, NewState}}. -call_generic({Mod, State}, Config, {Function, undefined}) -> - {NewConf, NewState} = catch_apply(Mod,Function,[Config, State], - {Config, State}), - {NewConf, {Mod, NewState}}; -call_generic({Mod, State}, Config, {Function, Tag}) -> - {NewConf, NewState} = catch_apply(Mod,Function,[Tag, Config, State], - {Config,State}), - {NewConf, {Mod, NewState}}. +call_generic({Mod, State}, Value, [Function | Args]) -> + {NewValue, NewState} = catch_apply(Mod, Function, Args ++ [Value, State], + {Value,State}), + {NewValue, {Mod, NewState}}. %% Generic call function call(Fun, Config, Meta) -> @@ -191,19 +187,21 @@ remove(_, Else) -> Else. %% Translate scopes, i.e. init_per_group,group1 -> end_per_group,group1 etc -scope({pre_init_per_testcase, TC}) -> - {post_end_per_testcase, TC}; -scope({pre_init_per_group, GroupName}) -> - {post_end_per_group, GroupName}; -scope({post_init_per_group, GroupName}) -> - {post_end_per_group, GroupName}; -scope({pre_init_per_suite, SuiteName}) -> - {post_end_per_suite, SuiteName}; -scope({post_init_per_suite, SuiteName}) -> - {post_end_per_suite, SuiteName}; +scope([pre_init_per_testcase, TC|_]) -> + [post_end_per_testcase, TC]; +scope([pre_init_per_group, GroupName|_]) -> + [post_end_per_group, GroupName]; +scope([post_init_per_group, GroupName|_]) -> + [post_end_per_group, GroupName]; +scope([pre_init_per_suite, SuiteName|_]) -> + [post_end_per_suite, SuiteName]; +scope([post_init_per_suite, SuiteName|_]) -> + [post_end_per_suite, SuiteName]; scope(init) -> none. +terminate_if_scope_ends(CBId, [Function,Tag|T], CBs) when T =/= [] -> + terminate_if_scope_ends(CBId,[Function,Tag],CBs); terminate_if_scope_ends(CBId, Function, CBs) -> case lists:keyfind(CBId, 1, CBs) of {CBId, Function, _ModState} = CB -> diff --git a/lib/common_test/test/ct_suite_callback_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE.erl index b6af8e0c2a..3a7727120d 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE.erl @@ -191,18 +191,18 @@ test_events(one_empty_scb) -> {?eh,scb,{empty_scb,pre_init_per_suite, [ct_scb_empty_SUITE,'$proplist',[]]}}, {?eh,scb,{empty_scb,post_init_per_suite, - [ct_scb_empty_SUITE,'$proplist',[]]}}, + [ct_scb_empty_SUITE,'$proplist','$proplist',[]]}}, {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite,ok}}, {?eh,tc_start,{ct_scb_empty_SUITE,test_case}}, {?eh,scb,{empty_scb,pre_init_per_testcase,[test_case,'$proplist',[]]}}, - {?eh,scb,{empty_scb,post_end_per_testcase,[test_case,'_',[]]}}, + {?eh,scb,{empty_scb,post_end_per_testcase,[test_case,'$proplist','_',[]]}}, {?eh,tc_done,{ct_scb_empty_SUITE,test_case,ok}}, {?eh,tc_start,{ct_scb_empty_SUITE,end_per_suite}}, {?eh,scb,{empty_scb,pre_end_per_suite, [ct_scb_empty_SUITE,'$proplist',[]]}}, - {?eh,scb,{empty_scb,post_end_per_suite,[ct_scb_empty_SUITE,'_',[]]}}, + {?eh,scb,{empty_scb,post_end_per_suite,[ct_scb_empty_SUITE,'$proplist','_',[]]}}, {?eh,tc_done,{ct_scb_empty_SUITE,end_per_suite,ok}}, {?eh,test_done,{'DEF','STOP_TIME'}}, {?eh,scb,{empty_scb,terminate,[[]]}}, @@ -218,22 +218,22 @@ test_events(two_empty_scb) -> {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, {?eh,scb,{'_',pre_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, {?eh,scb,{'_',pre_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, - {?eh,scb,{'_',post_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, - {?eh,scb,{'_',post_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, + {?eh,scb,{'_',post_init_per_suite,[ct_scb_empty_SUITE,'$proplist','$proplist',[]]}}, + {?eh,scb,{'_',post_init_per_suite,[ct_scb_empty_SUITE,'$proplist','$proplist',[]]}}, {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite,ok}}, {?eh,tc_start,{ct_scb_empty_SUITE,test_case}}, {?eh,scb,{'_',pre_init_per_testcase,[test_case,'$proplist',[]]}}, {?eh,scb,{'_',pre_init_per_testcase,[test_case,'$proplist',[]]}}, - {?eh,scb,{'_',post_end_per_testcase,[test_case,ok,[]]}}, - {?eh,scb,{'_',post_end_per_testcase,[test_case,ok,[]]}}, + {?eh,scb,{'_',post_end_per_testcase,[test_case,'$proplist',ok,[]]}}, + {?eh,scb,{'_',post_end_per_testcase,[test_case,'$proplist',ok,[]]}}, {?eh,tc_done,{ct_scb_empty_SUITE,test_case,ok}}, {?eh,tc_start,{ct_scb_empty_SUITE,end_per_suite}}, {?eh,scb,{'_',pre_end_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, {?eh,scb,{'_',pre_end_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, - {?eh,scb,{'_',post_end_per_suite,[ct_scb_empty_SUITE,'_',[]]}}, - {?eh,scb,{'_',post_end_per_suite,[ct_scb_empty_SUITE,'_',[]]}}, + {?eh,scb,{'_',post_end_per_suite,[ct_scb_empty_SUITE,'$proplist','_',[]]}}, + {?eh,scb,{'_',post_end_per_suite,[ct_scb_empty_SUITE,'$proplist','_',[]]}}, {?eh,tc_done,{ct_scb_empty_SUITE,end_per_suite,ok}}, {?eh,test_done,{'DEF','STOP_TIME'}}, {?eh,scb,{'_',terminate,[[]]}}, @@ -282,17 +282,17 @@ test_events(minimal_and_maximal_scb) -> {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, {?eh,scb,{'_',pre_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, - {?eh,scb,{'_',post_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, + {?eh,scb,{'_',post_init_per_suite,[ct_scb_empty_SUITE,'$proplist','$proplist',[]]}}, {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite,ok}}, {?eh,tc_start,{ct_scb_empty_SUITE,test_case}}, {?eh,scb,{'_',pre_init_per_testcase,[test_case,'$proplist',[]]}}, - {?eh,scb,{'_',post_end_per_testcase,[test_case,ok,[]]}}, + {?eh,scb,{'_',post_end_per_testcase,[test_case,'$proplist',ok,[]]}}, {?eh,tc_done,{ct_scb_empty_SUITE,test_case,ok}}, {?eh,tc_start,{ct_scb_empty_SUITE,end_per_suite}}, {?eh,scb,{'_',pre_end_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, - {?eh,scb,{'_',post_end_per_suite,[ct_scb_empty_SUITE,'_',[]]}}, + {?eh,scb,{'_',post_end_per_suite,[ct_scb_empty_SUITE,'$proplist','_',[]]}}, {?eh,tc_done,{ct_scb_empty_SUITE,end_per_suite,ok}}, {?eh,test_done,{'DEF','STOP_TIME'}}, {?eh,scb,{'_',terminate,[[]]}}, @@ -330,18 +330,18 @@ test_events(scope_per_suite_scb) -> {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,tc_start,{ct_scope_per_suite_scb_SUITE,init_per_suite}}, {?eh,scb,{'_',init,[[]]}}, - {?eh,scb,{'_',post_init_per_suite,[ct_scope_per_suite_scb_SUITE,'$proplist',[]]}}, + {?eh,scb,{'_',post_init_per_suite,[ct_scope_per_suite_scb_SUITE,'$proplist','$proplist',[]]}}, {?eh,tc_done,{ct_scope_per_suite_scb_SUITE,init_per_suite,ok}}, {?eh,tc_start,{ct_scope_per_suite_scb_SUITE,test_case}}, {?eh,scb,{'_',pre_init_per_testcase,[test_case,'$proplist',[]]}}, - {?eh,scb,{'_',post_end_per_testcase,[test_case,ok,[]]}}, + {?eh,scb,{'_',post_end_per_testcase,[test_case,'$proplist',ok,[]]}}, {?eh,tc_done,{ct_scope_per_suite_scb_SUITE,test_case,ok}}, {?eh,tc_start,{ct_scope_per_suite_scb_SUITE,end_per_suite}}, {?eh,scb,{'_',pre_end_per_suite, [ct_scope_per_suite_scb_SUITE,'$proplist',[]]}}, - {?eh,scb,{'_',post_end_per_suite,[ct_scope_per_suite_scb_SUITE,'_',[]]}}, + {?eh,scb,{'_',post_end_per_suite,[ct_scope_per_suite_scb_SUITE,'$proplist','_',[]]}}, {?eh,scb,{'_',terminate,[[]]}}, {?eh,tc_done,{ct_scope_per_suite_scb_SUITE,end_per_suite,ok}}, {?eh,test_done,{'DEF','STOP_TIME'}}, @@ -355,17 +355,17 @@ test_events(scope_suite_scb) -> {?eh,tc_start,{ct_scope_suite_scb_SUITE,init_per_suite}}, {?eh,scb,{'_',init,[[]]}}, {?eh,scb,{'_',pre_init_per_suite,[ct_scope_suite_scb_SUITE,'$proplist',[]]}}, - {?eh,scb,{'_',post_init_per_suite,[ct_scope_suite_scb_SUITE,'$proplist',[]]}}, + {?eh,scb,{'_',post_init_per_suite,[ct_scope_suite_scb_SUITE,'$proplist','$proplist',[]]}}, {?eh,tc_done,{ct_scope_suite_scb_SUITE,init_per_suite,ok}}, {?eh,tc_start,{ct_scope_suite_scb_SUITE,test_case}}, {?eh,scb,{'_',pre_init_per_testcase,[test_case,'$proplist',[]]}}, - {?eh,scb,{'_',post_end_per_testcase,[test_case,ok,[]]}}, + {?eh,scb,{'_',post_end_per_testcase,[test_case,'$proplist',ok,[]]}}, {?eh,tc_done,{ct_scope_suite_scb_SUITE,test_case,ok}}, {?eh,tc_start,{ct_scope_suite_scb_SUITE,end_per_suite}}, {?eh,scb,{'_',pre_end_per_suite,[ct_scope_suite_scb_SUITE,'$proplist',[]]}}, - {?eh,scb,{'_',post_end_per_suite,[ct_scope_suite_scb_SUITE,'_',[]]}}, + {?eh,scb,{'_',post_end_per_suite,[ct_scope_suite_scb_SUITE,'$proplist','_',[]]}}, {?eh,scb,{'_',terminate,[[]]}}, {?eh,tc_done,{ct_scope_suite_scb_SUITE,end_per_suite,ok}}, {?eh,test_done,{'DEF','STOP_TIME'}}, @@ -381,17 +381,17 @@ test_events(scope_per_group_scb) -> [{?eh,tc_start,{ct_scope_per_group_scb_SUITE,{init_per_group,group1,[]}}}, {?eh,scb,{'_',init,[[]]}}, - {?eh,scb,{'_',post_init_per_group,[group1,'$proplist',[]]}}, + {?eh,scb,{'_',post_init_per_group,[group1,'$proplist','$proplist',[]]}}, {?eh,tc_done,{ct_scope_per_group_scb_SUITE,{init_per_group,group1,[]},ok}}, {?eh,tc_start,{ct_scope_per_group_scb_SUITE,test_case}}, {?eh,scb,{'_',pre_init_per_testcase,[test_case,'$proplist',[]]}}, - {?eh,scb,{'_',post_end_per_testcase,[test_case,ok,[]]}}, + {?eh,scb,{'_',post_end_per_testcase,[test_case,'$proplist',ok,[]]}}, {?eh,tc_done,{ct_scope_per_group_scb_SUITE,test_case,ok}}, {?eh,tc_start,{ct_scope_per_group_scb_SUITE,{end_per_group,group1,[]}}}, {?eh,scb,{'_',pre_end_per_group,[group1,'$proplist',[]]}}, - {?eh,scb,{'_',post_end_per_group,[group1,'_',[]]}}, + {?eh,scb,{'_',post_end_per_group,[group1,'$proplist','_',[]]}}, {?eh,scb,{'_',terminate,[[]]}}, {?eh,tc_done,{ct_scope_per_group_scb_SUITE,{end_per_group,group1,[]},ok}}], @@ -410,7 +410,7 @@ test_events(fail_pre_suite_scb) -> {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, {?eh,scb,{'_',pre_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, - {?eh,scb,{'_',post_init_per_suite,[ct_scb_empty_SUITE, + {?eh,scb,{'_',post_init_per_suite,[ct_scb_empty_SUITE,'$proplist', {error,"Test failure"},[]]}}, {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite, {failed, {error,"Test failure"}}}}, @@ -448,7 +448,7 @@ test_events(fail_post_suite_scb) -> {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, {?eh,scb,{'_',pre_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, - {?eh,scb,{'_',post_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, + {?eh,scb,{'_',post_init_per_suite,[ct_scb_empty_SUITE,'$proplist','$proplist',[]]}}, {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite, {failed,{error,"Test failure"}}}}, {?eh,scb,{'_',on_tc_fail,[init_per_suite, {failed,"Test failure"}, []]}}, @@ -475,7 +475,7 @@ test_events(skip_pre_suite_scb) -> {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, {?eh,scb,{'_',pre_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, - {?eh,scb,{'_',post_init_per_suite,[ct_scb_empty_SUITE,{skip,"Test skip"},[]]}}, + {?eh,scb,{'_',post_init_per_suite,[ct_scb_empty_SUITE,'$proplist',{skip,"Test skip"},[]]}}, {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite,{skipped,"Test skip"}}}, {?eh,scb,{'_',on_tc_skip, [init_per_suite,{tc_user_skip,{skipped,"Test skip"}},[]]}}, @@ -499,7 +499,7 @@ test_events(skip_post_suite_scb) -> {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, {?eh,scb,{'_',pre_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, - {?eh,scb,{'_',post_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, + {?eh,scb,{'_',post_init_per_suite,[ct_scb_empty_SUITE,'$proplist','$proplist',[]]}}, {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite,{skipped,"Test skip"}}}, {?eh,scb,{'_',on_tc_skip, [init_per_suite,{tc_user_skip,{skipped,"Test skip"}},[]]}}, diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/empty_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/empty_scb.erl index 05f6563c45..d9aa1e77e4 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/empty_scb.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/empty_scb.erl @@ -38,17 +38,17 @@ -export([init/1]). -export([pre_init_per_suite/3]). --export([post_init_per_suite/3]). +-export([post_init_per_suite/4]). -export([pre_end_per_suite/3]). --export([post_end_per_suite/3]). +-export([post_end_per_suite/4]). -export([pre_init_per_group/3]). --export([post_init_per_group/3]). +-export([post_init_per_group/4]). -export([pre_end_per_group/3]). --export([post_end_per_group/3]). +-export([post_end_per_group/4]). -export([pre_init_per_testcase/3]). --export([post_end_per_testcase/3]). +-export([post_end_per_testcase/4]). -export([on_tc_fail/3]). -export([on_tc_skip/3]). @@ -95,22 +95,23 @@ pre_init_per_suite(Suite,Config,State) -> {Config, State}. %% @doc Called after init_per_suite. -%% you can change the config in this function. +%% you can change the return value in this function. -spec post_init_per_suite(Suite :: atom(), - Config :: config(), - State :: #state{}) -> + Config :: config(), + Return :: config() | skip_or_fail(), + State :: #state{}) -> {config() | skip_or_fail(), NewState :: #state{}}. -post_init_per_suite(Suite,Config,State) -> +post_init_per_suite(Suite,Config,Return,State) -> gen_event:notify( ?CT_EVMGR_REF, #event{ name = scb, node = node(), data = {?MODULE, post_init_per_suite, - [Suite,Config,State]}}), - {Config, State}. + [Suite,Config,Return,State]}}), + {Return, State}. -%% @doc Called before end_per_suite. Note that the config cannot be -%% changed here, only the status of the suite. +%% @doc Called before end_per_suite. The config/state can be changed here, +%% though it will only affect the *end_per_suite function. -spec pre_end_per_suite(Suite :: atom(), - Config :: config(), + Config :: config() | skip_or_fail(), State :: #state{}) -> {ok | skip_or_fail(), NewState :: #state{}}. pre_end_per_suite(Suite,Config,State) -> @@ -123,15 +124,16 @@ pre_end_per_suite(Suite,Config,State) -> %% @doc Called after end_per_suite. Note that the config cannot be %% changed here, only the status of the suite. -spec post_end_per_suite(Suite :: atom(), - Config :: config(), - State :: #state{}) -> + Config :: config(), + Return :: term(), + State :: #state{}) -> {ok | skip_or_fail(), NewState :: #state{}}. -post_end_per_suite(Suite,Config,State) -> +post_end_per_suite(Suite,Config,Return,State) -> gen_event:notify( ?CT_EVMGR_REF, #event{ name = scb, node = node(), data = {?MODULE, post_end_per_suite, - [Suite,Config,State]}}), - {Config, State}. + [Suite,Config,Return,State]}}), + {Return, State}. %% @doc Called before each init_per_group. %% You can change the config in this function. @@ -147,23 +149,24 @@ pre_init_per_group(Group,Config,State) -> {Config, State}. %% @doc Called after each init_per_group. -%% You can change the config in this function. +%% You can change the return value in this function. -spec post_init_per_group(Group :: atom(), - Config :: config(), - State :: #state{}) -> + Config :: config(), + Return :: config() | skip_or_fail(), + State :: #state{}) -> {config() | skip_or_fail(), NewState :: #state{}}. -post_init_per_group(Group,Config,State) -> +post_init_per_group(Group,Config,Return,State) -> gen_event:notify( ?CT_EVMGR_REF, #event{ name = scb, node = node(), data = {?MODULE, post_init_per_group, - [Group,Config,State]}}), - {Config, State}. + [Group,Config,Return,State]}}), + {Return, State}. -%% @doc Called after each end_per_group. Note that the config cannot be -%% changed here, only the status of the group. +%% @doc Called after each end_per_group. The config/state can be changed here, +%% though it will only affect the *end_per_group functions. -spec pre_end_per_group(Group :: atom(), - Config :: config(), - State :: #state{}) -> + Config :: config() | skip_or_fail(), + State :: #state{}) -> {ok | skip_or_fail(), NewState :: #state{}}. pre_end_per_group(Group,Config,State) -> gen_event:notify( @@ -175,15 +178,16 @@ pre_end_per_group(Group,Config,State) -> %% @doc Called after each end_per_group. Note that the config cannot be %% changed here, only the status of the group. -spec post_end_per_group(Group :: atom(), - Config :: config(), - State :: #state{}) -> + Config :: config(), + Return :: term(), + State :: #state{}) -> {ok | skip_or_fail(), NewState :: #state{}}. -post_end_per_group(Group,Config,State) -> +post_end_per_group(Group,Config,Return,State) -> gen_event:notify( ?CT_EVMGR_REF, #event{ name = scb, node = node(), data = {?MODULE, post_end_per_group, - [Group,Config,State]}}), - {Config, State}. + [Group,Config,Return,State]}}), + {Return, State}. %% @doc Called before each test case. %% You can change the config in this function. @@ -201,15 +205,16 @@ pre_init_per_testcase(TC,Config,State) -> %% @doc Called after each test case. Note that the config cannot be %% changed here, only the status of the test case. -spec post_end_per_testcase(TC :: atom(), - Config :: config(), - State :: #state{}) -> + Config :: config(), + Return :: term(), + State :: #state{}) -> {ok | skip_or_fail(), NewState :: #state{}}. -post_end_per_testcase(TC,Config,State) -> +post_end_per_testcase(TC,Config,Return,State) -> gen_event:notify( ?CT_EVMGR_REF, #event{ name = scb, node = node(), data = {?MODULE, post_end_per_testcase, - [TC,Config,State]}}), - {Config, State}. + [TC,Config,Return,State]}}), + {Return, State}. %% @doc Called after post_init_per_suite, post_end_per_suite, post_init_per_group, %% post_end_per_group and post_end_per_tc if the suite, group or test case failed. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/fail_post_suite_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/fail_post_suite_scb.erl index 2ba5013652..b3a3a5f94c 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/fail_post_suite_scb.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/fail_post_suite_scb.erl @@ -34,33 +34,33 @@ init(Opts) -> pre_init_per_suite(Suite, Config, State) -> empty_scb:pre_init_per_suite(Suite,Config,State). -post_init_per_suite(Suite,Config,State) -> - empty_scb:post_init_per_suite(Suite,Config,State), +post_init_per_suite(Suite,Config,Return,State) -> + empty_scb:post_init_per_suite(Suite,Config,Return,State), {{fail, "Test failure"}, State}. pre_end_per_suite(Suite,Config,State) -> empty_scb:pre_end_per_suite(Suite,Config,State). -post_end_per_suite(Suite,Config,State) -> - empty_scb:post_end_per_suite(Suite,Config,State). +post_end_per_suite(Suite,Config,Return,State) -> + empty_scb:post_end_per_suite(Suite,Config,Return,State). pre_init_per_group(Group,Config,State) -> empty_scb:pre_init_per_group(Group,Config,State). -post_init_per_group(Group,Config,State) -> - empty_scb:post_init_per_group(Group,Config,State). +post_init_per_group(Group,Config,Return,State) -> + empty_scb:post_init_per_group(Group,Config,Return,State). pre_end_per_group(Group,Config,State) -> empty_scb:pre_end_per_group(Group,Config,State). -post_end_per_group(Group,Config,State) -> - empty_scb:post_end_per_group(Group,Config,State). +post_end_per_group(Group,Config,Return,State) -> + empty_scb:post_end_per_group(Group,Config,Return,State). pre_init_per_testcase(TC,Config,State) -> empty_scb:pre_init_per_testcase(TC,Config,State). -post_end_per_testcase(TC,Config,State) -> - empty_scb:post_end_per_testcase(TC,Config,State). +post_end_per_testcase(TC,Config,Return,State) -> + empty_scb:post_end_per_testcase(TC,Config,Return,State). on_tc_fail(TC, Reason, State) -> empty_scb:on_tc_fail(TC,Reason,State). diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/fail_pre_suite_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/fail_pre_suite_scb.erl index f108624836..d49387ff8c 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/fail_pre_suite_scb.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/fail_pre_suite_scb.erl @@ -35,32 +35,32 @@ pre_init_per_suite(Suite, Config, State) -> empty_scb:pre_init_per_suite(Suite,Config,State), {{fail, "Test failure"}, State}. -post_init_per_suite(Suite,Config,State) -> - empty_scb:post_init_per_suite(Suite,Config,State). +post_init_per_suite(Suite,Config,Return,State) -> + empty_scb:post_init_per_suite(Suite,Config,Return,State). pre_end_per_suite(Suite,Config,State) -> empty_scb:pre_end_per_suite(Suite,Config,State). -post_end_per_suite(Suite,Config,State) -> - empty_scb:post_end_per_suite(Suite,Config,State). +post_end_per_suite(Suite,Config,Return,State) -> + empty_scb:post_end_per_suite(Suite,Config,Return,State). pre_init_per_group(Group,Config,State) -> empty_scb:pre_init_per_group(Group,Config,State). -post_init_per_group(Group,Config,State) -> - empty_scb:post_init_per_group(Group,Config,State). +post_init_per_group(Group,Config,Return,State) -> + empty_scb:post_init_per_group(Group,Config,Return,State). pre_end_per_group(Group,Config,State) -> empty_scb:pre_end_per_group(Group,Config,State). -post_end_per_group(Group,Config,State) -> - empty_scb:post_end_per_group(Group,Config,State). +post_end_per_group(Group,Config,Return,State) -> + empty_scb:post_end_per_group(Group,Config,Return,State). pre_init_per_testcase(TC,Config,State) -> empty_scb:pre_init_per_testcase(TC,Config,State). -post_end_per_testcase(TC,Config,State) -> - empty_scb:post_end_per_testcase(TC,Config,State). +post_end_per_testcase(TC,Config,Return,State) -> + empty_scb:post_end_per_testcase(TC,Config,Return,State). on_tc_fail(TC, Reason, State) -> empty_scb:on_tc_fail(TC,Reason,State). diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/skip_post_suite_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/skip_post_suite_scb.erl index 5462e34175..a2e0578814 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/skip_post_suite_scb.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/skip_post_suite_scb.erl @@ -34,33 +34,33 @@ init(Opts) -> pre_init_per_suite(Suite, Config, State) -> empty_scb:pre_init_per_suite(Suite,Config,State). -post_init_per_suite(Suite,Config,State) -> - empty_scb:post_init_per_suite(Suite,Config,State), +post_init_per_suite(Suite,Config,Return,State) -> + empty_scb:post_init_per_suite(Suite,Config,Return,State), {{skip, "Test skip"}, State}. pre_end_per_suite(Suite,Config,State) -> empty_scb:pre_end_per_suite(Suite,Config,State). -post_end_per_suite(Suite,Config,State) -> - empty_scb:post_end_per_suite(Suite,Config,State). +post_end_per_suite(Suite,Config,Return,State) -> + empty_scb:post_end_per_suite(Suite,Config,Return,State). pre_init_per_group(Group,Config,State) -> empty_scb:pre_init_per_group(Group,Config,State). -post_init_per_group(Group,Config,State) -> - empty_scb:post_init_per_group(Group,Config,State). +post_init_per_group(Group,Config,Return,State) -> + empty_scb:post_init_per_group(Group,Config,Return,State). pre_end_per_group(Group,Config,State) -> empty_scb:pre_end_per_group(Group,Config,State). -post_end_per_group(Group,Config,State) -> - empty_scb:post_end_per_group(Group,Config,State). +post_end_per_group(Group,Config,Return,State) -> + empty_scb:post_end_per_group(Group,Config,Return,State). pre_init_per_testcase(TC,Config,State) -> empty_scb:pre_init_per_testcase(TC,Config,State). -post_end_per_testcase(TC,Config,State) -> - empty_scb:post_end_per_testcase(TC,Config,State). +post_end_per_testcase(TC,Config,Return,State) -> + empty_scb:post_end_per_testcase(TC,Config,Return,State). on_tc_fail(TC, Reason, State) -> empty_scb:on_tc_fail(TC,Reason,State). diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/skip_pre_suite_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/skip_pre_suite_scb.erl index 006ae4a90f..4a0725ce2f 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/skip_pre_suite_scb.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/skip_pre_suite_scb.erl @@ -36,32 +36,32 @@ pre_init_per_suite(Suite, Config, State) -> empty_scb:pre_init_per_suite(Suite,Config,State), {{skip, "Test skip"}, State}. -post_init_per_suite(Suite,Config,State) -> - empty_scb:post_init_per_suite(Suite,Config,State). +post_init_per_suite(Suite,Config,Return,State) -> + empty_scb:post_init_per_suite(Suite,Config,Return,State). pre_end_per_suite(Suite,Config,State) -> empty_scb:pre_end_per_suite(Suite,Config,State). -post_end_per_suite(Suite,Config,State) -> - empty_scb:post_end_per_suite(Suite,Config,State). +post_end_per_suite(Suite,Config,Return,State) -> + empty_scb:post_end_per_suite(Suite,Config,Return,State). pre_init_per_group(Group,Config,State) -> empty_scb:pre_init_per_group(Group,Config,State). -post_init_per_group(Group,Config,State) -> - empty_scb:post_init_per_group(Group,Config,State). +post_init_per_group(Group,Config,Return,State) -> + empty_scb:post_init_per_group(Group,Config,Return,State). pre_end_per_group(Group,Config,State) -> empty_scb:pre_end_per_group(Group,Config,State). -post_end_per_group(Group,Config,State) -> - empty_scb:post_end_per_group(Group,Config,State). +post_end_per_group(Group,Config,Return,State) -> + empty_scb:post_end_per_group(Group,Config,Return,State). pre_init_per_testcase(TC,Config,State) -> empty_scb:pre_init_per_testcase(TC,Config,State). -post_end_per_testcase(TC,Config,State) -> - empty_scb:post_end_per_testcase(TC,Config,State). +post_end_per_testcase(TC,Config,Return,State) -> + empty_scb:post_end_per_testcase(TC,Config,Return,State). on_tc_fail(TC, Reason, State) -> empty_scb:on_tc_fail(TC,Reason,State). diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/undef_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/undef_scb.erl index 80d0f10415..9479f9d937 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/undef_scb.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/undef_scb.erl @@ -34,32 +34,32 @@ init(Opts) -> pre_init_per_suite(_Suite, _Config, _State) -> lists:flaten([1,2,[3,4]]). -post_init_per_suite(Suite,Config,State) -> - empty_scb:post_init_per_suite(Suite,Config,State). +post_init_per_suite(Suite,Config,Return,State) -> + empty_scb:post_init_per_suite(Suite,Config,Return,State). pre_end_per_suite(Suite,Config,State) -> empty_scb:pre_end_per_suite(Suite,Config,State). -post_end_per_suite(Suite,Config,State) -> - empty_scb:post_end_per_suite(Suite,Config,State). +post_end_per_suite(Suite,Config,Return,State) -> + empty_scb:post_end_per_suite(Suite,Config,Return,State). pre_init_per_group(Group,Config,State) -> empty_scb:pre_init_per_group(Group,Config,State). -post_init_per_group(Group,Config,State) -> - empty_scb:post_init_per_group(Group,Config,State). +post_init_per_group(Group,Config,Return,State) -> + empty_scb:post_init_per_group(Group,Config,Return,State). pre_end_per_group(Group,Config,State) -> empty_scb:pre_end_per_group(Group,Config,State). -post_end_per_group(Group,Config,State) -> - empty_scb:post_end_per_group(Group,Config,State). +post_end_per_group(Group,Config,Return,State) -> + empty_scb:post_end_per_group(Group,Config,Return,State). pre_init_per_testcase(TC,Config,State) -> empty_scb:pre_init_per_testcase(TC,Config,State). -post_end_per_testcase(TC,Config,State) -> - empty_scb:post_end_per_testcase(TC,Config,State). +post_end_per_testcase(TC,Config,Return,State) -> + empty_scb:post_end_per_testcase(TC,Config,Return,State). on_tc_fail(TC, Reason, State) -> empty_scb:on_tc_fail(TC,Reason,State). -- cgit v1.2.3 From 78be3bba07f0311c19e7e63b486bd8616a7f2759 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Wed, 24 Nov 2010 15:23:14 +0100 Subject: Add testcase for config updates --- lib/common_test/test/ct_suite_callback_SUITE.erl | 131 ++++++++++++++++++++- .../scb/tests/ct_update_config_SUITE.erl | 56 +++++++++ .../scb/tests/update_config_scb.erl | 82 +++++++++++++ lib/common_test/test/ct_test_support.erl | 17 ++- 4 files changed, 279 insertions(+), 7 deletions(-) create mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_update_config_SUITE.erl create mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/update_config_scb.erl (limited to 'lib/common_test') diff --git a/lib/common_test/test/ct_suite_callback_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE.erl index 3a7727120d..ab30ca368c 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE.erl @@ -76,7 +76,7 @@ all(suite) -> minimal_and_maximal_scb, faulty_scb_undef, scope_per_suite_scb, scope_per_group_scb, scope_suite_scb, fail_pre_suite_scb, fail_post_suite_scb, skip_pre_suite_scb, - skip_post_suite_scb + skip_post_suite_scb, update_config_scb ]). @@ -136,6 +136,10 @@ skip_post_suite_scb(Config) -> do_test(skip_post_suite_scb, "ct_scb_empty_SUITE.erl", [skip_post_suite_scb],Config). +update_config_scb(Config) -> + do_test(update_config_scb, "ct_update_config_SUITE.erl", + [update_config_scb],Config). + %%%----------------------------------------------------------------- %%% HELP FUNCTIONS %%%----------------------------------------------------------------- @@ -511,8 +515,133 @@ test_events(skip_post_suite_scb) -> {?eh,scb,{'_',on_tc_skip,[end_per_suite,{tc_auto_skip,"Test skip"},[]]}}, {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,scb,{'_',terminate,[[]]}}, + {?eh,stop_logging,[]} + ]; + +test_events(update_config_scb) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,scb,{'_',init,[[]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + + {?eh,tc_start,{ct_update_config_SUITE,init_per_suite}}, + {?eh,scb,{'_',pre_init_per_suite, + [ct_update_config_SUITE,contains([]),[]]}}, + {?eh,scb,{'_',post_init_per_suite, + [ct_update_config_SUITE, + '$proplist', + contains( + [init_per_suite, + pre_init_per_suite]), + []]}}, + {?eh,tc_done,{ct_update_config_SUITE,init_per_suite,ok}}, + + {?eh,tc_start,{ct_update_config_SUITE, {init_per_group,group1,[]}}}, + {?eh,scb,{'_',pre_init_per_group, + [group1,contains( + [post_init_per_suite, + init_per_suite, + pre_init_per_suite]), + []]}}, + {?eh,scb,{'_',post_init_per_group, + [group1, + contains( + [post_init_per_suite, + init_per_suite, + pre_init_per_suite]), + contains( + [init_per_group, + pre_init_per_group, + post_init_per_suite, + init_per_suite, + pre_init_per_suite]), + []]}}, + {?eh,tc_done,{ct_update_config_SUITE,{init_per_group,group1,[]},ok}}, + + {?eh,tc_start,{ct_update_config_SUITE,test_case}}, + {?eh,scb,{'_',pre_init_per_testcase, + [test_case,contains( + [post_init_per_group, + init_per_group, + pre_init_per_group, + post_init_per_suite, + init_per_suite, + pre_init_per_suite]), + []]}}, + {?eh,scb,{'_',post_end_per_testcase, + [test_case,contains( + [init_per_testcase, + pre_init_per_testcase, + post_init_per_group, + init_per_group, + pre_init_per_group, + post_init_per_suite, + init_per_suite, + pre_init_per_suite]), + ok,[]]}}, + {?eh,tc_done,{ct_update_config_SUITE,test_case,ok}}, + + {?eh,tc_start,{ct_update_config_SUITE, {end_per_group,group1,[]}}}, + {?eh,scb,{'_',pre_end_per_group, + [group1,contains( + [post_init_per_group, + init_per_group, + pre_init_per_group, + post_init_per_suite, + init_per_suite, + pre_init_per_suite]), + []]}}, + {?eh,scb,{'_',post_end_per_group, + [group1, + contains( + [pre_end_per_group, + post_init_per_group, + init_per_group, + pre_init_per_group, + post_init_per_suite, + init_per_suite, + pre_init_per_suite]), + ok,[]]}}, + {?eh,tc_done,{ct_update_config_SUITE,{end_per_group,group1,[]},ok}}, + + {?eh,tc_start,{ct_update_config_SUITE,end_per_suite}}, + {?eh,scb,{'_',pre_end_per_suite, + [ct_update_config_SUITE,contains( + [post_init_per_suite, + init_per_suite, + pre_init_per_suite]), + []]}}, + {?eh,scb,{'_',post_end_per_suite, + [ct_update_config_SUITE,contains( + [pre_end_per_suite, + post_init_per_suite, + init_per_suite, + pre_init_per_suite]), + '_',[]]}}, + {?eh,tc_done,{ct_update_config_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,scb,{'_',terminate,[contains( + [post_end_per_suite, + pre_end_per_suite, + post_init_per_suite, + init_per_suite, + pre_init_per_suite])]}}, {?eh,stop_logging,[]} ]; test_events(ok) -> ok. + + +%% test events help functions +contains(List) -> + fun(Proplist) when is_list(Proplist) -> + contains(List,Proplist) + end. +contains([Ele|T],[{Ele,_}|T2])-> + contains(T,T2); +contains(List,[_|T]) -> + contains(List,T); +contains([],_) -> + match. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_update_config_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_update_config_SUITE.erl new file mode 100644 index 0000000000..57fea347f6 --- /dev/null +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_update_config_SUITE.erl @@ -0,0 +1,56 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(ct_update_config_SUITE). + +-suite_defaults([{timetrap, {minutes, 10}}]). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-include("ct.hrl"). + +%% Test server callback functions +init_per_suite(Config) -> + [{init_per_suite,now()}|Config]. + +end_per_suite(_Config) -> + ok. + +init_per_testcase(_TestCase, Config) -> + [{init_per_testcase,now()}|Config]. + +end_per_testcase(_TestCase, _Config) -> + ok. + +init_per_group(GroupName, Config) -> + [{init_per_group,now()}|Config]. + +end_per_group(GroupName, Config) -> + ok. + +all() -> + [{group,group1}]. + +groups() -> + [{group1,[],[test_case]}]. + +%% Test cases starts here. +test_case(Config) when is_list(Config) -> + ok. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/update_config_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/update_config_scb.erl new file mode 100644 index 0000000000..6f21e49656 --- /dev/null +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/update_config_scb.erl @@ -0,0 +1,82 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(update_config_scb). + + +-include_lib("common_test/src/ct_util.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + + +%% Suite Callbacks +-compile(export_all). + +init(Opts) -> + empty_scb:init(Opts). + +pre_init_per_suite(Suite, Config, State) -> + empty_scb:pre_init_per_suite(Suite,Config,State), + {[{pre_init_per_suite,now()}|Config],State}. + +post_init_per_suite(Suite,Config,Return,State) -> + empty_scb:post_init_per_suite(Suite,Config,Return,State), + {[{post_init_per_suite,now()}|Return],State}. + +pre_end_per_suite(Suite,Config,State) -> + empty_scb:pre_end_per_suite(Suite,Config,State), + {[{pre_end_per_suite,now()}|Config],State}. + +post_end_per_suite(Suite,Config,Return,State) -> + empty_scb:post_end_per_suite(Suite,Config,Return,State), + NewConfig = [{post_end_per_suite,now()}|Config], + {NewConfig,NewConfig}. + +pre_init_per_group(Group,Config,State) -> + empty_scb:pre_init_per_group(Group,Config,State), + {[{pre_init_per_group,now()}|Config],State}. + +post_init_per_group(Group,Config,Return,State) -> + empty_scb:post_init_per_group(Group,Config,Return,State), + {[{post_init_per_group,now()}|Return],State}. + +pre_end_per_group(Group,Config,State) -> + empty_scb:pre_end_per_group(Group,Config,State), + {[{pre_end_per_group,now()}|Config],State}. + +post_end_per_group(Group,Config,Return,State) -> + empty_scb:post_end_per_group(Group,Config,Return,State), + {[{post_end_per_group,now()}|Config],State}. + +pre_init_per_testcase(TC,Config,State) -> + empty_scb:pre_init_per_testcase(TC,Config,State), + {[{pre_init_per_testcase,now()}|Config],State}. + +post_end_per_testcase(TC,Config,Return,State) -> + empty_scb:post_end_per_testcase(TC,Config,Return,State), + {[{post_end_per_testcase,now()}|Config],State}. + +on_tc_fail(TC, Reason, State) -> + empty_scb:on_tc_fail(TC,Reason,State). + +on_tc_skip(TC, Reason, State) -> + empty_scb:on_tc_skip(TC,Reason,State). + +terminate(State) -> + empty_scb:terminate(State). diff --git a/lib/common_test/test/ct_test_support.erl b/lib/common_test/test/ct_test_support.erl index d9b9f85ded..5009741f59 100644 --- a/lib/common_test/test/ct_test_support.erl +++ b/lib/common_test/test/ct_test_support.erl @@ -891,17 +891,22 @@ locate({TEH,Name,Data}, Node, [{TEH,#event{name=Name, locate({TEH,Name,Data}, Node, [_|Evs], Config) -> nomatch. -match_data([H1|MatchT],[H2|ValT]) -> - match_data(H1,H2), - match_data(MatchT,ValT); -match_data(Tuple1,Tuple2) when is_tuple(Tuple1),is_tuple(Tuple2) -> - match_data(tuple_to_list(Tuple1),tuple_to_list(Tuple2)); match_data(D,D) -> match; match_data('_',_) -> match; +match_data(Fun,Data) when is_function(Fun) -> + Fun(Data); match_data('$proplist',Proplist) -> - lists:foreach(fun({_,_}) -> ok end,Proplist); + match_data( + fun(List) -> + lists:foreach(fun({_,_}) -> ok end,List) + end,Proplist); +match_data([H1|MatchT],[H2|ValT]) -> + match_data(H1,H2), + match_data(MatchT,ValT); +match_data(Tuple1,Tuple2) when is_tuple(Tuple1),is_tuple(Tuple2) -> + match_data(tuple_to_list(Tuple1),tuple_to_list(Tuple2)); match_data([],[]) -> match. -- cgit v1.2.3 From c0c7e05de55b83ed6d53da628cb345fc4f4da864 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Tue, 30 Nov 2010 14:48:34 +0100 Subject: Add test case for init_per_suite recover scenario --- lib/common_test/test/ct_suite_callback_SUITE.erl | 52 ++++++++++++++- .../scb/tests/ct_scb_fail_per_suite_SUITE.erl | 47 ++++++++++++++ .../scb/tests/recover_post_suite_scb.erl | 74 ++++++++++++++++++++++ 3 files changed, 171 insertions(+), 2 deletions(-) create mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scb_fail_per_suite_SUITE.erl create mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/recover_post_suite_scb.erl (limited to 'lib/common_test') diff --git a/lib/common_test/test/ct_suite_callback_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE.erl index ab30ca368c..53087956b9 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE.erl @@ -76,7 +76,7 @@ all(suite) -> minimal_and_maximal_scb, faulty_scb_undef, scope_per_suite_scb, scope_per_group_scb, scope_suite_scb, fail_pre_suite_scb, fail_post_suite_scb, skip_pre_suite_scb, - skip_post_suite_scb, update_config_scb + skip_post_suite_scb, recover_post_suite_scb, update_config_scb ]). @@ -136,6 +136,10 @@ skip_post_suite_scb(Config) -> do_test(skip_post_suite_scb, "ct_scb_empty_SUITE.erl", [skip_post_suite_scb],Config). +recover_post_suite_scb(Config) -> + do_test(recover_post_suite_scb, "ct_scb_fail_per_suite_SUITE.erl", + [recover_post_suite_scb],Config). + update_config_scb(Config) -> do_test(update_config_scb, "ct_update_config_SUITE.erl", [update_config_scb],Config). @@ -415,7 +419,7 @@ test_events(fail_pre_suite_scb) -> {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, {?eh,scb,{'_',pre_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, {?eh,scb,{'_',post_init_per_suite,[ct_scb_empty_SUITE,'$proplist', - {error,"Test failure"},[]]}}, + {fail,"Test failure"},[]]}}, {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite, {failed, {error,"Test failure"}}}}, {?eh,scb,{'_',on_tc_fail, @@ -519,6 +523,36 @@ test_events(skip_post_suite_scb) -> {?eh,stop_logging,[]} ]; +test_events(recover_post_suite_scb) -> + Suite = ct_scb_fail_per_suite_SUITE, + [ + {?eh,start_logging,'_'}, + {?eh,scb,{'_',init,[[]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{Suite,init_per_suite}}, + {?eh,scb,{'_',pre_init_per_suite,[Suite,'$proplist','$proplist']}}, + {?eh,scb,{'_',post_init_per_suite,[Suite,contains([tc_status]), + {'EXIT',{'_','_'}},[]]}}, + {?eh,tc_done,{Suite,init_per_suite,ok}}, + + {?eh,tc_start,{Suite,test_case}}, + {?eh,scb,{'_',pre_init_per_testcase, + [test_case, not_contains([tc_status]),[]]}}, + {?eh,scb,{'_',post_end_per_testcase, + [test_case, contains([tc_status]),'_',[]]}}, + {?eh,tc_done,{Suite,test_case,ok}}, + + {?eh,tc_start,{Suite,end_per_suite}}, + {?eh,scb,{'_',pre_end_per_suite, + [Suite,not_contains([tc_status]),[]]}}, + {?eh,scb,{'_',post_end_per_suite, + [Suite,not_contains([tc_status]),'_',[]]}}, + {?eh,tc_done,{Suite,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,scb,{'_',terminate,[[]]}}, + {?eh,stop_logging,[]} + ]; + test_events(update_config_scb) -> [ {?eh,start_logging,{'DEF','RUNDIR'}}, @@ -639,9 +673,23 @@ contains(List) -> fun(Proplist) when is_list(Proplist) -> contains(List,Proplist) end. +contains([{Ele,Pos}|T] = L,[H|T2]) -> + case element(Pos,H) of + Ele -> + contains(T,T2); + _ -> + contains(L,T2) + end; contains([Ele|T],[{Ele,_}|T2])-> contains(T,T2); contains(List,[_|T]) -> contains(List,T); contains([],_) -> match. + +not_contains(List) -> + fun(Proplist) when is_list(Proplist) -> + [] = [Ele || {Ele,_} <- Proplist, + Test <- List, + Test =:= Ele] + end. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scb_fail_per_suite_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scb_fail_per_suite_SUITE.erl new file mode 100644 index 0000000000..dfc7c37e8d --- /dev/null +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scb_fail_per_suite_SUITE.erl @@ -0,0 +1,47 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(ct_scb_fail_per_suite_SUITE). + +-suite_defaults([{timetrap, {minutes, 10}}]). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-include("ct.hrl"). + +%% Test server callback functions +init_per_suite(Config) -> + ok = nok. + +end_per_suite(_Config) -> + ok. + +init_per_testcase(_TestCase, Config) -> + Config. + +end_per_testcase(_TestCase, _Config) -> + ok. + +all() -> + [test_case]. + +%% Test cases starts here. +test_case(Config) when is_list(Config) -> + ok. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/recover_post_suite_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/recover_post_suite_scb.erl new file mode 100644 index 0000000000..864a09e3d0 --- /dev/null +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/recover_post_suite_scb.erl @@ -0,0 +1,74 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(recover_post_suite_scb). + + +-include_lib("common_test/src/ct_util.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + + +%% Suite Callbacks +-compile(export_all). + +init(Opts) -> + empty_scb:init(Opts). + +pre_init_per_suite(Suite, Config, State) -> + empty_scb:pre_init_per_suite(Suite,Config,State). + +post_init_per_suite(Suite,Config,{'EXIT',Reason} = Return,State) -> + empty_scb:post_init_per_suite(Suite,Config,Return,State), + {lists:keydelete(tc_status,1,Config),State}; +post_init_per_suite(Suite,Config,Return,State) -> + empty_scb:post_init_per_suite(Suite,Config,Return,State). + +pre_end_per_suite(Suite,Config,State) -> + empty_scb:pre_end_per_suite(Suite,Config,State). + +post_end_per_suite(Suite,Config,Return,State) -> + empty_scb:post_end_per_suite(Suite,Config,Return,State). + +pre_init_per_group(Group,Config,State) -> + empty_scb:pre_init_per_group(Group,Config,State). + +post_init_per_group(Group,Config,Return,State) -> + empty_scb:post_init_per_group(Group,Config,Return,State). + +pre_end_per_group(Group,Config,State) -> + empty_scb:pre_end_per_group(Group,Config,State). + +post_end_per_group(Group,Config,Return,State) -> + empty_scb:post_end_per_group(Group,Config,Return,State). + +pre_init_per_testcase(TC,Config,State) -> + empty_scb:pre_init_per_testcase(TC,Config,State). + +post_end_per_testcase(TC,Config,Return,State) -> + empty_scb:post_end_per_testcase(TC,Config,Return,State). + +on_tc_fail(TC, Reason, State) -> + empty_scb:on_tc_fail(TC,Reason,State). + +on_tc_skip(TC, Reason, State) -> + empty_scb:on_tc_skip(TC,Reason,State). + +terminate(State) -> + empty_scb:terminate(State). -- cgit v1.2.3 From b299052f8d69ef4fff19d83d0f75ded72d65e9e3 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Tue, 30 Nov 2010 18:25:36 +0100 Subject: Update ct_framework calls to allow manipulation of test results in end_tc without breaking backwards compatability (I hope) --- lib/common_test/src/ct_framework.erl | 22 +++++++++++----------- lib/common_test/src/ct_suite_callback.erl | 30 ++++++++++++++++++------------ 2 files changed, 29 insertions(+), 23 deletions(-) (limited to 'lib/common_test') diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl index f7c07a5374..dbf367e4d8 100644 --- a/lib/common_test/src/ct_framework.erl +++ b/lib/common_test/src/ct_framework.erl @@ -484,21 +484,27 @@ end_tc(Mod,Func,TCPid,Result,Args,Return) -> case get('$test_server_framework_test') of undefined -> - FinalResult = ct_suite_callback:end_tc( - Mod, FuncSpec, Args, Result, Return), + {FinalResult,FinalNotify} = + case ct_suite_callback:end_tc( + Mod, FuncSpec, Args, Result, Return) of + '$ct_no_change' -> + {FinalResult = ok,Result}; + FinalResult -> + {FinalResult,FinalResult} + end, % send sync notification so that event handlers may print % in the log file before it gets closed ct_event:sync_notify(#event{name=tc_done, node=node(), data={Mod,FuncSpec, - tag_scb(FinalResult)}}); + tag_scb(FinalNotify)}}); Fun -> % send sync notification so that event handlers may print % in the log file before it gets closed ct_event:sync_notify(#event{name=tc_done, node=node(), data={Mod,FuncSpec,tag(Result)}}), - FinalResult = Fun(end_tc, ok) + FinalResult = Fun(end_tc, Return) end, @@ -521,13 +527,7 @@ end_tc(Mod,Func,TCPid,Result,Args,Return) -> _ -> ok end, - case FinalResult of - Result -> - ok; - _Else -> - FinalResult - end. - + FinalResult. %% {error,Reason} | {skip,Reason} | {timetrap_timeout,TVal} | %% {testcase_aborted,Reason} | testcase_aborted_or_killed | diff --git a/lib/common_test/src/ct_suite_callback.erl b/lib/common_test/src/ct_suite_callback.erl index 06c7fc3833..4973ed685c 100644 --- a/lib/common_test/src/ct_suite_callback.erl +++ b/lib/common_test/src/ct_suite_callback.erl @@ -91,25 +91,25 @@ init_tc(_Mod, TC, Config) -> end_tc(ct_framework, _Func, _Args, Result, _Return) -> Result; -end_tc(Mod, init_per_suite, Config, _Result, Return) when is_list(Return) -> - call(fun call_generic/3, Return, [post_init_per_suite, Mod, Config]); -end_tc(Mod, init_per_suite, Config, Result, _Return) -> - call(fun call_generic/3, Result, [post_init_per_suite, Mod, Config]); +end_tc(Mod, init_per_suite, Config, Result, Return) -> + call(fun call_generic/3, Return, [post_init_per_suite, Mod, Config], + '$ct_no_change'); end_tc(Mod, end_per_suite, Config, Result, _Return) -> - call(fun call_generic/3, Result, [post_end_per_suite, Mod, Config]); + call(fun call_generic/3, Result, [post_end_per_suite, Mod, Config], + '$ct_no_change'); -end_tc(_Mod, {init_per_group, GroupName, _}, Config, _Result, Return) - when is_list(Return) -> - call(fun call_generic/3, Return, [post_init_per_group, GroupName, Config]); -end_tc(_Mod, {init_per_group, GroupName, _}, Config, Result, _Return) -> - call(fun call_generic/3, Result, [post_init_per_group, GroupName, Config]); +end_tc(_Mod, {init_per_group, GroupName, _}, Config, Result, Return) -> + call(fun call_generic/3, Return, [post_init_per_group, GroupName, Config], + '$ct_no_change'); end_tc(_Mod, {end_per_group, GroupName, _}, Config, Result, _Return) -> - call(fun call_generic/3, Result, [post_end_per_group, GroupName, Config]); + call(fun call_generic/3, Result, [post_end_per_group, GroupName, Config], + '$ct_no_change'); end_tc(_Mod, TC, Config, Result, _Return) -> - call(fun call_generic/3, Result, [post_end_per_testcase, TC, Config]). + call(fun call_generic/3, Result, [post_end_per_testcase, TC, Config], + '$ct_no_change'). on_tc_skip(How, {_Suite, Case, Reason}) -> call(fun call_cleanup/3, {How, Reason}, [on_tc_skip, Case]). @@ -146,6 +146,12 @@ call(Fun, Config, Meta) -> call([{CBId,Fun} || {CBId,_, _} <- CBs] ++ get_new_callbacks(Config, Fun), remove(?config_name,Config), Meta, CBs). +call(Fun, Config, Meta, NoChangeRet) when is_function(Fun) -> + case call(Fun,Config,Meta) of + Config -> NoChangeRet; + NewReturn -> NewReturn + end; + call([{CB, call_init, NextFun} | Rest], Config, Meta, CBs) -> try {Config, {NewId, _, {Mod,_State}} = NewCB} = call_init(CB, Config, Meta), -- cgit v1.2.3 From 96f93c7e2a157442f60bb1b16ab0ce76d8b9dbca Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Wed, 1 Dec 2010 11:13:29 +0100 Subject: Add state update tests for suite callbacks --- lib/common_test/test/ct_suite_callback_SUITE.erl | 43 ++++++++++- .../scb/tests/ct_scb_fail_one_skip_one_SUITE.erl | 64 +++++++++++++++++ .../scb/tests/state_update_scb.erl | 83 ++++++++++++++++++++++ 3 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scb_fail_one_skip_one_SUITE.erl create mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/state_update_scb.erl (limited to 'lib/common_test') diff --git a/lib/common_test/test/ct_suite_callback_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE.erl index 53087956b9..d60d24e237 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE.erl @@ -76,7 +76,8 @@ all(suite) -> minimal_and_maximal_scb, faulty_scb_undef, scope_per_suite_scb, scope_per_group_scb, scope_suite_scb, fail_pre_suite_scb, fail_post_suite_scb, skip_pre_suite_scb, - skip_post_suite_scb, recover_post_suite_scb, update_config_scb + skip_post_suite_scb, recover_post_suite_scb, update_config_scb, + state_update_scb ]). @@ -144,6 +145,10 @@ update_config_scb(Config) -> do_test(update_config_scb, "ct_update_config_SUITE.erl", [update_config_scb],Config). +state_update_scb(Config) -> + do_test(state_update_scb, "ct_scb_fail_one_skip_one_SUITE.erl", + [state_update_scb,state_update_scb],Config). + %%%----------------------------------------------------------------- %%% HELP FUNCTIONS %%%----------------------------------------------------------------- @@ -664,6 +669,40 @@ test_events(update_config_scb) -> {?eh,stop_logging,[]} ]; +test_events(state_update_scb) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,scb,{'_',init,[[]]}}, + {?eh,scb,{'_',init,[[]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{'_',init_per_suite}}, + + {?eh,tc_done,{'_',end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,scb,{'_',terminate,[contains( + [post_end_per_suite,pre_end_per_suite, + post_end_per_group,pre_end_per_group, + post_end_per_testcase,pre_init_per_testcase, + on_tc_skip,post_end_per_testcase, + pre_init_per_testcase,on_tc_fail, + post_end_per_testcase,pre_init_per_testcase, + post_init_per_group,pre_init_per_group, + post_init_per_suite,pre_init_per_suite, + init])]}}, + {?eh,scb,{'_',terminate,[contains( + [post_end_per_suite,pre_end_per_suite, + post_end_per_group,pre_end_per_group, + post_end_per_testcase,pre_init_per_testcase, + on_tc_skip,post_end_per_testcase, + pre_init_per_testcase,on_tc_fail, + post_end_per_testcase,pre_init_per_testcase, + post_init_per_group,pre_init_per_group, + post_init_per_suite,pre_init_per_suite, + init] + )]}}, + {?eh,stop_logging,[]} + ]; + test_events(ok) -> ok. @@ -682,6 +721,8 @@ contains([{Ele,Pos}|T] = L,[H|T2]) -> end; contains([Ele|T],[{Ele,_}|T2])-> contains(T,T2); +contains([Ele|T],[Ele|T2])-> + contains(T,T2); contains(List,[_|T]) -> contains(List,T); contains([],_) -> diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scb_fail_one_skip_one_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scb_fail_one_skip_one_SUITE.erl new file mode 100644 index 0000000000..dfeacfe8b1 --- /dev/null +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scb_fail_one_skip_one_SUITE.erl @@ -0,0 +1,64 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(ct_scb_fail_one_skip_one_SUITE). + +-suite_defaults([{timetrap, {minutes, 10}}]). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-include("ct.hrl"). + +%% Test server callback functions +init_per_suite(Config) -> + Config. + +end_per_suite(_Config) -> + ok. + +init_per_group(_Group,Config) -> + Config. + +end_per_group(_Group,_Config) -> + ok. + +init_per_testcase(test_case2, Config) -> + {skip,"skip it"}; +init_per_testcase(_TestCase, Config) -> + Config. + +end_per_testcase(_TestCase, _Config) -> + ok. + +groups() -> + [{group1,[],[test_case1,test_case2,test_case3]}]. + +all() -> + [{group,group1}]. + +%% Test cases starts here. +test_case1(Config) -> + ok = nok. + +test_case2(Config) -> + ok. + +test_case3(Config) -> + ok. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/state_update_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/state_update_scb.erl new file mode 100644 index 0000000000..1da0f7a6e4 --- /dev/null +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/state_update_scb.erl @@ -0,0 +1,83 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(state_update_scb). + + +-include_lib("common_test/src/ct_util.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + +%% Suite Callbacks +-compile(export_all). + +init(Opts) -> + {Id,State} = empty_scb:init(Opts), + {Id,[init|State]}. + +pre_init_per_suite(Suite, Config, State) -> + empty_scb:pre_init_per_suite(Suite,Config,State), + {Config, [pre_init_per_suite|State]}. + +post_init_per_suite(Suite,Config,Return,State) -> + empty_scb:post_init_per_suite(Suite,Config,Return,State), + {Config, [post_init_per_suite|State]}. + +pre_end_per_suite(Suite,Config,State) -> + empty_scb:pre_end_per_suite(Suite,Config,State), + {Config, [pre_end_per_suite|State]}. + +post_end_per_suite(Suite,Config,Return,State) -> + empty_scb:post_end_per_suite(Suite,Config,Return,State), + {Return, [post_end_per_suite|State]}. + +pre_init_per_group(Group,Config,State) -> + empty_scb:pre_init_per_group(Group,Config,State), + {Config, [pre_init_per_group|State]}. + +post_init_per_group(Group,Config,Return,State) -> + empty_scb:post_init_per_group(Group,Config,Return,State), + {Return, [post_init_per_group|State]}. + +pre_end_per_group(Group,Config,State) -> + empty_scb:pre_end_per_group(Group,Config,State), + {Config, [pre_end_per_group|State]}. + +post_end_per_group(Group,Config,Return,State) -> + empty_scb:post_end_per_group(Group,Config,Return,State), + {Return, [post_end_per_group|State]}. + +pre_init_per_testcase(TC,Config,State) -> + empty_scb:pre_init_per_testcase(TC,Config,State), + {Config, [pre_init_per_testcase|State]}. + +post_end_per_testcase(TC,Config,Return,State) -> + empty_scb:post_end_per_testcase(TC,Config,Return,State), + {Return, [post_end_per_testcase|State]}. + +on_tc_fail(TC, Reason, State) -> + empty_scb:on_tc_fail(TC,Reason,State), + [on_tc_fail|State]. + +on_tc_skip(TC, Reason, State) -> + empty_scb:on_tc_skip(TC,Reason,State), + [on_tc_skip|State]. + +terminate(State) -> + empty_scb:terminate(State). -- cgit v1.2.3 From 963d9f96452243a31cdcaa793a4bbe221a30a6f5 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Wed, 1 Dec 2010 15:44:17 +0100 Subject: Add locking mechanism for scb state when using parallel groups --- lib/common_test/src/Makefile | 3 +- lib/common_test/src/ct_suite_callback.erl | 52 ++++++-- lib/common_test/src/ct_suite_callback_lock.erl | 131 +++++++++++++++++++++ lib/common_test/test/ct_suite_callback_SUITE.erl | 30 +++-- .../scb/tests/ct_scb_fail_one_skip_one_SUITE.erl | 2 +- 5 files changed, 200 insertions(+), 18 deletions(-) create mode 100644 lib/common_test/src/ct_suite_callback_lock.erl (limited to 'lib/common_test') diff --git a/lib/common_test/src/Makefile b/lib/common_test/src/Makefile index 14a0a27051..abf7816a91 100644 --- a/lib/common_test/src/Makefile +++ b/lib/common_test/src/Makefile @@ -68,7 +68,8 @@ MODULES= \ ct_config_plain \ ct_config_xml \ ct_slave \ - ct_suite_callback + ct_suite_callback\ + ct_suite_callback_lock TARGET_MODULES= $(MODULES:%=$(EBIN)/%) diff --git a/lib/common_test/src/ct_suite_callback.erl b/lib/common_test/src/ct_suite_callback.erl index 4973ed685c..46bc250106 100644 --- a/lib/common_test/src/ct_suite_callback.erl +++ b/lib/common_test/src/ct_suite_callback.erl @@ -34,6 +34,8 @@ -type proplist() :: [{atom(),term()}]. -define(config_name, suite_callbacks). +-define(LOCK_STATE_TIMEOUT, 500). +-define(LOCK_NAME, '$ct_suite_callback_lock'). %% ------------------------------------------------------------------------- %% API Functions @@ -69,7 +71,8 @@ init_tc(Mod, init_per_suite, Config) -> call(fun call_generic/3, Config, [pre_init_per_suite, Mod]); init_tc(Mod, end_per_suite, Config) -> call(fun call_generic/3, Config, [pre_end_per_suite, Mod]); -init_tc(_Mod, {init_per_group, GroupName, _}, Config) -> +init_tc(Mod, {init_per_group, GroupName, Opts}, Config) -> + maybe_start_locker(Mod, GroupName, Opts), call(fun call_generic/3, Config, [pre_init_per_group, GroupName]); init_tc(_Mod, {end_per_group, GroupName, _}, Config) -> call(fun call_generic/3, Config, [pre_end_per_group, GroupName]); @@ -91,7 +94,7 @@ init_tc(_Mod, TC, Config) -> end_tc(ct_framework, _Func, _Args, Result, _Return) -> Result; -end_tc(Mod, init_per_suite, Config, Result, Return) -> +end_tc(Mod, init_per_suite, Config, _Result, Return) -> call(fun call_generic/3, Return, [post_init_per_suite, Mod, Config], '$ct_no_change'); @@ -99,13 +102,15 @@ end_tc(Mod, end_per_suite, Config, Result, _Return) -> call(fun call_generic/3, Result, [post_end_per_suite, Mod, Config], '$ct_no_change'); -end_tc(_Mod, {init_per_group, GroupName, _}, Config, Result, Return) -> +end_tc(_Mod, {init_per_group, GroupName, _}, Config, _Result, Return) -> call(fun call_generic/3, Return, [post_init_per_group, GroupName, Config], '$ct_no_change'); -end_tc(_Mod, {end_per_group, GroupName, _}, Config, Result, _Return) -> - call(fun call_generic/3, Result, [post_end_per_group, GroupName, Config], - '$ct_no_change'); +end_tc(Mod, {end_per_group, GroupName, Opts}, Config, Result, _Return) -> + Res = call(fun call_generic/3, Result, + [post_end_per_group, GroupName, Config], '$ct_no_change'), + maybe_stop_locker(Mod, GroupName,Opts), + Res; end_tc(_Mod, TC, Config, Result, _Return) -> call(fun call_generic/3, Result, [post_end_per_testcase, TC, Config], @@ -142,9 +147,13 @@ call_generic({Mod, State}, Value, [Function | Args]) -> %% Generic call function call(Fun, Config, Meta) -> + maybe_lock(), CBs = get_callbacks(), - call([{CBId,Fun} || {CBId,_, _} <- CBs] ++ get_new_callbacks(Config, Fun), - remove(?config_name,Config), Meta, CBs). + Res = call([{CBId,Fun} || {CBId,_, _} <- CBs] ++ + get_new_callbacks(Config, Fun), + remove(?config_name,Config), Meta, CBs), + maybe_unlock(), + Res. call(Fun, Config, Meta, NoChangeRet) when is_function(Fun) -> case call(Fun,Config,Meta) of @@ -255,3 +264,30 @@ catch_apply(M,F,A, Default) -> [M,F,length(A)]))}) end end. + + +%% We need to lock around the state for parallel groups only. This is because +%% we will get several processes reading and writing the state for a single +%% scb at the same time. +maybe_start_locker(Mod,GroupName,Opts) -> + case lists:member(parallel,Opts) of + true -> + {ok, _Pid} = ct_suite_callback_lock:start({Mod,GroupName}); + false -> + ok + end. + +maybe_stop_locker(Mod,GroupName,Opts) -> + case lists:member(parallel,Opts) of + true -> + stopped = ct_suite_callback_lock:stop({Mod,GroupName}); + false -> + ok + end. + + +maybe_lock() -> + locked = ct_suite_callback_lock:request(). + +maybe_unlock() -> + unlocked = ct_suite_callback_lock:release(). diff --git a/lib/common_test/src/ct_suite_callback_lock.erl b/lib/common_test/src/ct_suite_callback_lock.erl new file mode 100644 index 0000000000..84dafd1e42 --- /dev/null +++ b/lib/common_test/src/ct_suite_callback_lock.erl @@ -0,0 +1,131 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-2010. 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% +%% + +%%% @doc Common Test Framework test execution control module. +%%% +%%%

This module is a proxy for calling and handling locks in suite callbacks.

+ +-module(ct_suite_callback_lock). + +-behaviour(gen_server). + +%% API +-export([start/1, stop/1, request/0, release/0]). + +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, + terminate/2, code_change/3]). + +-define(SERVER, ?MODULE). + +-record(state, { id, locked = false, requests = [] }). + +%%%=================================================================== +%%% API +%%%=================================================================== + +%% @doc Starts the server +start(Id) -> + case gen_server:start({local, ?SERVER}, ?MODULE, Id, []) of + {error,{already_started, Pid}} -> + {ok,Pid}; + Else -> + Else + end. + +stop(Id) -> + try + gen_server:call(?SERVER, {stop,Id}) + catch exit:{noproc,_} -> + stopped + end. + +request() -> + try + gen_server:call(?SERVER,{request,self()},infinity) + catch exit:{noproc,_} -> + locked + end. + +release() -> + try + gen_server:call(?SERVER,{release,self()}) + catch exit:{noproc,_} -> + unlocked + end. + +%%%=================================================================== +%%% gen_server callbacks +%%%=================================================================== + +%% @doc Initiates the server +init(Id) -> + {ok, #state{ id = Id }}. + +%% @doc Handling call messages +handle_call({stop,Id}, _From, #state{ id = Id, requests = Reqs } = State) -> + [gen_server:reply(Req, locker_stopped) || {Req,_ReqId} <- Reqs], + {stop, normal, stopped, State}; +handle_call({stop,_Id}, _From, State) -> + {reply, stopped, State}; +handle_call({request, Pid}, _From, #state{ locked = false, + requests = [] } = State) -> + Ref = monitor(process, Pid), + {reply, locked, State#state{ locked = {true, Pid, Ref}} }; +handle_call({request, Pid}, From, #state{ requests = Reqs } = State) -> + {noreply, State#state{ requests = Reqs ++ [{From,Pid}] }}; +handle_call({release, Pid}, _From, #state{ locked = {true, Pid, Ref}, + requests = []} = State) -> + demonitor(Ref,[flush]), + {reply, unlocked, State#state{ locked = false }}; +handle_call({release, Pid}, _From, + #state{ locked = {true, Pid, Ref}, + requests = [{NextFrom,NextPid}|Rest]} = State) -> + demonitor(Ref,[flush]), + gen_server:reply(NextFrom,locked), + NextRef = monitor(process, NextPid), + {reply,unlocked,State#state{ locked = {true, NextPid, NextRef}, + requests = Rest } }; +handle_call({release, _Pid}, _From, State) -> + {reply, not_locked, State}. + +%% @doc Handling cast messages +handle_cast(_Msg, State) -> + {noreply, State}. + +%% @doc Handling all non call/cast messages +handle_info({'DOWN',Ref,process,Pid,_}, + #state{ locked = {true, Pid, Ref}, + requests = [{NextFrom,NextPid}|Rest] } = State) -> + gen_server:reply(NextFrom, locked), + NextRef = monitor(process, NextPid), + {noreply,State#state{ locked = {true, NextPid, NextRef}, + requests = Rest } }. + +%% @doc This function is called by a gen_server when it is about to terminate. +terminate(_Reason, _State) -> + ok. + +%% @doc Convert process state when code is changed +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +%% ------------------------------------------------------------------------- +%% Internal Functions +%% ------------------------------------------------------------------------- diff --git a/lib/common_test/test/ct_suite_callback_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE.erl index d60d24e237..e6e4d5706b 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE.erl @@ -682,20 +682,24 @@ test_events(state_update_scb) -> {?eh,scb,{'_',terminate,[contains( [post_end_per_suite,pre_end_per_suite, post_end_per_group,pre_end_per_group, - post_end_per_testcase,pre_init_per_testcase, - on_tc_skip,post_end_per_testcase, - pre_init_per_testcase,on_tc_fail, - post_end_per_testcase,pre_init_per_testcase, + {not_in_order, + [post_end_per_testcase,pre_init_per_testcase, + on_tc_skip,post_end_per_testcase, + pre_init_per_testcase,on_tc_fail, + post_end_per_testcase,pre_init_per_testcase] + }, post_init_per_group,pre_init_per_group, post_init_per_suite,pre_init_per_suite, init])]}}, {?eh,scb,{'_',terminate,[contains( [post_end_per_suite,pre_end_per_suite, post_end_per_group,pre_end_per_group, - post_end_per_testcase,pre_init_per_testcase, - on_tc_skip,post_end_per_testcase, - pre_init_per_testcase,on_tc_fail, - post_end_per_testcase,pre_init_per_testcase, + {not_in_order, + [post_end_per_testcase,pre_init_per_testcase, + on_tc_skip,post_end_per_testcase, + pre_init_per_testcase,on_tc_fail, + post_end_per_testcase,pre_init_per_testcase] + }, post_init_per_group,pre_init_per_group, post_init_per_suite,pre_init_per_suite, init] @@ -712,6 +716,10 @@ contains(List) -> fun(Proplist) when is_list(Proplist) -> contains(List,Proplist) end. + +contains([{not_in_order,List}|T],Rest) -> + contains_parallel(List,Rest), + contains(T,Rest); contains([{Ele,Pos}|T] = L,[H|T2]) -> case element(Pos,H) of Ele -> @@ -728,6 +736,12 @@ contains(List,[_|T]) -> contains([],_) -> match. +contains_parallel([Key | T], Elems) -> + contains([Key],Elems), + contains_parallel(T,Elems); +contains_parallel([],Elems) -> + match. + not_contains(List) -> fun(Proplist) when is_list(Proplist) -> [] = [Ele || {Ele,_} <- Proplist, diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scb_fail_one_skip_one_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scb_fail_one_skip_one_SUITE.erl index dfeacfe8b1..593bd4a534 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scb_fail_one_skip_one_SUITE.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scb_fail_one_skip_one_SUITE.erl @@ -48,7 +48,7 @@ end_per_testcase(_TestCase, _Config) -> ok. groups() -> - [{group1,[],[test_case1,test_case2,test_case3]}]. + [{group1,[parallel],[{group2,[parallel],[test_case1,test_case2,test_case3]}]}]. all() -> [{group,group1}]. -- cgit v1.2.3 From 6288b704f2ee0699407f645536ad69e0dd07756d Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 2 Dec 2010 15:27:10 +0100 Subject: Started work on documenting suite callbacks, this is a partial commit --- lib/common_test/doc/src/Makefile | 2 +- lib/common_test/doc/src/ct_suite_callbacks.xml | 94 ++++++++++++++++++++++++++ lib/common_test/doc/src/ref_man.xml | 1 + 3 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 lib/common_test/doc/src/ct_suite_callbacks.xml (limited to 'lib/common_test') diff --git a/lib/common_test/doc/src/Makefile b/lib/common_test/doc/src/Makefile index 1a767a8197..be066143e0 100644 --- a/lib/common_test/doc/src/Makefile +++ b/lib/common_test/doc/src/Makefile @@ -52,7 +52,7 @@ CT_XML_FILES = $(CT_MODULES:=.xml) XML_APPLICATION_FILES = ref_man.xml XML_REF1_FILES = ct_run.xml -XML_REF3_FILES = $(CT_XML_FILES) +XML_REF3_FILES = $(CT_XML_FILES) ct_suite_callbacks.xml XML_REF6_FILES = common_test_app.xml XML_PART_FILES = part.xml diff --git a/lib/common_test/doc/src/ct_suite_callbacks.xml b/lib/common_test/doc/src/ct_suite_callbacks.xml new file mode 100644 index 0000000000..28a496a47b --- /dev/null +++ b/lib/common_test/doc/src/ct_suite_callbacks.xml @@ -0,0 +1,94 @@ + + + + + +
+ + 20102010 + Ericsson AB. 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. + + + + Suite Callbacks + Lukas Larsson + Lukas Larsson + + + + 2010-12-02 + PA1 + suite_callback.sgml +
+ ct_suite_callback + A callback interface on top of common test + + + +

The Suite Callback framework allows extensions of the default + behaviour of Common Test by means of callbacks before and after all + test suite calls.

+ +

In brief, Suite Callbacks allows you to:

+ + + Manipulating the runtime config before each suite configuration calls + Manipulating the return of all suite configuration calls + + +

The following sections describe the mandatory and optional suite callback + functions Common Test will call during test execution. For more details + see Suite Callbacks in the User's Guide.

+ +
+ +
+ CALLBACK FUNCTIONS +

The following functions define the callback interface + for a suite callback.

+
+ + + + Module:init(Opts) -> {Id,State} + asdas + + Opts = term() + Id = term() + GroupName = term() + + + +

MANDATORY

+ +

+ +

If {skip,Reason} is returned, all test cases + in the module will be skipped, and the Reason will + be printed on the HTML result page.

+ +

For details on groups, see + Test case + groups in the User's Guide.

+ +
+
+ + +
+ +
+ + diff --git a/lib/common_test/doc/src/ref_man.xml b/lib/common_test/doc/src/ref_man.xml index d5985bb021..100c0fe5d7 100644 --- a/lib/common_test/doc/src/ref_man.xml +++ b/lib/common_test/doc/src/ref_man.xml @@ -76,6 +76,7 @@ + -- cgit v1.2.3 From 8b33f2edabbfd684e619238bbfaa10cc16e2a0a7 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Tue, 7 Dec 2010 19:14:03 +0100 Subject: Fix bug which caused scb to be added too much when initiated in the suite info function --- lib/common_test/src/ct_framework.erl | 4 +++- lib/common_test/src/ct_suite_callback.erl | 8 +++++++- 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'lib/common_test') diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl index dbf367e4d8..d05c30f5e1 100644 --- a/lib/common_test/src/ct_framework.erl +++ b/lib/common_test/src/ct_framework.erl @@ -251,7 +251,9 @@ add_defaults(Mod,Func,FuncInfo,DoInit) -> (_) -> false end, SuiteInfo) of true -> - SuiteInfo1 = merge_with_suite_defaults(Mod,SuiteInfo), + SuiteInfoNoSCB = + lists:keydelete(suite_callbacks,1,SuiteInfo), + SuiteInfo1 = merge_with_suite_defaults(Mod,SuiteInfoNoSCB), case add_defaults1(Mod,Func,FuncInfo,SuiteInfo1,DoInit) of Error = {error,_} -> {SuiteInfo1,Error}; MergedInfo -> {SuiteInfo1,MergedInfo} diff --git a/lib/common_test/src/ct_suite_callback.erl b/lib/common_test/src/ct_suite_callback.erl index 46bc250106..4f6bf9942e 100644 --- a/lib/common_test/src/ct_suite_callback.erl +++ b/lib/common_test/src/ct_suite_callback.erl @@ -68,7 +68,13 @@ terminate(Callbacks) -> init_tc(ct_framework, _Func, Args) -> Args; init_tc(Mod, init_per_suite, Config) -> - call(fun call_generic/3, Config, [pre_init_per_suite, Mod]); + Info = case catch proplists:get_value(suite_callbacks, Mod:suite()) of + List when is_list(List) -> + [{suite_callbacks,List}]; + _Else -> + [] + end, + call(fun call_generic/3, Config ++ Info, [pre_init_per_suite, Mod]); init_tc(Mod, end_per_suite, Config) -> call(fun call_generic/3, Config, [pre_end_per_suite, Mod]); init_tc(Mod, {init_per_group, GroupName, Opts}, Config) -> -- cgit v1.2.3 From 8ed5c47ca047405b2c00a979a8567412e5283322 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Wed, 8 Dec 2010 17:16:49 +0100 Subject: Add so that failures in SCB:init/1 causes the entire scb scope to fail --- lib/common_test/src/ct_run.erl | 2 + lib/common_test/src/ct_suite_callback.erl | 9 +-- lib/common_test/src/ct_util.erl | 10 +++- lib/common_test/test/ct_suite_callback_SUITE.erl | 76 +++++++++++++++++++----- 4 files changed, 76 insertions(+), 21 deletions(-) (limited to 'lib/common_test') diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl index 78782d346a..7d6a2f54d9 100644 --- a/lib/common_test/src/ct_run.erl +++ b/lib/common_test/src/ct_run.erl @@ -2203,6 +2203,8 @@ opts2args(EnvStartOpts) -> end, EHs), [_LastAnd|StrsR] = lists:reverse(lists:flatten(Strs)), [{event_handler_init,lists:reverse(StrsR)}]; + ({suite_callbacks,[]}) -> + []; ({Opt,As=[A|_]}) when is_atom(A) -> [{Opt,[atom_to_list(Atom) || Atom <- As]}]; ({Opt,Strs=[S|_]}) when is_list(S) -> diff --git a/lib/common_test/src/ct_suite_callback.erl b/lib/common_test/src/ct_suite_callback.erl index 4f6bf9942e..8372303737 100644 --- a/lib/common_test/src/ct_suite_callback.erl +++ b/lib/common_test/src/ct_suite_callback.erl @@ -46,8 +46,7 @@ {error, Reason :: term()}. init(Opts) -> call([{CB, call_init, undefined} || CB <- get_new_callbacks(Opts)], - ct_suite_callback_init_dummy, init, []), - ok. + ok, init, []). %% @doc Called after all suites are done. @@ -181,9 +180,11 @@ call([{CB, call_init, NextFun} | Rest], Config, Meta, CBs) -> [Mod,NewId]), call(NewRest, Config, Meta, NewCBs) catch Error:Reason -> + Trace = erlang:get_stacktrace(), ct_logs:log("Suite Callback","Failed to start a SCB: ~p:~p", - [Error,{Reason,erlang:get_stacktrace()}]), - call(Rest, Config, Meta, CBs) + [Error,{Reason,Trace}]), + call([], {fail,"Failed to start SCB" + ", see the CT Log for details"}, Meta, CBs) end; call([{CBId, Fun} | Rest], Config, Meta, CBs) -> try diff --git a/lib/common_test/src/ct_util.erl b/lib/common_test/src/ct_util.erl index fddeff881e..2f5a90a543 100644 --- a/lib/common_test/src/ct_util.erl +++ b/lib/common_test/src/ct_util.erl @@ -163,8 +163,14 @@ do_start(Parent,Mode,LogDir) -> {StartTime,TestLogDir} = ct_logs:init(Mode), %% Initiate suite_callbacks - ok = ct_suite_callback:init(Opts), - + case catch ct_suite_callback:init(Opts) of + ok -> + ok; + {_,SCBReason} -> + ct_logs:tc_print('Suite Callback',SCBReason,[]), + Parent ! {self(), SCBReason}, + self() ! {{stop,normal},{self(),make_ref()}} + end, ct_event:notify(#event{name=test_start, node=node(), diff --git a/lib/common_test/test/ct_suite_callback_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE.erl index e6e4d5706b..8d620be7ba 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE.erl @@ -70,15 +70,18 @@ all() -> all(suite). all(suite) -> - lists:reverse( + %% lists:reverse( [ - one_scb, two_scb, faulty_scb_no_init, minimal_scb, + one_scb, two_scb, faulty_scb_no_init, faulty_scb_exit_in_init, + faulty_scb_exit_in_init_scope_suite, minimal_scb, minimal_and_maximal_scb, faulty_scb_undef, scope_per_suite_scb, scope_per_group_scb, scope_suite_scb, fail_pre_suite_scb, fail_post_suite_scb, skip_pre_suite_scb, skip_post_suite_scb, recover_post_suite_scb, update_config_scb, state_update_scb - ]). + ] + %%) + . %%-------------------------------------------------------------------- @@ -96,7 +99,8 @@ two_scb(Config) when is_list(Config) -> faulty_scb_no_init(Config) when is_list(Config) -> do_test(faulty_scb_no_init, "ct_scb_empty_SUITE.erl",[askjhdkljashdkaj], - Config). + Config,{error,"Failed to start SCB, see the " + "CT Log for details"}). minimal_scb(Config) when is_list(Config) -> do_test(minimal_scb, "ct_scb_empty_SUITE.erl",[minimal_scb],Config). @@ -109,6 +113,17 @@ faulty_scb_undef(Config) when is_list(Config) -> do_test(faulty_scb_undef, "ct_scb_empty_SUITE.erl", [undef_scb],Config). +faulty_scb_exit_in_init_scope_suite(Config) when is_list(Config) -> + do_test(faulty_scb_exit_in_init_scope_suite, + "ct_exit_in_init_scope_suite_scb_SUITE.erl", + [],Config). + +faulty_scb_exit_in_init(Config) when is_list(Config) -> + do_test(faulty_scb_exit_in_init, "ct_scb_empty_SUITE.erl", + [crash_init_scb], Config, + {error,"Failed to start SCB, see the " + "CT Log for details"}). + scope_per_suite_scb(Config) when is_list(Config) -> do_test(scope_per_suite_scb, "ct_scope_per_suite_scb_SUITE.erl", [],Config). @@ -153,21 +168,28 @@ state_update_scb(Config) -> %%% HELP FUNCTIONS %%%----------------------------------------------------------------- -do_test(Tag, SuiteWildCard, SCBs, Config) -> +do_test(Tag, SWC, SCBs, Config) -> + do_test(Tag, SWC, SCBs, Config, ok). +do_test(Tag, SWC, SCBs, Config, {error,_} = Res) -> + do_test(Tag, SWC, SCBs, Config, Res, 1); +do_test(Tag, SWC, SCBs, Config, Res) -> + do_test(Tag, SWC, SCBs, Config, Res, 2). + +do_test(Tag, SuiteWildCard, SCBs, Config, Res, EC) -> DataDir = ?config(data_dir, Config), Suites = filelib:wildcard( filename:join([DataDir,"scb/tests",SuiteWildCard])), {Opts,ERPid} = setup([{suite,Suites}, {suite_callbacks,SCBs},{label,Tag}], Config), - ok = ct_test_support:run(Opts, Config), + Res = ct_test_support:run(Opts, Config), Events = ct_test_support:get_events(ERPid, Config), ct_test_support:log_events(Tag, reformat(Events, ?eh), ?config(priv_dir, Config)), - TestEvents = events_to_check(Tag), + TestEvents = events_to_check(Tag, EC), ok = ct_test_support:verify_events(TestEvents, Events, Config). setup(Test, Config) -> @@ -258,14 +280,6 @@ test_events(faulty_scb_no_init) -> [ {?eh,start_logging,{'DEF','RUNDIR'}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, - {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, - {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite,ok}}, - - {?eh,tc_start,{ct_scb_empty_SUITE,test_case}}, - {?eh,tc_done,{ct_scb_empty_SUITE,test_case,ok}}, - - {?eh,tc_start,{ct_scb_empty_SUITE,end_per_suite}}, - {?eh,tc_done,{ct_scb_empty_SUITE,end_per_suite,ok}}, {?eh,test_done,{'DEF','STOP_TIME'}}, {?eh,stop_logging,[]} ]; @@ -337,6 +351,38 @@ test_events(faulty_scb_undef) -> {?eh,stop_logging,[]} ]; +test_events(faulty_scb_exit_in_init_scope_suite) -> + [{?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{'_',init_per_suite}}, + {?eh,scb,{empty_scb,init,[[]]}}, + {?eh,tc_done, + {ct_exit_in_init_scope_suite_scb_SUITE,init_per_suite, + {failed, + {error, + "Failed to start SCB, see the CT Log for details"}}}}, + {?eh,tc_auto_skip, + {ct_exit_in_init_scope_suite_scb_SUITE,test_case, + {failed, + {ct_exit_in_init_scope_suite_scb_SUITE,init_per_suite, + {failed, + "Failed to start SCB, see the CT Log for details"}}}}}, + {?eh,tc_auto_skip, + {ct_exit_in_init_scope_suite_scb_SUITE,end_per_suite, + {failed, + {ct_exit_in_init_scope_suite_scb_SUITE,init_per_suite, + {failed, + "Failed to start SCB, see the CT Log for details"}}}}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]}]; + +test_events(faulty_scb_exit_in_init) -> + [{?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,scb,{empty_scb,init,[[]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]}]; + test_events(scope_per_suite_scb) -> [ {?eh,start_logging,{'DEF','RUNDIR'}}, -- cgit v1.2.3 From 7f25a132488707b167d1d5b3c59ba58b0600e848 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 9 Dec 2010 11:48:15 +0100 Subject: Added tests for starting SCB's with arguments and fixed a bug with how SCB's are parsed from the command line --- lib/common_test/src/ct_run.erl | 45 ++++++- lib/common_test/test/ct_suite_callback_SUITE.erl | 147 +++++++++++++++++++-- .../tests/ct_scope_per_group_state_scb_SUITE.erl | 56 ++++++++ .../tests/ct_scope_per_suite_state_scb_SUITE.erl | 47 +++++++ .../scb/tests/ct_scope_suite_state_scb_SUITE.erl | 50 +++++++ 5 files changed, 330 insertions(+), 15 deletions(-) create mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_group_state_scb_SUITE.erl create mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_suite_state_scb_SUITE.erl create mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_suite_state_scb_SUITE.erl (limited to 'lib/common_test') diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl index 7d6a2f54d9..a12d4d6f18 100644 --- a/lib/common_test/src/ct_run.erl +++ b/lib/common_test/src/ct_run.erl @@ -172,9 +172,7 @@ script_start1(Parent, Args) -> ([]) -> true end, false, Args), EvHandlers = event_handler_args2opts(Args), - SuiteCBs = get_start_opt(suite_callbacks, - fun(CBs) -> [list_to_atom(CB) || CB <- CBs] end, - [], Args), + SuiteCBs = suite_callbacks_args2opts(Args), %% check flags and set corresponding application env variables @@ -2076,6 +2074,33 @@ get_start_opt(Key, IfExists, IfNotExists, Args) -> IfNotExists end. +suite_callbacks_args2opts(Args) -> + suite_callbacks_args2opts( + proplists:get_value(suite_callbacks, Args, []),[]). + +suite_callbacks_args2opts([SCB,Arg,"and"| Rest],Acc) -> + suite_callbacks_args2opts(Rest,[{list_to_atom(SCB), + parse_scb_args(Arg)}|Acc]); +suite_callbacks_args2opts([SCB], Acc) -> + suite_callbacks_args2opts([SCB,"and"],Acc); +suite_callbacks_args2opts([SCB, "and" | Rest], Acc) -> + suite_callbacks_args2opts(Rest,[list_to_atom(SCB)|Acc]); +suite_callbacks_args2opts([SCB, Args], Acc) -> + suite_callbacks_args2opts([SCB, Args, "and"],Acc); +suite_callbacks_args2opts([],Acc) -> + lists:reverse(Acc). + +parse_scb_args(String) -> + try + true = io_lib:printable_list(String), + {ok,Toks,_} = erl_scan:string(String++"."), + {ok, Args} = erl_parse:parse_term(Toks), + Args + catch _:_ -> + String + end. + + event_handler_args2opts(Args) -> case proplists:get_value(event_handler, Args) of undefined -> @@ -2205,6 +2230,20 @@ opts2args(EnvStartOpts) -> [{event_handler_init,lists:reverse(StrsR)}]; ({suite_callbacks,[]}) -> []; + ({suite_callbacks,SCBs}) when is_list(SCBs) -> + io:format(user,"suite_callbacks: ~p",[SCBs]), + Strs = lists:flatmap( + fun({SCB,Arg}) -> + [atom_to_list(SCB), + lists:flatten( + io_lib:format("~p",[Arg])), + "and"]; + (SCB) when is_atom(SCB) -> + [atom_to_list(SCB),"and"] + end,SCBs), + [_LastAnd|StrsR] = lists:reverse(Strs), + io:format(user,"return: ~p",[lists:reverse(StrsR)]), + [{suite_callbacks,lists:reverse(StrsR)}]; ({Opt,As=[A|_]}) when is_atom(A) -> [{Opt,[atom_to_list(Atom) || Atom <- As]}]; ({Opt,Strs=[S|_]}) when is_list(S) -> diff --git a/lib/common_test/test/ct_suite_callback_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE.erl index 8d620be7ba..88ce5e0e51 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE.erl @@ -70,17 +70,19 @@ all() -> all(suite). all(suite) -> - %% lists:reverse( + lists:reverse( [ one_scb, two_scb, faulty_scb_no_init, faulty_scb_exit_in_init, faulty_scb_exit_in_init_scope_suite, minimal_scb, - minimal_and_maximal_scb, faulty_scb_undef, scope_per_suite_scb, - scope_per_group_scb, scope_suite_scb, + minimal_and_maximal_scb, faulty_scb_undef, + scope_per_suite_scb, scope_per_group_scb, scope_suite_scb, + scope_per_suite_state_scb, scope_per_group_state_scb, + scope_suite_state_scb, fail_pre_suite_scb, fail_post_suite_scb, skip_pre_suite_scb, skip_post_suite_scb, recover_post_suite_scb, update_config_scb, - state_update_scb + state_update_scb, options_scb ] - %%) + ) . @@ -136,34 +138,51 @@ scope_per_group_scb(Config) when is_list(Config) -> do_test(scope_per_group_scb, "ct_scope_per_group_scb_SUITE.erl", [],Config). -fail_pre_suite_scb(Config) -> +scope_per_suite_state_scb(Config) when is_list(Config) -> + do_test(scope_per_suite_state_scb, "ct_scope_per_suite_state_scb_SUITE.erl", + [],Config). + +scope_suite_state_scb(Config) when is_list(Config) -> + do_test(scope_suite_state_scb, "ct_scope_suite_state_scb_SUITE.erl", + [],Config). + +scope_per_group_state_scb(Config) when is_list(Config) -> + do_test(scope_per_group_state_scb, "ct_scope_per_group_state_scb_SUITE.erl", + [],Config). + +fail_pre_suite_scb(Config) when is_list(Config) -> do_test(fail_pre_suite_scb, "ct_scb_empty_SUITE.erl", [fail_pre_suite_scb],Config). -fail_post_suite_scb(Config) -> +fail_post_suite_scb(Config) when is_list(Config) -> do_test(fail_post_suite_scb, "ct_scb_empty_SUITE.erl", [fail_post_suite_scb],Config). -skip_pre_suite_scb(Config) -> +skip_pre_suite_scb(Config) when is_list(Config) -> do_test(skip_pre_suite_scb, "ct_scb_empty_SUITE.erl", [skip_pre_suite_scb],Config). -skip_post_suite_scb(Config) -> +skip_post_suite_scb(Config) when is_list(Config) -> do_test(skip_post_suite_scb, "ct_scb_empty_SUITE.erl", [skip_post_suite_scb],Config). -recover_post_suite_scb(Config) -> +recover_post_suite_scb(Config) when is_list(Config) -> do_test(recover_post_suite_scb, "ct_scb_fail_per_suite_SUITE.erl", [recover_post_suite_scb],Config). -update_config_scb(Config) -> +update_config_scb(Config) when is_list(Config) -> do_test(update_config_scb, "ct_update_config_SUITE.erl", [update_config_scb],Config). -state_update_scb(Config) -> +state_update_scb(Config) when is_list(Config) -> do_test(state_update_scb, "ct_scb_fail_one_skip_one_SUITE.erl", [state_update_scb,state_update_scb],Config). +options_scb(Config) when is_list(Config) -> + do_test(options_scb, "ct_scb_empty_SUITE.erl", + [{empty_scb,[test]}],Config). + + %%%----------------------------------------------------------------- %%% HELP FUNCTIONS %%%----------------------------------------------------------------- @@ -460,6 +479,83 @@ test_events(scope_per_group_scb) -> {?eh,stop_logging,[]} ]; +test_events(scope_per_suite_state_scb) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_scope_per_suite_state_scb_SUITE,init_per_suite}}, + {?eh,scb,{'_',init,[[test]]}}, + {?eh,scb,{'_',post_init_per_suite,[ct_scope_per_suite_state_scb_SUITE,'$proplist','$proplist',[test]]}}, + {?eh,tc_done,{ct_scope_per_suite_state_scb_SUITE,init_per_suite,ok}}, + + {?eh,tc_start,{ct_scope_per_suite_state_scb_SUITE,test_case}}, + {?eh,scb,{'_',pre_init_per_testcase,[test_case,'$proplist',[test]]}}, + {?eh,scb,{'_',post_end_per_testcase,[test_case,'$proplist',ok,[test]]}}, + {?eh,tc_done,{ct_scope_per_suite_state_scb_SUITE,test_case,ok}}, + + {?eh,tc_start,{ct_scope_per_suite_state_scb_SUITE,end_per_suite}}, + {?eh,scb,{'_',pre_end_per_suite, + [ct_scope_per_suite_state_scb_SUITE,'$proplist',[test]]}}, + {?eh,scb,{'_',post_end_per_suite,[ct_scope_per_suite_state_scb_SUITE,'$proplist','_',[test]]}}, + {?eh,scb,{'_',terminate,[[test]]}}, + {?eh,tc_done,{ct_scope_per_suite_state_scb_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]; + +test_events(scope_suite_state_scb) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_scope_suite_state_scb_SUITE,init_per_suite}}, + {?eh,scb,{'_',init,[[test]]}}, + {?eh,scb,{'_',pre_init_per_suite,[ct_scope_suite_state_scb_SUITE,'$proplist',[test]]}}, + {?eh,scb,{'_',post_init_per_suite,[ct_scope_suite_state_scb_SUITE,'$proplist','$proplist',[test]]}}, + {?eh,tc_done,{ct_scope_suite_state_scb_SUITE,init_per_suite,ok}}, + + {?eh,tc_start,{ct_scope_suite_state_scb_SUITE,test_case}}, + {?eh,scb,{'_',pre_init_per_testcase,[test_case,'$proplist',[test]]}}, + {?eh,scb,{'_',post_end_per_testcase,[test_case,'$proplist',ok,[test]]}}, + {?eh,tc_done,{ct_scope_suite_state_scb_SUITE,test_case,ok}}, + + {?eh,tc_start,{ct_scope_suite_state_scb_SUITE,end_per_suite}}, + {?eh,scb,{'_',pre_end_per_suite,[ct_scope_suite_state_scb_SUITE,'$proplist',[test]]}}, + {?eh,scb,{'_',post_end_per_suite,[ct_scope_suite_state_scb_SUITE,'$proplist','_',[test]]}}, + {?eh,scb,{'_',terminate,[[test]]}}, + {?eh,tc_done,{ct_scope_suite_state_scb_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]; + +test_events(scope_per_group_state_scb) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_scope_per_group_state_scb_SUITE,init_per_suite}}, + {?eh,tc_done,{ct_scope_per_group_state_scb_SUITE,init_per_suite,ok}}, + + [{?eh,tc_start,{ct_scope_per_group_state_scb_SUITE,{init_per_group,group1,[]}}}, + {?eh,scb,{'_',init,[[test]]}}, + {?eh,scb,{'_',post_init_per_group,[group1,'$proplist','$proplist',[test]]}}, + {?eh,tc_done,{ct_scope_per_group_state_scb_SUITE,{init_per_group,group1,[]},ok}}, + + {?eh,tc_start,{ct_scope_per_group_state_scb_SUITE,test_case}}, + {?eh,scb,{'_',pre_init_per_testcase,[test_case,'$proplist',[test]]}}, + {?eh,scb,{'_',post_end_per_testcase,[test_case,'$proplist',ok,[test]]}}, + {?eh,tc_done,{ct_scope_per_group_state_scb_SUITE,test_case,ok}}, + + {?eh,tc_start,{ct_scope_per_group_state_scb_SUITE,{end_per_group,group1,[]}}}, + {?eh,scb,{'_',pre_end_per_group,[group1,'$proplist',[test]]}}, + {?eh,scb,{'_',post_end_per_group,[group1,'$proplist','_',[test]]}}, + {?eh,scb,{'_',terminate,[[test]]}}, + {?eh,tc_done,{ct_scope_per_group_state_scb_SUITE,{end_per_group,group1,[]},ok}}], + + {?eh,tc_start,{ct_scope_per_group_state_scb_SUITE,end_per_suite}}, + {?eh,tc_done,{ct_scope_per_group_state_scb_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]; + test_events(fail_pre_suite_scb) -> [ {?eh,start_logging,{'DEF','RUNDIR'}}, @@ -753,6 +849,33 @@ test_events(state_update_scb) -> {?eh,stop_logging,[]} ]; +test_events(options_scb) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,scb,{empty_scb,init,[[test]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, + {?eh,scb,{empty_scb,pre_init_per_suite, + [ct_scb_empty_SUITE,'$proplist',[test]]}}, + {?eh,scb,{empty_scb,post_init_per_suite, + [ct_scb_empty_SUITE,'$proplist','$proplist',[test]]}}, + {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite,ok}}, + + {?eh,tc_start,{ct_scb_empty_SUITE,test_case}}, + {?eh,scb,{empty_scb,pre_init_per_testcase,[test_case,'$proplist',[test]]}}, + {?eh,scb,{empty_scb,post_end_per_testcase,[test_case,'$proplist','_',[test]]}}, + {?eh,tc_done,{ct_scb_empty_SUITE,test_case,ok}}, + + {?eh,tc_start,{ct_scb_empty_SUITE,end_per_suite}}, + {?eh,scb,{empty_scb,pre_end_per_suite, + [ct_scb_empty_SUITE,'$proplist',[test]]}}, + {?eh,scb,{empty_scb,post_end_per_suite,[ct_scb_empty_SUITE,'$proplist','_',[test]]}}, + {?eh,tc_done,{ct_scb_empty_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,scb,{empty_scb,terminate,[[test]]}}, + {?eh,stop_logging,[]} + ]; + test_events(ok) -> ok. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_group_state_scb_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_group_state_scb_SUITE.erl new file mode 100644 index 0000000000..63dd767b25 --- /dev/null +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_group_state_scb_SUITE.erl @@ -0,0 +1,56 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(ct_scope_per_group_state_scb_SUITE). + +-suite_defaults([{timetrap, {minutes, 10}}]). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-include("ct.hrl"). + +%% Test server callback functions +init_per_suite(Config) -> + Config. + +end_per_suite(_Config) -> + ok. + +init_per_testcase(_TestCase, Config) -> + Config. + +end_per_testcase(_TestCase, _Config) -> + ok. + +init_per_group(_GroupName, Config) -> + [{suite_callbacks,[{empty_scb,[test]}]}|Config]. + +end_per_group(_GroupName, _Config) -> + ok. + +all() -> + [{group,group1}]. + +groups() -> + [{group1,[],[test_case]}]. + +%% Test cases starts here. +test_case(Config) when is_list(Config) -> + ok. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_suite_state_scb_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_suite_state_scb_SUITE.erl new file mode 100644 index 0000000000..02a011f91b --- /dev/null +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_suite_state_scb_SUITE.erl @@ -0,0 +1,47 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(ct_scope_per_suite_state_scb_SUITE). + +-suite_defaults([{timetrap, {minutes, 10}}]). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-include("ct.hrl"). + +%% Test server callback functions +init_per_suite(Config) -> + [{suite_callbacks,[{empty_scb,[test]}]}|Config]. + +end_per_suite(_Config) -> + ok. + +init_per_testcase(_TestCase, Config) -> + Config. + +end_per_testcase(_TestCase, _Config) -> + ok. + +all() -> + [test_case]. + +%% Test cases starts here. +test_case(Config) when is_list(Config) -> + ok. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_suite_state_scb_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_suite_state_scb_SUITE.erl new file mode 100644 index 0000000000..869532f5cd --- /dev/null +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_suite_state_scb_SUITE.erl @@ -0,0 +1,50 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(ct_scope_suite_state_scb_SUITE). + +-suite_defaults([{timetrap, {minutes, 10}}]). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-include("ct.hrl"). + +%% Test server callback functions +suite() -> + [{suite_callbacks,[{empty_scb,[test]}]}]. + +init_per_suite(Config) -> + Config. + +end_per_suite(_Config) -> + ok. + +init_per_testcase(_TestCase, Config) -> + Config. + +end_per_testcase(_TestCase, _Config) -> + ok. + +all() -> + [test_case]. + +%% Test cases starts here. +test_case(Config) when is_list(Config) -> + ok. -- cgit v1.2.3 From 5f19d44a842ae4d6b1b977273308edb1131cb8d0 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 9 Dec 2010 11:52:58 +0100 Subject: Add test suites for failing in init/1 function --- .../scb/tests/crash_init_scb.erl | 34 +++++++++++++++ .../ct_exit_in_init_scope_suite_scb_SUITE.erl | 50 ++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/crash_init_scb.erl create mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_exit_in_init_scope_suite_scb_SUITE.erl (limited to 'lib/common_test') diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/crash_init_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/crash_init_scb.erl new file mode 100644 index 0000000000..683459853f --- /dev/null +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/crash_init_scb.erl @@ -0,0 +1,34 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(crash_init_scb). + + +-include_lib("common_test/src/ct_util.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + + +%% Suite Callbacks +-export([init/1]). + +init(Opts) -> + empty_scb:init(Opts), + exit(diediedie). + diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_exit_in_init_scope_suite_scb_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_exit_in_init_scope_suite_scb_SUITE.erl new file mode 100644 index 0000000000..bfaeb7ca3a --- /dev/null +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_exit_in_init_scope_suite_scb_SUITE.erl @@ -0,0 +1,50 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(ct_exit_in_init_scope_suite_scb_SUITE). + +-suite_defaults([{timetrap, {minutes, 10}}]). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-include_lib("common_test/include/ct.hrl"). + +%% Test server callback functions +suite() -> + [{suite_callbacks,[crash_init_scb]}]. + +init_per_suite(Config) -> + Config. + +end_per_suite(_Config) -> + ok. + +init_per_testcase(_TestCase, Config) -> + Config. + +end_per_testcase(_TestCase, _Config) -> + ok. + +all() -> + [test_case]. + +%% Test cases starts here. +test_case(Config) when is_list(Config) -> + ok. -- cgit v1.2.3 From 9cedf681e9b3f2144cf44fbb4ae7f4a0e4aa9bf6 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 9 Dec 2010 12:36:15 +0100 Subject: Add tests for SCB's with same id and fixed bug relating to it --- lib/common_test/src/ct_suite_callback.erl | 5 +- lib/common_test/test/ct_suite_callback_SUITE.erl | 46 +++++++++++++- .../scb/tests/same_id_scb.erl | 72 ++++++++++++++++++++++ lib/common_test/test/ct_test_support.erl | 12 +++- 4 files changed, 131 insertions(+), 4 deletions(-) create mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/same_id_scb.erl (limited to 'lib/common_test') diff --git a/lib/common_test/src/ct_suite_callback.erl b/lib/common_test/src/ct_suite_callback.erl index 8372303737..508d3b5bd6 100644 --- a/lib/common_test/src/ct_suite_callback.erl +++ b/lib/common_test/src/ct_suite_callback.erl @@ -169,8 +169,9 @@ call(Fun, Config, Meta, NoChangeRet) when is_function(Fun) -> call([{CB, call_init, NextFun} | Rest], Config, Meta, CBs) -> try {Config, {NewId, _, {Mod,_State}} = NewCB} = call_init(CB, Config, Meta), - {NewCBs, NewRest} = case proplists:get_value(NewId, CBs, NextFun) of - undefined -> {CBs ++ [NewCB],Rest}; + {NewCBs, NewRest} = case lists:keyfind(NewId, 1, CBs) of + false when NextFun == undefined -> + {CBs ++ [NewCB],Rest}; ExistingCB when is_tuple(ExistingCB) -> {CBs, Rest}; _ -> diff --git a/lib/common_test/test/ct_suite_callback_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE.erl index 88ce5e0e51..6d61fbb21d 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE.erl @@ -80,7 +80,7 @@ all(suite) -> scope_suite_state_scb, fail_pre_suite_scb, fail_post_suite_scb, skip_pre_suite_scb, skip_post_suite_scb, recover_post_suite_scb, update_config_scb, - state_update_scb, options_scb + state_update_scb, options_scb, same_id_scb ] ) . @@ -182,6 +182,10 @@ options_scb(Config) when is_list(Config) -> do_test(options_scb, "ct_scb_empty_SUITE.erl", [{empty_scb,[test]}],Config). +same_id_scb(Config) when is_list(Config) -> + do_test(same_id_scb, "ct_scb_empty_SUITE.erl", + [same_id_scb,same_id_scb],Config). + %%%----------------------------------------------------------------- %%% HELP FUNCTIONS @@ -876,6 +880,46 @@ test_events(options_scb) -> {?eh,stop_logging,[]} ]; +test_events(same_id_scb) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,scb,{'_',init,[[]]}}, + {?eh,scb,{'_',init,[[]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, + {?eh,scb,{'_',pre_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, + {negative, + {?eh,scb,{'_',pre_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, + {?eh,scb,{'_',post_init_per_suite, + [ct_scb_empty_SUITE,'$proplist','$proplist',[]]}}}, + {negative, + {?eh,scb,{'_',post_init_per_suite, + [ct_scb_empty_SUITE,'$proplist','$proplist',[]]}}, + {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite,ok}}}, + + {?eh,tc_start,{ct_scb_empty_SUITE,test_case}}, + {?eh,scb,{'_',pre_init_per_testcase,[test_case,'$proplist',[]]}}, + {negative, + {?eh,scb,{'_',pre_init_per_testcase,[test_case,'$proplist',[]]}}, + {?eh,scb,{'_',post_end_per_testcase,[test_case,'$proplist',ok,[]]}}}, + {negative, + {?eh,scb,{'_',post_end_per_testcase,[test_case,'$proplist',ok,[]]}}, + {?eh,tc_done,{ct_scb_empty_SUITE,test_case,ok}}}, + + {?eh,tc_start,{ct_scb_empty_SUITE,end_per_suite}}, + {?eh,scb,{'_',pre_end_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, + {negative, + {?eh,scb,{'_',pre_end_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, + {?eh,scb,{'_',post_end_per_suite,[ct_scb_empty_SUITE,'$proplist','_',[]]}}}, + {negative, + {?eh,scb,{'_',post_end_per_suite, + [ct_scb_empty_SUITE,'$proplist','_',[]]}}, + {?eh,tc_done,{ct_scb_empty_SUITE,end_per_suite,ok}}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,scb,{'_',terminate,[[]]}}, + {?eh,stop_logging,[]} + ]; + test_events(ok) -> ok. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/same_id_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/same_id_scb.erl new file mode 100644 index 0000000000..6853aa52e8 --- /dev/null +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/same_id_scb.erl @@ -0,0 +1,72 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(same_id_scb). + + +-include_lib("common_test/src/ct_util.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + + +%% Suite Callbacks +-compile(export_all). + +init(Opts) -> + {_,State} = empty_scb:init(Opts), + {?MODULE,State}. + +pre_init_per_suite(Suite, Config, State) -> + empty_scb:pre_init_per_suite(Suite,Config,State). + +post_init_per_suite(Suite,Config,Return,State) -> + empty_scb:post_init_per_suite(Suite,Config,Return,State). + +pre_end_per_suite(Suite,Config,State) -> + empty_scb:pre_end_per_suite(Suite,Config,State). + +post_end_per_suite(Suite,Config,Return,State) -> + empty_scb:post_end_per_suite(Suite,Config,Return,State). + +pre_init_per_group(Group,Config,State) -> + empty_scb:pre_init_per_group(Group,Config,State). + +post_init_per_group(Group,Config,Return,State) -> + empty_scb:post_init_per_group(Group,Config,Return,State). + +pre_end_per_group(Group,Config,State) -> + empty_scb:pre_end_per_group(Group,Config,State). + +post_end_per_group(Group,Config,Return,State) -> + empty_scb:post_end_per_group(Group,Config,Return,State). + +pre_init_per_testcase(TC,Config,State) -> + empty_scb:pre_init_per_testcase(TC,Config,State). + +post_end_per_testcase(TC,Config,Return,State) -> + empty_scb:post_end_per_testcase(TC,Config,Return,State). + +on_tc_fail(TC, Reason, State) -> + empty_scb:on_tc_fail(TC,Reason,State). + +on_tc_skip(TC, Reason, State) -> + empty_scb:on_tc_skip(TC,Reason,State). + +terminate(State) -> + empty_scb:terminate(State). diff --git a/lib/common_test/test/ct_test_support.erl b/lib/common_test/test/ct_test_support.erl index 5009741f59..981504b660 100644 --- a/lib/common_test/test/ct_test_support.erl +++ b/lib/common_test/test/ct_test_support.erl @@ -876,6 +876,16 @@ locate({TEH,tc_done,{undefined,undefined,{testcase_aborted, nomatch end; +%% Negative matching: Given two events, the first should not be present before +%% the other is matched. +locate({negative,NotMatch, Match} = Neg, Node, Evs, Config) -> + case locate(NotMatch, Node, Evs, Config) of + nomatch -> + locate(Match, Node, Evs, Config); + _ -> + exit({found_negative_event,Neg}) + end; + %% matches any event of type Name locate({TEH,Name,Data}, Node, [{TEH,#event{name=Name, data = EvData, @@ -888,7 +898,7 @@ locate({TEH,Name,Data}, Node, [{TEH,#event{name=Name, nomatch end; -locate({TEH,Name,Data}, Node, [_|Evs], Config) -> +locate({_TEH,_Name,_Data}, _Node, [_|_Evs], _Config) -> nomatch. match_data(D,D) -> -- cgit v1.2.3 From 0a5c83dc4cbf10e46ab6afa8c8cad05005406263 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Fri, 10 Dec 2010 15:57:24 +0100 Subject: Update test support so that if common test fails to be stopped in a suite, the ct node is restarted and the test case fails --- lib/common_test/test/ct_test_support.erl | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'lib/common_test') diff --git a/lib/common_test/test/ct_test_support.erl b/lib/common_test/test/ct_test_support.erl index 981504b660..b4f1a0e71f 100644 --- a/lib/common_test/test/ct_test_support.erl +++ b/lib/common_test/test/ct_test_support.erl @@ -58,6 +58,10 @@ init_per_suite(Config, Level) -> _ -> ok end, + + start_slave(Config, Level). + +start_slave(Config,Level) -> [_,Host] = string:tokens(atom_to_list(node()), "@"), test_server:format(0, "Trying to start ~s~n", ["ct@"++Host]), @@ -136,9 +140,16 @@ init_per_testcase(_TestCase, Config) -> end_per_testcase(_TestCase, Config) -> CTNode = ?config(ct_node, Config), - wait_for_ct_stop(CTNode), - ok. - + case wait_for_ct_stop(CTNode) of + %% Common test was not stopped to we restart node. + false -> + cover:stop(CTNode), + slave:stop(CTNode), + start_slave(Config,proplists:get_value(trace_level,Config)), + {fail, "Could not stop common_test"}; + true -> + ok + end. %%%----------------------------------------------------------------- %%% @@ -229,11 +240,11 @@ wait_for_ct_stop(CTNode) -> wait_for_ct_stop(0, CTNode) -> test_server:format(0, "Giving up! Stopping ~p.", [CTNode]), - ok; + false; wait_for_ct_stop(Retries, CTNode) -> case rpc:call(CTNode, erlang, whereis, [ct_util_server]) of undefined -> - ok; + true; Pid -> test_server:format(0, "Waiting for CT (~p) to finish (~p)...", [Pid,Retries]), -- cgit v1.2.3 From 3163804a22daa8e123078291496778963e16f7fe Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 27 Jan 2011 10:09:22 +0100 Subject: Update suite callback test timeout so that beam debug test runs do not timeout --- lib/common_test/test/ct_suite_callback_SUITE.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/common_test') diff --git a/lib/common_test/test/ct_suite_callback_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE.erl index 6d61fbb21d..adb950614e 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE.erl @@ -64,7 +64,7 @@ end_per_testcase(TestCase, Config) -> suite() -> - [{timetrap,{seconds,15}}]. + [{timetrap,{seconds,20}}]. all() -> all(suite). -- cgit v1.2.3 From 15e8dd20b5ba2c82e683e87254f18c9af3625481 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Wed, 9 Feb 2011 16:54:20 +0100 Subject: Add documentation for SCBs --- lib/common_test/doc/src/Makefile | 1 + lib/common_test/doc/src/common_test_app.xml | 10 +- lib/common_test/doc/src/ct_suite_callbacks.xml | 503 ++++++++++++++++++++- lib/common_test/doc/src/event_handler_chapter.xml | 11 +- lib/common_test/doc/src/part.xml | 1 + lib/common_test/doc/src/run_test_chapter.xml | 11 +- .../doc/src/suite_callbacks_chapter.xml | 394 ++++++++++++++++ lib/common_test/doc/src/write_test_chapter.xml | 1 + lib/common_test/src/ct.erl | 6 +- 9 files changed, 910 insertions(+), 28 deletions(-) create mode 100644 lib/common_test/doc/src/suite_callbacks_chapter.xml (limited to 'lib/common_test') diff --git a/lib/common_test/doc/src/Makefile b/lib/common_test/doc/src/Makefile index be066143e0..a3f740852c 100644 --- a/lib/common_test/doc/src/Makefile +++ b/lib/common_test/doc/src/Makefile @@ -71,6 +71,7 @@ XML_CHAPTER_FILES = \ cover_chapter.xml \ ct_master_chapter.xml \ event_handler_chapter.xml \ + suite_callbacks_chapter.xml \ dependencies_chapter.xml \ notes.xml \ notes_history.xml diff --git a/lib/common_test/doc/src/common_test_app.xml b/lib/common_test/doc/src/common_test_app.xml index e30eef2488..a735dc85a8 100644 --- a/lib/common_test/doc/src/common_test_app.xml +++ b/lib/common_test/doc/src/common_test_app.xml @@ -131,7 +131,8 @@ Info = {timetrap,Time} | {require,Required} | {require,Name,Required} | {userdata,UserData} | - {silent_connections,Conns} | {stylesheet,CSSFile} + {silent_connections,Conns} | {stylesheet,CSSFile} | + {suite_callbacks, SCBs} Time = MilliSec | {seconds,integer()} | {minutes,integer()} | {hours,integer()} MilliSec = integer() @@ -143,6 +144,9 @@ UserData = term() Conns = [atom()] CSSFile = string() + SCBs = [SCBModule | {SCBModule, SCBInitArgs}] + SCBModule = atom() + SCBInitArgs = term() @@ -170,6 +174,10 @@

With userdata, it is possible for the user to specify arbitrary test suite related information which can be read by calling ct:userdata/2.

+ +

The suite_callbacks tag specifies which + Suite Callbacks + are to be run together with this suite.

Other tuples than the ones defined will simply be ignored.

diff --git a/lib/common_test/doc/src/ct_suite_callbacks.xml b/lib/common_test/doc/src/ct_suite_callbacks.xml index 28a496a47b..cea5804825 100644 --- a/lib/common_test/doc/src/ct_suite_callbacks.xml +++ b/lib/common_test/doc/src/ct_suite_callbacks.xml @@ -1,4 +1,4 @@ - + @@ -33,24 +33,43 @@ suite_callback.sgml ct_suite_callback - A callback interface on top of common test + A callback interface on top of Common Test -

The Suite Callback framework allows extensions of the default - behaviour of Common Test by means of callbacks before and after all - test suite calls.

+

This feature is in alpha release right now. This means that the + interface may change in the future and that there may be bugs. We + encourage you to use this feature, but be prepared + that there might be bugs and that the interface might change + inbetween releases.

+ +

The Suite Callback (henceforth called SCB) framework allows + extensions of the default behaviour of Common Test by means of callbacks + before and after all test suite calls. It is meant for advanced users of + Common Test which want to abstract out behaviour which is common to + multiple test suites.

In brief, Suite Callbacks allows you to:

- Manipulating the runtime config before each suite configuration calls - Manipulating the return of all suite configuration calls + Manipulate the runtime config before each suite + configuration calls + Manipulate the return of all suite configuration calls and in + extension the result of the test themselves. -

The following sections describe the mandatory and optional suite callback - functions Common Test will call during test execution. For more details - see Suite Callbacks in the User's Guide.

+

The following sections describe the mandatory and optional SCB + functions Common Test will call during test execution. For more details + see Suite Callbacks in + the User's Guide.

+ +

For information about how to add a SCB to your suite see + Installing an SCB + in the User's Guide.

+ +

See the + Example SCB + in the User's Guide for a minimal example of an SCB.

@@ -62,31 +81,469 @@ - Module:init(Opts) -> {Id,State} - asdas + Module:init(Id, Opts) -> State + Initiates the Suite Callback + Id = reference() | term() Opts = term() - Id = term() - GroupName = term() + State = term()

MANDATORY

+ +

Always called before any other callback function. + Use this to initiate any common state. + It should return a state for this SCB.

+ +

Id is the return value of + id/1, or a reference + if id/1 is not implemented. +

+ +

For details about when init is called see + scope + in the User's Guide.

+ +
+
+ + + Module:pre_init_per_suite(SuiteName, Config, SCBState) -> + Result + Called before init_per_suite + + SuiteName = atom() + Config = NewConfig = [{Key,Value}] + SCBState = NewSCBState = term() + Result = {Return, NewSCBState} + Return = NewConfig | SkipOrFail + SkipOrFail = {fail, Reason} | {skip, Reason} + Key = atom() + Value = term() + Reason = term() + + + +

OPTIONAL

+ +

This function is called before + + init_per_suite if it exists. + It typically contains initialization/logging which needs to be done + before init_per_suite is called. + If {skip,Reason} or {fail,Reason} is returned, + init_per_suite and all test cases of the suite will be skipped and + Reason printed in the overview log of the suite.

-

+

SuiteName is the name of the suite to be run.

+ +

Config is the original config list of the test suite.

+ +

SCBState is the current internal state of the SCB.

+ +

Return is the result of the init_per_suite function. + If it is {skip,Reason} or {fail,Reason} + init_per_suite + will never be called, instead the initiation is considered + to be skipped/failed respectively. If a NewConfig list + is returned, + init_per_suite will be called with that NewConfig list. + See + Manipulating tests in the User's Guide for more details.

+ + +

Note that this function is only called if the SCB has been added + before init_per_suite is run, see + SCB Scoping + in the User's Guide for details.

+
+
+ + + Module:post_init_per_suite(SuiteName, Config, Return, SCBState) -> + Result + Called after init_per_suite + + SuiteName = atom() + Config = [{Key,Value}] + Return = NewReturn = Config | SkipOrFail | term() + SkipOrFail = {fail, Reason} | {skip, Reason} | term() + SCBState = NewSCBState = term() + Result = {NewReturn, NewSCBState} + Key = atom() + Value = term() + Reason = term() + + + +

OPTIONAL

+ +

Return is what + init_per_suite + returned, i.e. {fail,Reason}, {skip,Reason}, a Config + list or a term describing how + init_per_suite + failed.

+ +

NewReturn is the possibly modified return value of + init_per_suite + . It is here possible to recover from a failure in + init_per_suite + by returning the ConfigList with the tc_status + element removed.

+ +

SCBState is the current internal state of the SCB.

+ +

This function is called after + + init_per_suite if it exists.

+ +

Note that this function is only called if the SCB has been added + before or in init_per_suite, see + SCB Scoping + in the User's Guide for details.

+
+
+ + + Module:pre_init_per_group(GroupName, Config, SCBState) -> + Result + Called before init_per_group + + GroupName = atom() + Config = NewConfig = [{Key,Value}] + SCBState = NewSCBState = term() + Result = {NewConfig | SkipOrFail, NewSCBState} + SkipOrFail = {fail,Reason} | {skip, Reason} + Key = atom() + Value = term() + Reason = term() + + + +

OPTIONAL

-

If {skip,Reason} is returned, all test cases - in the module will be skipped, and the Reason will - be printed on the HTML result page.

+

This function is called before + + init_per_group if it exists. It behaves the same way as + + pre_init_per_suite, but for the + + init_per_group instead.

+
+
+ + + Module:post_init_per_group(GroupName, Config, Return, SCBState) -> + Result + Called after init_per_group + + GroupName = atom() + Config = [{Key,Value}] + Return = NewReturn = Config | SkipOrFail | term() + SkipOrFail = {fail,Reason} | {skip, Reason} + SCBState = NewSCBState = term() + Result = {NewReturn, NewSCBState} + Key = atom() + Value = term() + Reason = term() + + + +

OPTIONAL

-

For details on groups, see - Test case - groups in the User's Guide.

+

This function is called after + + init_per_group if it exists. It behaves the same way as + + post_init_per_suite, but for the + + init_per_group instead.

+
+
+ + + Module:pre_init_per_testcase(TestcaseName, Config, SCBState) -> + Result + Called before init_per_testcase + + TestcaseName = atom() + Config = NewConfig = [{Key,Value}] + SCBState = NewSCBState = term() + Result = {NewConfig | SkipOrFail, NewSCBState} + SkipOrFail = {fail,Reason} | {skip, Reason} + Key = atom() + Value = term() + Reason = term() + -
+ +

OPTIONAL

+ +

This function is called before + + init_per_testcase if it exists. It behaves the same way as + + pre_init_per_suite, but for the + + init_per_testcase function instead.

+ +

Note that it is not possible to add SCB's here right now, + that feature might be added later, + but it would right now break backwards compatability.

+
+ + + + Module:post_end_per_testcase(TestcaseName, Config, Return, SCBState) + -> Result + Called after end_per_testcase + + TestcaseName = atom() + Config = [{Key,Value}] + Return = NewReturn = Config | SkipOrFail | term() + SkipOrFail = {fail,Reason} | {skip, Reason} + SCBState = NewSCBState = term() + Result = {NewReturn, NewSCBState} + Key = atom() + Value = term() + Reason = term() + + + +

OPTIONAL

+ +

This function is called after + + end_per_testcase if it exists. It behaves the same way as + + post_init_per_suite, but for the + + end_per_testcase function instead.

+
+
+ + + Module:pre_end_per_group(GroupName, Config, SCBState) -> + Result + Called before end_per_group + + GroupName = atom() + Config = NewConfig = [{Key,Value}] + SCBState = NewSCBState = term() + Result = {NewConfig | SkipOrFail, NewSCBState} + SkipOrFail = {fail,Reason} | {skip, Reason} + Key = atom() + Value = term() + Reason = term() + + + +

OPTIONAL

+ +

This function is called before + + end_per_group if it exists. It behaves the same way as + + pre_init_per_suite, but for the + + end_per_group function instead.

+
+
+ + + Module:post_end_per_group(GroupName, Config, Return, SCBState) -> + Result + Called after end_per_group + + GroupName = atom() + Config = [{Key,Value}] + Return = NewReturn = Config | SkipOrFail | term() + SkipOrFail = {fail,Reason} | {skip, Reason} + SCBState = NewSCBState = term() + Result = {NewReturn, NewSCBState} + Key = atom() + Value = term() + Reason = term() + + + +

OPTIONAL

+ +

This function is called after + + end_per_group if it exists. It behaves the same way as + + post_init_per_suite, but for the + + end_per_group function instead.

+
+
+ + + Module:pre_end_per_suite(SuiteName, Config, SCBState) -> + Result + Called before end_per_suite + + SuiteName = atom() + Config = NewConfig = [{Key,Value}] + SCBState = NewSCBState = term() + Result = {NewConfig | SkipOrFail, NewSCBState} + SkipOrFail = {fail,Reason} | {skip, Reason} + Key = atom() + Value = term() + Reason = term() + + + +

OPTIONAL

+ +

This function is called before + + end_per_suite if it exists. It behaves the same way as + + pre_init_per_suite, but for the + + end_per_suite function instead.

+
+
+ + + Module:post_end_per_suite(SuiteName, Config, Return, SCBState) -> + Result + Called after end_per_suite + + SuiteName = atom() + Config = [{Key,Value}] + Return = NewReturn = Config | SkipOrFail | term() + SkipOrFail = {fail,Reason} | {skip, Reason} + SCBState = NewSCBState = term() + Result = {NewReturn, NewSCBState} + Key = atom() + Value = term() + Reason = term() + + + +

OPTIONAL

+ +

This function is called after + + end_per_suite if it exists. It behaves the same way as + + post_init_per_suite, but for the + + end_per_suite function instead.

+
+
+ + + Module:on_tc_fail(TestcaseName, Reason, SCBState) -> + NewSCBState + Called after the SCB scope ends + + TestcaseName = init_per_suite | end_per_suite | + init_per_group | end_per_group | atom() + Reason = term() + SCBState = NewSCBState = term() + + + +

OPTIONAL

+ +

This function is called whenever a testcase fails. + It is called after the post function has been called for + the testcase which failed. i.e. + if init_per_suite fails this function is called after + + post_init_per_suite, and if a testcase fails it is called + after + post_end_per_testcase.

+ +

The data which comes with the Reason follows the same format as the + FailReason + in the tc_done event. + See Event Handling + in the User's Guide for details.

+
+
+ + + Module:on_tc_skip(TestcaseName, Reason, SCBState) -> + NewSCBState + Called after the SCB scope ends + + TestcaseName = end_per_suite | init_per_group | + end_per_group | atom() + Reason = {tc_auto_skip | tc_user_skip, term()} + SCBState = NewSCBState = term() + + + +

OPTIONAL

+ +

This function is called whenever a testcase is skipped. + It is called after the post function has been called for the + testcase which was skipped. + i.e. if init_per_group is skipped this function is called after + post_init_per_group + , and if a testcase is skipped it is called after + post_end_per_testcase + .

+ +

The data which comes with the Reason follows the same format as + tc_auto_skip + and + tc_user_skip events. + See Event Handling + in the User's Guide for details.

+
+
+ + + Module:terminate(SCBState) + Called after the SCB scope ends + + SCBState = term() + + + +

OPTIONAL

+ +

This function is called at the end of an SCB's + scope. +

+
+
+ + + Module:id(Opts) -> Id + Called before the init function of an SCB + + Opts = term() + Id = term() + + + +

OPTIONAL

+ +

The Id is used to uniquely identify an SCB instance, + if two SCB's return the same Id the second SCB is ignored + and subsequent calls to the SCB will only be made to the first + instance. For more information see + Installing an SCB + in the User's Guide. +

+ +

This function should NOT have any side effects as it might + be called multiple times by Common Test.

+ +

If not implemented the SCB will act as if this function returned a + call to make_ref/0.

+
- diff --git a/lib/common_test/doc/src/event_handler_chapter.xml b/lib/common_test/doc/src/event_handler_chapter.xml index 904876ac46..a01feb59d1 100644 --- a/lib/common_test/doc/src/event_handler_chapter.xml +++ b/lib/common_test/doc/src/event_handler_chapter.xml @@ -61,6 +61,7 @@ itself.

+ Usage

Event handlers may be installed by means of an event_handler start flag (ct_run) or option (ct:run_test/1), where the @@ -120,6 +121,7 @@ node the event has originated from (only relevant for CT Master event handlers). data is specific for the particular event.

+

General events:

@@ -172,6 +174,7 @@ are also given.

+ #event{name = tc_done, data = {Suite,FuncOrGroup,Result}}

Suite = atom(), name of the suite.

FuncOrGroup = Func | {Conf,GroupName,GroupProperties}

@@ -181,12 +184,14 @@ (unknown if init- or end function times out).

GroupProperties = list(), list of execution properties for the group.

Result = ok | {skipped,SkipReason} | {failed,FailReason}, the result.

+

SkipReason = {require_failed,RequireInfo} | {require_failed_in_suite0,RequireInfo} | {failed,{Suite,init_per_testcase,FailInfo}} | UserTerm, the reason why the case has been skipped.

-

FailReason = {error,FailInfo} | + +

FailReason = {error,FailInfo} | {error,{RunTimeError,StackTrace}} | {timetrap_timeout,integer()} | {failed,{Suite,end_per_testcase,FailInfo}}, reason for failure.

@@ -209,6 +214,7 @@ end_per_testcase for the case failed.

+ #event{name = tc_auto_skip, data = {Suite,Func,Reason}}

Suite = atom(), the name of the suite.

Func = atom(), the name of the test case or configuration function.

@@ -234,7 +240,8 @@ skipped because of init_per_testcase failing, since that information is carried with the tc_done event.

- + + #event{name = tc_user_skip, data = {Suite,TestCase,Comment}}

Suite = atom(), name of the suite.

TestCase = atom(), name of the test case.

diff --git a/lib/common_test/doc/src/part.xml b/lib/common_test/doc/src/part.xml index 53a4cb1bbf..1a09ec1da2 100644 --- a/lib/common_test/doc/src/part.xml +++ b/lib/common_test/doc/src/part.xml @@ -75,6 +75,7 @@ + diff --git a/lib/common_test/doc/src/run_test_chapter.xml b/lib/common_test/doc/src/run_test_chapter.xml index 94fcf6bf01..81e752680b 100644 --- a/lib/common_test/doc/src/run_test_chapter.xml +++ b/lib/common_test/doc/src/run_test_chapter.xml @@ -105,6 +105,7 @@ RPC from a remote node.

+
Running tests from the OS command line @@ -147,6 +148,8 @@ event handlers. ]]>, to install event handlers including start arguments. + ]]>, to install + Suite Callbacks including start arguments. , specifies include directories (see above). , disables the automatic test suite compilation feature (see above). ]]>, extends timetrap @@ -333,8 +336,8 @@ with dir.

+
- Using test specifications

The most flexible way to specify what to test, is to use a so @@ -440,6 +443,9 @@ {event_handler, NodeRefs, EventHandlers}. {event_handler, EventHandlers, InitArgs}. {event_handler, NodeRefs, EventHandlers, InitArgs}. + + {suite_callbacks, SCBModules}. + {suite_callbacks, NodeRefs, SCBModules}.

Test terms:

@@ -478,6 +484,9 @@
       LogDir        = string()
       EventHandlers = atom() | [atom()]
       InitArgs      = [term()]
+      SCBModules    = [SCBModule | {SCBModule, SCBInitArgs}]
+      SCBModule     = atom()
+      SCBInitArgs   = term()
       DirRef        = DirAlias | Dir
       Suites        = atom() | [atom()] | all
       Suite         = atom()
diff --git a/lib/common_test/doc/src/suite_callbacks_chapter.xml b/lib/common_test/doc/src/suite_callbacks_chapter.xml
new file mode 100644
index 0000000000..89f78898d4
--- /dev/null
+++ b/lib/common_test/doc/src/suite_callbacks_chapter.xml
@@ -0,0 +1,394 @@
+
+
+
+
+  
+ + 20112011 + Ericsson AB. 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. + + + + Suite Callbacks + Lukas Larsson + + + + suite_callbacks_chapter.xml +
+ + +
+ General +

This feature is in alpha release right now. This means that the + interface may change in the future and that there may be bugs. We + encourage you to use this feature, but be prepared + that there might be bugs and that the interface might change + inbetween releases.

+

+ The Suite Callback (henceforth called SCB) framework allows + extensions of the default behaviour of Common Test by means of callbacks + before and after all test suite calls. SCBs allow advanced Common Test + users to abstract out behaviour which is common to multiple test suites + without littering all test suites with library calls. Some example + usages are: logging, starting and monitoring external systems, + building C files needed by the tests and much more!

+ +

In brief, Suite Callbacks allows you to:

+ + + Manipulate the runtime config before each suite + configuration calls + Manipulate the return of all suite configuration calls and in + extension the result of the test themselves. + + +

The following sections describe how to use SCBs, when they are run + and how to manipulate your test results in an SCB

+ +

When executing within an SCB all timetraps are shutoff. So + if your SCB never returns, the entire test run will be stalled!

+
+ +
+ + +
+ Installing an SCB +

There are multiple ways to install an SCB in your test run. You can do it + for all tests in a run, for specific test suites and for specific groups + within a test suite. If you want an SCB to be present in all test suites + within your testrun there are three different ways to accomplish that.

+ + + Add -suite_callbacks as an argument to + ct_run. + To add multiple SCBs using this method append them to each other + using the keyword and, i.e. + ct_run -suite_callbacks scb1 [{debug,true}] and scb2 .... + Add the suite_callbacks tag to your + + Test Specification + Add the suite_callbacks tag to your call to + ct:run_test/1 + + +

You can also add SCBs within a test suite. This is done by returning + {suite_callbacks,[SCB]} in the config list from + suite/0, + + init_per_suite/1 or + + init_per_group/2. SCB in this case can be either + only the module name of the SCB or a tuple with the module name and the + initial arguments to the SCB. Eg: + {suite_callbacks,[my_scb_module]} or + {suite_callbacks,[{my_scb_module,[{debug,true}]}]}

+ +
+ Overriding SCBs +

By default each installation of an SCB will cause a new instance of it + to be activated. This can cause problems if you want to be able to + override SCBs in testspecifications while still having them in the + suite info function. The + id/1 + callback exists to address this problem. By returning the same + id in both places, Common Test knows that this SCB + has already been installed and will not try to install it again.

+
+ +
+ + +
+ SCB Scope +

Once the SCB is installed into a certain test run it will be there until + it's scope is expired. The scope of an SCB depends on when it is + installed. + The init/2 is + called at the beginning of the scope and the + terminate/1 + function is called when the scope ends.

+ + + SCB Installed in + SCB scope begins before + SCB scope ends after + + + ct_run + the first test suite is to be run. + the last test suite has been run. + + + ct:run_test + the first test suite is to be run. + the last test suite has been run. + + + + Test Specification + the first test suite is to be run. + the last test suite has been run. + + + suite/0 + + + pre_init_per_suite/3 is called. + + post_end_per_suite/4 has been called for that test suite. + + + + init_per_suite/1 + + post_init_per_suite/4 is called. + + post_end_per_suite/4 has been called for that test suite. + + + + init_per_group/2 + + post_init_per_group/4 is called. + + post_end_per_group/4 has been called for that group. + + Scope of an SCB +
+ +
+ CTH Processes and Tables +

CTHs are run with the same process scoping as normal test suites + i.e. a different process will execute the init_per_suite hooks then the + init_per_group or per_testcase hooks. So if you want to spawn a + process in the CTH you cannot link with the CTH process as it will exit + after the post hook ends. Also if you for some reason need an ETS + table with your CTH, you will have to spawn a process which handles + it.

+
+ +
+ + +
+ Manipulating tests +

It is through SCB's possible to manipulate the results of tests and + configuration functions. The main purpose of doing this with SCBs is to + allow common patterns to be abstracted out from test test suites and applied to + multiple test suites without duplicating any code. All of the callback + functions for an SCB follow a common interface, this interface is + described below.

+ + +
+ Pre test manipulation +

+ It is possible in an SCB to hook in behaviour before + init_per_suite, + init_per_group, + init_per_testcase, + end_per_group and + end_per_suite. + This is done in the SCB functions called pre_<name of function>. + All of these function take the same three arguments: Name, + Config and SCBState. The return value of the SCB function + is always a combination of an result for the suite/group/test and an + updated SCBState. If you want the test suite to continue on + executing you should return the config list which you want the test to + use as the result. If you for some reason want to skip/fail the test, + return a tuple with skip or fail and a reason as the + result. Example: +

+ pre_init_per_suite(SuiteName, Config, SCBState) -> + case db:connect() of + {error,_Reason} -> + {{fail, "Could not connect to DB"}, SCBState}; + {ok, Handle} -> + {[{db_handle, Handle} | Config], SCBState#state{ handle = Handle }} + end. + +
+ + +
+ Post test manipulation +

It is also possible in an SCB to hook in behaviour after + init_per_suite, + init_per_group, + end_per_testcase, + end_per_group and + end_per_suite. + This is done in the SCB functions called post_<name of function>. + All of these function take the same four arguments: Name, + Config, Return and SCBState. Config in this + case is the same Config as the testcase is called with. + Return is the value returned by the testcase. If the testcase + failed by crashing, Return will be + {'EXIT',{{Error,Reason},Stacktrace}}.

+ +

The return value of the SCB function is always a combination of an + result for the suite/group/test and an updated SCBState. If + you want the callback to not affect the outcome of the test you should + return the Return data as it is given to the SCB. You can also + modify the result of the test. By returning the Config list + with the tc_status element removed you can recover from a test + failure. As in all the pre hooks, it is also possible to fail/skip + the test case in the post hook. Example:

+ + post_end_per_testcase(_TC, Config, {'EXIT',{_,_}}, SCBState) -> + case db:check_consistency() of + true -> + %% DB is good, pass the test. + {proplists:delete(tc_status, Config), SCBState}; + false -> + %% DB is not good, mark as skipped instead of failing + {{skip, "DB is inconsisten!"}, SCBState} + end; +post_end_per_testcase(_TC, Config, Return, SCBState) -> + %% Do nothing if tc does not crash. + {Return, SCBState}. + + Recovering from a testcase failure using SCBs should only be done as + a last resort. If used wrongly it could become very difficult to + determine which tests pass or fail in a test run + +
+ + +
+ Skip and Fail +

+ After any post hook has been executed for all installed SCBs, + on_tc_fail + or on_tc_skip + might be called if the testcase failed or was skipped + respectively. You cannot affect the outcome of the tests any further at + this point. +

+
+ +
+ + +
+ Example SCB +

The SCB below will log information about a test run into a format + parseable by file:consult/1. +

+ %%% @doc Common Test Example Suite Callback module. +-module(example_scb). + +%% Suite Callbacks +-export([id/1]). +-export([init/2]). + +-export([pre_init_per_suite/3]). +-export([post_init_per_suite/4]). +-export([pre_end_per_suite/3]). +-export([post_end_per_suite/4]). + +-export([pre_init_per_group/3]). +-export([post_init_per_group/4]). +-export([pre_end_per_group/3]). +-export([post_end_per_group/4]). + +-export([pre_init_per_testcase/3]). +-export([post_end_per_testcase/4]). + +-export([on_tc_fail/3]). +-export([on_tc_skip/3]). + +-export([terminate/1]). + +-record(state, { file_handle, total, suite_total, ts, tcs, data }). + +%% @doc Return a unique id for this SCB. +id(Opts) -> + proplists:get_value(filename, Opts, "/tmp/file.log"). + +%% @doc Always called before any other callback function. Use this to initiate +%% any common state. +init(Id, Opts) -> + {ok,D} = file:open(Id,[write]), + #state{ file_handle = D, total = 0, data = [] }. + +%% @doc Called before init_per_suite is called. +pre_init_per_suite(Suite,Config,State) -> + {Config, State#state{ suite_total = 0, tcs = [] }}. + +%% @doc Called after init_per_suite. +post_init_per_suite(Suite,Config,Return,State) -> + {Return, State}. + +%% @doc Called before end_per_suite. +pre_end_per_suite(Suite,Config,State) -> + {Config, State}. + +%% @doc Called after end_per_suite. +post_end_per_suite(Suite,Config,Return,State) -> + Data = {suites, Suite, State#state.suite_total, lists:reverse(State#state.tcs)}, + {Return, State#state{ data = [Data | State#state.data] , + total = State#state.total + State#state.suite_total } }. + +%% @doc Called before each init_per_group. +pre_init_per_group(Group,Config,State) -> + {Config, State}. + +%% @doc Called after each init_per_group. +post_init_per_group(Group,Config,Return,State) -> + {Return, State}. + +%% @doc Called after each end_per_group. +pre_end_per_group(Group,Config,State) -> + {Config, State}. + +%% @doc Called after each end_per_group. +post_end_per_group(Group,Config,Return,State) -> + {Return, State}. + +%% @doc Called before each test case. +pre_init_per_testcase(TC,Config,State) -> + {Config, State#state{ ts = now(), total = State#state.suite_total + 1 } }. + +%% @doc Called after each test case. +post_end_per_testcase(TC,Config,Return,State) -> + TCInfo = {testcase, TC, Return, timer:now_diff(now(), State#state.ts)}, + {Return, State#state{ ts = undefined, tcs = [TCInfo | State#state.tcs] } }. + +%% @doc Called after post_init_per_suite, post_end_per_suite, post_init_per_group, +%% post_end_per_group and post_end_per_testcase if the suite, group or test case failed. +on_tc_fail(TC, Reason, State) -> + State. + +%% @doc Called when a test case is skipped by either user action +%% or due to an init function failing. +on_tc_skip(TC, Reason, State) -> + State. + +%% @doc Called when the scope of the SCB is done +terminate(State) -> + io:format(State#state.file_handle, "~p.~n", + [{test_run, State#state.total, State#state.data}]), + file:close(State#state.file_handle), + ok. +
+ +
+ + + + diff --git a/lib/common_test/doc/src/write_test_chapter.xml b/lib/common_test/doc/src/write_test_chapter.xml index 5afec6de6a..76493d3616 100644 --- a/lib/common_test/doc/src/write_test_chapter.xml +++ b/lib/common_test/doc/src/write_test_chapter.xml @@ -115,6 +115,7 @@

+
Init and end per test case diff --git a/lib/common_test/src/ct.erl b/lib/common_test/src/ct.erl index 405dc40c8b..eb0eceeb46 100644 --- a/lib/common_test/src/ct.erl +++ b/lib/common_test/src/ct.erl @@ -148,7 +148,8 @@ 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} | {basic_html,Bool} | +%%% {suite_callbacks, SCBs} %%% TestDirs = [string()] | string() %%% Suites = [string()] | string() %%% Cases = [atom()] | atom() @@ -176,6 +177,9 @@ run(TestDirs) -> %%% DecryptKeyOrFile = {key,DecryptKey} | {file,DecryptFile} %%% DecryptKey = string() %%% DecryptFile = string() +%%% SCBs = [SCBModule | {SCBModule, SCBInitArgs}] +%%% SCBModule = atom() +%%% SCBInitArgs = term() %%% Result = [TestResult] | {error,Reason} %%% @doc Run tests as specified by the combination of options in Opts. %%% The options are the same as those used with the -- cgit v1.2.3 From e34cd721545915266a00b1ec55a9a5867c8459a4 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Wed, 9 Feb 2011 13:59:50 +0100 Subject: Update SCBs to use a specific id/1 function for SCb overriding instead of returning it from init/1. --- lib/common_test/src/ct_suite_callback.erl | 43 +++++----- lib/common_test/test/ct_suite_callback_SUITE.erl | 97 ++++++++++++++++------ .../scb/tests/crash_id_scb.erl | 34 ++++++++ .../scb/tests/crash_init_scb.erl | 6 +- .../scb/tests/empty_scb.erl | 26 ++++-- .../scb/tests/fail_post_suite_scb.erl | 4 +- .../scb/tests/fail_pre_suite_scb.erl | 4 +- .../scb/tests/id_no_init_scb.erl | 32 +++++++ .../scb/tests/minimal_scb.erl | 6 +- .../scb/tests/recover_post_suite_scb.erl | 4 +- .../scb/tests/same_id_scb.erl | 9 +- .../scb/tests/skip_post_suite_scb.erl | 4 +- .../scb/tests/skip_pre_suite_scb.erl | 4 +- .../scb/tests/state_update_scb.erl | 6 +- .../scb/tests/undef_scb.erl | 4 +- .../scb/tests/update_config_scb.erl | 4 +- 16 files changed, 206 insertions(+), 81 deletions(-) create mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/crash_id_scb.erl create mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/id_no_init_scb.erl (limited to 'lib/common_test') diff --git a/lib/common_test/src/ct_suite_callback.erl b/lib/common_test/src/ct_suite_callback.erl index 508d3b5bd6..947fa0c716 100644 --- a/lib/common_test/src/ct_suite_callback.erl +++ b/lib/common_test/src/ct_suite_callback.erl @@ -45,7 +45,7 @@ -spec init(State :: term()) -> ok | {error, Reason :: term()}. init(Opts) -> - call([{CB, call_init, undefined} || CB <- get_new_callbacks(Opts)], + call([{CB, call_id, undefined} || CB <- get_new_callbacks(Opts)], ok, init, []). @@ -130,12 +130,16 @@ on_tc_fail(_How, {_Suite, Case, Reason}) -> %% ------------------------------------------------------------------------- %% Internal Functions %% ------------------------------------------------------------------------- -call_init(Mod, Config, Meta) when is_atom(Mod) -> - call_init({Mod, []}, Config, Meta); -call_init({Mod, State}, Config, Scope) -> - {Id, NewState} = Mod:init(State), - {Config, {Id, scope(Scope), {Mod, NewState}}}. +call_id(Mod, Config, Meta) when is_atom(Mod) -> + call_id({Mod, []}, Config, Meta); +call_id({Mod, Opts}, Config, Scope) -> + Id = catch_apply(Mod,id,[Opts], make_ref()), + {Config, {Id, scope(Scope), {Mod, {Id,Opts}}}}. +call_init({Mod,{Id,Opts}},Config,_Meta) -> + NewState = Mod:init(Id, Opts), + {Config, {Mod, NewState}}. + call_terminate({Mod, State}, _, _) -> catch_apply(Mod,terminate,[State], ok), {[],{Mod,State}}. @@ -166,19 +170,20 @@ call(Fun, Config, Meta, NoChangeRet) when is_function(Fun) -> NewReturn -> NewReturn end; -call([{CB, call_init, NextFun} | Rest], Config, Meta, CBs) -> +call([{CB, call_id, NextFun} | Rest], Config, Meta, CBs) -> try - {Config, {NewId, _, {Mod,_State}} = NewCB} = call_init(CB, Config, Meta), - {NewCBs, NewRest} = case lists:keyfind(NewId, 1, CBs) of - false when NextFun == undefined -> - {CBs ++ [NewCB],Rest}; - ExistingCB when is_tuple(ExistingCB) -> - {CBs, Rest}; - _ -> - {CBs ++ [NewCB],[{NewId, NextFun} | Rest]} - end, - ct_logs:log("Suite Callback","Started a SCB: Mod: ~p, Id: ~p", - [Mod,NewId]), + {Config, {NewId, _, _} = NewCB} = call_id(CB, Config, Meta), + {NewCBs, NewRest} = + case lists:keyfind(NewId, 1, CBs) of + false when NextFun =:= undefined -> + {CBs ++ [NewCB], + [{NewId, fun call_init/3} | Rest]}; + ExistingCB when is_tuple(ExistingCB) -> + {CBs, Rest}; + _ -> + {CBs ++ [NewCB], + [{NewId, fun call_init/3},{NewId,NextFun} | Rest]} + end, call(NewRest, Config, Meta, NewCBs) catch Error:Reason -> Trace = erlang:get_stacktrace(), @@ -237,7 +242,7 @@ terminate_if_scope_ends(CBId, Function, CBs) -> %% Fetch callback functions get_new_callbacks(Config, Fun) -> lists:foldl(fun(NewCB, Acc) -> - [{NewCB, call_init, Fun} | Acc] + [{NewCB, call_id, Fun} | Acc] end, [], get_new_callbacks(Config)). get_new_callbacks(Config) when is_list(Config) -> diff --git a/lib/common_test/test/ct_suite_callback_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE.erl index adb950614e..19feacad1d 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE.erl @@ -72,7 +72,8 @@ all() -> all(suite) -> lists:reverse( [ - one_scb, two_scb, faulty_scb_no_init, faulty_scb_exit_in_init, + one_scb, two_scb, faulty_scb_no_init, faulty_scb_id_no_init, + faulty_scb_exit_in_init, faulty_scb_exit_in_id, faulty_scb_exit_in_init_scope_suite, minimal_scb, minimal_and_maximal_scb, faulty_scb_undef, scope_per_suite_scb, scope_per_group_scb, scope_suite_scb, @@ -104,6 +105,11 @@ faulty_scb_no_init(Config) when is_list(Config) -> Config,{error,"Failed to start SCB, see the " "CT Log for details"}). +faulty_scb_id_no_init(Config) when is_list(Config) -> + do_test(faulty_scb_id_no_init, "ct_scb_empty_SUITE.erl",[id_no_init_scb], + Config,{error,"Failed to start SCB, see the " + "CT Log for details"}). + minimal_scb(Config) when is_list(Config) -> do_test(minimal_scb, "ct_scb_empty_SUITE.erl",[minimal_scb],Config). @@ -126,6 +132,12 @@ faulty_scb_exit_in_init(Config) when is_list(Config) -> {error,"Failed to start SCB, see the " "CT Log for details"}). +faulty_scb_exit_in_id(Config) when is_list(Config) -> + do_test(faulty_scb_exit_in_id, "ct_scb_empty_SUITE.erl", + [crash_id_scb], Config, + {error,"Failed to start SCB, see the " + "CT Log for details"}). + scope_per_suite_scb(Config) when is_list(Config) -> do_test(scope_per_suite_scb, "ct_scope_per_suite_scb_SUITE.erl", [],Config). @@ -243,7 +255,8 @@ events_to_check(Test, N) -> test_events(one_empty_scb) -> [ {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{empty_scb,init,[[]]}}, + {?eh,scb,{empty_scb,id,[[]]}}, + {?eh,scb,{empty_scb,init,[{'_','_','_'},[]]}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, {?eh,scb,{empty_scb,pre_init_per_suite, @@ -270,8 +283,10 @@ test_events(one_empty_scb) -> test_events(two_empty_scb) -> [ {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{'_',init,[[]]}}, - {?eh,scb,{'_',init,[[]]}}, + {?eh,scb,{'_',id,[[]]}}, + {?eh,scb,{'_',init,['_',[]]}}, + {?eh,scb,{'_',id,[[]]}}, + {?eh,scb,{'_',init,['_',[]]}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, {?eh,scb,{'_',pre_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, @@ -307,10 +322,21 @@ test_events(faulty_scb_no_init) -> {?eh,stop_logging,[]} ]; +test_events(faulty_scb_id_no_init) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,scb,{'_',id,[[]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {negative,{?eh,tc_start,'_'}, + {?eh,test_done,{'DEF','STOP_TIME'}}}, + {?eh,stop_logging,[]} + ]; + test_events(minimal_scb) -> [ {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{'_',init,[[]]}}, + {negative,{?eh,scb,{'_',id,['_',[]]}}, + {?eh,scb,{'_',init,['_',[]]}}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite,ok}}, @@ -327,8 +353,10 @@ test_events(minimal_scb) -> test_events(minimal_and_maximal_scb) -> [ {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{'_',init,[[]]}}, - {?eh,scb,{'_',init,[[]]}}, + {negative,{?eh,scb,{'_',id,['_',[]]}}, + {?eh,scb,{'_',init,['_',[]]}}}, + {?eh,scb,{'_',id,[[]]}}, + {?eh,scb,{'_',init,['_',[]]}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, {?eh,scb,{'_',pre_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, @@ -355,7 +383,7 @@ test_events(faulty_scb_undef) -> {failed,FailReasonStr}}, [ {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{'_',init,[[]]}}, + {?eh,scb,{'_',init,['_',[]]}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite, @@ -378,7 +406,7 @@ test_events(faulty_scb_exit_in_init_scope_suite) -> [{?eh,start_logging,{'DEF','RUNDIR'}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,tc_start,{'_',init_per_suite}}, - {?eh,scb,{empty_scb,init,[[]]}}, + {?eh,scb,{empty_scb,init,['_',[]]}}, {?eh,tc_done, {ct_exit_in_init_scope_suite_scb_SUITE,init_per_suite, {failed, @@ -401,17 +429,26 @@ test_events(faulty_scb_exit_in_init_scope_suite) -> test_events(faulty_scb_exit_in_init) -> [{?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{empty_scb,init,[[]]}}, + {?eh,scb,{empty_scb,init,['_',[]]}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,test_done,{'DEF','STOP_TIME'}}, {?eh,stop_logging,[]}]; +test_events(faulty_scb_exit_in_id) -> + [{?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,scb,{empty_scb,id,[[]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {negative, {?eh,tc_start,'_'}, + {?eh,test_done,{'DEF','STOP_TIME'}}}, + {?eh,stop_logging,[]}]; + test_events(scope_per_suite_scb) -> [ {?eh,start_logging,{'DEF','RUNDIR'}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,tc_start,{ct_scope_per_suite_scb_SUITE,init_per_suite}}, - {?eh,scb,{'_',init,[[]]}}, + {?eh,scb,{'_',id,[[]]}}, + {?eh,scb,{'_',init,['_',[]]}}, {?eh,scb,{'_',post_init_per_suite,[ct_scope_per_suite_scb_SUITE,'$proplist','$proplist',[]]}}, {?eh,tc_done,{ct_scope_per_suite_scb_SUITE,init_per_suite,ok}}, @@ -435,7 +472,8 @@ test_events(scope_suite_scb) -> {?eh,start_logging,{'DEF','RUNDIR'}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,tc_start,{ct_scope_suite_scb_SUITE,init_per_suite}}, - {?eh,scb,{'_',init,[[]]}}, + {?eh,scb,{'_',id,[[]]}}, + {?eh,scb,{'_',init,['_',[]]}}, {?eh,scb,{'_',pre_init_per_suite,[ct_scope_suite_scb_SUITE,'$proplist',[]]}}, {?eh,scb,{'_',post_init_per_suite,[ct_scope_suite_scb_SUITE,'$proplist','$proplist',[]]}}, {?eh,tc_done,{ct_scope_suite_scb_SUITE,init_per_suite,ok}}, @@ -462,7 +500,8 @@ test_events(scope_per_group_scb) -> {?eh,tc_done,{ct_scope_per_group_scb_SUITE,init_per_suite,ok}}, [{?eh,tc_start,{ct_scope_per_group_scb_SUITE,{init_per_group,group1,[]}}}, - {?eh,scb,{'_',init,[[]]}}, + {?eh,scb,{'_',id,[[]]}}, + {?eh,scb,{'_',init,['_',[]]}}, {?eh,scb,{'_',post_init_per_group,[group1,'$proplist','$proplist',[]]}}, {?eh,tc_done,{ct_scope_per_group_scb_SUITE,{init_per_group,group1,[]},ok}}, @@ -488,7 +527,8 @@ test_events(scope_per_suite_state_scb) -> {?eh,start_logging,{'DEF','RUNDIR'}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,tc_start,{ct_scope_per_suite_state_scb_SUITE,init_per_suite}}, - {?eh,scb,{'_',init,[[test]]}}, + {?eh,scb,{'_',id,[[test]]}}, + {?eh,scb,{'_',init,['_',[test]]}}, {?eh,scb,{'_',post_init_per_suite,[ct_scope_per_suite_state_scb_SUITE,'$proplist','$proplist',[test]]}}, {?eh,tc_done,{ct_scope_per_suite_state_scb_SUITE,init_per_suite,ok}}, @@ -512,7 +552,8 @@ test_events(scope_suite_state_scb) -> {?eh,start_logging,{'DEF','RUNDIR'}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,tc_start,{ct_scope_suite_state_scb_SUITE,init_per_suite}}, - {?eh,scb,{'_',init,[[test]]}}, + {?eh,scb,{'_',id,[[test]]}}, + {?eh,scb,{'_',init,['_',[test]]}}, {?eh,scb,{'_',pre_init_per_suite,[ct_scope_suite_state_scb_SUITE,'$proplist',[test]]}}, {?eh,scb,{'_',post_init_per_suite,[ct_scope_suite_state_scb_SUITE,'$proplist','$proplist',[test]]}}, {?eh,tc_done,{ct_scope_suite_state_scb_SUITE,init_per_suite,ok}}, @@ -539,7 +580,8 @@ test_events(scope_per_group_state_scb) -> {?eh,tc_done,{ct_scope_per_group_state_scb_SUITE,init_per_suite,ok}}, [{?eh,tc_start,{ct_scope_per_group_state_scb_SUITE,{init_per_group,group1,[]}}}, - {?eh,scb,{'_',init,[[test]]}}, + {?eh,scb,{'_',id,[[test]]}}, + {?eh,scb,{'_',init,['_',[test]]}}, {?eh,scb,{'_',post_init_per_group,[group1,'$proplist','$proplist',[test]]}}, {?eh,tc_done,{ct_scope_per_group_state_scb_SUITE,{init_per_group,group1,[]},ok}}, @@ -563,7 +605,7 @@ test_events(scope_per_group_state_scb) -> test_events(fail_pre_suite_scb) -> [ {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{'_',init,[[]]}}, + {?eh,scb,{'_',init,['_',[]]}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, @@ -603,7 +645,7 @@ test_events(fail_pre_suite_scb) -> test_events(fail_post_suite_scb) -> [ {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{'_',init,[[]]}}, + {?eh,scb,{'_',init,['_',[]]}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, {?eh,scb,{'_',pre_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, @@ -630,7 +672,7 @@ test_events(fail_post_suite_scb) -> test_events(skip_pre_suite_scb) -> [ {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{'_',init,[[]]}}, + {?eh,scb,{'_',init,['_',[]]}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, {?eh,scb,{'_',pre_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, @@ -653,7 +695,7 @@ test_events(skip_pre_suite_scb) -> test_events(skip_post_suite_scb) -> [ {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{'_',init,[[]]}}, + {?eh,scb,{'_',init,['_',[]]}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, @@ -678,7 +720,7 @@ test_events(recover_post_suite_scb) -> Suite = ct_scb_fail_per_suite_SUITE, [ {?eh,start_logging,'_'}, - {?eh,scb,{'_',init,[[]]}}, + {?eh,scb,{'_',init,['_',[]]}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,tc_start,{Suite,init_per_suite}}, {?eh,scb,{'_',pre_init_per_suite,[Suite,'$proplist','$proplist']}}, @@ -707,7 +749,7 @@ test_events(recover_post_suite_scb) -> test_events(update_config_scb) -> [ {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{'_',init,[[]]}}, + {?eh,scb,{'_',init,['_',[]]}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,tc_start,{ct_update_config_SUITE,init_per_suite}}, @@ -818,8 +860,8 @@ test_events(update_config_scb) -> test_events(state_update_scb) -> [ {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{'_',init,[[]]}}, - {?eh,scb,{'_',init,[[]]}}, + {?eh,scb,{'_',init,['_',[]]}}, + {?eh,scb,{'_',init,['_',[]]}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,tc_start,{'_',init_per_suite}}, @@ -856,7 +898,7 @@ test_events(state_update_scb) -> test_events(options_scb) -> [ {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{empty_scb,init,[[test]]}}, + {?eh,scb,{empty_scb,init,['_',[test]]}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, {?eh,scb,{empty_scb,pre_init_per_suite, @@ -883,8 +925,9 @@ test_events(options_scb) -> test_events(same_id_scb) -> [ {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{'_',init,[[]]}}, - {?eh,scb,{'_',init,[[]]}}, + {?eh,scb,{'_',id,[[]]}}, + {?eh,scb,{'_',init,[same_id_scb,[]]}}, + {?eh,scb,{'_',id,[[]]}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, {?eh,scb,{'_',pre_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/crash_id_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/crash_id_scb.erl new file mode 100644 index 0000000000..2c256c46df --- /dev/null +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/crash_id_scb.erl @@ -0,0 +1,34 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(crash_id_scb). + + +-include_lib("common_test/src/ct_util.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + + +%% Suite Callbacks +-export([id/1]). + +id(Opts) -> + empty_scb:id(Opts), + exit(diediedie). + diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/crash_init_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/crash_init_scb.erl index 683459853f..c4138bbcef 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/crash_init_scb.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/crash_init_scb.erl @@ -26,9 +26,9 @@ %% Suite Callbacks --export([init/1]). +-export([init/2]). -init(Opts) -> - empty_scb:init(Opts), +init(Id, Opts) -> + empty_scb:init(Id, Opts), exit(diediedie). diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/empty_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/empty_scb.erl index d9aa1e77e4..a82ca02d04 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/empty_scb.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/empty_scb.erl @@ -35,7 +35,8 @@ -module(empty_scb). %% Suite Callbacks --export([init/1]). +-export([id/1]). +-export([init/2]). -export([pre_init_per_suite/3]). -export([post_init_per_suite/4]). @@ -68,16 +69,23 @@ -record(state, { id = ?MODULE :: term()}). %% @doc Always called before any other callback function. Use this to initiate -%% any common state. It should return an ID for this SCB and a state. The ID -%% is used to uniquly identify an SCB instance, if two SCB's return the same -%% ID the seconds SCB is ignored. This function should NOT have any side -%% effects as it might be called multiple times by common test. --spec init(Opts :: proplist()) -> +%% any common state. It should return an ID for this SCB and a state. +-spec init(Id :: term(), Opts :: proplist()) -> {Id :: term(), State :: #state{}}. -init(Opts) -> +init(Id, Opts) -> gen_event:notify(?CT_EVMGR_REF, #event{ name = scb, node = node(), - data = {?MODULE, init, [Opts]}}), - {now(), Opts}. + data = {?MODULE, init, [Id, Opts]}}), + Opts. + +%% @doc The ID is used to uniquly identify an SCB instance, if two SCB's +%% return the same ID the seconds SCB is ignored. This function should NOT +%% have any side effects as it might be called multiple times by common test. +-spec id(Opts :: proplist()) -> + Id :: term(). +id(Opts) -> + gen_event:notify(?CT_EVMGR_REF, #event{ name = scb, node = node(), + data = {?MODULE, id, [Opts]}}), + now(). %% @doc Called before init_per_suite is called. Note that this callback is %% only called if the SCB is added before init_per_suite is run (eg. in a test diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/fail_post_suite_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/fail_post_suite_scb.erl index b3a3a5f94c..44c72f6795 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/fail_post_suite_scb.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/fail_post_suite_scb.erl @@ -28,8 +28,8 @@ %% Suite Callbacks -compile(export_all). -init(Opts) -> - empty_scb:init(Opts). +init(Id, Opts) -> + empty_scb:init(Id, Opts). pre_init_per_suite(Suite, Config, State) -> empty_scb:pre_init_per_suite(Suite,Config,State). diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/fail_pre_suite_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/fail_pre_suite_scb.erl index d49387ff8c..90f10d7531 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/fail_pre_suite_scb.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/fail_pre_suite_scb.erl @@ -28,8 +28,8 @@ %% Suite Callbacks -compile(export_all). -init(Opts) -> - empty_scb:init(Opts). +init(Id, Opts) -> + empty_scb:init(Id, Opts). pre_init_per_suite(Suite, Config, State) -> empty_scb:pre_init_per_suite(Suite,Config,State), diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/id_no_init_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/id_no_init_scb.erl new file mode 100644 index 0000000000..11fb8d739f --- /dev/null +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/id_no_init_scb.erl @@ -0,0 +1,32 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(id_no_init_scb). + + +-include_lib("common_test/src/ct_util.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + + +%% Suite Callbacks +-export([id/1]). + +id(Opts) -> + empty_scb:id(Opts). diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/minimal_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/minimal_scb.erl index e5fdbfb8a0..b3feb1383c 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/minimal_scb.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/minimal_scb.erl @@ -26,8 +26,8 @@ %% Suite Callbacks --export([init/1]). +-export([init/2]). -init(Opts) -> - empty_scb:init(Opts). +init(Id, Opts) -> + empty_scb:init(Id, Opts). diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/recover_post_suite_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/recover_post_suite_scb.erl index 864a09e3d0..26468f0789 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/recover_post_suite_scb.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/recover_post_suite_scb.erl @@ -28,8 +28,8 @@ %% Suite Callbacks -compile(export_all). -init(Opts) -> - empty_scb:init(Opts). +init(Id, Opts) -> + empty_scb:init(Id, Opts). pre_init_per_suite(Suite, Config, State) -> empty_scb:pre_init_per_suite(Suite,Config,State). diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/same_id_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/same_id_scb.erl index 6853aa52e8..0fa708d5b6 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/same_id_scb.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/same_id_scb.erl @@ -28,9 +28,12 @@ %% Suite Callbacks -compile(export_all). -init(Opts) -> - {_,State} = empty_scb:init(Opts), - {?MODULE,State}. +id(Opts) -> + empty_scb:id(Opts), + ?MODULE. + +init(Id, Opts) -> + empty_scb:init(Id, Opts). pre_init_per_suite(Suite, Config, State) -> empty_scb:pre_init_per_suite(Suite,Config,State). diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/skip_post_suite_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/skip_post_suite_scb.erl index a2e0578814..bb93ebee0f 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/skip_post_suite_scb.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/skip_post_suite_scb.erl @@ -28,8 +28,8 @@ %% Suite Callbacks -compile(export_all). -init(Opts) -> - empty_scb:init(Opts). +init(Id, Opts) -> + empty_scb:init(Id, Opts). pre_init_per_suite(Suite, Config, State) -> empty_scb:pre_init_per_suite(Suite,Config,State). diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/skip_pre_suite_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/skip_pre_suite_scb.erl index 4a0725ce2f..9818964e7f 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/skip_pre_suite_scb.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/skip_pre_suite_scb.erl @@ -28,8 +28,8 @@ %% Suite Callbacks -compile(export_all). -init(Opts) -> - empty_scb:init(Opts). +init(Id, Opts) -> + empty_scb:init(Id, Opts). pre_init_per_suite(Suite, Config, State) -> diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/state_update_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/state_update_scb.erl index 1da0f7a6e4..13c50cf1a1 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/state_update_scb.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/state_update_scb.erl @@ -27,9 +27,9 @@ %% Suite Callbacks -compile(export_all). -init(Opts) -> - {Id,State} = empty_scb:init(Opts), - {Id,[init|State]}. +init(Id, Opts) -> + State = empty_scb:init(Id, Opts), + [init|State]. pre_init_per_suite(Suite, Config, State) -> empty_scb:pre_init_per_suite(Suite,Config,State), diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/undef_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/undef_scb.erl index 9479f9d937..1cb64574c3 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/undef_scb.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/undef_scb.erl @@ -28,8 +28,8 @@ %% Suite Callbacks -compile(export_all). -init(Opts) -> - empty_scb:init(Opts). +init(Id, Opts) -> + empty_scb:init(Id, Opts). pre_init_per_suite(_Suite, _Config, _State) -> lists:flaten([1,2,[3,4]]). diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/update_config_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/update_config_scb.erl index 6f21e49656..46a027403d 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/update_config_scb.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/update_config_scb.erl @@ -28,8 +28,8 @@ %% Suite Callbacks -compile(export_all). -init(Opts) -> - empty_scb:init(Opts). +init(Id, Opts) -> + empty_scb:init(Id, Opts). pre_init_per_suite(Suite, Config, State) -> empty_scb:pre_init_per_suite(Suite,Config,State), -- cgit v1.2.3 From ff8d3f0f39b0d1347cd94e1d0d3ab422ad7b06d7 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Wed, 9 Feb 2011 14:01:39 +0100 Subject: Fix bug where the state of an SCB was altered when no on_tc_* existed --- lib/common_test/src/ct_suite_callback.erl | 4 +-- lib/common_test/test/ct_suite_callback_SUITE.erl | 21 ++++++++++-- .../scb/tests/minimal_terminate_scb.erl | 38 ++++++++++++++++++++++ 3 files changed, 57 insertions(+), 6 deletions(-) create mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/minimal_terminate_scb.erl (limited to 'lib/common_test') diff --git a/lib/common_test/src/ct_suite_callback.erl b/lib/common_test/src/ct_suite_callback.erl index 947fa0c716..a93b05b1d2 100644 --- a/lib/common_test/src/ct_suite_callback.erl +++ b/lib/common_test/src/ct_suite_callback.erl @@ -34,8 +34,6 @@ -type proplist() :: [{atom(),term()}]. -define(config_name, suite_callbacks). --define(LOCK_STATE_TIMEOUT, 500). --define(LOCK_NAME, '$ct_suite_callback_lock'). %% ------------------------------------------------------------------------- %% API Functions @@ -146,7 +144,7 @@ call_terminate({Mod, State}, _, _) -> call_cleanup({Mod, State}, Reason, [Function | Args]) -> NewState = catch_apply(Mod,Function, Args ++ [Reason, State], - {Reason,State}), + State), {Reason, {Mod, NewState}}. call_generic({Mod, State}, Value, [Function | Args]) -> diff --git a/lib/common_test/test/ct_suite_callback_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE.erl index 19feacad1d..67f3cf430a 100644 --- a/lib/common_test/test/ct_suite_callback_SUITE.erl +++ b/lib/common_test/test/ct_suite_callback_SUITE.erl @@ -81,7 +81,8 @@ all(suite) -> scope_suite_state_scb, fail_pre_suite_scb, fail_post_suite_scb, skip_pre_suite_scb, skip_post_suite_scb, recover_post_suite_scb, update_config_scb, - state_update_scb, options_scb, same_id_scb + state_update_scb, options_scb, same_id_scb, + fail_n_skip_with_minimal_scb ] ) . @@ -197,7 +198,10 @@ options_scb(Config) when is_list(Config) -> same_id_scb(Config) when is_list(Config) -> do_test(same_id_scb, "ct_scb_empty_SUITE.erl", [same_id_scb,same_id_scb],Config). - + +fail_n_skip_with_minimal_scb(Config) when is_list(Config) -> + do_test(fail_n_skip_with_minimal_scb, "ct_scb_fail_one_skip_one_SUITE.erl", + [minimal_terminate_scb],Config). %%%----------------------------------------------------------------- %%% HELP FUNCTIONS @@ -963,6 +967,17 @@ test_events(same_id_scb) -> {?eh,stop_logging,[]} ]; +test_events(fail_n_skip_with_minimal_scb) -> + [{?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,scb,{'_',init,['_',[]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{'_',init_per_suite}}, + + {?eh,tc_done,{'_',end_per_suite,ok}}, + {?eh,scb,{'_',terminate,[[]]}}, + {?eh,stop_logging,[]} + ]; + test_events(ok) -> ok. @@ -995,7 +1010,7 @@ contains([],_) -> contains_parallel([Key | T], Elems) -> contains([Key],Elems), contains_parallel(T,Elems); -contains_parallel([],Elems) -> +contains_parallel([],_Elems) -> match. not_contains(List) -> diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/minimal_terminate_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/minimal_terminate_scb.erl new file mode 100644 index 0000000000..3f76d2f47d --- /dev/null +++ b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/minimal_terminate_scb.erl @@ -0,0 +1,38 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(minimal_terminate_scb). + + +-include_lib("common_test/src/ct_util.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + + +%% Suite Callbacks +-export([init/2]). +-export([terminate/1]). + +init(Id, Opts) -> + empty_scb:init(Id, Opts). + +terminate(State) -> + empty_scb:terminate(State). + + -- cgit v1.2.3 From ade343808a1a634bd39ab1c94ecadfd070a189de Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Wed, 9 Feb 2011 15:49:32 +0100 Subject: Rename Suite Callback to Common Test Hook in code and testcases --- lib/common_test/src/Makefile | 4 +- lib/common_test/src/ct.erl | 8 +- lib/common_test/src/ct_framework.erl | 40 +- lib/common_test/src/ct_hooks.erl | 305 ++++++ lib/common_test/src/ct_hooks_lock.erl | 132 +++ lib/common_test/src/ct_run.erl | 110 +-- lib/common_test/src/ct_suite_callback.erl | 304 ------ lib/common_test/src/ct_suite_callback_lock.erl | 131 --- lib/common_test/src/ct_testspec.erl | 24 +- lib/common_test/src/ct_util.erl | 14 +- lib/common_test/src/ct_util.hrl | 2 +- lib/common_test/test/Makefile | 2 +- .../ct_error_SUITE_data/error/test/empty_scb.erl | 187 ---- lib/common_test/test/ct_hooks_SUITE.erl | 1021 ++++++++++++++++++++ .../ct_hooks_SUITE_data/cth/tests/crash_id_cth.erl | 34 + .../cth/tests/crash_init_cth.erl | 34 + .../cth/tests/ct_cth_empty_SUITE.erl | 47 + .../cth/tests/ct_cth_fail_one_skip_one_SUITE.erl | 64 ++ .../cth/tests/ct_cth_fail_per_suite_SUITE.erl | 47 + .../ct_exit_in_init_scope_suite_cth_SUITE.erl | 50 + .../cth/tests/ct_scope_per_group_cth_SUITE.erl | 56 ++ .../tests/ct_scope_per_group_state_cth_SUITE.erl | 56 ++ .../cth/tests/ct_scope_per_suite_cth_SUITE.erl | 47 + .../tests/ct_scope_per_suite_state_cth_SUITE.erl | 47 + .../cth/tests/ct_scope_per_tc_cth_SUITE.erl | 110 +++ .../cth/tests/ct_scope_suite_cth_SUITE.erl | 50 + .../cth/tests/ct_scope_suite_state_cth_SUITE.erl | 50 + .../cth/tests/ct_update_config_SUITE.erl | 56 ++ .../ct_hooks_SUITE_data/cth/tests/empty_cth.erl | 277 ++++++ .../cth/tests/fail_post_suite_cth.erl | 72 ++ .../cth/tests/fail_pre_suite_cth.erl | 72 ++ .../cth/tests/id_no_init_cth.erl | 32 + .../ct_hooks_SUITE_data/cth/tests/minimal_cth.erl | 33 + .../cth/tests/minimal_terminate_cth.erl | 38 + .../cth/tests/recover_post_suite_cth.erl | 74 ++ .../ct_hooks_SUITE_data/cth/tests/same_id_cth.erl | 75 ++ .../cth/tests/skip_post_suite_cth.erl | 72 ++ .../cth/tests/skip_pre_suite_cth.erl | 73 ++ .../cth/tests/state_update_cth.erl | 83 ++ .../ct_hooks_SUITE_data/cth/tests/undef_cth.erl | 71 ++ .../cth/tests/update_config_cth.erl | 82 ++ lib/common_test/test/ct_suite_callback_SUITE.erl | 1021 -------------------- .../scb/tests/crash_id_scb.erl | 34 - .../scb/tests/crash_init_scb.erl | 34 - .../ct_exit_in_init_scope_suite_scb_SUITE.erl | 50 - .../scb/tests/ct_scb_empty_SUITE.erl | 47 - .../scb/tests/ct_scb_fail_one_skip_one_SUITE.erl | 64 -- .../scb/tests/ct_scb_fail_per_suite_SUITE.erl | 47 - .../scb/tests/ct_scope_per_group_scb_SUITE.erl | 56 -- .../tests/ct_scope_per_group_state_scb_SUITE.erl | 56 -- .../scb/tests/ct_scope_per_suite_scb_SUITE.erl | 47 - .../tests/ct_scope_per_suite_state_scb_SUITE.erl | 47 - .../scb/tests/ct_scope_per_tc_scb_SUITE.erl | 110 --- .../scb/tests/ct_scope_suite_scb_SUITE.erl | 50 - .../scb/tests/ct_scope_suite_state_scb_SUITE.erl | 50 - .../scb/tests/ct_update_config_SUITE.erl | 56 -- .../scb/tests/empty_scb.erl | 277 ------ .../scb/tests/fail_post_suite_scb.erl | 72 -- .../scb/tests/fail_pre_suite_scb.erl | 72 -- .../scb/tests/id_no_init_scb.erl | 32 - .../scb/tests/minimal_scb.erl | 33 - .../scb/tests/minimal_terminate_scb.erl | 38 - .../scb/tests/recover_post_suite_scb.erl | 74 -- .../scb/tests/same_id_scb.erl | 75 -- .../scb/tests/skip_post_suite_scb.erl | 72 -- .../scb/tests/skip_pre_suite_scb.erl | 73 -- .../scb/tests/state_update_scb.erl | 83 -- .../scb/tests/undef_scb.erl | 71 -- .../scb/tests/update_config_scb.erl | 82 -- 69 files changed, 3362 insertions(+), 3547 deletions(-) create mode 100644 lib/common_test/src/ct_hooks.erl create mode 100644 lib/common_test/src/ct_hooks_lock.erl delete mode 100644 lib/common_test/src/ct_suite_callback.erl delete mode 100644 lib/common_test/src/ct_suite_callback_lock.erl delete mode 100644 lib/common_test/test/ct_error_SUITE_data/error/test/empty_scb.erl create mode 100644 lib/common_test/test/ct_hooks_SUITE.erl create mode 100644 lib/common_test/test/ct_hooks_SUITE_data/cth/tests/crash_id_cth.erl create mode 100644 lib/common_test/test/ct_hooks_SUITE_data/cth/tests/crash_init_cth.erl create mode 100644 lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_cth_empty_SUITE.erl create mode 100644 lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_cth_fail_one_skip_one_SUITE.erl create mode 100644 lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_cth_fail_per_suite_SUITE.erl create mode 100644 lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_exit_in_init_scope_suite_cth_SUITE.erl create mode 100644 lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_per_group_cth_SUITE.erl create mode 100644 lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_per_group_state_cth_SUITE.erl create mode 100644 lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_per_suite_cth_SUITE.erl create mode 100644 lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_per_suite_state_cth_SUITE.erl create mode 100644 lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_per_tc_cth_SUITE.erl create mode 100644 lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_suite_cth_SUITE.erl create mode 100644 lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_suite_state_cth_SUITE.erl create mode 100644 lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_update_config_SUITE.erl create mode 100644 lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl create mode 100644 lib/common_test/test/ct_hooks_SUITE_data/cth/tests/fail_post_suite_cth.erl create mode 100644 lib/common_test/test/ct_hooks_SUITE_data/cth/tests/fail_pre_suite_cth.erl create mode 100644 lib/common_test/test/ct_hooks_SUITE_data/cth/tests/id_no_init_cth.erl create mode 100644 lib/common_test/test/ct_hooks_SUITE_data/cth/tests/minimal_cth.erl create mode 100644 lib/common_test/test/ct_hooks_SUITE_data/cth/tests/minimal_terminate_cth.erl create mode 100644 lib/common_test/test/ct_hooks_SUITE_data/cth/tests/recover_post_suite_cth.erl create mode 100644 lib/common_test/test/ct_hooks_SUITE_data/cth/tests/same_id_cth.erl create mode 100644 lib/common_test/test/ct_hooks_SUITE_data/cth/tests/skip_post_suite_cth.erl create mode 100644 lib/common_test/test/ct_hooks_SUITE_data/cth/tests/skip_pre_suite_cth.erl create mode 100644 lib/common_test/test/ct_hooks_SUITE_data/cth/tests/state_update_cth.erl create mode 100644 lib/common_test/test/ct_hooks_SUITE_data/cth/tests/undef_cth.erl create mode 100644 lib/common_test/test/ct_hooks_SUITE_data/cth/tests/update_config_cth.erl delete mode 100644 lib/common_test/test/ct_suite_callback_SUITE.erl delete mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/crash_id_scb.erl delete mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/crash_init_scb.erl delete mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_exit_in_init_scope_suite_scb_SUITE.erl delete mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scb_empty_SUITE.erl delete mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scb_fail_one_skip_one_SUITE.erl delete mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scb_fail_per_suite_SUITE.erl delete mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_group_scb_SUITE.erl delete mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_group_state_scb_SUITE.erl delete mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_suite_scb_SUITE.erl delete mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_suite_state_scb_SUITE.erl delete mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_tc_scb_SUITE.erl delete mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_suite_scb_SUITE.erl delete mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_suite_state_scb_SUITE.erl delete mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_update_config_SUITE.erl delete mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/empty_scb.erl delete mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/fail_post_suite_scb.erl delete mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/fail_pre_suite_scb.erl delete mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/id_no_init_scb.erl delete mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/minimal_scb.erl delete mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/minimal_terminate_scb.erl delete mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/recover_post_suite_scb.erl delete mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/same_id_scb.erl delete mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/skip_post_suite_scb.erl delete mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/skip_pre_suite_scb.erl delete mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/state_update_scb.erl delete mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/undef_scb.erl delete mode 100644 lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/update_config_scb.erl (limited to 'lib/common_test') diff --git a/lib/common_test/src/Makefile b/lib/common_test/src/Makefile index abf7816a91..378a7ba08c 100644 --- a/lib/common_test/src/Makefile +++ b/lib/common_test/src/Makefile @@ -68,8 +68,8 @@ MODULES= \ ct_config_plain \ ct_config_xml \ ct_slave \ - ct_suite_callback\ - ct_suite_callback_lock + ct_hooks\ + ct_hooks_lock TARGET_MODULES= $(MODULES:%=$(EBIN)/%) diff --git a/lib/common_test/src/ct.erl b/lib/common_test/src/ct.erl index eb0eceeb46..b0a92dcc15 100644 --- a/lib/common_test/src/ct.erl +++ b/lib/common_test/src/ct.erl @@ -149,7 +149,7 @@ run(TestDirs) -> %%% {repeat,N} | {duration,DurTime} | {until,StopTime} | %%% {force_stop,Bool} | {decrypt,DecryptKeyOrFile} | %%% {refresh_logs,LogDir} | {basic_html,Bool} | -%%% {suite_callbacks, SCBs} +%%% {ct_hooks, CTHs} %%% TestDirs = [string()] | string() %%% Suites = [string()] | string() %%% Cases = [atom()] | atom() @@ -177,9 +177,9 @@ run(TestDirs) -> %%% DecryptKeyOrFile = {key,DecryptKey} | {file,DecryptFile} %%% DecryptKey = string() %%% DecryptFile = string() -%%% SCBs = [SCBModule | {SCBModule, SCBInitArgs}] -%%% SCBModule = atom() -%%% SCBInitArgs = term() +%%% CTHs = [CTHModule | {CTHModule, CTHInitArgs}] +%%% CTHModule = atom() +%%% CTHInitArgs = term() %%% Result = [TestResult] | {error,Reason} %%% @doc Run tests as specified by the combination of options in Opts. %%% The options are the same as those used with the diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl index d05c30f5e1..04829004f4 100644 --- a/lib/common_test/src/ct_framework.erl +++ b/lib/common_test/src/ct_framework.erl @@ -229,7 +229,7 @@ init_tc2(Mod,Func,SuiteInfo,MergeResult,Config,DoInit) -> end. ct_suite_init(Mod, Func, [Config]) when is_list(Config) -> - case ct_suite_callback:init_tc( Mod, Func, Config) of + case ct_hooks:init_tc( Mod, Func, Config) of NewConfig when is_list(NewConfig) -> {ok, [NewConfig]}; Else -> @@ -251,9 +251,9 @@ add_defaults(Mod,Func,FuncInfo,DoInit) -> (_) -> false end, SuiteInfo) of true -> - SuiteInfoNoSCB = - lists:keydelete(suite_callbacks,1,SuiteInfo), - SuiteInfo1 = merge_with_suite_defaults(Mod,SuiteInfoNoSCB), + SuiteInfoNoCTH = + lists:keydelete(ct_hooks,1,SuiteInfo), + SuiteInfo1 = merge_with_suite_defaults(Mod,SuiteInfoNoCTH), case add_defaults1(Mod,Func,FuncInfo,SuiteInfo1,DoInit) of Error = {error,_} -> {SuiteInfo1,Error}; MergedInfo -> {SuiteInfo1,MergedInfo} @@ -376,8 +376,8 @@ configure([{timetrap,off}|Rest],Info,SuiteInfo,Scope,Config) -> configure([{timetrap,Time}|Rest],Info,SuiteInfo,Scope,Config) -> Dog = test_server:timetrap(Time), configure(Rest,Info,SuiteInfo,Scope,[{watchdog,Dog}|Config]); -configure([{suite_callbacks, CB} | Rest], Info, SuiteInfo, Scope, Config) -> - configure(Rest, Info, SuiteInfo, Scope, [{suite_callbacks, CB} | Config]); +configure([{ct_hooks, Hook} | Rest], Info, SuiteInfo, Scope, Config) -> + configure(Rest, Info, SuiteInfo, Scope, [{ct_hooks, Hook} | Config]); configure([_|Rest],Info,SuiteInfo,Scope,Config) -> configure(Rest,Info,SuiteInfo,Scope,Config); configure([],_,_,_,Config) -> @@ -487,7 +487,7 @@ end_tc(Mod,Func,TCPid,Result,Args,Return) -> case get('$test_server_framework_test') of undefined -> {FinalResult,FinalNotify} = - case ct_suite_callback:end_tc( + case ct_hooks:end_tc( Mod, FuncSpec, Args, Result, Return) of '$ct_no_change' -> {FinalResult = ok,Result}; @@ -499,7 +499,7 @@ end_tc(Mod,Func,TCPid,Result,Args,Return) -> ct_event:sync_notify(#event{name=tc_done, node=node(), data={Mod,FuncSpec, - tag_scb(FinalNotify)}}); + tag_cth(FinalNotify)}}); Fun -> % send sync notification so that event handlers may print % in the log file before it gets closed @@ -545,19 +545,19 @@ tag(E = testcase_aborted_or_killed) -> tag(Other) -> Other. -tag_scb({STag,Reason}) when STag == skip; STag == skipped -> +tag_cth({STag,Reason}) when STag == skip; STag == skipped -> {skipped,Reason}; -tag_scb({fail, Reason}) -> +tag_cth({fail, Reason}) -> {failed, {error,Reason}}; -tag_scb(E = {ETag,_}) when ETag == error; ETag == 'EXIT'; +tag_cth(E = {ETag,_}) when ETag == error; ETag == 'EXIT'; ETag == timetrap_timeout; ETag == testcase_aborted -> {failed,E}; -tag_scb(E = testcase_aborted_or_killed) -> +tag_cth(E = testcase_aborted_or_killed) -> {failed,E}; -tag_scb(List) when is_list(List) -> +tag_cth(List) when is_list(List) -> ok; -tag_scb(Other) -> +tag_cth(Other) -> Other. %%%----------------------------------------------------------------- @@ -1188,13 +1188,13 @@ report(What,Data) -> {_Suite,Case,Result} = Data, case Result of {failed, _} -> - ct_suite_callback:on_tc_fail(What, Data); + ct_hooks:on_tc_fail(What, Data); {skipped,{failed,{_,init_per_testcase,_}}} -> - ct_suite_callback:on_tc_skip(tc_auto_skip, Data); + ct_hooks:on_tc_skip(tc_auto_skip, Data); {skipped,{require_failed,_}} -> - ct_suite_callback:on_tc_skip(tc_auto_skip, Data); + ct_hooks:on_tc_skip(tc_auto_skip, Data); {skipped,_} -> - ct_suite_callback:on_tc_skip(tc_user_skip, Data); + ct_hooks:on_tc_skip(tc_user_skip, Data); _Else -> ok end, @@ -1224,7 +1224,7 @@ report(What,Data) -> ct_event:sync_notify(#event{name=tc_user_skip, node=node(), data=Data}), - ct_suite_callback:on_tc_skip(What, Data), + ct_hooks:on_tc_skip(What, Data), add_to_stats(user_skipped); tc_auto_skip -> %% test case skipped because of error in init_per_suite @@ -1237,7 +1237,7 @@ report(What,Data) -> ct_event:sync_notify(#event{name=tc_auto_skip, node=node(), data=Data}), - ct_suite_callback:on_tc_skip(What, Data), + ct_hooks:on_tc_skip(What, Data), if Case /= end_per_suite, Case /= end_per_group -> add_to_stats(auto_skipped); true -> diff --git a/lib/common_test/src/ct_hooks.erl b/lib/common_test/src/ct_hooks.erl new file mode 100644 index 0000000000..8e80ce8f37 --- /dev/null +++ b/lib/common_test/src/ct_hooks.erl @@ -0,0 +1,305 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-2010. 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% +%% + +%%% @doc Common Test Framework test execution control module. +%%% +%%%

This module is a proxy for calling and handling common test hooks.

+ +-module(ct_hooks). + +%% API Exports +-export([init/1]). +-export([init_tc/3]). +-export([end_tc/5]). +-export([terminate/1]). +-export([on_tc_skip/2]). +-export([on_tc_fail/2]). + +-type proplist() :: [{atom(),term()}]. + +%% If you change this, remember to update ct_util:look -> stop clause as well. +-define(config_name, ct_hooks). + +%% ------------------------------------------------------------------------- +%% API Functions +%% ------------------------------------------------------------------------- + +%% @doc Called before any suites are started +-spec init(State :: term()) -> ok | + {error, Reason :: term()}. +init(Opts) -> + call([{Hook, call_id, undefined} || Hook <- get_new_hooks(Opts)], + ok, init, []). + + +%% @doc Called after all suites are done. +-spec terminate(Hooks :: term()) -> + ok. +terminate(Hooks) -> + call([{HookId, fun call_terminate/3} || {HookId,_,_} <- Hooks], + ct_hooks_terminate_dummy, terminate, Hooks), + ok. + +%% @doc Called as each test case is started. This includes all configuration +%% tests. +-spec init_tc(Mod :: atom(), Func :: atom(), Args :: list()) -> + NewConfig :: proplist() | + {skip, Reason :: term()} | + {auto_skip, Reason :: term()} | + {fail, Reason :: term()}. +init_tc(ct_framework, _Func, Args) -> + Args; +init_tc(Mod, init_per_suite, Config) -> + Info = case catch proplists:get_value(ct_hooks, Mod:suite()) of + List when is_list(List) -> + [{ct_hooks,List}]; + _Else -> + [] + end, + call(fun call_generic/3, Config ++ Info, [pre_init_per_suite, Mod]); +init_tc(Mod, end_per_suite, Config) -> + call(fun call_generic/3, Config, [pre_end_per_suite, Mod]); +init_tc(Mod, {init_per_group, GroupName, Opts}, Config) -> + maybe_start_locker(Mod, GroupName, Opts), + call(fun call_generic/3, Config, [pre_init_per_group, GroupName]); +init_tc(_Mod, {end_per_group, GroupName, _}, Config) -> + call(fun call_generic/3, Config, [pre_end_per_group, GroupName]); +init_tc(_Mod, TC, Config) -> + call(fun call_generic/3, Config, [pre_init_per_testcase, TC]). + +%% @doc Called as each test case is completed. This includes all configuration +%% tests. +-spec end_tc(Mod :: atom(), + Func :: atom(), + Args :: list(), + Result :: term(), + Resturn :: term()) -> + NewConfig :: proplist() | + {skip, Reason :: term()} | + {auto_skip, Reason :: term()} | + {fail, Reason :: term()} | + ok. +end_tc(ct_framework, _Func, _Args, Result, _Return) -> + Result; + +end_tc(Mod, init_per_suite, Config, _Result, Return) -> + call(fun call_generic/3, Return, [post_init_per_suite, Mod, Config], + '$ct_no_change'); + +end_tc(Mod, end_per_suite, Config, Result, _Return) -> + call(fun call_generic/3, Result, [post_end_per_suite, Mod, Config], + '$ct_no_change'); + +end_tc(_Mod, {init_per_group, GroupName, _}, Config, _Result, Return) -> + call(fun call_generic/3, Return, [post_init_per_group, GroupName, Config], + '$ct_no_change'); + +end_tc(Mod, {end_per_group, GroupName, Opts}, Config, Result, _Return) -> + Res = call(fun call_generic/3, Result, + [post_end_per_group, GroupName, Config], '$ct_no_change'), + maybe_stop_locker(Mod, GroupName,Opts), + Res; + +end_tc(_Mod, TC, Config, Result, _Return) -> + call(fun call_generic/3, Result, [post_end_per_testcase, TC, Config], + '$ct_no_change'). + +on_tc_skip(How, {_Suite, Case, Reason}) -> + call(fun call_cleanup/3, {How, Reason}, [on_tc_skip, Case]). + +on_tc_fail(_How, {_Suite, Case, Reason}) -> + call(fun call_cleanup/3, Reason, [on_tc_fail, Case]). + +%% ------------------------------------------------------------------------- +%% Internal Functions +%% ------------------------------------------------------------------------- +call_id(Mod, Config, Meta) when is_atom(Mod) -> + call_id({Mod, []}, Config, Meta); +call_id({Mod, Opts}, Config, Scope) -> + Id = catch_apply(Mod,id,[Opts], make_ref()), + {Config, {Id, scope(Scope), {Mod, {Id,Opts}}}}. + +call_init({Mod,{Id,Opts}},Config,_Meta) -> + NewState = Mod:init(Id, Opts), + {Config, {Mod, NewState}}. + +call_terminate({Mod, State}, _, _) -> + catch_apply(Mod,terminate,[State], ok), + {[],{Mod,State}}. + +call_cleanup({Mod, State}, Reason, [Function | Args]) -> + NewState = catch_apply(Mod,Function, Args ++ [Reason, State], + State), + {Reason, {Mod, NewState}}. + +call_generic({Mod, State}, Value, [Function | Args]) -> + {NewValue, NewState} = catch_apply(Mod, Function, Args ++ [Value, State], + {Value,State}), + {NewValue, {Mod, NewState}}. + +%% Generic call function +call(Fun, Config, Meta) -> + maybe_lock(), + Hooks = get_hooks(), + Res = call([{HookId,Fun} || {HookId,_, _} <- Hooks] ++ + get_new_hooks(Config, Fun), + remove(?config_name,Config), Meta, Hooks), + maybe_unlock(), + Res. + +call(Fun, Config, Meta, NoChangeRet) when is_function(Fun) -> + case call(Fun,Config,Meta) of + Config -> NoChangeRet; + NewReturn -> NewReturn + end; + +call([{Hook, call_id, NextFun} | Rest], Config, Meta, Hooks) -> + try + {Config, {NewId, _, _} = NewHook} = call_id(Hook, Config, Meta), + {NewHooks, NewRest} = + case lists:keyfind(NewId, 1, Hooks) of + false when NextFun =:= undefined -> + {Hooks ++ [NewHook], + [{NewId, fun call_init/3} | Rest]}; + ExistingHook when is_tuple(ExistingHook) -> + {Hooks, Rest}; + _ -> + {Hooks ++ [NewHook], + [{NewId, fun call_init/3},{NewId,NextFun} | Rest]} + end, + call(NewRest, Config, Meta, NewHooks) + catch Error:Reason -> + Trace = erlang:get_stacktrace(), + ct_logs:log("Suite Hook","Failed to start a CTH: ~p:~p", + [Error,{Reason,Trace}]), + call([], {fail,"Failed to start CTH" + ", see the CT Log for details"}, Meta, Hooks) + end; +call([{HookId, Fun} | Rest], Config, Meta, Hooks) -> + try + {_,Scope,ModState} = lists:keyfind(HookId, 1, Hooks), + {NewConf, NewHookInfo} = Fun(ModState, Config, Meta), + NewCalls = get_new_hooks(NewConf, Fun), + NewHooks = lists:keyreplace(HookId, 1, Hooks, {HookId, Scope, NewHookInfo}), + call(NewCalls ++ Rest, remove(?config_name, NewConf), Meta, + terminate_if_scope_ends(HookId, Meta, NewHooks)) + catch throw:{error_in_cth_call,Reason} -> + call(Rest, {fail, Reason}, Meta, + terminate_if_scope_ends(HookId, Meta, Hooks)) + end; +call([], Config, _Meta, Hooks) -> + save_suite_data_async(Hooks), + Config. + +remove(Key,List) when is_list(List) -> + [Conf || Conf <- List, is_tuple(Conf) =:= false + orelse element(1, Conf) =/= Key]; +remove(_, Else) -> + Else. + +%% Translate scopes, i.e. init_per_group,group1 -> end_per_group,group1 etc +scope([pre_init_per_testcase, TC|_]) -> + [post_end_per_testcase, TC]; +scope([pre_init_per_group, GroupName|_]) -> + [post_end_per_group, GroupName]; +scope([post_init_per_group, GroupName|_]) -> + [post_end_per_group, GroupName]; +scope([pre_init_per_suite, SuiteName|_]) -> + [post_end_per_suite, SuiteName]; +scope([post_init_per_suite, SuiteName|_]) -> + [post_end_per_suite, SuiteName]; +scope(init) -> + none. + +terminate_if_scope_ends(HookId, [Function,Tag|T], Hooks) when T =/= [] -> + terminate_if_scope_ends(HookId,[Function,Tag],Hooks); +terminate_if_scope_ends(HookId, Function, Hooks) -> + case lists:keyfind(HookId, 1, Hooks) of + {HookId, Function, _ModState} = Hook -> + terminate([Hook]), + lists:keydelete(HookId, 1, Hooks); + _ -> + Hooks + end. + +%% Fetch hook functions +get_new_hooks(Config, Fun) -> + lists:foldl(fun(NewHook, Acc) -> + [{NewHook, call_id, Fun} | Acc] + end, [], get_new_hooks(Config)). + +get_new_hooks(Config) when is_list(Config) -> + lists:flatmap(fun({?config_name, HookConfigs}) -> + HookConfigs; + (_) -> + [] + end, Config); +get_new_hooks(_Config) -> + []. + +save_suite_data_async(Hooks) -> + ct_util:save_suite_data_async(?config_name, Hooks). + +get_hooks() -> + ct_util:read_suite_data(?config_name). + +catch_apply(M,F,A, Default) -> + try + apply(M,F,A) + catch error:Reason -> + case erlang:get_stacktrace() of + %% Return the default if it was the CTH module which did not have the function. + [{M,F,A}|_] when Reason == undef -> + Default; + Trace -> + ct_logs:log("Suite Hook","Call to CTH failed: ~p:~p", + [error,{Reason,Trace}]), + throw({error_in_cth_call, + lists:flatten( + io_lib:format("~p:~p/~p CTH call failed", + [M,F,length(A)]))}) + end + end. + + +%% We need to lock around the state for parallel groups only. This is because +%% we will get several processes reading and writing the state for a single +%% cth at the same time. +maybe_start_locker(Mod,GroupName,Opts) -> + case lists:member(parallel,Opts) of + true -> + {ok, _Pid} = ct_hooks_lock:start({Mod,GroupName}); + false -> + ok + end. + +maybe_stop_locker(Mod,GroupName,Opts) -> + case lists:member(parallel,Opts) of + true -> + stopped = ct_hooks_lock:stop({Mod,GroupName}); + false -> + ok + end. + + +maybe_lock() -> + locked = ct_hooks_lock:request(). + +maybe_unlock() -> + unlocked = ct_hooks_lock:release(). diff --git a/lib/common_test/src/ct_hooks_lock.erl b/lib/common_test/src/ct_hooks_lock.erl new file mode 100644 index 0000000000..98794201bb --- /dev/null +++ b/lib/common_test/src/ct_hooks_lock.erl @@ -0,0 +1,132 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-2010. 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% +%% + +%%% @doc Common Test Framework test execution control module. +%%% +%%%

This module is a proxy for calling and handling locks in +%%% common test hooks.

+ +-module(ct_hooks_lock). + +-behaviour(gen_server). + +%% API +-export([start/1, stop/1, request/0, release/0]). + +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, + terminate/2, code_change/3]). + +-define(SERVER, ?MODULE). + +-record(state, { id, locked = false, requests = [] }). + +%%%=================================================================== +%%% API +%%%=================================================================== + +%% @doc Starts the server +start(Id) -> + case gen_server:start({local, ?SERVER}, ?MODULE, Id, []) of + {error,{already_started, Pid}} -> + {ok,Pid}; + Else -> + Else + end. + +stop(Id) -> + try + gen_server:call(?SERVER, {stop,Id}) + catch exit:{noproc,_} -> + stopped + end. + +request() -> + try + gen_server:call(?SERVER,{request,self()},infinity) + catch exit:{noproc,_} -> + locked + end. + +release() -> + try + gen_server:call(?SERVER,{release,self()}) + catch exit:{noproc,_} -> + unlocked + end. + +%%%=================================================================== +%%% gen_server callbacks +%%%=================================================================== + +%% @doc Initiates the server +init(Id) -> + {ok, #state{ id = Id }}. + +%% @doc Handling call messages +handle_call({stop,Id}, _From, #state{ id = Id, requests = Reqs } = State) -> + [gen_server:reply(Req, locker_stopped) || {Req,_ReqId} <- Reqs], + {stop, normal, stopped, State}; +handle_call({stop,_Id}, _From, State) -> + {reply, stopped, State}; +handle_call({request, Pid}, _From, #state{ locked = false, + requests = [] } = State) -> + Ref = monitor(process, Pid), + {reply, locked, State#state{ locked = {true, Pid, Ref}} }; +handle_call({request, Pid}, From, #state{ requests = Reqs } = State) -> + {noreply, State#state{ requests = Reqs ++ [{From,Pid}] }}; +handle_call({release, Pid}, _From, #state{ locked = {true, Pid, Ref}, + requests = []} = State) -> + demonitor(Ref,[flush]), + {reply, unlocked, State#state{ locked = false }}; +handle_call({release, Pid}, _From, + #state{ locked = {true, Pid, Ref}, + requests = [{NextFrom,NextPid}|Rest]} = State) -> + demonitor(Ref,[flush]), + gen_server:reply(NextFrom,locked), + NextRef = monitor(process, NextPid), + {reply,unlocked,State#state{ locked = {true, NextPid, NextRef}, + requests = Rest } }; +handle_call({release, _Pid}, _From, State) -> + {reply, not_locked, State}. + +%% @doc Handling cast messages +handle_cast(_Msg, State) -> + {noreply, State}. + +%% @doc Handling all non call/cast messages +handle_info({'DOWN',Ref,process,Pid,_}, + #state{ locked = {true, Pid, Ref}, + requests = [{NextFrom,NextPid}|Rest] } = State) -> + gen_server:reply(NextFrom, locked), + NextRef = monitor(process, NextPid), + {noreply,State#state{ locked = {true, NextPid, NextRef}, + requests = Rest } }. + +%% @doc This function is called by a gen_server when it is about to terminate. +terminate(_Reason, _State) -> + ok. + +%% @doc Convert process state when code is changed +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +%% ------------------------------------------------------------------------- +%% Internal Functions +%% ------------------------------------------------------------------------- diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl index a12d4d6f18..36fccf65f3 100644 --- a/lib/common_test/src/ct_run.erl +++ b/lib/common_test/src/ct_run.erl @@ -54,7 +54,7 @@ logdir, config = [], event_handlers = [], - suite_callbacks = [], + ct_hooks = [], include = [], silent_connections, stylesheet, @@ -172,7 +172,7 @@ script_start1(Parent, Args) -> ([]) -> true end, false, Args), EvHandlers = event_handler_args2opts(Args), - SuiteCBs = suite_callbacks_args2opts(Args), + CTHooks = ct_hooks_args2opts(Args), %% check flags and set corresponding application env variables @@ -236,7 +236,7 @@ script_start1(Parent, Args) -> StartOpts = #opts{label = Label, vts = Vts, shell = Shell, cover = Cover, logdir = LogDir, event_handlers = EvHandlers, - suite_callbacks = SuiteCBs, + ct_hooks = CTHooks, include = IncludeDirs, silent_connections = SilentConns, stylesheet = Stylesheet, @@ -308,9 +308,9 @@ script_start2(StartOpts = #opts{vts = undefined, SpecStartOpts#opts.scale_timetraps), AllEvHs = merge_vals([StartOpts#opts.event_handlers, SpecStartOpts#opts.event_handlers]), - AllSuiteCBs = merge_vals( - [StartOpts#opts.suite_callbacks, - SpecStartOpts#opts.suite_callbacks]), + AllCTHooks = merge_vals( + [StartOpts#opts.ct_hooks, + SpecStartOpts#opts.ct_hooks]), AllInclude = merge_vals([StartOpts#opts.include, SpecStartOpts#opts.include]), @@ -322,7 +322,7 @@ script_start2(StartOpts = #opts{vts = undefined, logdir = LogDir, config = SpecStartOpts#opts.config, event_handlers = AllEvHs, - suite_callbacks = AllSuiteCBs, + ct_hooks = AllCTHooks, include = AllInclude, multiply_timetraps = MultTT, scale_timetraps = ScaleTT}} @@ -341,7 +341,7 @@ script_start2(StartOpts = #opts{vts = undefined, {undefined,_} -> % no testspec used case check_and_install_configfiles(InitConfig, TheLogDir, Opts#opts.event_handlers, - Opts#opts.suite_callbacks) of + Opts#opts.ct_hooks) of ok -> % go on read tests from start flags script_start3(Opts#opts{config=InitConfig, logdir=TheLogDir}, Args); @@ -353,7 +353,7 @@ script_start2(StartOpts = #opts{vts = undefined, AllConfig = merge_vals([InitConfig, Opts#opts.config]), case check_and_install_configfiles(AllConfig, TheLogDir, Opts#opts.event_handlers, - Opts#opts.suite_callbacks) of + Opts#opts.ct_hooks) of ok -> % read tests from spec {Run,Skip} = ct_testspec:prepare_tests(Terms, node()), do_run(Run, Skip, Opts#opts{config=AllConfig, @@ -369,7 +369,7 @@ script_start2(StartOpts, Args) -> LogDir = which(logdir, StartOpts#opts.logdir), case check_and_install_configfiles(InitConfig, LogDir, StartOpts#opts.event_handlers, - StartOpts#opts.suite_callbacks) of + StartOpts#opts.ct_hooks) of ok -> % go on read tests from start flags script_start3(StartOpts#opts{config=InitConfig, logdir=LogDir}, Args); @@ -377,12 +377,12 @@ script_start2(StartOpts, Args) -> Error end. -check_and_install_configfiles(Configs, LogDir, EvHandlers, SuiteCBs) -> +check_and_install_configfiles(Configs, LogDir, EvHandlers, CTHooks) -> case ct_config:check_config_files(Configs) of false -> install([{config,Configs}, {event_handler,EvHandlers}, - {suite_callbacks,SuiteCBs}], LogDir); + {ct_hooks,CTHooks}], LogDir); {value,{error,{nofile,File}}} -> {error,{cant_read_config_file,File}}; {value,{error,{wrong_config,Message}}}-> @@ -450,13 +450,13 @@ script_start4(#opts{vts = true, config = Config, event_handlers = EvHandlers, script_start4(#opts{label = Label, shell = true, config = Config, event_handlers = EvHandlers, - suite_callbacks = SuiteCBs, + ct_hooks = CTHooks, logdir = LogDir, testspecs = Specs}, _Args) -> %% label - used by ct_logs application:set_env(common_test, test_label, Label), InstallOpts = [{config,Config},{event_handler,EvHandlers}, - {suite_callbacks, SuiteCBs}], + {ct_hooks, CTHooks}], if Config == [] -> ok; true -> @@ -522,7 +522,7 @@ script_usage() -> "\n\t[-stylesheet CSSFile]" "\n\t[-cover CoverCfgFile]" "\n\t[-event_handler EvHandler1 EvHandler2 .. EvHandlerN]" - "\n\t[-suite_callbacks SuiteCB1 SuiteCB2 .. SuiteCBN]" + "\n\t[-ct_hooks CTHook1 CTHook2 .. CTHookN]" "\n\t[-include InclDir1 InclDir2 .. InclDirN]" "\n\t[-no_auto_compile]" "\n\t[-multiply_timetraps N]" @@ -541,7 +541,7 @@ script_usage() -> "\n\t[-stylesheet CSSFile]" "\n\t[-cover CoverCfgFile]" "\n\t[-event_handler EvHandler1 EvHandler2 .. EvHandlerN]" - "\n\t[-suite_callbacks SuiteCB1 SuiteCB2 .. SuiteCBN]" + "\n\t[-ct_hooks CTHook1 CTHook2 .. CTHookN]" "\n\t[-include InclDir1 InclDir2 .. InclDirN]" "\n\t[-no_auto_compile]" "\n\t[-multiply_timetraps N]" @@ -680,8 +680,8 @@ run_test1(StartOpts) -> end, Hs)) end, - %% Suite Callbacks - SuiteCBs = get_start_opt(suite_callbacks, value, [], StartOpts), + %% CT Hooks + CTHooks = get_start_opt(ct_hooks, value, [], StartOpts), %% silent connections SilentConns = get_start_opt(silent_connections, @@ -753,7 +753,7 @@ run_test1(StartOpts) -> Opts = #opts{label = Label, cover = Cover, step = Step, logdir = LogDir, config = CfgFiles, event_handlers = EvHandlers, - suite_callbacks = SuiteCBs, + ct_hooks = CTHooks, include = Include, silent_connections = SilentConns, stylesheet = Stylesheet, @@ -806,15 +806,15 @@ run_spec_file(Relaxed, AllInclude = merge_vals([Opts#opts.include, SpecOpts#opts.include]), - AllSuiteCBs = merge_vals([Opts#opts.suite_callbacks, - SpecOpts#opts.suite_callbacks]), + AllCTHooks = merge_vals([Opts#opts.ct_hooks, + SpecOpts#opts.ct_hooks]), application:set_env(common_test, include, AllInclude), case check_and_install_configfiles(AllConfig, which(logdir,LogDir), AllEvHs, - AllSuiteCBs) of + AllCTHooks) of ok -> Opts1 = Opts#opts{label = Label, cover = Cover, @@ -825,7 +825,7 @@ run_spec_file(Relaxed, testspecs = AbsSpecs, multiply_timetraps = MultTT, scale_timetraps = ScaleTT, - suite_callbacks = AllSuiteCBs}, + ct_hooks = AllCTHooks}, {Run,Skip} = ct_testspec:prepare_tests(TS, node()), reformat_result(catch do_run(Run, Skip, Opts1, StartOpts)); {error,GCFReason} -> @@ -836,11 +836,11 @@ run_spec_file(Relaxed, run_prepared(Run, Skip, Opts = #opts{logdir = LogDir, config = CfgFiles, event_handlers = EvHandlers, - suite_callbacks = SuiteCBs}, + ct_hooks = CTHooks}, StartOpts) -> LogDir1 = which(logdir, LogDir), case check_and_install_configfiles(CfgFiles, LogDir1, - EvHandlers, SuiteCBs) of + EvHandlers, CTHooks) of ok -> reformat_result(catch do_run(Run, Skip, Opts#opts{logdir = LogDir1}, StartOpts)); @@ -872,7 +872,7 @@ check_config_file(Callback, File)-> run_dir(Opts = #opts{logdir = LogDir, config = CfgFiles, event_handlers = EvHandlers, - suite_callbacks = SuiteCB }, StartOpts) -> + ct_hooks = CTHook }, StartOpts) -> LogDir1 = which(logdir, LogDir), Opts1 = Opts#opts{logdir = LogDir1}, AbsCfgFiles = @@ -895,7 +895,7 @@ run_dir(Opts = #opts{logdir = LogDir, end, CfgFiles), case install([{config,AbsCfgFiles}, {event_handler,EvHandlers}, - {suite_callbacks, SuiteCB}], LogDir1) of + {ct_hooks, CTHook}], LogDir1) of ok -> ok; {error,IReason} -> exit(IReason) end, @@ -1001,7 +1001,7 @@ run_testspec1(TestSpec) -> LogDir1 = which(logdir,Opts#opts.logdir), case check_and_install_configfiles(Opts#opts.config, LogDir1, Opts#opts.event_handlers, - Opts#opts.suite_callbacks) of + Opts#opts.ct_hooks) of ok -> Opts1 = Opts#opts{testspecs = [], logdir = LogDir1, @@ -1019,7 +1019,7 @@ get_data_for_node(#testspec{label = Labels, config = Cfgs, userconfig = UsrCfgs, event_handler = EvHs, - suite_callbacks = SuCBs, + ct_hooks = CTHooks, include = Incl, multiply_timetraps = MTs, scale_timetraps = STs}, Node) -> @@ -1034,14 +1034,14 @@ get_data_for_node(#testspec{label = Labels, ConfigFiles = [{?ct_config_txt,F} || {N,F} <- Cfgs, N==Node] ++ [CBF || {N,CBF} <- UsrCfgs, N==Node], EvHandlers = [{H,A} || {N,H,A} <- EvHs, N==Node], - SuiteCBs = [CB || {N,CB} <- SuCBs, N==Node], + FiltCTHooks = [Hook || {N,Hook} <- CTHooks, N==Node], Include = [I || {N,I} <- Incl, N==Node], #opts{label = Label, logdir = LogDir, cover = Cover, config = ConfigFiles, event_handlers = EvHandlers, - suite_callbacks = SuiteCBs, + ct_hooks = FiltCTHooks, include = Include, multiply_timetraps = MT, scale_timetraps = ST}. @@ -2074,23 +2074,23 @@ get_start_opt(Key, IfExists, IfNotExists, Args) -> IfNotExists end. -suite_callbacks_args2opts(Args) -> - suite_callbacks_args2opts( - proplists:get_value(suite_callbacks, Args, []),[]). - -suite_callbacks_args2opts([SCB,Arg,"and"| Rest],Acc) -> - suite_callbacks_args2opts(Rest,[{list_to_atom(SCB), - parse_scb_args(Arg)}|Acc]); -suite_callbacks_args2opts([SCB], Acc) -> - suite_callbacks_args2opts([SCB,"and"],Acc); -suite_callbacks_args2opts([SCB, "and" | Rest], Acc) -> - suite_callbacks_args2opts(Rest,[list_to_atom(SCB)|Acc]); -suite_callbacks_args2opts([SCB, Args], Acc) -> - suite_callbacks_args2opts([SCB, Args, "and"],Acc); -suite_callbacks_args2opts([],Acc) -> +ct_hooks_args2opts(Args) -> + ct_hooks_args2opts( + proplists:get_value(ct_hooks, Args, []),[]). + +ct_hooks_args2opts([CTH,Arg,"and"| Rest],Acc) -> + ct_hooks_args2opts(Rest,[{list_to_atom(CTH), + parse_cth_args(Arg)}|Acc]); +ct_hooks_args2opts([CTH], Acc) -> + ct_hooks_args2opts([CTH,"and"],Acc); +ct_hooks_args2opts([CTH, "and" | Rest], Acc) -> + ct_hooks_args2opts(Rest,[list_to_atom(CTH)|Acc]); +ct_hooks_args2opts([CTH, Args], Acc) -> + ct_hooks_args2opts([CTH, Args, "and"],Acc); +ct_hooks_args2opts([],Acc) -> lists:reverse(Acc). -parse_scb_args(String) -> +parse_cth_args(String) -> try true = io_lib:printable_list(String), {ok,Toks,_} = erl_scan:string(String++"."), @@ -2228,22 +2228,22 @@ opts2args(EnvStartOpts) -> end, EHs), [_LastAnd|StrsR] = lists:reverse(lists:flatten(Strs)), [{event_handler_init,lists:reverse(StrsR)}]; - ({suite_callbacks,[]}) -> + ({ct_hooks,[]}) -> []; - ({suite_callbacks,SCBs}) when is_list(SCBs) -> - io:format(user,"suite_callbacks: ~p",[SCBs]), + ({ct_hooks,CTHs}) when is_list(CTHs) -> + io:format(user,"ct_hooks: ~p",[CTHs]), Strs = lists:flatmap( - fun({SCB,Arg}) -> - [atom_to_list(SCB), + fun({CTH,Arg}) -> + [atom_to_list(CTH), lists:flatten( io_lib:format("~p",[Arg])), "and"]; - (SCB) when is_atom(SCB) -> - [atom_to_list(SCB),"and"] - end,SCBs), + (CTH) when is_atom(CTH) -> + [atom_to_list(CTH),"and"] + end,CTHs), [_LastAnd|StrsR] = lists:reverse(Strs), io:format(user,"return: ~p",[lists:reverse(StrsR)]), - [{suite_callbacks,lists:reverse(StrsR)}]; + [{ct_hooks,lists:reverse(StrsR)}]; ({Opt,As=[A|_]}) when is_atom(A) -> [{Opt,[atom_to_list(Atom) || Atom <- As]}]; ({Opt,Strs=[S|_]}) when is_list(S) -> diff --git a/lib/common_test/src/ct_suite_callback.erl b/lib/common_test/src/ct_suite_callback.erl deleted file mode 100644 index a93b05b1d2..0000000000 --- a/lib/common_test/src/ct_suite_callback.erl +++ /dev/null @@ -1,304 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2004-2010. 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% -%% - -%%% @doc Common Test Framework test execution control module. -%%% -%%%

This module is a proxy for calling and handling suite callbacks.

- --module(ct_suite_callback). - -%% API Exports --export([init/1]). --export([init_tc/3]). --export([end_tc/5]). --export([terminate/1]). --export([on_tc_skip/2]). --export([on_tc_fail/2]). - --type proplist() :: [{atom(),term()}]. - --define(config_name, suite_callbacks). - -%% ------------------------------------------------------------------------- -%% API Functions -%% ------------------------------------------------------------------------- - -%% @doc Called before any suites are started --spec init(State :: term()) -> ok | - {error, Reason :: term()}. -init(Opts) -> - call([{CB, call_id, undefined} || CB <- get_new_callbacks(Opts)], - ok, init, []). - - -%% @doc Called after all suites are done. --spec terminate(Callbacks :: term()) -> - ok. -terminate(Callbacks) -> - call([{CBId, fun call_terminate/3} || {CBId,_,_} <- Callbacks], - ct_suite_callback_terminate_dummy, terminate, Callbacks), - ok. - -%% @doc Called as each test case is started. This includes all configuration -%% tests. --spec init_tc(Mod :: atom(), Func :: atom(), Args :: list()) -> - NewConfig :: proplist() | - {skip, Reason :: term()} | - {auto_skip, Reason :: term()} | - {fail, Reason :: term()}. -init_tc(ct_framework, _Func, Args) -> - Args; -init_tc(Mod, init_per_suite, Config) -> - Info = case catch proplists:get_value(suite_callbacks, Mod:suite()) of - List when is_list(List) -> - [{suite_callbacks,List}]; - _Else -> - [] - end, - call(fun call_generic/3, Config ++ Info, [pre_init_per_suite, Mod]); -init_tc(Mod, end_per_suite, Config) -> - call(fun call_generic/3, Config, [pre_end_per_suite, Mod]); -init_tc(Mod, {init_per_group, GroupName, Opts}, Config) -> - maybe_start_locker(Mod, GroupName, Opts), - call(fun call_generic/3, Config, [pre_init_per_group, GroupName]); -init_tc(_Mod, {end_per_group, GroupName, _}, Config) -> - call(fun call_generic/3, Config, [pre_end_per_group, GroupName]); -init_tc(_Mod, TC, Config) -> - call(fun call_generic/3, Config, [pre_init_per_testcase, TC]). - -%% @doc Called as each test case is completed. This includes all configuration -%% tests. --spec end_tc(Mod :: atom(), - Func :: atom(), - Args :: list(), - Result :: term(), - Resturn :: term()) -> - NewConfig :: proplist() | - {skip, Reason :: term()} | - {auto_skip, Reason :: term()} | - {fail, Reason :: term()} | - ok. -end_tc(ct_framework, _Func, _Args, Result, _Return) -> - Result; - -end_tc(Mod, init_per_suite, Config, _Result, Return) -> - call(fun call_generic/3, Return, [post_init_per_suite, Mod, Config], - '$ct_no_change'); - -end_tc(Mod, end_per_suite, Config, Result, _Return) -> - call(fun call_generic/3, Result, [post_end_per_suite, Mod, Config], - '$ct_no_change'); - -end_tc(_Mod, {init_per_group, GroupName, _}, Config, _Result, Return) -> - call(fun call_generic/3, Return, [post_init_per_group, GroupName, Config], - '$ct_no_change'); - -end_tc(Mod, {end_per_group, GroupName, Opts}, Config, Result, _Return) -> - Res = call(fun call_generic/3, Result, - [post_end_per_group, GroupName, Config], '$ct_no_change'), - maybe_stop_locker(Mod, GroupName,Opts), - Res; - -end_tc(_Mod, TC, Config, Result, _Return) -> - call(fun call_generic/3, Result, [post_end_per_testcase, TC, Config], - '$ct_no_change'). - -on_tc_skip(How, {_Suite, Case, Reason}) -> - call(fun call_cleanup/3, {How, Reason}, [on_tc_skip, Case]). - -on_tc_fail(_How, {_Suite, Case, Reason}) -> - call(fun call_cleanup/3, Reason, [on_tc_fail, Case]). - -%% ------------------------------------------------------------------------- -%% Internal Functions -%% ------------------------------------------------------------------------- -call_id(Mod, Config, Meta) when is_atom(Mod) -> - call_id({Mod, []}, Config, Meta); -call_id({Mod, Opts}, Config, Scope) -> - Id = catch_apply(Mod,id,[Opts], make_ref()), - {Config, {Id, scope(Scope), {Mod, {Id,Opts}}}}. - -call_init({Mod,{Id,Opts}},Config,_Meta) -> - NewState = Mod:init(Id, Opts), - {Config, {Mod, NewState}}. - -call_terminate({Mod, State}, _, _) -> - catch_apply(Mod,terminate,[State], ok), - {[],{Mod,State}}. - -call_cleanup({Mod, State}, Reason, [Function | Args]) -> - NewState = catch_apply(Mod,Function, Args ++ [Reason, State], - State), - {Reason, {Mod, NewState}}. - -call_generic({Mod, State}, Value, [Function | Args]) -> - {NewValue, NewState} = catch_apply(Mod, Function, Args ++ [Value, State], - {Value,State}), - {NewValue, {Mod, NewState}}. - -%% Generic call function -call(Fun, Config, Meta) -> - maybe_lock(), - CBs = get_callbacks(), - Res = call([{CBId,Fun} || {CBId,_, _} <- CBs] ++ - get_new_callbacks(Config, Fun), - remove(?config_name,Config), Meta, CBs), - maybe_unlock(), - Res. - -call(Fun, Config, Meta, NoChangeRet) when is_function(Fun) -> - case call(Fun,Config,Meta) of - Config -> NoChangeRet; - NewReturn -> NewReturn - end; - -call([{CB, call_id, NextFun} | Rest], Config, Meta, CBs) -> - try - {Config, {NewId, _, _} = NewCB} = call_id(CB, Config, Meta), - {NewCBs, NewRest} = - case lists:keyfind(NewId, 1, CBs) of - false when NextFun =:= undefined -> - {CBs ++ [NewCB], - [{NewId, fun call_init/3} | Rest]}; - ExistingCB when is_tuple(ExistingCB) -> - {CBs, Rest}; - _ -> - {CBs ++ [NewCB], - [{NewId, fun call_init/3},{NewId,NextFun} | Rest]} - end, - call(NewRest, Config, Meta, NewCBs) - catch Error:Reason -> - Trace = erlang:get_stacktrace(), - ct_logs:log("Suite Callback","Failed to start a SCB: ~p:~p", - [Error,{Reason,Trace}]), - call([], {fail,"Failed to start SCB" - ", see the CT Log for details"}, Meta, CBs) - end; -call([{CBId, Fun} | Rest], Config, Meta, CBs) -> - try - {_,Scope,ModState} = lists:keyfind(CBId, 1, CBs), - {NewConf, NewCBInfo} = Fun(ModState, Config, Meta), - NewCalls = get_new_callbacks(NewConf, Fun), - NewCBs = lists:keyreplace(CBId, 1, CBs, {CBId, Scope, NewCBInfo}), - call(NewCalls ++ Rest, remove(?config_name, NewConf), Meta, - terminate_if_scope_ends(CBId, Meta, NewCBs)) - catch throw:{error_in_scb_call,Reason} -> - call(Rest, {fail, Reason}, Meta, - terminate_if_scope_ends(CBId, Meta, CBs)) - end; -call([], Config, _Meta, CBs) -> - save_suite_data_async(CBs), - Config. - -remove(Key,List) when is_list(List) -> - [Conf || Conf <- List, is_tuple(Conf) =:= false - orelse element(1, Conf) =/= Key]; -remove(_, Else) -> - Else. - -%% Translate scopes, i.e. init_per_group,group1 -> end_per_group,group1 etc -scope([pre_init_per_testcase, TC|_]) -> - [post_end_per_testcase, TC]; -scope([pre_init_per_group, GroupName|_]) -> - [post_end_per_group, GroupName]; -scope([post_init_per_group, GroupName|_]) -> - [post_end_per_group, GroupName]; -scope([pre_init_per_suite, SuiteName|_]) -> - [post_end_per_suite, SuiteName]; -scope([post_init_per_suite, SuiteName|_]) -> - [post_end_per_suite, SuiteName]; -scope(init) -> - none. - -terminate_if_scope_ends(CBId, [Function,Tag|T], CBs) when T =/= [] -> - terminate_if_scope_ends(CBId,[Function,Tag],CBs); -terminate_if_scope_ends(CBId, Function, CBs) -> - case lists:keyfind(CBId, 1, CBs) of - {CBId, Function, _ModState} = CB -> - terminate([CB]), - lists:keydelete(CBId, 1, CBs); - _ -> - CBs - end. - -%% Fetch callback functions -get_new_callbacks(Config, Fun) -> - lists:foldl(fun(NewCB, Acc) -> - [{NewCB, call_id, Fun} | Acc] - end, [], get_new_callbacks(Config)). - -get_new_callbacks(Config) when is_list(Config) -> - lists:flatmap(fun({?config_name, CallbackConfigs}) -> - CallbackConfigs; - (_) -> - [] - end, Config); -get_new_callbacks(_Config) -> - []. - -save_suite_data_async(CBs) -> - ct_util:save_suite_data_async(?config_name, CBs). - -get_callbacks() -> - ct_util:read_suite_data(?config_name). - -catch_apply(M,F,A, Default) -> - try - apply(M,F,A) - catch error:Reason -> - case erlang:get_stacktrace() of - %% Return the default if it was the SCB module which did not have the function. - [{M,F,A}|_] when Reason == undef -> - Default; - Trace -> - ct_logs:log("Suite Callback","Call to SCB failed: ~p:~p", - [error,{Reason,Trace}]), - throw({error_in_scb_call, - lists:flatten( - io_lib:format("~p:~p/~p SCB call failed", - [M,F,length(A)]))}) - end - end. - - -%% We need to lock around the state for parallel groups only. This is because -%% we will get several processes reading and writing the state for a single -%% scb at the same time. -maybe_start_locker(Mod,GroupName,Opts) -> - case lists:member(parallel,Opts) of - true -> - {ok, _Pid} = ct_suite_callback_lock:start({Mod,GroupName}); - false -> - ok - end. - -maybe_stop_locker(Mod,GroupName,Opts) -> - case lists:member(parallel,Opts) of - true -> - stopped = ct_suite_callback_lock:stop({Mod,GroupName}); - false -> - ok - end. - - -maybe_lock() -> - locked = ct_suite_callback_lock:request(). - -maybe_unlock() -> - unlocked = ct_suite_callback_lock:release(). diff --git a/lib/common_test/src/ct_suite_callback_lock.erl b/lib/common_test/src/ct_suite_callback_lock.erl deleted file mode 100644 index 84dafd1e42..0000000000 --- a/lib/common_test/src/ct_suite_callback_lock.erl +++ /dev/null @@ -1,131 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2004-2010. 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% -%% - -%%% @doc Common Test Framework test execution control module. -%%% -%%%

This module is a proxy for calling and handling locks in suite callbacks.

- --module(ct_suite_callback_lock). - --behaviour(gen_server). - -%% API --export([start/1, stop/1, request/0, release/0]). - -%% gen_server callbacks --export([init/1, handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3]). - --define(SERVER, ?MODULE). - --record(state, { id, locked = false, requests = [] }). - -%%%=================================================================== -%%% API -%%%=================================================================== - -%% @doc Starts the server -start(Id) -> - case gen_server:start({local, ?SERVER}, ?MODULE, Id, []) of - {error,{already_started, Pid}} -> - {ok,Pid}; - Else -> - Else - end. - -stop(Id) -> - try - gen_server:call(?SERVER, {stop,Id}) - catch exit:{noproc,_} -> - stopped - end. - -request() -> - try - gen_server:call(?SERVER,{request,self()},infinity) - catch exit:{noproc,_} -> - locked - end. - -release() -> - try - gen_server:call(?SERVER,{release,self()}) - catch exit:{noproc,_} -> - unlocked - end. - -%%%=================================================================== -%%% gen_server callbacks -%%%=================================================================== - -%% @doc Initiates the server -init(Id) -> - {ok, #state{ id = Id }}. - -%% @doc Handling call messages -handle_call({stop,Id}, _From, #state{ id = Id, requests = Reqs } = State) -> - [gen_server:reply(Req, locker_stopped) || {Req,_ReqId} <- Reqs], - {stop, normal, stopped, State}; -handle_call({stop,_Id}, _From, State) -> - {reply, stopped, State}; -handle_call({request, Pid}, _From, #state{ locked = false, - requests = [] } = State) -> - Ref = monitor(process, Pid), - {reply, locked, State#state{ locked = {true, Pid, Ref}} }; -handle_call({request, Pid}, From, #state{ requests = Reqs } = State) -> - {noreply, State#state{ requests = Reqs ++ [{From,Pid}] }}; -handle_call({release, Pid}, _From, #state{ locked = {true, Pid, Ref}, - requests = []} = State) -> - demonitor(Ref,[flush]), - {reply, unlocked, State#state{ locked = false }}; -handle_call({release, Pid}, _From, - #state{ locked = {true, Pid, Ref}, - requests = [{NextFrom,NextPid}|Rest]} = State) -> - demonitor(Ref,[flush]), - gen_server:reply(NextFrom,locked), - NextRef = monitor(process, NextPid), - {reply,unlocked,State#state{ locked = {true, NextPid, NextRef}, - requests = Rest } }; -handle_call({release, _Pid}, _From, State) -> - {reply, not_locked, State}. - -%% @doc Handling cast messages -handle_cast(_Msg, State) -> - {noreply, State}. - -%% @doc Handling all non call/cast messages -handle_info({'DOWN',Ref,process,Pid,_}, - #state{ locked = {true, Pid, Ref}, - requests = [{NextFrom,NextPid}|Rest] } = State) -> - gen_server:reply(NextFrom, locked), - NextRef = monitor(process, NextPid), - {noreply,State#state{ locked = {true, NextPid, NextRef}, - requests = Rest } }. - -%% @doc This function is called by a gen_server when it is about to terminate. -terminate(_Reason, _State) -> - ok. - -%% @doc Convert process state when code is changed -code_change(_OldVsn, State, _Extra) -> - {ok, State}. - -%% ------------------------------------------------------------------------- -%% Internal Functions -%% ------------------------------------------------------------------------- diff --git a/lib/common_test/src/ct_testspec.erl b/lib/common_test/src/ct_testspec.erl index 942241da6c..db1d4c5fb0 100644 --- a/lib/common_test/src/ct_testspec.erl +++ b/lib/common_test/src/ct_testspec.erl @@ -625,19 +625,19 @@ add_tests([{event_handler,Node,H,Args}|Ts],Spec) when is_atom(H) -> Node1 = ref2node(Node,Spec#testspec.nodes), add_tests(Ts,Spec#testspec{event_handler=[{Node1,H,Args}|EvHs]}); -%% --- suite_callbacks -- -add_tests([{suite_callbacks, all_nodes, CBs} | Ts], Spec) -> - Tests = [{suite_callbacks,N,CBs} || N <- list_nodes(Spec)], +%% --- ct_hooks -- +add_tests([{ct_hooks, all_nodes, Hooks} | Ts], Spec) -> + Tests = [{ct_hooks,N,Hooks} || N <- list_nodes(Spec)], add_tests(Tests ++ Ts, Spec); -add_tests([{suite_callbacks, Node, [CB|CBs]}|Ts], Spec) -> - SuiteCbs = Spec#testspec.suite_callbacks, +add_tests([{ct_hooks, Node, [Hook|Hooks]}|Ts], Spec) -> + SuiteCbs = Spec#testspec.ct_hooks, Node1 = ref2node(Node,Spec#testspec.nodes), - add_tests([{suite_callbacks, Node, CBs} | Ts], - Spec#testspec{suite_callbacks = [{Node1,CB} | SuiteCbs]}); -add_tests([{suite_callbacks, _Node, []}|Ts], Spec) -> + add_tests([{ct_hooks, Node, Hooks} | Ts], + Spec#testspec{ct_hooks = [{Node1,Hook} | SuiteCbs]}); +add_tests([{ct_hooks, _Node, []}|Ts], Spec) -> add_tests(Ts, Spec); -add_tests([{suite_callbacks, CBs}|Ts], Spec) -> - add_tests([{suite_callbacks, all_nodes, CBs}|Ts], Spec); +add_tests([{ct_hooks, Hooks}|Ts], Spec) -> + add_tests([{ct_hooks, all_nodes, Hooks}|Ts], Spec); %% --- include --- add_tests([{include,all_nodes,InclDirs}|Ts],Spec) -> @@ -1065,8 +1065,8 @@ valid_terms() -> {event_handler,2}, {event_handler,3}, {event_handler,4}, - {suite_callbacks,2}, - {suite_callbacks,3}, + {ct_hooks,2}, + {ct_hooks,3}, {multiply_timetraps,2}, {multiply_timetraps,3}, {scale_timetraps,2}, diff --git a/lib/common_test/src/ct_util.erl b/lib/common_test/src/ct_util.erl index 2f5a90a543..45146de57c 100644 --- a/lib/common_test/src/ct_util.erl +++ b/lib/common_test/src/ct_util.erl @@ -162,13 +162,13 @@ do_start(Parent,Mode,LogDir) -> end, {StartTime,TestLogDir} = ct_logs:init(Mode), - %% Initiate suite_callbacks - case catch ct_suite_callback:init(Opts) of + %% Initiate ct_hooks + case catch ct_hooks:init(Opts) of ok -> ok; - {_,SCBReason} -> - ct_logs:tc_print('Suite Callback',SCBReason,[]), - Parent ! {self(), SCBReason}, + {_,CTHReason} -> + ct_logs:tc_print('Suite Callback',CTHReason,[]), + Parent ! {self(), CTHReason}, self() ! {{stop,normal},{self(),make_ref()}} end, @@ -320,9 +320,9 @@ loop(Mode,TestData,StartDir) -> node=node(), data=Time}), Callbacks = ets:lookup_element(?suite_table, - suite_callbacks, + ct_hooks, #suite_data.value), - ct_suite_callback:terminate(Callbacks), + ct_hooks:terminate(Callbacks), close_connections(ets:tab2list(?conn_table)), ets:delete(?conn_table), ets:delete(?board_table), diff --git a/lib/common_test/src/ct_util.hrl b/lib/common_test/src/ct_util.hrl index 99f029bc0e..4ed29bdcd1 100644 --- a/lib/common_test/src/ct_util.hrl +++ b/lib/common_test/src/ct_util.hrl @@ -36,7 +36,7 @@ config=[], userconfig=[], event_handler=[], - suite_callbacks=[], + ct_hooks=[], include=[], multiply_timetraps=[], scale_timetraps=[], diff --git a/lib/common_test/test/Makefile b/lib/common_test/test/Makefile index 28be9f56f1..be4b4c32b8 100644 --- a/lib/common_test/test/Makefile +++ b/lib/common_test/test/Makefile @@ -41,7 +41,7 @@ MODULES= \ ct_config_SUITE \ ct_master_SUITE \ ct_misc_1_SUITE \ - ct_suite_callback_SUITE + ct_hooks_SUITE ERL_FILES= $(MODULES:%=%.erl) diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/empty_scb.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/empty_scb.erl deleted file mode 100644 index 41808b4f1d..0000000000 --- a/lib/common_test/test/ct_error_SUITE_data/error/test/empty_scb.erl +++ /dev/null @@ -1,187 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2010. 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% -%% - -%%% @doc Common Test Example Suite Callback module. -%%% -%%%

This module gives an example of a common test SCB (Suite CallBack). -%%% There are many ways to add a SCB to a test run, you can do it either in -%%% the command line using -suite_callback, in a test spec using -%%% {suite_callback,M} or in the suite it self by returning suite_callback -%%% from either suite/0, init_per_suite/1, init_per_group/2 and -%%% init_per_testcase/2. The scope of the SCB is determined by where is it -%%% started. If it is started in the command line or test spec then it will -%%% be stopped at the end of all tests. If it is started in init_per_suite, -%%% it will be stopped after end_per_suite and so on. See terminate -%%% documentation for a table describing the scoping machanics. -%%% -%%% All of callbacks except init/1 in a SCB are optional.

- --module(empty_scb). - -%% Suite Callbacks --export([init/1]). - --export([pre_init_suite/3]). --export([post_init_suite/3]). --export([pre_end_suite/3]). --export([post_end_suite/3]). - --export([pre_init_group/3]). --export([post_init_group/3]). --export([pre_end_group/3]). --export([post_end_group/3]). - --export([pre_init_tc/3]). --export([post_end_tc/3]). - --export([on_tc_fail/3]). - --export([terminate/2]). - --type proplist() :: list({atom(),term()}). --type config() :: proplist(). --type reason() :: term(). --type skip_or_fail() :: {skip, reason()} | - {auto_skip, reason()} | - {fail, reason()}. - --record(state, { id = ?MODULE :: term()}). - -%% @doc Always called before any other callback function. Use this to initiate -%% any common state. It should return an ID for this SCB and a state. The ID -%% is used to uniquly identify an SCB instance, if two SCB's return the same -%% ID the seconds SCB is ignored. This function should NOT have any side -%% effects as it might be called multiple times by common test. --spec init(Opts :: proplist()) -> - {Id :: term(), State :: #state{}}. -init(Opts) -> - {?MODULE, #state{ }}. - -%% @doc Called before init_per_suite is called. Note that this callback is -%% only called if the SCB is added before init_per_suite is run (eg. in a test -%% specification, suite/0 function etc). -%% You can change the config in the this function. --spec pre_init_suite(Suite :: atom(), - Config :: config(), - State :: #state{}) -> - {config() | skip_or_fail(), NewState :: #state{}}. -pre_init_suite(Suite,Config,State) -> - {Config, State}. - -%% @doc Called after init_per_suite. -%% you can change the config in this function. --spec post_init_suite(Suite :: atom(), - Config :: config(), - State :: #state{}) -> - {config() | skip_or_fail(), NewState :: #state{}}. -post_init_suite(Suite,Config,State) -> - {Config, State}. - -%% @doc Called before end_per_suite. Note that the config cannot be -%% changed here, only the status of the suite. --spec pre_end_suite(Suite :: atom(), - Config :: config(), - State :: #state{}) -> - {ok | skip_or_fail(), NewState :: #state{}}. -pre_end_suite(Suite,Config,State) -> {Config, State}. - -%% @doc Called after end_per_suite. Note that the config cannot be -%% changed here, only the status of the suite. --spec post_end_suite(Suite :: atom(), - Config :: config(), - State :: #state{}) -> - {ok | skip_or_fail(), NewState :: #state{}}. -post_end_suite(Suite,Config,State) -> {Config, State}. - -%% @doc Called before each init_per_group. -%% You can change the config in this function. --spec pre_init_group(Group :: atom(), - Config :: config(), - State :: #state{}) -> - {config() | skip_or_fail(), NewState :: #state{}}. -pre_init_group(Group,Config,State) -> {Config, State}. - -%% @doc Called after each init_per_group. -%% You can change the config in this function. --spec post_init_group(Group :: atom(), - Config :: config(), - State :: #state{}) -> - {config() | skip_or_fail(), NewState :: #state{}}. -post_init_group(Group,Config,State) -> {Config, State}. - -%% @doc Called after each end_per_group. Note that the config cannot be -%% changed here, only the status of the group. --spec pre_end_group(Group :: atom(), - Config :: config(), - State :: #state{}) -> - {ok | skip_or_fail(), NewState :: #state{}}. -pre_end_group(Group,Config,State) -> {Config, State}. - -%% @doc Called after each end_per_group. Note that the config cannot be -%% changed here, only the status of the group. --spec post_end_group(Group :: atom(), - Config :: config(), - State :: #state{}) -> - {ok | skip_or_fail(), NewState :: #state{}}. -post_end_group(Group,Config,State) -> {Config, State}. - -%% @doc Called before each test case. -%% You can change the config in this function. --spec pre_init_tc(TC :: atom(), - Config :: config(), - State :: #state{}) -> - {config() | skip_or_fail(), NewState :: #state{}}. -pre_init_tc(TC,Config,State) -> {Config, State}. - -%% @doc Called after each test case. Note that the config cannot be -%% changed here, only the status of the test case. --spec post_end_tc(TC :: atom(), - Config :: config(), - State :: #state{}) -> - {ok | skip_or_fail(), NewState :: #state{}}. -post_end_tc(TC,Config,State) -> {Config, State}. - -%% @doc Called after post_init_suite, post_end_suite, post_init_group, -%% post_end_group and post_end_tc if the suite, group or test case failed. -%% This function should be used for extra cleanup which might be needed. -%% It is not possible to modify the config or the status of the test run. --spec on_tc_fail(TC :: init_per_suite | end_per_suite | - init_per_group | end_per_group | atom(), - Config :: config(), State :: #state{}) -> - ok. -on_tc_fail(_TC, _Config, _State) -> - ok. - -%% @doc Called when the scope of the SCB is done, this depends on -%% when the SCB was specified. This translation table describes when this -%% function is called. -%% -%% | Started in | terminate called | -%% |---------------------|-------------------------| -%% | command_line | after all tests are run | -%% | test spec | after all tests are run | -%% | suite/0 | after SUITE is done | -%% | init_per_suite/1 | after SUITE is done | -%% | init_per_group/2 | after group is done | -%% | init_per_testcase/2 | after test case is done | -%% |-----------------------------------------------| -%% --spec terminate(Config :: proplist(), State :: #state{}) -> - term(). -terminate(Config,State) -> {Config, State}. diff --git a/lib/common_test/test/ct_hooks_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE.erl new file mode 100644 index 0000000000..1e187aa205 --- /dev/null +++ b/lib/common_test/test/ct_hooks_SUITE.erl @@ -0,0 +1,1021 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009-2010. 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% +%% + +%%%------------------------------------------------------------------- +%%% File: ct_error_SUITE +%%% +%%% Description: +%%% Test various errors in Common Test suites. +%%% +%%% The suites used for the test are located in the data directory. +%%%------------------------------------------------------------------- +-module(ct_hooks_SUITE). + +-compile(export_all). + +-include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + +-define(eh, ct_test_support_eh). + +%%-------------------------------------------------------------------- +%% TEST SERVER CALLBACK FUNCTIONS +%%-------------------------------------------------------------------- + +%%-------------------------------------------------------------------- +%% Description: Since Common Test starts another Test Server +%% instance, the tests need to be performed on a separate node (or +%% there will be clashes with logging processes etc). +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + DataDir = ?config(data_dir, Config), + TestDir = filename:join(DataDir,"cth/tests/"), + CTHs = filelib:wildcard(filename:join(TestDir,"*_cth.erl")), + io:format("CTHs: ~p",[CTHs]), + [io:format("Compiling ~p: ~p", + [FileName,compile:file(FileName,[{outdir,TestDir},debug_info])]) || + FileName <- CTHs], + ct_test_support:init_per_suite([{path_dirs,[TestDir]} | Config]). + +end_per_suite(Config) -> + ct_test_support:end_per_suite(Config). + +init_per_testcase(TestCase, Config) -> + ct_test_support:init_per_testcase(TestCase, Config). + +end_per_testcase(TestCase, Config) -> + ct_test_support:end_per_testcase(TestCase, Config). + + +suite() -> + [{timetrap,{seconds,20}}]. + +all() -> + all(suite). + +all(suite) -> + lists:reverse( + [ + one_cth, two_cth, faulty_cth_no_init, faulty_cth_id_no_init, + faulty_cth_exit_in_init, faulty_cth_exit_in_id, + faulty_cth_exit_in_init_scope_suite, minimal_cth, + minimal_and_maximal_cth, faulty_cth_undef, + scope_per_suite_cth, scope_per_group_cth, scope_suite_cth, + scope_per_suite_state_cth, scope_per_group_state_cth, + scope_suite_state_cth, + fail_pre_suite_cth, fail_post_suite_cth, skip_pre_suite_cth, + skip_post_suite_cth, recover_post_suite_cth, update_config_cth, + state_update_cth, options_cth, same_id_cth, + fail_n_skip_with_minimal_cth + ] + ) + . + + +%%-------------------------------------------------------------------- +%% TEST CASES +%%-------------------------------------------------------------------- + +%%%----------------------------------------------------------------- +%%% +one_cth(Config) when is_list(Config) -> + do_test(one_empty_cth, "ct_cth_empty_SUITE.erl",[empty_cth], Config). + +two_cth(Config) when is_list(Config) -> + do_test(two_empty_cth, "ct_cth_empty_SUITE.erl",[empty_cth,empty_cth], + Config). + +faulty_cth_no_init(Config) when is_list(Config) -> + do_test(faulty_cth_no_init, "ct_cth_empty_SUITE.erl",[askjhdkljashdkaj], + Config,{error,"Failed to start CTH, see the " + "CT Log for details"}). + +faulty_cth_id_no_init(Config) when is_list(Config) -> + do_test(faulty_cth_id_no_init, "ct_cth_empty_SUITE.erl",[id_no_init_cth], + Config,{error,"Failed to start CTH, see the " + "CT Log for details"}). + +minimal_cth(Config) when is_list(Config) -> + do_test(minimal_cth, "ct_cth_empty_SUITE.erl",[minimal_cth],Config). + +minimal_and_maximal_cth(Config) when is_list(Config) -> + do_test(minimal_and_maximal_cth, "ct_cth_empty_SUITE.erl", + [minimal_cth, empty_cth],Config). + +faulty_cth_undef(Config) when is_list(Config) -> + do_test(faulty_cth_undef, "ct_cth_empty_SUITE.erl", + [undef_cth],Config). + +faulty_cth_exit_in_init_scope_suite(Config) when is_list(Config) -> + do_test(faulty_cth_exit_in_init_scope_suite, + "ct_exit_in_init_scope_suite_cth_SUITE.erl", + [],Config). + +faulty_cth_exit_in_init(Config) when is_list(Config) -> + do_test(faulty_cth_exit_in_init, "ct_cth_empty_SUITE.erl", + [crash_init_cth], Config, + {error,"Failed to start CTH, see the " + "CT Log for details"}). + +faulty_cth_exit_in_id(Config) when is_list(Config) -> + do_test(faulty_cth_exit_in_id, "ct_cth_empty_SUITE.erl", + [crash_id_cth], Config, + {error,"Failed to start CTH, see the " + "CT Log for details"}). + +scope_per_suite_cth(Config) when is_list(Config) -> + do_test(scope_per_suite_cth, "ct_scope_per_suite_cth_SUITE.erl", + [],Config). + +scope_suite_cth(Config) when is_list(Config) -> + do_test(scope_suite_cth, "ct_scope_suite_cth_SUITE.erl", + [],Config). + +scope_per_group_cth(Config) when is_list(Config) -> + do_test(scope_per_group_cth, "ct_scope_per_group_cth_SUITE.erl", + [],Config). + +scope_per_suite_state_cth(Config) when is_list(Config) -> + do_test(scope_per_suite_state_cth, "ct_scope_per_suite_state_cth_SUITE.erl", + [],Config). + +scope_suite_state_cth(Config) when is_list(Config) -> + do_test(scope_suite_state_cth, "ct_scope_suite_state_cth_SUITE.erl", + [],Config). + +scope_per_group_state_cth(Config) when is_list(Config) -> + do_test(scope_per_group_state_cth, "ct_scope_per_group_state_cth_SUITE.erl", + [],Config). + +fail_pre_suite_cth(Config) when is_list(Config) -> + do_test(fail_pre_suite_cth, "ct_cth_empty_SUITE.erl", + [fail_pre_suite_cth],Config). + +fail_post_suite_cth(Config) when is_list(Config) -> + do_test(fail_post_suite_cth, "ct_cth_empty_SUITE.erl", + [fail_post_suite_cth],Config). + +skip_pre_suite_cth(Config) when is_list(Config) -> + do_test(skip_pre_suite_cth, "ct_cth_empty_SUITE.erl", + [skip_pre_suite_cth],Config). + +skip_post_suite_cth(Config) when is_list(Config) -> + do_test(skip_post_suite_cth, "ct_cth_empty_SUITE.erl", + [skip_post_suite_cth],Config). + +recover_post_suite_cth(Config) when is_list(Config) -> + do_test(recover_post_suite_cth, "ct_cth_fail_per_suite_SUITE.erl", + [recover_post_suite_cth],Config). + +update_config_cth(Config) when is_list(Config) -> + do_test(update_config_cth, "ct_update_config_SUITE.erl", + [update_config_cth],Config). + +state_update_cth(Config) when is_list(Config) -> + do_test(state_update_cth, "ct_cth_fail_one_skip_one_SUITE.erl", + [state_update_cth,state_update_cth],Config). + +options_cth(Config) when is_list(Config) -> + do_test(options_cth, "ct_cth_empty_SUITE.erl", + [{empty_cth,[test]}],Config). + +same_id_cth(Config) when is_list(Config) -> + do_test(same_id_cth, "ct_cth_empty_SUITE.erl", + [same_id_cth,same_id_cth],Config). + +fail_n_skip_with_minimal_cth(Config) when is_list(Config) -> + do_test(fail_n_skip_with_minimal_cth, "ct_cth_fail_one_skip_one_SUITE.erl", + [minimal_terminate_cth],Config). + +%%%----------------------------------------------------------------- +%%% HELP FUNCTIONS +%%%----------------------------------------------------------------- + +do_test(Tag, SWC, CTHs, Config) -> + do_test(Tag, SWC, CTHs, Config, ok). +do_test(Tag, SWC, CTHs, Config, {error,_} = Res) -> + do_test(Tag, SWC, CTHs, Config, Res, 1); +do_test(Tag, SWC, CTHs, Config, Res) -> + do_test(Tag, SWC, CTHs, Config, Res, 2). + +do_test(Tag, SuiteWildCard, CTHs, Config, Res, EC) -> + + DataDir = ?config(data_dir, Config), + Suites = filelib:wildcard( + filename:join([DataDir,"cth/tests",SuiteWildCard])), + {Opts,ERPid} = setup([{suite,Suites}, + {ct_hooks,CTHs},{label,Tag}], Config), + Res = ct_test_support:run(Opts, Config), + Events = ct_test_support:get_events(ERPid, Config), + + ct_test_support:log_events(Tag, + reformat(Events, ?eh), + ?config(priv_dir, Config)), + + TestEvents = events_to_check(Tag, EC), + ok = ct_test_support:verify_events(TestEvents, Events, Config). + +setup(Test, Config) -> + Opts0 = ct_test_support:get_opts(Config), + Level = ?config(trace_level, Config), + EvHArgs = [{cbm,ct_test_support},{trace_level,Level}], + Opts = Opts0 ++ [{event_handler,{?eh,EvHArgs}}|Test], + ERPid = ct_test_support:start_event_receiver(Config), + {Opts,ERPid}. + +reformat(Events, EH) -> + ct_test_support:reformat(Events, EH). +%reformat(Events, _EH) -> +% Events. + +%%%----------------------------------------------------------------- +%%% TEST EVENTS +%%%----------------------------------------------------------------- +events_to_check(Test) -> + %% 2 tests (ct:run_test + script_start) is default + events_to_check(Test, 2). + +events_to_check(_, 0) -> + []; +events_to_check(Test, N) -> + test_events(Test) ++ events_to_check(Test, N-1). + +test_events(one_empty_cth) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,cth,{empty_cth,id,[[]]}}, + {?eh,cth,{empty_cth,init,[{'_','_','_'},[]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_cth_empty_SUITE,init_per_suite}}, + {?eh,cth,{empty_cth,pre_init_per_suite, + [ct_cth_empty_SUITE,'$proplist',[]]}}, + {?eh,cth,{empty_cth,post_init_per_suite, + [ct_cth_empty_SUITE,'$proplist','$proplist',[]]}}, + {?eh,tc_done,{ct_cth_empty_SUITE,init_per_suite,ok}}, + + {?eh,tc_start,{ct_cth_empty_SUITE,test_case}}, + {?eh,cth,{empty_cth,pre_init_per_testcase,[test_case,'$proplist',[]]}}, + {?eh,cth,{empty_cth,post_end_per_testcase,[test_case,'$proplist','_',[]]}}, + {?eh,tc_done,{ct_cth_empty_SUITE,test_case,ok}}, + + {?eh,tc_start,{ct_cth_empty_SUITE,end_per_suite}}, + {?eh,cth,{empty_cth,pre_end_per_suite, + [ct_cth_empty_SUITE,'$proplist',[]]}}, + {?eh,cth,{empty_cth,post_end_per_suite,[ct_cth_empty_SUITE,'$proplist','_',[]]}}, + {?eh,tc_done,{ct_cth_empty_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,cth,{empty_cth,terminate,[[]]}}, + {?eh,stop_logging,[]} + ]; + +test_events(two_empty_cth) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,cth,{'_',id,[[]]}}, + {?eh,cth,{'_',init,['_',[]]}}, + {?eh,cth,{'_',id,[[]]}}, + {?eh,cth,{'_',init,['_',[]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_cth_empty_SUITE,init_per_suite}}, + {?eh,cth,{'_',pre_init_per_suite,[ct_cth_empty_SUITE,'$proplist',[]]}}, + {?eh,cth,{'_',pre_init_per_suite,[ct_cth_empty_SUITE,'$proplist',[]]}}, + {?eh,cth,{'_',post_init_per_suite,[ct_cth_empty_SUITE,'$proplist','$proplist',[]]}}, + {?eh,cth,{'_',post_init_per_suite,[ct_cth_empty_SUITE,'$proplist','$proplist',[]]}}, + {?eh,tc_done,{ct_cth_empty_SUITE,init_per_suite,ok}}, + + {?eh,tc_start,{ct_cth_empty_SUITE,test_case}}, + {?eh,cth,{'_',pre_init_per_testcase,[test_case,'$proplist',[]]}}, + {?eh,cth,{'_',pre_init_per_testcase,[test_case,'$proplist',[]]}}, + {?eh,cth,{'_',post_end_per_testcase,[test_case,'$proplist',ok,[]]}}, + {?eh,cth,{'_',post_end_per_testcase,[test_case,'$proplist',ok,[]]}}, + {?eh,tc_done,{ct_cth_empty_SUITE,test_case,ok}}, + + {?eh,tc_start,{ct_cth_empty_SUITE,end_per_suite}}, + {?eh,cth,{'_',pre_end_per_suite,[ct_cth_empty_SUITE,'$proplist',[]]}}, + {?eh,cth,{'_',pre_end_per_suite,[ct_cth_empty_SUITE,'$proplist',[]]}}, + {?eh,cth,{'_',post_end_per_suite,[ct_cth_empty_SUITE,'$proplist','_',[]]}}, + {?eh,cth,{'_',post_end_per_suite,[ct_cth_empty_SUITE,'$proplist','_',[]]}}, + {?eh,tc_done,{ct_cth_empty_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,cth,{'_',terminate,[[]]}}, + {?eh,cth,{'_',terminate,[[]]}}, + {?eh,stop_logging,[]} + ]; + +test_events(faulty_cth_no_init) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]; + +test_events(faulty_cth_id_no_init) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,cth,{'_',id,[[]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {negative,{?eh,tc_start,'_'}, + {?eh,test_done,{'DEF','STOP_TIME'}}}, + {?eh,stop_logging,[]} + ]; + +test_events(minimal_cth) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {negative,{?eh,cth,{'_',id,['_',[]]}}, + {?eh,cth,{'_',init,['_',[]]}}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_cth_empty_SUITE,init_per_suite}}, + {?eh,tc_done,{ct_cth_empty_SUITE,init_per_suite,ok}}, + + {?eh,tc_start,{ct_cth_empty_SUITE,test_case}}, + {?eh,tc_done,{ct_cth_empty_SUITE,test_case,ok}}, + + {?eh,tc_start,{ct_cth_empty_SUITE,end_per_suite}}, + {?eh,tc_done,{ct_cth_empty_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]; + +test_events(minimal_and_maximal_cth) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {negative,{?eh,cth,{'_',id,['_',[]]}}, + {?eh,cth,{'_',init,['_',[]]}}}, + {?eh,cth,{'_',id,[[]]}}, + {?eh,cth,{'_',init,['_',[]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_cth_empty_SUITE,init_per_suite}}, + {?eh,cth,{'_',pre_init_per_suite,[ct_cth_empty_SUITE,'$proplist',[]]}}, + {?eh,cth,{'_',post_init_per_suite,[ct_cth_empty_SUITE,'$proplist','$proplist',[]]}}, + {?eh,tc_done,{ct_cth_empty_SUITE,init_per_suite,ok}}, + + {?eh,tc_start,{ct_cth_empty_SUITE,test_case}}, + {?eh,cth,{'_',pre_init_per_testcase,[test_case,'$proplist',[]]}}, + {?eh,cth,{'_',post_end_per_testcase,[test_case,'$proplist',ok,[]]}}, + {?eh,tc_done,{ct_cth_empty_SUITE,test_case,ok}}, + + {?eh,tc_start,{ct_cth_empty_SUITE,end_per_suite}}, + {?eh,cth,{'_',pre_end_per_suite,[ct_cth_empty_SUITE,'$proplist',[]]}}, + {?eh,cth,{'_',post_end_per_suite,[ct_cth_empty_SUITE,'$proplist','_',[]]}}, + {?eh,tc_done,{ct_cth_empty_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,cth,{'_',terminate,[[]]}}, + {?eh,stop_logging,[]} + ]; + +test_events(faulty_cth_undef) -> + FailReasonStr = "undef_cth:pre_init_per_suite/3 CTH call failed", + FailReason = {ct_cth_empty_SUITE,init_per_suite, + {failed,FailReasonStr}}, + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,cth,{'_',init,['_',[]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_cth_empty_SUITE,init_per_suite}}, + {?eh,tc_done,{ct_cth_empty_SUITE,init_per_suite, + {failed, {error,FailReasonStr}}}}, + {?eh,cth,{'_',on_tc_fail,'_'}}, + + {?eh,tc_auto_skip,{ct_cth_empty_SUITE,test_case, + {failed, FailReason}}}, + {?eh,cth,{'_',on_tc_skip,'_'}}, + + {?eh,tc_auto_skip,{ct_cth_empty_SUITE,end_per_suite, + {failed, FailReason}}}, + {?eh,cth,{'_',on_tc_skip,'_'}}, + + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]; + +test_events(faulty_cth_exit_in_init_scope_suite) -> + [{?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{'_',init_per_suite}}, + {?eh,cth,{empty_cth,init,['_',[]]}}, + {?eh,tc_done, + {ct_exit_in_init_scope_suite_cth_SUITE,init_per_suite, + {failed, + {error, + "Failed to start CTH, see the CT Log for details"}}}}, + {?eh,tc_auto_skip, + {ct_exit_in_init_scope_suite_cth_SUITE,test_case, + {failed, + {ct_exit_in_init_scope_suite_cth_SUITE,init_per_suite, + {failed, + "Failed to start CTH, see the CT Log for details"}}}}}, + {?eh,tc_auto_skip, + {ct_exit_in_init_scope_suite_cth_SUITE,end_per_suite, + {failed, + {ct_exit_in_init_scope_suite_cth_SUITE,init_per_suite, + {failed, + "Failed to start CTH, see the CT Log for details"}}}}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]}]; + +test_events(faulty_cth_exit_in_init) -> + [{?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,cth,{empty_cth,init,['_',[]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]}]; + +test_events(faulty_cth_exit_in_id) -> + [{?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,cth,{empty_cth,id,[[]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {negative, {?eh,tc_start,'_'}, + {?eh,test_done,{'DEF','STOP_TIME'}}}, + {?eh,stop_logging,[]}]; + +test_events(scope_per_suite_cth) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_scope_per_suite_cth_SUITE,init_per_suite}}, + {?eh,cth,{'_',id,[[]]}}, + {?eh,cth,{'_',init,['_',[]]}}, + {?eh,cth,{'_',post_init_per_suite,[ct_scope_per_suite_cth_SUITE,'$proplist','$proplist',[]]}}, + {?eh,tc_done,{ct_scope_per_suite_cth_SUITE,init_per_suite,ok}}, + + {?eh,tc_start,{ct_scope_per_suite_cth_SUITE,test_case}}, + {?eh,cth,{'_',pre_init_per_testcase,[test_case,'$proplist',[]]}}, + {?eh,cth,{'_',post_end_per_testcase,[test_case,'$proplist',ok,[]]}}, + {?eh,tc_done,{ct_scope_per_suite_cth_SUITE,test_case,ok}}, + + {?eh,tc_start,{ct_scope_per_suite_cth_SUITE,end_per_suite}}, + {?eh,cth,{'_',pre_end_per_suite, + [ct_scope_per_suite_cth_SUITE,'$proplist',[]]}}, + {?eh,cth,{'_',post_end_per_suite,[ct_scope_per_suite_cth_SUITE,'$proplist','_',[]]}}, + {?eh,cth,{'_',terminate,[[]]}}, + {?eh,tc_done,{ct_scope_per_suite_cth_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]; + +test_events(scope_suite_cth) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_scope_suite_cth_SUITE,init_per_suite}}, + {?eh,cth,{'_',id,[[]]}}, + {?eh,cth,{'_',init,['_',[]]}}, + {?eh,cth,{'_',pre_init_per_suite,[ct_scope_suite_cth_SUITE,'$proplist',[]]}}, + {?eh,cth,{'_',post_init_per_suite,[ct_scope_suite_cth_SUITE,'$proplist','$proplist',[]]}}, + {?eh,tc_done,{ct_scope_suite_cth_SUITE,init_per_suite,ok}}, + + {?eh,tc_start,{ct_scope_suite_cth_SUITE,test_case}}, + {?eh,cth,{'_',pre_init_per_testcase,[test_case,'$proplist',[]]}}, + {?eh,cth,{'_',post_end_per_testcase,[test_case,'$proplist',ok,[]]}}, + {?eh,tc_done,{ct_scope_suite_cth_SUITE,test_case,ok}}, + + {?eh,tc_start,{ct_scope_suite_cth_SUITE,end_per_suite}}, + {?eh,cth,{'_',pre_end_per_suite,[ct_scope_suite_cth_SUITE,'$proplist',[]]}}, + {?eh,cth,{'_',post_end_per_suite,[ct_scope_suite_cth_SUITE,'$proplist','_',[]]}}, + {?eh,cth,{'_',terminate,[[]]}}, + {?eh,tc_done,{ct_scope_suite_cth_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]; + +test_events(scope_per_group_cth) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_scope_per_group_cth_SUITE,init_per_suite}}, + {?eh,tc_done,{ct_scope_per_group_cth_SUITE,init_per_suite,ok}}, + + [{?eh,tc_start,{ct_scope_per_group_cth_SUITE,{init_per_group,group1,[]}}}, + {?eh,cth,{'_',id,[[]]}}, + {?eh,cth,{'_',init,['_',[]]}}, + {?eh,cth,{'_',post_init_per_group,[group1,'$proplist','$proplist',[]]}}, + {?eh,tc_done,{ct_scope_per_group_cth_SUITE,{init_per_group,group1,[]},ok}}, + + {?eh,tc_start,{ct_scope_per_group_cth_SUITE,test_case}}, + {?eh,cth,{'_',pre_init_per_testcase,[test_case,'$proplist',[]]}}, + {?eh,cth,{'_',post_end_per_testcase,[test_case,'$proplist',ok,[]]}}, + {?eh,tc_done,{ct_scope_per_group_cth_SUITE,test_case,ok}}, + + {?eh,tc_start,{ct_scope_per_group_cth_SUITE,{end_per_group,group1,[]}}}, + {?eh,cth,{'_',pre_end_per_group,[group1,'$proplist',[]]}}, + {?eh,cth,{'_',post_end_per_group,[group1,'$proplist','_',[]]}}, + {?eh,cth,{'_',terminate,[[]]}}, + {?eh,tc_done,{ct_scope_per_group_cth_SUITE,{end_per_group,group1,[]},ok}}], + + {?eh,tc_start,{ct_scope_per_group_cth_SUITE,end_per_suite}}, + {?eh,tc_done,{ct_scope_per_group_cth_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]; + +test_events(scope_per_suite_state_cth) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_scope_per_suite_state_cth_SUITE,init_per_suite}}, + {?eh,cth,{'_',id,[[test]]}}, + {?eh,cth,{'_',init,['_',[test]]}}, + {?eh,cth,{'_',post_init_per_suite,[ct_scope_per_suite_state_cth_SUITE,'$proplist','$proplist',[test]]}}, + {?eh,tc_done,{ct_scope_per_suite_state_cth_SUITE,init_per_suite,ok}}, + + {?eh,tc_start,{ct_scope_per_suite_state_cth_SUITE,test_case}}, + {?eh,cth,{'_',pre_init_per_testcase,[test_case,'$proplist',[test]]}}, + {?eh,cth,{'_',post_end_per_testcase,[test_case,'$proplist',ok,[test]]}}, + {?eh,tc_done,{ct_scope_per_suite_state_cth_SUITE,test_case,ok}}, + + {?eh,tc_start,{ct_scope_per_suite_state_cth_SUITE,end_per_suite}}, + {?eh,cth,{'_',pre_end_per_suite, + [ct_scope_per_suite_state_cth_SUITE,'$proplist',[test]]}}, + {?eh,cth,{'_',post_end_per_suite,[ct_scope_per_suite_state_cth_SUITE,'$proplist','_',[test]]}}, + {?eh,cth,{'_',terminate,[[test]]}}, + {?eh,tc_done,{ct_scope_per_suite_state_cth_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]; + +test_events(scope_suite_state_cth) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_scope_suite_state_cth_SUITE,init_per_suite}}, + {?eh,cth,{'_',id,[[test]]}}, + {?eh,cth,{'_',init,['_',[test]]}}, + {?eh,cth,{'_',pre_init_per_suite,[ct_scope_suite_state_cth_SUITE,'$proplist',[test]]}}, + {?eh,cth,{'_',post_init_per_suite,[ct_scope_suite_state_cth_SUITE,'$proplist','$proplist',[test]]}}, + {?eh,tc_done,{ct_scope_suite_state_cth_SUITE,init_per_suite,ok}}, + + {?eh,tc_start,{ct_scope_suite_state_cth_SUITE,test_case}}, + {?eh,cth,{'_',pre_init_per_testcase,[test_case,'$proplist',[test]]}}, + {?eh,cth,{'_',post_end_per_testcase,[test_case,'$proplist',ok,[test]]}}, + {?eh,tc_done,{ct_scope_suite_state_cth_SUITE,test_case,ok}}, + + {?eh,tc_start,{ct_scope_suite_state_cth_SUITE,end_per_suite}}, + {?eh,cth,{'_',pre_end_per_suite,[ct_scope_suite_state_cth_SUITE,'$proplist',[test]]}}, + {?eh,cth,{'_',post_end_per_suite,[ct_scope_suite_state_cth_SUITE,'$proplist','_',[test]]}}, + {?eh,cth,{'_',terminate,[[test]]}}, + {?eh,tc_done,{ct_scope_suite_state_cth_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]; + +test_events(scope_per_group_state_cth) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_scope_per_group_state_cth_SUITE,init_per_suite}}, + {?eh,tc_done,{ct_scope_per_group_state_cth_SUITE,init_per_suite,ok}}, + + [{?eh,tc_start,{ct_scope_per_group_state_cth_SUITE,{init_per_group,group1,[]}}}, + {?eh,cth,{'_',id,[[test]]}}, + {?eh,cth,{'_',init,['_',[test]]}}, + {?eh,cth,{'_',post_init_per_group,[group1,'$proplist','$proplist',[test]]}}, + {?eh,tc_done,{ct_scope_per_group_state_cth_SUITE,{init_per_group,group1,[]},ok}}, + + {?eh,tc_start,{ct_scope_per_group_state_cth_SUITE,test_case}}, + {?eh,cth,{'_',pre_init_per_testcase,[test_case,'$proplist',[test]]}}, + {?eh,cth,{'_',post_end_per_testcase,[test_case,'$proplist',ok,[test]]}}, + {?eh,tc_done,{ct_scope_per_group_state_cth_SUITE,test_case,ok}}, + + {?eh,tc_start,{ct_scope_per_group_state_cth_SUITE,{end_per_group,group1,[]}}}, + {?eh,cth,{'_',pre_end_per_group,[group1,'$proplist',[test]]}}, + {?eh,cth,{'_',post_end_per_group,[group1,'$proplist','_',[test]]}}, + {?eh,cth,{'_',terminate,[[test]]}}, + {?eh,tc_done,{ct_scope_per_group_state_cth_SUITE,{end_per_group,group1,[]},ok}}], + + {?eh,tc_start,{ct_scope_per_group_state_cth_SUITE,end_per_suite}}, + {?eh,tc_done,{ct_scope_per_group_state_cth_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]; + +test_events(fail_pre_suite_cth) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,cth,{'_',init,['_',[]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + + + {?eh,tc_start,{ct_cth_empty_SUITE,init_per_suite}}, + {?eh,cth,{'_',pre_init_per_suite,[ct_cth_empty_SUITE,'$proplist',[]]}}, + {?eh,cth,{'_',post_init_per_suite,[ct_cth_empty_SUITE,'$proplist', + {fail,"Test failure"},[]]}}, + {?eh,tc_done,{ct_cth_empty_SUITE,init_per_suite, + {failed, {error,"Test failure"}}}}, + {?eh,cth,{'_',on_tc_fail, + [init_per_suite,{failed,"Test failure"},[]]}}, + + + {?eh,tc_auto_skip,{ct_cth_empty_SUITE,test_case, + {failed,{ct_cth_empty_SUITE,init_per_suite, + {failed,"Test failure"}}}}}, + {?eh,cth,{'_',on_tc_skip, + [test_case, {tc_auto_skip, + {failed, {ct_cth_empty_SUITE, init_per_suite, + {failed, "Test failure"}}}},[]]}}, + + + {?eh,tc_auto_skip, {ct_cth_empty_SUITE, end_per_suite, + {failed, {ct_cth_empty_SUITE, init_per_suite, + {failed, "Test failure"}}}}}, + {?eh,cth,{'_',on_tc_skip, + [end_per_suite, {tc_auto_skip, + {failed, {ct_cth_empty_SUITE, init_per_suite, + {failed, "Test failure"}}}},[]]}}, + + + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,cth, {'_',terminate,[[]]}}, + {?eh,stop_logging,[]} + ]; + +test_events(fail_post_suite_cth) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,cth,{'_',init,['_',[]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_cth_empty_SUITE,init_per_suite}}, + {?eh,cth,{'_',pre_init_per_suite,[ct_cth_empty_SUITE,'$proplist',[]]}}, + {?eh,cth,{'_',post_init_per_suite,[ct_cth_empty_SUITE,'$proplist','$proplist',[]]}}, + {?eh,tc_done,{ct_cth_empty_SUITE,init_per_suite, + {failed,{error,"Test failure"}}}}, + {?eh,cth,{'_',on_tc_fail,[init_per_suite, {failed,"Test failure"}, []]}}, + + {?eh,tc_auto_skip,{ct_cth_empty_SUITE,test_case, + {failed,{ct_cth_empty_SUITE,init_per_suite, + {failed,"Test failure"}}}}}, + {?eh,cth,{'_',on_tc_skip,[test_case,{tc_auto_skip,'_'},[]]}}, + + {?eh,tc_auto_skip, {ct_cth_empty_SUITE, end_per_suite, + {failed, {ct_cth_empty_SUITE, init_per_suite, + {failed, "Test failure"}}}}}, + {?eh,cth,{'_',on_tc_skip,[end_per_suite,{tc_auto_skip,'_'},[]]}}, + + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,cth, {'_',terminate,[[]]}}, + {?eh,stop_logging,[]} + ]; + +test_events(skip_pre_suite_cth) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,cth,{'_',init,['_',[]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_cth_empty_SUITE,init_per_suite}}, + {?eh,cth,{'_',pre_init_per_suite,[ct_cth_empty_SUITE,'$proplist',[]]}}, + {?eh,cth,{'_',post_init_per_suite,[ct_cth_empty_SUITE,'$proplist',{skip,"Test skip"},[]]}}, + {?eh,tc_done,{ct_cth_empty_SUITE,init_per_suite,{skipped,"Test skip"}}}, + {?eh,cth,{'_',on_tc_skip, + [init_per_suite,{tc_user_skip,{skipped,"Test skip"}},[]]}}, + + {?eh,tc_auto_skip,{ct_cth_empty_SUITE,test_case,"Test skip"}}, + {?eh,cth,{'_',on_tc_skip,[test_case,{tc_auto_skip,"Test skip"},[]]}}, + + {?eh,tc_auto_skip, {ct_cth_empty_SUITE, end_per_suite,"Test skip"}}, + {?eh,cth,{'_',on_tc_skip,[end_per_suite,{tc_auto_skip,"Test skip"},[]]}}, + + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,cth, {'_',terminate,[[]]}}, + {?eh,stop_logging,[]} + ]; + +test_events(skip_post_suite_cth) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,cth,{'_',init,['_',[]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + + {?eh,tc_start,{ct_cth_empty_SUITE,init_per_suite}}, + {?eh,cth,{'_',pre_init_per_suite,[ct_cth_empty_SUITE,'$proplist',[]]}}, + {?eh,cth,{'_',post_init_per_suite,[ct_cth_empty_SUITE,'$proplist','$proplist',[]]}}, + {?eh,tc_done,{ct_cth_empty_SUITE,init_per_suite,{skipped,"Test skip"}}}, + {?eh,cth,{'_',on_tc_skip, + [init_per_suite,{tc_user_skip,{skipped,"Test skip"}},[]]}}, + + {?eh,tc_auto_skip,{ct_cth_empty_SUITE,test_case,"Test skip"}}, + {?eh,cth,{'_',on_tc_skip,[test_case,{tc_auto_skip,"Test skip"},[]]}}, + + {?eh,tc_auto_skip, {ct_cth_empty_SUITE, end_per_suite,"Test skip"}}, + {?eh,cth,{'_',on_tc_skip,[end_per_suite,{tc_auto_skip,"Test skip"},[]]}}, + + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,cth,{'_',terminate,[[]]}}, + {?eh,stop_logging,[]} + ]; + +test_events(recover_post_suite_cth) -> + Suite = ct_cth_fail_per_suite_SUITE, + [ + {?eh,start_logging,'_'}, + {?eh,cth,{'_',init,['_',[]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{Suite,init_per_suite}}, + {?eh,cth,{'_',pre_init_per_suite,[Suite,'$proplist','$proplist']}}, + {?eh,cth,{'_',post_init_per_suite,[Suite,contains([tc_status]), + {'EXIT',{'_','_'}},[]]}}, + {?eh,tc_done,{Suite,init_per_suite,ok}}, + + {?eh,tc_start,{Suite,test_case}}, + {?eh,cth,{'_',pre_init_per_testcase, + [test_case, not_contains([tc_status]),[]]}}, + {?eh,cth,{'_',post_end_per_testcase, + [test_case, contains([tc_status]),'_',[]]}}, + {?eh,tc_done,{Suite,test_case,ok}}, + + {?eh,tc_start,{Suite,end_per_suite}}, + {?eh,cth,{'_',pre_end_per_suite, + [Suite,not_contains([tc_status]),[]]}}, + {?eh,cth,{'_',post_end_per_suite, + [Suite,not_contains([tc_status]),'_',[]]}}, + {?eh,tc_done,{Suite,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,cth,{'_',terminate,[[]]}}, + {?eh,stop_logging,[]} + ]; + +test_events(update_config_cth) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,cth,{'_',init,['_',[]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + + {?eh,tc_start,{ct_update_config_SUITE,init_per_suite}}, + {?eh,cth,{'_',pre_init_per_suite, + [ct_update_config_SUITE,contains([]),[]]}}, + {?eh,cth,{'_',post_init_per_suite, + [ct_update_config_SUITE, + '$proplist', + contains( + [init_per_suite, + pre_init_per_suite]), + []]}}, + {?eh,tc_done,{ct_update_config_SUITE,init_per_suite,ok}}, + + {?eh,tc_start,{ct_update_config_SUITE, {init_per_group,group1,[]}}}, + {?eh,cth,{'_',pre_init_per_group, + [group1,contains( + [post_init_per_suite, + init_per_suite, + pre_init_per_suite]), + []]}}, + {?eh,cth,{'_',post_init_per_group, + [group1, + contains( + [post_init_per_suite, + init_per_suite, + pre_init_per_suite]), + contains( + [init_per_group, + pre_init_per_group, + post_init_per_suite, + init_per_suite, + pre_init_per_suite]), + []]}}, + {?eh,tc_done,{ct_update_config_SUITE,{init_per_group,group1,[]},ok}}, + + {?eh,tc_start,{ct_update_config_SUITE,test_case}}, + {?eh,cth,{'_',pre_init_per_testcase, + [test_case,contains( + [post_init_per_group, + init_per_group, + pre_init_per_group, + post_init_per_suite, + init_per_suite, + pre_init_per_suite]), + []]}}, + {?eh,cth,{'_',post_end_per_testcase, + [test_case,contains( + [init_per_testcase, + pre_init_per_testcase, + post_init_per_group, + init_per_group, + pre_init_per_group, + post_init_per_suite, + init_per_suite, + pre_init_per_suite]), + ok,[]]}}, + {?eh,tc_done,{ct_update_config_SUITE,test_case,ok}}, + + {?eh,tc_start,{ct_update_config_SUITE, {end_per_group,group1,[]}}}, + {?eh,cth,{'_',pre_end_per_group, + [group1,contains( + [post_init_per_group, + init_per_group, + pre_init_per_group, + post_init_per_suite, + init_per_suite, + pre_init_per_suite]), + []]}}, + {?eh,cth,{'_',post_end_per_group, + [group1, + contains( + [pre_end_per_group, + post_init_per_group, + init_per_group, + pre_init_per_group, + post_init_per_suite, + init_per_suite, + pre_init_per_suite]), + ok,[]]}}, + {?eh,tc_done,{ct_update_config_SUITE,{end_per_group,group1,[]},ok}}, + + {?eh,tc_start,{ct_update_config_SUITE,end_per_suite}}, + {?eh,cth,{'_',pre_end_per_suite, + [ct_update_config_SUITE,contains( + [post_init_per_suite, + init_per_suite, + pre_init_per_suite]), + []]}}, + {?eh,cth,{'_',post_end_per_suite, + [ct_update_config_SUITE,contains( + [pre_end_per_suite, + post_init_per_suite, + init_per_suite, + pre_init_per_suite]), + '_',[]]}}, + {?eh,tc_done,{ct_update_config_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,cth,{'_',terminate,[contains( + [post_end_per_suite, + pre_end_per_suite, + post_init_per_suite, + init_per_suite, + pre_init_per_suite])]}}, + {?eh,stop_logging,[]} + ]; + +test_events(state_update_cth) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,cth,{'_',init,['_',[]]}}, + {?eh,cth,{'_',init,['_',[]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{'_',init_per_suite}}, + + {?eh,tc_done,{'_',end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,cth,{'_',terminate,[contains( + [post_end_per_suite,pre_end_per_suite, + post_end_per_group,pre_end_per_group, + {not_in_order, + [post_end_per_testcase,pre_init_per_testcase, + on_tc_skip,post_end_per_testcase, + pre_init_per_testcase,on_tc_fail, + post_end_per_testcase,pre_init_per_testcase] + }, + post_init_per_group,pre_init_per_group, + post_init_per_suite,pre_init_per_suite, + init])]}}, + {?eh,cth,{'_',terminate,[contains( + [post_end_per_suite,pre_end_per_suite, + post_end_per_group,pre_end_per_group, + {not_in_order, + [post_end_per_testcase,pre_init_per_testcase, + on_tc_skip,post_end_per_testcase, + pre_init_per_testcase,on_tc_fail, + post_end_per_testcase,pre_init_per_testcase] + }, + post_init_per_group,pre_init_per_group, + post_init_per_suite,pre_init_per_suite, + init] + )]}}, + {?eh,stop_logging,[]} + ]; + +test_events(options_cth) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,cth,{empty_cth,init,['_',[test]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_cth_empty_SUITE,init_per_suite}}, + {?eh,cth,{empty_cth,pre_init_per_suite, + [ct_cth_empty_SUITE,'$proplist',[test]]}}, + {?eh,cth,{empty_cth,post_init_per_suite, + [ct_cth_empty_SUITE,'$proplist','$proplist',[test]]}}, + {?eh,tc_done,{ct_cth_empty_SUITE,init_per_suite,ok}}, + + {?eh,tc_start,{ct_cth_empty_SUITE,test_case}}, + {?eh,cth,{empty_cth,pre_init_per_testcase,[test_case,'$proplist',[test]]}}, + {?eh,cth,{empty_cth,post_end_per_testcase,[test_case,'$proplist','_',[test]]}}, + {?eh,tc_done,{ct_cth_empty_SUITE,test_case,ok}}, + + {?eh,tc_start,{ct_cth_empty_SUITE,end_per_suite}}, + {?eh,cth,{empty_cth,pre_end_per_suite, + [ct_cth_empty_SUITE,'$proplist',[test]]}}, + {?eh,cth,{empty_cth,post_end_per_suite,[ct_cth_empty_SUITE,'$proplist','_',[test]]}}, + {?eh,tc_done,{ct_cth_empty_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,cth,{empty_cth,terminate,[[test]]}}, + {?eh,stop_logging,[]} + ]; + +test_events(same_id_cth) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,cth,{'_',id,[[]]}}, + {?eh,cth,{'_',init,[same_id_cth,[]]}}, + {?eh,cth,{'_',id,[[]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{ct_cth_empty_SUITE,init_per_suite}}, + {?eh,cth,{'_',pre_init_per_suite,[ct_cth_empty_SUITE,'$proplist',[]]}}, + {negative, + {?eh,cth,{'_',pre_init_per_suite,[ct_cth_empty_SUITE,'$proplist',[]]}}, + {?eh,cth,{'_',post_init_per_suite, + [ct_cth_empty_SUITE,'$proplist','$proplist',[]]}}}, + {negative, + {?eh,cth,{'_',post_init_per_suite, + [ct_cth_empty_SUITE,'$proplist','$proplist',[]]}}, + {?eh,tc_done,{ct_cth_empty_SUITE,init_per_suite,ok}}}, + + {?eh,tc_start,{ct_cth_empty_SUITE,test_case}}, + {?eh,cth,{'_',pre_init_per_testcase,[test_case,'$proplist',[]]}}, + {negative, + {?eh,cth,{'_',pre_init_per_testcase,[test_case,'$proplist',[]]}}, + {?eh,cth,{'_',post_end_per_testcase,[test_case,'$proplist',ok,[]]}}}, + {negative, + {?eh,cth,{'_',post_end_per_testcase,[test_case,'$proplist',ok,[]]}}, + {?eh,tc_done,{ct_cth_empty_SUITE,test_case,ok}}}, + + {?eh,tc_start,{ct_cth_empty_SUITE,end_per_suite}}, + {?eh,cth,{'_',pre_end_per_suite,[ct_cth_empty_SUITE,'$proplist',[]]}}, + {negative, + {?eh,cth,{'_',pre_end_per_suite,[ct_cth_empty_SUITE,'$proplist',[]]}}, + {?eh,cth,{'_',post_end_per_suite,[ct_cth_empty_SUITE,'$proplist','_',[]]}}}, + {negative, + {?eh,cth,{'_',post_end_per_suite, + [ct_cth_empty_SUITE,'$proplist','_',[]]}}, + {?eh,tc_done,{ct_cth_empty_SUITE,end_per_suite,ok}}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,cth,{'_',terminate,[[]]}}, + {?eh,stop_logging,[]} + ]; + +test_events(fail_n_skip_with_minimal_cth) -> + [{?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,cth,{'_',init,['_',[]]}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,tc_start,{'_',init_per_suite}}, + + {?eh,tc_done,{'_',end_per_suite,ok}}, + {?eh,cth,{'_',terminate,[[]]}}, + {?eh,stop_logging,[]} + ]; + +test_events(ok) -> + ok. + + +%% test events help functions +contains(List) -> + fun(Proplist) when is_list(Proplist) -> + contains(List,Proplist) + end. + +contains([{not_in_order,List}|T],Rest) -> + contains_parallel(List,Rest), + contains(T,Rest); +contains([{Ele,Pos}|T] = L,[H|T2]) -> + case element(Pos,H) of + Ele -> + contains(T,T2); + _ -> + contains(L,T2) + end; +contains([Ele|T],[{Ele,_}|T2])-> + contains(T,T2); +contains([Ele|T],[Ele|T2])-> + contains(T,T2); +contains(List,[_|T]) -> + contains(List,T); +contains([],_) -> + match. + +contains_parallel([Key | T], Elems) -> + contains([Key],Elems), + contains_parallel(T,Elems); +contains_parallel([],_Elems) -> + match. + +not_contains(List) -> + fun(Proplist) when is_list(Proplist) -> + [] = [Ele || {Ele,_} <- Proplist, + Test <- List, + Test =:= Ele] + end. diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/crash_id_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/crash_id_cth.erl new file mode 100644 index 0000000000..02c36e378c --- /dev/null +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/crash_id_cth.erl @@ -0,0 +1,34 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(crash_id_cth). + + +-include_lib("common_test/src/ct_util.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + + +%% CT Hooks +-export([id/1]). + +id(Opts) -> + empty_cth:id(Opts), + exit(diediedie). + diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/crash_init_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/crash_init_cth.erl new file mode 100644 index 0000000000..6ed23565f6 --- /dev/null +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/crash_init_cth.erl @@ -0,0 +1,34 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(crash_init_cth). + + +-include_lib("common_test/src/ct_util.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + + +%% CT Hooks +-export([init/2]). + +init(Id, Opts) -> + empty_cth:init(Id, Opts), + exit(diediedie). + diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_cth_empty_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_cth_empty_SUITE.erl new file mode 100644 index 0000000000..499069b382 --- /dev/null +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_cth_empty_SUITE.erl @@ -0,0 +1,47 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(ct_cth_empty_SUITE). + +-suite_defaults([{timetrap, {minutes, 10}}]). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-include("ct.hrl"). + +%% Test server callback functions +init_per_suite(Config) -> + Config. + +end_per_suite(_Config) -> + ok. + +init_per_testcase(_TestCase, Config) -> + Config. + +end_per_testcase(_TestCase, _Config) -> + ok. + +all() -> + [test_case]. + +%% Test cases starts here. +test_case(Config) when is_list(Config) -> + ok. diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_cth_fail_one_skip_one_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_cth_fail_one_skip_one_SUITE.erl new file mode 100644 index 0000000000..017812c719 --- /dev/null +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_cth_fail_one_skip_one_SUITE.erl @@ -0,0 +1,64 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(ct_cth_fail_one_skip_one_SUITE). + +-suite_defaults([{timetrap, {minutes, 10}}]). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-include("ct.hrl"). + +%% Test server callback functions +init_per_suite(Config) -> + Config. + +end_per_suite(_Config) -> + ok. + +init_per_group(_Group,Config) -> + Config. + +end_per_group(_Group,_Config) -> + ok. + +init_per_testcase(test_case2, Config) -> + {skip,"skip it"}; +init_per_testcase(_TestCase, Config) -> + Config. + +end_per_testcase(_TestCase, _Config) -> + ok. + +groups() -> + [{group1,[parallel],[{group2,[parallel],[test_case1,test_case2,test_case3]}]}]. + +all() -> + [{group,group1}]. + +%% Test cases starts here. +test_case1(Config) -> + ok = nok. + +test_case2(Config) -> + ok. + +test_case3(Config) -> + ok. diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_cth_fail_per_suite_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_cth_fail_per_suite_SUITE.erl new file mode 100644 index 0000000000..136a15ec96 --- /dev/null +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_cth_fail_per_suite_SUITE.erl @@ -0,0 +1,47 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(ct_cth_fail_per_suite_SUITE). + +-suite_defaults([{timetrap, {minutes, 10}}]). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-include("ct.hrl"). + +%% Test server callback functions +init_per_suite(Config) -> + ok = nok. + +end_per_suite(_Config) -> + ok. + +init_per_testcase(_TestCase, Config) -> + Config. + +end_per_testcase(_TestCase, _Config) -> + ok. + +all() -> + [test_case]. + +%% Test cases starts here. +test_case(Config) when is_list(Config) -> + ok. diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_exit_in_init_scope_suite_cth_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_exit_in_init_scope_suite_cth_SUITE.erl new file mode 100644 index 0000000000..42be0a659e --- /dev/null +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_exit_in_init_scope_suite_cth_SUITE.erl @@ -0,0 +1,50 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(ct_exit_in_init_scope_suite_cth_SUITE). + +-suite_defaults([{timetrap, {minutes, 10}}]). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-include_lib("common_test/include/ct.hrl"). + +%% Test server callback functions +suite() -> + [{ct_hooks,[crash_init_cth]}]. + +init_per_suite(Config) -> + Config. + +end_per_suite(_Config) -> + ok. + +init_per_testcase(_TestCase, Config) -> + Config. + +end_per_testcase(_TestCase, _Config) -> + ok. + +all() -> + [test_case]. + +%% Test cases starts here. +test_case(Config) when is_list(Config) -> + ok. diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_per_group_cth_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_per_group_cth_SUITE.erl new file mode 100644 index 0000000000..628bca774c --- /dev/null +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_per_group_cth_SUITE.erl @@ -0,0 +1,56 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(ct_scope_per_group_cth_SUITE). + +-suite_defaults([{timetrap, {minutes, 10}}]). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-include("ct.hrl"). + +%% Test server callback functions +init_per_suite(Config) -> + Config. + +end_per_suite(_Config) -> + ok. + +init_per_testcase(_TestCase, Config) -> + Config. + +end_per_testcase(_TestCase, _Config) -> + ok. + +init_per_group(GroupName, Config) -> + [{ct_hooks,[empty_cth]}|Config]. + +end_per_group(GroupName, Config) -> + ok. + +all() -> + [{group,group1}]. + +groups() -> + [{group1,[],[test_case]}]. + +%% Test cases starts here. +test_case(Config) when is_list(Config) -> + ok. diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_per_group_state_cth_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_per_group_state_cth_SUITE.erl new file mode 100644 index 0000000000..14ea52bf8c --- /dev/null +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_per_group_state_cth_SUITE.erl @@ -0,0 +1,56 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(ct_scope_per_group_state_cth_SUITE). + +-suite_defaults([{timetrap, {minutes, 10}}]). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-include("ct.hrl"). + +%% Test server callback functions +init_per_suite(Config) -> + Config. + +end_per_suite(_Config) -> + ok. + +init_per_testcase(_TestCase, Config) -> + Config. + +end_per_testcase(_TestCase, _Config) -> + ok. + +init_per_group(_GroupName, Config) -> + [{ct_hooks,[{empty_cth,[test]}]}|Config]. + +end_per_group(_GroupName, _Config) -> + ok. + +all() -> + [{group,group1}]. + +groups() -> + [{group1,[],[test_case]}]. + +%% Test cases starts here. +test_case(Config) when is_list(Config) -> + ok. diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_per_suite_cth_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_per_suite_cth_SUITE.erl new file mode 100644 index 0000000000..5c1658be44 --- /dev/null +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_per_suite_cth_SUITE.erl @@ -0,0 +1,47 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(ct_scope_per_suite_cth_SUITE). + +-suite_defaults([{timetrap, {minutes, 10}}]). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-include("ct.hrl"). + +%% Test server callback functions +init_per_suite(Config) -> + [{ct_hooks,[empty_cth]}|Config]. + +end_per_suite(_Config) -> + ok. + +init_per_testcase(_TestCase, Config) -> + Config. + +end_per_testcase(_TestCase, _Config) -> + ok. + +all() -> + [test_case]. + +%% Test cases starts here. +test_case(Config) when is_list(Config) -> + ok. diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_per_suite_state_cth_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_per_suite_state_cth_SUITE.erl new file mode 100644 index 0000000000..96d00e3b28 --- /dev/null +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_per_suite_state_cth_SUITE.erl @@ -0,0 +1,47 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(ct_scope_per_suite_state_cth_SUITE). + +-suite_defaults([{timetrap, {minutes, 10}}]). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-include("ct.hrl"). + +%% Test server callback functions +init_per_suite(Config) -> + [{ct_hooks,[{empty_cth,[test]}]}|Config]. + +end_per_suite(_Config) -> + ok. + +init_per_testcase(_TestCase, Config) -> + Config. + +end_per_testcase(_TestCase, _Config) -> + ok. + +all() -> + [test_case]. + +%% Test cases starts here. +test_case(Config) when is_list(Config) -> + ok. diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_per_tc_cth_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_per_tc_cth_SUITE.erl new file mode 100644 index 0000000000..fa632444c5 --- /dev/null +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_per_tc_cth_SUITE.erl @@ -0,0 +1,110 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(ct_scope_per_tc_cth_SUITE). + +-suite_defaults([{timetrap, {minutes, 10}}]). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-include("ct.hrl"). + +%% Test server callback functions +%%-------------------------------------------------------------------- +%% @doc +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Initiation before the whole suite +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%% +%% @spec init_per_suite(Config) -> Config +%% @end +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + Config. + +%%-------------------------------------------------------------------- +%% @doc +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Cleanup after the whole suite +%% +%% @spec end_per_suite(Config) -> _ +%% @end +%%-------------------------------------------------------------------- +end_per_suite(_Config) -> + ok. + +%%-------------------------------------------------------------------- +%% @doc +%% Case - atom() +%% Name of the test case that is about to be run. +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Initiation before each test case +%% +%% Note: This function is free to add any key/value pairs to the Config +%% variable, but should NOT alter/remove any existing entries. +%% Initiation before each test case +%% +%% @spec init_per_testcase(TestCase, Config) -> Config +%% @end +%%-------------------------------------------------------------------- +init_per_testcase(_TestCase, Config) -> + [{ct_hooks,[empty_cth]}|Config]. + +%%-------------------------------------------------------------------- +%% @doc +%% Case - atom() +%% Name of the test case that is about to be run. +%% Config - [tuple()] +%% A list of key/value pairs, holding the test case configuration. +%% +%% Cleanup after each test case +%% +%% @spec end_per_testcase(TestCase, Config) -> _ +%% @end +%%-------------------------------------------------------------------- +end_per_testcase(_TestCase, _Config) -> + ok. + +%%-------------------------------------------------------------------- +%% @doc +%% TestCases - [Case] +%% Case - atom() +%% Name of a test case. +%% +%% Returns a list of all test cases in this test suite +%% +%% @spec all() -> TestCases +%% @end +%%-------------------------------------------------------------------- +all() -> + [test_case]. + +%% Test cases starts here. +%%-------------------------------------------------------------------- +test_case(Config) when is_list(Config) -> + ok. diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_suite_cth_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_suite_cth_SUITE.erl new file mode 100644 index 0000000000..988a0969ca --- /dev/null +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_suite_cth_SUITE.erl @@ -0,0 +1,50 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(ct_scope_suite_cth_SUITE). + +-suite_defaults([{timetrap, {minutes, 10}}]). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-include("ct.hrl"). + +%% Test server callback functions +suite() -> + [{ct_hooks,[empty_cth]}]. + +init_per_suite(Config) -> + Config. + +end_per_suite(_Config) -> + ok. + +init_per_testcase(_TestCase, Config) -> + Config. + +end_per_testcase(_TestCase, _Config) -> + ok. + +all() -> + [test_case]. + +%% Test cases starts here. +test_case(Config) when is_list(Config) -> + ok. diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_suite_state_cth_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_suite_state_cth_SUITE.erl new file mode 100644 index 0000000000..18b68fbcdc --- /dev/null +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_suite_state_cth_SUITE.erl @@ -0,0 +1,50 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(ct_scope_suite_state_cth_SUITE). + +-suite_defaults([{timetrap, {minutes, 10}}]). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-include("ct.hrl"). + +%% Test server callback functions +suite() -> + [{ct_hooks,[{empty_cth,[test]}]}]. + +init_per_suite(Config) -> + Config. + +end_per_suite(_Config) -> + ok. + +init_per_testcase(_TestCase, Config) -> + Config. + +end_per_testcase(_TestCase, _Config) -> + ok. + +all() -> + [test_case]. + +%% Test cases starts here. +test_case(Config) when is_list(Config) -> + ok. diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_update_config_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_update_config_SUITE.erl new file mode 100644 index 0000000000..57fea347f6 --- /dev/null +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_update_config_SUITE.erl @@ -0,0 +1,56 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(ct_update_config_SUITE). + +-suite_defaults([{timetrap, {minutes, 10}}]). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-include("ct.hrl"). + +%% Test server callback functions +init_per_suite(Config) -> + [{init_per_suite,now()}|Config]. + +end_per_suite(_Config) -> + ok. + +init_per_testcase(_TestCase, Config) -> + [{init_per_testcase,now()}|Config]. + +end_per_testcase(_TestCase, _Config) -> + ok. + +init_per_group(GroupName, Config) -> + [{init_per_group,now()}|Config]. + +end_per_group(GroupName, Config) -> + ok. + +all() -> + [{group,group1}]. + +groups() -> + [{group1,[],[test_case]}]. + +%% Test cases starts here. +test_case(Config) when is_list(Config) -> + ok. diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl new file mode 100644 index 0000000000..7654a7ee2f --- /dev/null +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl @@ -0,0 +1,277 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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% +%% + +%%% @doc Common Test Example Suite Callback module. +%%% +%%%

This module gives an example of a common test CTH (Common Test Hook). +%%% There are many ways to add a CTH to a test run, you can do it either in +%%% the command line using -ct_hook, in a test spec using +%%% {ct_hook,M} or in the suite it self by returning ct_hook +%%% from either suite/0, init_per_suite/1, init_per_group/2 and +%%% init_per_testcase/2. The scope of the CTH is determined by where is it +%%% started. If it is started in the command line or test spec then it will +%%% be stopped at the end of all tests. If it is started in init_per_suite, +%%% it will be stopped after end_per_suite and so on. See terminate +%%% documentation for a table describing the scoping machanics. +%%% +%%% All of callbacks except init/1 in a CTH are optional.

+ +-module(empty_cth). + +%% CT Hooks +-export([id/1]). +-export([init/2]). + +-export([pre_init_per_suite/3]). +-export([post_init_per_suite/4]). +-export([pre_end_per_suite/3]). +-export([post_end_per_suite/4]). + +-export([pre_init_per_group/3]). +-export([post_init_per_group/4]). +-export([pre_end_per_group/3]). +-export([post_end_per_group/4]). + +-export([pre_init_per_testcase/3]). +-export([post_end_per_testcase/4]). + +-export([on_tc_fail/3]). +-export([on_tc_skip/3]). + +-export([terminate/1]). + +-include_lib("common_test/src/ct_util.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + +-type proplist() :: list({atom(),term()}). +-type config() :: proplist(). +-type reason() :: term(). +-type skip_or_fail() :: {skip, reason()} | + {auto_skip, reason()} | + {fail, reason()}. + +-record(state, { id = ?MODULE :: term()}). + +%% @doc Always called before any other callback function. Use this to initiate +%% any common state. It should return an state for this CTH. +-spec init(Id :: term(), Opts :: proplist()) -> + {Id :: term(), State :: #state{}}. +init(Id, Opts) -> + gen_event:notify(?CT_EVMGR_REF, #event{ name = cth, node = node(), + data = {?MODULE, init, [Id, Opts]}}), + Opts. + +%% @doc The ID is used to uniquly identify an CTH instance, if two CTH's +%% return the same ID the seconds CTH is ignored. This function should NOT +%% have any side effects as it might be called multiple times by common test. +-spec id(Opts :: proplist()) -> + Id :: term(). +id(Opts) -> + gen_event:notify(?CT_EVMGR_REF, #event{ name = cth, node = node(), + data = {?MODULE, id, [Opts]}}), + now(). + +%% @doc Called before init_per_suite is called. Note that this callback is +%% only called if the CTH is added before init_per_suite is run (eg. in a test +%% specification, suite/0 function etc). +%% You can change the config in the this function. +-spec pre_init_per_suite(Suite :: atom(), + Config :: config(), + State :: #state{}) -> + {config() | skip_or_fail(), NewState :: #state{}}. +pre_init_per_suite(Suite,Config,State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = cth, node = node(), + data = {?MODULE, pre_init_per_suite, + [Suite,Config,State]}}), + {Config, State}. + +%% @doc Called after init_per_suite. +%% you can change the return value in this function. +-spec post_init_per_suite(Suite :: atom(), + Config :: config(), + Return :: config() | skip_or_fail(), + State :: #state{}) -> + {config() | skip_or_fail(), NewState :: #state{}}. +post_init_per_suite(Suite,Config,Return,State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = cth, node = node(), + data = {?MODULE, post_init_per_suite, + [Suite,Config,Return,State]}}), + {Return, State}. + +%% @doc Called before end_per_suite. The config/state can be changed here, +%% though it will only affect the *end_per_suite function. +-spec pre_end_per_suite(Suite :: atom(), + Config :: config() | skip_or_fail(), + State :: #state{}) -> + {ok | skip_or_fail(), NewState :: #state{}}. +pre_end_per_suite(Suite,Config,State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = cth, node = node(), + data = {?MODULE, pre_end_per_suite, + [Suite,Config,State]}}), + {Config, State}. + +%% @doc Called after end_per_suite. Note that the config cannot be +%% changed here, only the status of the suite. +-spec post_end_per_suite(Suite :: atom(), + Config :: config(), + Return :: term(), + State :: #state{}) -> + {ok | skip_or_fail(), NewState :: #state{}}. +post_end_per_suite(Suite,Config,Return,State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = cth, node = node(), + data = {?MODULE, post_end_per_suite, + [Suite,Config,Return,State]}}), + {Return, State}. + +%% @doc Called before each init_per_group. +%% You can change the config in this function. +-spec pre_init_per_group(Group :: atom(), + Config :: config(), + State :: #state{}) -> + {config() | skip_or_fail(), NewState :: #state{}}. +pre_init_per_group(Group,Config,State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = cth, node = node(), + data = {?MODULE, pre_init_per_group, + [Group,Config,State]}}), + {Config, State}. + +%% @doc Called after each init_per_group. +%% You can change the return value in this function. +-spec post_init_per_group(Group :: atom(), + Config :: config(), + Return :: config() | skip_or_fail(), + State :: #state{}) -> + {config() | skip_or_fail(), NewState :: #state{}}. +post_init_per_group(Group,Config,Return,State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = cth, node = node(), + data = {?MODULE, post_init_per_group, + [Group,Config,Return,State]}}), + {Return, State}. + +%% @doc Called after each end_per_group. The config/state can be changed here, +%% though it will only affect the *end_per_group functions. +-spec pre_end_per_group(Group :: atom(), + Config :: config() | skip_or_fail(), + State :: #state{}) -> + {ok | skip_or_fail(), NewState :: #state{}}. +pre_end_per_group(Group,Config,State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = cth, node = node(), + data = {?MODULE, pre_end_per_group, + [Group,Config,State]}}), + {Config, State}. + +%% @doc Called after each end_per_group. Note that the config cannot be +%% changed here, only the status of the group. +-spec post_end_per_group(Group :: atom(), + Config :: config(), + Return :: term(), + State :: #state{}) -> + {ok | skip_or_fail(), NewState :: #state{}}. +post_end_per_group(Group,Config,Return,State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = cth, node = node(), + data = {?MODULE, post_end_per_group, + [Group,Config,Return,State]}}), + {Return, State}. + +%% @doc Called before each test case. +%% You can change the config in this function. +-spec pre_init_per_testcase(TC :: atom(), + Config :: config(), + State :: #state{}) -> + {config() | skip_or_fail(), NewState :: #state{}}. +pre_init_per_testcase(TC,Config,State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = cth, node = node(), + data = {?MODULE, pre_init_per_testcase, + [TC,Config,State]}}), + {Config, State}. + +%% @doc Called after each test case. Note that the config cannot be +%% changed here, only the status of the test case. +-spec post_end_per_testcase(TC :: atom(), + Config :: config(), + Return :: term(), + State :: #state{}) -> + {ok | skip_or_fail(), NewState :: #state{}}. +post_end_per_testcase(TC,Config,Return,State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = cth, node = node(), + data = {?MODULE, post_end_per_testcase, + [TC,Config,Return,State]}}), + {Return, State}. + +%% @doc Called after post_init_per_suite, post_end_per_suite, post_init_per_group, +%% post_end_per_group and post_end_per_tc if the suite, group or test case failed. +%% This function should be used for extra cleanup which might be needed. +%% It is not possible to modify the config or the status of the test run. +-spec on_tc_fail(TC :: init_per_suite | end_per_suite | + init_per_group | end_per_group | atom(), + Reason :: term(), State :: #state{}) -> + NewState :: #state{}. +on_tc_fail(TC, Reason, State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = cth, node = node(), + data = {?MODULE, on_tc_fail, + [TC,Reason,State]}}), + State. + +%% @doc Called when a test case is skipped by either user action +%% or due to an init function failing. Test case can be +%% end_per_suite, init_per_group, end_per_group and the actual test cases. +-spec on_tc_skip(TC :: end_per_suite | + init_per_group | end_per_group | atom(), + {tc_auto_skip, {failed, {Mod :: atom(), Function :: atom(), Reason :: term()}}} | + {tc_user_skip, {skipped, Reason :: term()}}, + State :: #state{}) -> + NewState :: #state{}. +on_tc_skip(TC, Reason, State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = cth, node = node(), + data = {?MODULE, on_tc_skip, + [TC,Reason,State]}}), + State. + +%% @doc Called when the scope of the CTH is done, this depends on +%% when the CTH was specified. This translation table describes when this +%% function is called. +%% +%% | Started in | terminate called | +%% |---------------------|-------------------------| +%% | command_line | after all tests are run | +%% | test spec | after all tests are run | +%% | suite/0 | after SUITE is done | +%% | init_per_suite/1 | after SUITE is done | +%% | init_per_group/2 | after group is done | +%% |-----------------------------------------------| +%% +-spec terminate(State :: #state{}) -> + term(). +terminate(State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = cth, node = node(), + data = {?MODULE, terminate, [State]}}), + ok. diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/fail_post_suite_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/fail_post_suite_cth.erl new file mode 100644 index 0000000000..b4c26259a6 --- /dev/null +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/fail_post_suite_cth.erl @@ -0,0 +1,72 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(fail_post_suite_cth). + + +-include_lib("common_test/src/ct_util.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + + +%% CT Hooks +-compile(export_all). + +init(Id, Opts) -> + empty_cth:init(Id, Opts). + +pre_init_per_suite(Suite, Config, State) -> + empty_cth:pre_init_per_suite(Suite,Config,State). + +post_init_per_suite(Suite,Config,Return,State) -> + empty_cth:post_init_per_suite(Suite,Config,Return,State), + {{fail, "Test failure"}, State}. + +pre_end_per_suite(Suite,Config,State) -> + empty_cth:pre_end_per_suite(Suite,Config,State). + +post_end_per_suite(Suite,Config,Return,State) -> + empty_cth:post_end_per_suite(Suite,Config,Return,State). + +pre_init_per_group(Group,Config,State) -> + empty_cth:pre_init_per_group(Group,Config,State). + +post_init_per_group(Group,Config,Return,State) -> + empty_cth:post_init_per_group(Group,Config,Return,State). + +pre_end_per_group(Group,Config,State) -> + empty_cth:pre_end_per_group(Group,Config,State). + +post_end_per_group(Group,Config,Return,State) -> + empty_cth:post_end_per_group(Group,Config,Return,State). + +pre_init_per_testcase(TC,Config,State) -> + empty_cth:pre_init_per_testcase(TC,Config,State). + +post_end_per_testcase(TC,Config,Return,State) -> + empty_cth:post_end_per_testcase(TC,Config,Return,State). + +on_tc_fail(TC, Reason, State) -> + empty_cth:on_tc_fail(TC,Reason,State). + +on_tc_skip(TC, Reason, State) -> + empty_cth:on_tc_skip(TC,Reason,State). + +terminate(State) -> + empty_cth:terminate(State). diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/fail_pre_suite_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/fail_pre_suite_cth.erl new file mode 100644 index 0000000000..acf80a1b2e --- /dev/null +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/fail_pre_suite_cth.erl @@ -0,0 +1,72 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(fail_pre_suite_cth). + + +-include_lib("common_test/src/ct_util.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + + +%% CT Hooks +-compile(export_all). + +init(Id, Opts) -> + empty_cth:init(Id, Opts). + +pre_init_per_suite(Suite, Config, State) -> + empty_cth:pre_init_per_suite(Suite,Config,State), + {{fail, "Test failure"}, State}. + +post_init_per_suite(Suite,Config,Return,State) -> + empty_cth:post_init_per_suite(Suite,Config,Return,State). + +pre_end_per_suite(Suite,Config,State) -> + empty_cth:pre_end_per_suite(Suite,Config,State). + +post_end_per_suite(Suite,Config,Return,State) -> + empty_cth:post_end_per_suite(Suite,Config,Return,State). + +pre_init_per_group(Group,Config,State) -> + empty_cth:pre_init_per_group(Group,Config,State). + +post_init_per_group(Group,Config,Return,State) -> + empty_cth:post_init_per_group(Group,Config,Return,State). + +pre_end_per_group(Group,Config,State) -> + empty_cth:pre_end_per_group(Group,Config,State). + +post_end_per_group(Group,Config,Return,State) -> + empty_cth:post_end_per_group(Group,Config,Return,State). + +pre_init_per_testcase(TC,Config,State) -> + empty_cth:pre_init_per_testcase(TC,Config,State). + +post_end_per_testcase(TC,Config,Return,State) -> + empty_cth:post_end_per_testcase(TC,Config,Return,State). + +on_tc_fail(TC, Reason, State) -> + empty_cth:on_tc_fail(TC,Reason,State). + +on_tc_skip(TC, Reason, State) -> + empty_cth:on_tc_skip(TC,Reason,State). + +terminate(State) -> + empty_cth:terminate(State). diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/id_no_init_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/id_no_init_cth.erl new file mode 100644 index 0000000000..58ed400e1c --- /dev/null +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/id_no_init_cth.erl @@ -0,0 +1,32 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(id_no_init_cth). + + +-include_lib("common_test/src/ct_util.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + + +%% CT Hooks +-export([id/1]). + +id(Opts) -> + empty_cth:id(Opts). diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/minimal_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/minimal_cth.erl new file mode 100644 index 0000000000..a18f4bf2f3 --- /dev/null +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/minimal_cth.erl @@ -0,0 +1,33 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(minimal_cth). + + +-include_lib("common_test/src/ct_util.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + + +%% CT Hooks +-export([init/2]). + +init(Id, Opts) -> + empty_cth:init(Id, Opts). + diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/minimal_terminate_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/minimal_terminate_cth.erl new file mode 100644 index 0000000000..79cd55f68e --- /dev/null +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/minimal_terminate_cth.erl @@ -0,0 +1,38 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(minimal_terminate_cth). + + +-include_lib("common_test/src/ct_util.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + + +%% CT Hooks +-export([init/2]). +-export([terminate/1]). + +init(Id, Opts) -> + empty_cth:init(Id, Opts). + +terminate(State) -> + empty_cth:terminate(State). + + diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/recover_post_suite_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/recover_post_suite_cth.erl new file mode 100644 index 0000000000..01a932bd59 --- /dev/null +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/recover_post_suite_cth.erl @@ -0,0 +1,74 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(recover_post_suite_cth). + + +-include_lib("common_test/src/ct_util.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + + +%% CT Hooks +-compile(export_all). + +init(Id, Opts) -> + empty_cth:init(Id, Opts). + +pre_init_per_suite(Suite, Config, State) -> + empty_cth:pre_init_per_suite(Suite,Config,State). + +post_init_per_suite(Suite,Config,{'EXIT',Reason} = Return,State) -> + empty_cth:post_init_per_suite(Suite,Config,Return,State), + {lists:keydelete(tc_status,1,Config),State}; +post_init_per_suite(Suite,Config,Return,State) -> + empty_cth:post_init_per_suite(Suite,Config,Return,State). + +pre_end_per_suite(Suite,Config,State) -> + empty_cth:pre_end_per_suite(Suite,Config,State). + +post_end_per_suite(Suite,Config,Return,State) -> + empty_cth:post_end_per_suite(Suite,Config,Return,State). + +pre_init_per_group(Group,Config,State) -> + empty_cth:pre_init_per_group(Group,Config,State). + +post_init_per_group(Group,Config,Return,State) -> + empty_cth:post_init_per_group(Group,Config,Return,State). + +pre_end_per_group(Group,Config,State) -> + empty_cth:pre_end_per_group(Group,Config,State). + +post_end_per_group(Group,Config,Return,State) -> + empty_cth:post_end_per_group(Group,Config,Return,State). + +pre_init_per_testcase(TC,Config,State) -> + empty_cth:pre_init_per_testcase(TC,Config,State). + +post_end_per_testcase(TC,Config,Return,State) -> + empty_cth:post_end_per_testcase(TC,Config,Return,State). + +on_tc_fail(TC, Reason, State) -> + empty_cth:on_tc_fail(TC,Reason,State). + +on_tc_skip(TC, Reason, State) -> + empty_cth:on_tc_skip(TC,Reason,State). + +terminate(State) -> + empty_cth:terminate(State). diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/same_id_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/same_id_cth.erl new file mode 100644 index 0000000000..acfb93fe26 --- /dev/null +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/same_id_cth.erl @@ -0,0 +1,75 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(same_id_cth). + + +-include_lib("common_test/src/ct_util.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + + +%% CT Hooks +-compile(export_all). + +id(Opts) -> + empty_cth:id(Opts), + ?MODULE. + +init(Id, Opts) -> + empty_cth:init(Id, Opts). + +pre_init_per_suite(Suite, Config, State) -> + empty_cth:pre_init_per_suite(Suite,Config,State). + +post_init_per_suite(Suite,Config,Return,State) -> + empty_cth:post_init_per_suite(Suite,Config,Return,State). + +pre_end_per_suite(Suite,Config,State) -> + empty_cth:pre_end_per_suite(Suite,Config,State). + +post_end_per_suite(Suite,Config,Return,State) -> + empty_cth:post_end_per_suite(Suite,Config,Return,State). + +pre_init_per_group(Group,Config,State) -> + empty_cth:pre_init_per_group(Group,Config,State). + +post_init_per_group(Group,Config,Return,State) -> + empty_cth:post_init_per_group(Group,Config,Return,State). + +pre_end_per_group(Group,Config,State) -> + empty_cth:pre_end_per_group(Group,Config,State). + +post_end_per_group(Group,Config,Return,State) -> + empty_cth:post_end_per_group(Group,Config,Return,State). + +pre_init_per_testcase(TC,Config,State) -> + empty_cth:pre_init_per_testcase(TC,Config,State). + +post_end_per_testcase(TC,Config,Return,State) -> + empty_cth:post_end_per_testcase(TC,Config,Return,State). + +on_tc_fail(TC, Reason, State) -> + empty_cth:on_tc_fail(TC,Reason,State). + +on_tc_skip(TC, Reason, State) -> + empty_cth:on_tc_skip(TC,Reason,State). + +terminate(State) -> + empty_cth:terminate(State). diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/skip_post_suite_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/skip_post_suite_cth.erl new file mode 100644 index 0000000000..6d4605b33b --- /dev/null +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/skip_post_suite_cth.erl @@ -0,0 +1,72 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(skip_post_suite_cth). + + +-include_lib("common_test/src/ct_util.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + + +%% CT Hooks +-compile(export_all). + +init(Id, Opts) -> + empty_cth:init(Id, Opts). + +pre_init_per_suite(Suite, Config, State) -> + empty_cth:pre_init_per_suite(Suite,Config,State). + +post_init_per_suite(Suite,Config,Return,State) -> + empty_cth:post_init_per_suite(Suite,Config,Return,State), + {{skip, "Test skip"}, State}. + +pre_end_per_suite(Suite,Config,State) -> + empty_cth:pre_end_per_suite(Suite,Config,State). + +post_end_per_suite(Suite,Config,Return,State) -> + empty_cth:post_end_per_suite(Suite,Config,Return,State). + +pre_init_per_group(Group,Config,State) -> + empty_cth:pre_init_per_group(Group,Config,State). + +post_init_per_group(Group,Config,Return,State) -> + empty_cth:post_init_per_group(Group,Config,Return,State). + +pre_end_per_group(Group,Config,State) -> + empty_cth:pre_end_per_group(Group,Config,State). + +post_end_per_group(Group,Config,Return,State) -> + empty_cth:post_end_per_group(Group,Config,Return,State). + +pre_init_per_testcase(TC,Config,State) -> + empty_cth:pre_init_per_testcase(TC,Config,State). + +post_end_per_testcase(TC,Config,Return,State) -> + empty_cth:post_end_per_testcase(TC,Config,Return,State). + +on_tc_fail(TC, Reason, State) -> + empty_cth:on_tc_fail(TC,Reason,State). + +on_tc_skip(TC, Reason, State) -> + empty_cth:on_tc_skip(TC,Reason,State). + +terminate(State) -> + empty_cth:terminate(State). diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/skip_pre_suite_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/skip_pre_suite_cth.erl new file mode 100644 index 0000000000..49efd0d0cd --- /dev/null +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/skip_pre_suite_cth.erl @@ -0,0 +1,73 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(skip_pre_suite_cth). + + +-include_lib("common_test/src/ct_util.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + + +%% CT Hooks +-compile(export_all). + +init(Id, Opts) -> + empty_cth:init(Id, Opts). + + +pre_init_per_suite(Suite, Config, State) -> + empty_cth:pre_init_per_suite(Suite,Config,State), + {{skip, "Test skip"}, State}. + +post_init_per_suite(Suite,Config,Return,State) -> + empty_cth:post_init_per_suite(Suite,Config,Return,State). + +pre_end_per_suite(Suite,Config,State) -> + empty_cth:pre_end_per_suite(Suite,Config,State). + +post_end_per_suite(Suite,Config,Return,State) -> + empty_cth:post_end_per_suite(Suite,Config,Return,State). + +pre_init_per_group(Group,Config,State) -> + empty_cth:pre_init_per_group(Group,Config,State). + +post_init_per_group(Group,Config,Return,State) -> + empty_cth:post_init_per_group(Group,Config,Return,State). + +pre_end_per_group(Group,Config,State) -> + empty_cth:pre_end_per_group(Group,Config,State). + +post_end_per_group(Group,Config,Return,State) -> + empty_cth:post_end_per_group(Group,Config,Return,State). + +pre_init_per_testcase(TC,Config,State) -> + empty_cth:pre_init_per_testcase(TC,Config,State). + +post_end_per_testcase(TC,Config,Return,State) -> + empty_cth:post_end_per_testcase(TC,Config,Return,State). + +on_tc_fail(TC, Reason, State) -> + empty_cth:on_tc_fail(TC,Reason,State). + +on_tc_skip(TC, Reason, State) -> + empty_cth:on_tc_skip(TC,Reason,State). + +terminate(State) -> + empty_cth:terminate(State). diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/state_update_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/state_update_cth.erl new file mode 100644 index 0000000000..53d75e6ce3 --- /dev/null +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/state_update_cth.erl @@ -0,0 +1,83 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(state_update_cth). + + +-include_lib("common_test/src/ct_util.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + +%% CT Hooks +-compile(export_all). + +init(Id, Opts) -> + State = empty_cth:init(Id, Opts), + [init|State]. + +pre_init_per_suite(Suite, Config, State) -> + empty_cth:pre_init_per_suite(Suite,Config,State), + {Config, [pre_init_per_suite|State]}. + +post_init_per_suite(Suite,Config,Return,State) -> + empty_cth:post_init_per_suite(Suite,Config,Return,State), + {Config, [post_init_per_suite|State]}. + +pre_end_per_suite(Suite,Config,State) -> + empty_cth:pre_end_per_suite(Suite,Config,State), + {Config, [pre_end_per_suite|State]}. + +post_end_per_suite(Suite,Config,Return,State) -> + empty_cth:post_end_per_suite(Suite,Config,Return,State), + {Return, [post_end_per_suite|State]}. + +pre_init_per_group(Group,Config,State) -> + empty_cth:pre_init_per_group(Group,Config,State), + {Config, [pre_init_per_group|State]}. + +post_init_per_group(Group,Config,Return,State) -> + empty_cth:post_init_per_group(Group,Config,Return,State), + {Return, [post_init_per_group|State]}. + +pre_end_per_group(Group,Config,State) -> + empty_cth:pre_end_per_group(Group,Config,State), + {Config, [pre_end_per_group|State]}. + +post_end_per_group(Group,Config,Return,State) -> + empty_cth:post_end_per_group(Group,Config,Return,State), + {Return, [post_end_per_group|State]}. + +pre_init_per_testcase(TC,Config,State) -> + empty_cth:pre_init_per_testcase(TC,Config,State), + {Config, [pre_init_per_testcase|State]}. + +post_end_per_testcase(TC,Config,Return,State) -> + empty_cth:post_end_per_testcase(TC,Config,Return,State), + {Return, [post_end_per_testcase|State]}. + +on_tc_fail(TC, Reason, State) -> + empty_cth:on_tc_fail(TC,Reason,State), + [on_tc_fail|State]. + +on_tc_skip(TC, Reason, State) -> + empty_cth:on_tc_skip(TC,Reason,State), + [on_tc_skip|State]. + +terminate(State) -> + empty_cth:terminate(State). diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/undef_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/undef_cth.erl new file mode 100644 index 0000000000..4c44ef025b --- /dev/null +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/undef_cth.erl @@ -0,0 +1,71 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(undef_cth). + + +-include_lib("common_test/src/ct_util.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + + +%% CT Hooks +-compile(export_all). + +init(Id, Opts) -> + empty_cth:init(Id, Opts). + +pre_init_per_suite(_Suite, _Config, _State) -> + lists:flaten([1,2,[3,4]]). + +post_init_per_suite(Suite,Config,Return,State) -> + empty_cth:post_init_per_suite(Suite,Config,Return,State). + +pre_end_per_suite(Suite,Config,State) -> + empty_cth:pre_end_per_suite(Suite,Config,State). + +post_end_per_suite(Suite,Config,Return,State) -> + empty_cth:post_end_per_suite(Suite,Config,Return,State). + +pre_init_per_group(Group,Config,State) -> + empty_cth:pre_init_per_group(Group,Config,State). + +post_init_per_group(Group,Config,Return,State) -> + empty_cth:post_init_per_group(Group,Config,Return,State). + +pre_end_per_group(Group,Config,State) -> + empty_cth:pre_end_per_group(Group,Config,State). + +post_end_per_group(Group,Config,Return,State) -> + empty_cth:post_end_per_group(Group,Config,Return,State). + +pre_init_per_testcase(TC,Config,State) -> + empty_cth:pre_init_per_testcase(TC,Config,State). + +post_end_per_testcase(TC,Config,Return,State) -> + empty_cth:post_end_per_testcase(TC,Config,Return,State). + +on_tc_fail(TC, Reason, State) -> + empty_cth:on_tc_fail(TC,Reason,State). + +on_tc_skip(TC, Reason, State) -> + empty_cth:on_tc_skip(TC,Reason,State). + +terminate(State) -> + empty_cth:terminate(State). diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/update_config_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/update_config_cth.erl new file mode 100644 index 0000000000..788ef2cec2 --- /dev/null +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/update_config_cth.erl @@ -0,0 +1,82 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010. 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(update_config_cth). + + +-include_lib("common_test/src/ct_util.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + + +%% CT Hooks +-compile(export_all). + +init(Id, Opts) -> + empty_cth:init(Id, Opts). + +pre_init_per_suite(Suite, Config, State) -> + empty_cth:pre_init_per_suite(Suite,Config,State), + {[{pre_init_per_suite,now()}|Config],State}. + +post_init_per_suite(Suite,Config,Return,State) -> + empty_cth:post_init_per_suite(Suite,Config,Return,State), + {[{post_init_per_suite,now()}|Return],State}. + +pre_end_per_suite(Suite,Config,State) -> + empty_cth:pre_end_per_suite(Suite,Config,State), + {[{pre_end_per_suite,now()}|Config],State}. + +post_end_per_suite(Suite,Config,Return,State) -> + empty_cth:post_end_per_suite(Suite,Config,Return,State), + NewConfig = [{post_end_per_suite,now()}|Config], + {NewConfig,NewConfig}. + +pre_init_per_group(Group,Config,State) -> + empty_cth:pre_init_per_group(Group,Config,State), + {[{pre_init_per_group,now()}|Config],State}. + +post_init_per_group(Group,Config,Return,State) -> + empty_cth:post_init_per_group(Group,Config,Return,State), + {[{post_init_per_group,now()}|Return],State}. + +pre_end_per_group(Group,Config,State) -> + empty_cth:pre_end_per_group(Group,Config,State), + {[{pre_end_per_group,now()}|Config],State}. + +post_end_per_group(Group,Config,Return,State) -> + empty_cth:post_end_per_group(Group,Config,Return,State), + {[{post_end_per_group,now()}|Config],State}. + +pre_init_per_testcase(TC,Config,State) -> + empty_cth:pre_init_per_testcase(TC,Config,State), + {[{pre_init_per_testcase,now()}|Config],State}. + +post_end_per_testcase(TC,Config,Return,State) -> + empty_cth:post_end_per_testcase(TC,Config,Return,State), + {[{post_end_per_testcase,now()}|Config],State}. + +on_tc_fail(TC, Reason, State) -> + empty_cth:on_tc_fail(TC,Reason,State). + +on_tc_skip(TC, Reason, State) -> + empty_cth:on_tc_skip(TC,Reason,State). + +terminate(State) -> + empty_cth:terminate(State). diff --git a/lib/common_test/test/ct_suite_callback_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE.erl deleted file mode 100644 index 67f3cf430a..0000000000 --- a/lib/common_test/test/ct_suite_callback_SUITE.erl +++ /dev/null @@ -1,1021 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2009-2010. 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% -%% - -%%%------------------------------------------------------------------- -%%% File: ct_error_SUITE -%%% -%%% Description: -%%% Test various errors in Common Test suites. -%%% -%%% The suites used for the test are located in the data directory. -%%%------------------------------------------------------------------- --module(ct_suite_callback_SUITE). - --compile(export_all). - --include_lib("test_server/include/test_server.hrl"). --include_lib("common_test/include/ct_event.hrl"). - --define(eh, ct_test_support_eh). - -%%-------------------------------------------------------------------- -%% TEST SERVER CALLBACK FUNCTIONS -%%-------------------------------------------------------------------- - -%%-------------------------------------------------------------------- -%% Description: Since Common Test starts another Test Server -%% instance, the tests need to be performed on a separate node (or -%% there will be clashes with logging processes etc). -%%-------------------------------------------------------------------- -init_per_suite(Config) -> - DataDir = ?config(data_dir, Config), - TestDir = filename:join(DataDir,"scb/tests/"), - SCBs = filelib:wildcard(filename:join(TestDir,"*_scb.erl")), - io:format("SCBs: ~p",[SCBs]), - [io:format("Compiling ~p: ~p", - [FileName,compile:file(FileName,[{outdir,TestDir},debug_info])]) || - FileName <- SCBs], - ct_test_support:init_per_suite([{path_dirs,[TestDir]} | Config]). - -end_per_suite(Config) -> - ct_test_support:end_per_suite(Config). - -init_per_testcase(TestCase, Config) -> - ct_test_support:init_per_testcase(TestCase, Config). - -end_per_testcase(TestCase, Config) -> - ct_test_support:end_per_testcase(TestCase, Config). - - -suite() -> - [{timetrap,{seconds,20}}]. - -all() -> - all(suite). - -all(suite) -> - lists:reverse( - [ - one_scb, two_scb, faulty_scb_no_init, faulty_scb_id_no_init, - faulty_scb_exit_in_init, faulty_scb_exit_in_id, - faulty_scb_exit_in_init_scope_suite, minimal_scb, - minimal_and_maximal_scb, faulty_scb_undef, - scope_per_suite_scb, scope_per_group_scb, scope_suite_scb, - scope_per_suite_state_scb, scope_per_group_state_scb, - scope_suite_state_scb, - fail_pre_suite_scb, fail_post_suite_scb, skip_pre_suite_scb, - skip_post_suite_scb, recover_post_suite_scb, update_config_scb, - state_update_scb, options_scb, same_id_scb, - fail_n_skip_with_minimal_scb - ] - ) - . - - -%%-------------------------------------------------------------------- -%% TEST CASES -%%-------------------------------------------------------------------- - -%%%----------------------------------------------------------------- -%%% -one_scb(Config) when is_list(Config) -> - do_test(one_empty_scb, "ct_scb_empty_SUITE.erl",[empty_scb], Config). - -two_scb(Config) when is_list(Config) -> - do_test(two_empty_scb, "ct_scb_empty_SUITE.erl",[empty_scb,empty_scb], - Config). - -faulty_scb_no_init(Config) when is_list(Config) -> - do_test(faulty_scb_no_init, "ct_scb_empty_SUITE.erl",[askjhdkljashdkaj], - Config,{error,"Failed to start SCB, see the " - "CT Log for details"}). - -faulty_scb_id_no_init(Config) when is_list(Config) -> - do_test(faulty_scb_id_no_init, "ct_scb_empty_SUITE.erl",[id_no_init_scb], - Config,{error,"Failed to start SCB, see the " - "CT Log for details"}). - -minimal_scb(Config) when is_list(Config) -> - do_test(minimal_scb, "ct_scb_empty_SUITE.erl",[minimal_scb],Config). - -minimal_and_maximal_scb(Config) when is_list(Config) -> - do_test(minimal_and_maximal_scb, "ct_scb_empty_SUITE.erl", - [minimal_scb, empty_scb],Config). - -faulty_scb_undef(Config) when is_list(Config) -> - do_test(faulty_scb_undef, "ct_scb_empty_SUITE.erl", - [undef_scb],Config). - -faulty_scb_exit_in_init_scope_suite(Config) when is_list(Config) -> - do_test(faulty_scb_exit_in_init_scope_suite, - "ct_exit_in_init_scope_suite_scb_SUITE.erl", - [],Config). - -faulty_scb_exit_in_init(Config) when is_list(Config) -> - do_test(faulty_scb_exit_in_init, "ct_scb_empty_SUITE.erl", - [crash_init_scb], Config, - {error,"Failed to start SCB, see the " - "CT Log for details"}). - -faulty_scb_exit_in_id(Config) when is_list(Config) -> - do_test(faulty_scb_exit_in_id, "ct_scb_empty_SUITE.erl", - [crash_id_scb], Config, - {error,"Failed to start SCB, see the " - "CT Log for details"}). - -scope_per_suite_scb(Config) when is_list(Config) -> - do_test(scope_per_suite_scb, "ct_scope_per_suite_scb_SUITE.erl", - [],Config). - -scope_suite_scb(Config) when is_list(Config) -> - do_test(scope_suite_scb, "ct_scope_suite_scb_SUITE.erl", - [],Config). - -scope_per_group_scb(Config) when is_list(Config) -> - do_test(scope_per_group_scb, "ct_scope_per_group_scb_SUITE.erl", - [],Config). - -scope_per_suite_state_scb(Config) when is_list(Config) -> - do_test(scope_per_suite_state_scb, "ct_scope_per_suite_state_scb_SUITE.erl", - [],Config). - -scope_suite_state_scb(Config) when is_list(Config) -> - do_test(scope_suite_state_scb, "ct_scope_suite_state_scb_SUITE.erl", - [],Config). - -scope_per_group_state_scb(Config) when is_list(Config) -> - do_test(scope_per_group_state_scb, "ct_scope_per_group_state_scb_SUITE.erl", - [],Config). - -fail_pre_suite_scb(Config) when is_list(Config) -> - do_test(fail_pre_suite_scb, "ct_scb_empty_SUITE.erl", - [fail_pre_suite_scb],Config). - -fail_post_suite_scb(Config) when is_list(Config) -> - do_test(fail_post_suite_scb, "ct_scb_empty_SUITE.erl", - [fail_post_suite_scb],Config). - -skip_pre_suite_scb(Config) when is_list(Config) -> - do_test(skip_pre_suite_scb, "ct_scb_empty_SUITE.erl", - [skip_pre_suite_scb],Config). - -skip_post_suite_scb(Config) when is_list(Config) -> - do_test(skip_post_suite_scb, "ct_scb_empty_SUITE.erl", - [skip_post_suite_scb],Config). - -recover_post_suite_scb(Config) when is_list(Config) -> - do_test(recover_post_suite_scb, "ct_scb_fail_per_suite_SUITE.erl", - [recover_post_suite_scb],Config). - -update_config_scb(Config) when is_list(Config) -> - do_test(update_config_scb, "ct_update_config_SUITE.erl", - [update_config_scb],Config). - -state_update_scb(Config) when is_list(Config) -> - do_test(state_update_scb, "ct_scb_fail_one_skip_one_SUITE.erl", - [state_update_scb,state_update_scb],Config). - -options_scb(Config) when is_list(Config) -> - do_test(options_scb, "ct_scb_empty_SUITE.erl", - [{empty_scb,[test]}],Config). - -same_id_scb(Config) when is_list(Config) -> - do_test(same_id_scb, "ct_scb_empty_SUITE.erl", - [same_id_scb,same_id_scb],Config). - -fail_n_skip_with_minimal_scb(Config) when is_list(Config) -> - do_test(fail_n_skip_with_minimal_scb, "ct_scb_fail_one_skip_one_SUITE.erl", - [minimal_terminate_scb],Config). - -%%%----------------------------------------------------------------- -%%% HELP FUNCTIONS -%%%----------------------------------------------------------------- - -do_test(Tag, SWC, SCBs, Config) -> - do_test(Tag, SWC, SCBs, Config, ok). -do_test(Tag, SWC, SCBs, Config, {error,_} = Res) -> - do_test(Tag, SWC, SCBs, Config, Res, 1); -do_test(Tag, SWC, SCBs, Config, Res) -> - do_test(Tag, SWC, SCBs, Config, Res, 2). - -do_test(Tag, SuiteWildCard, SCBs, Config, Res, EC) -> - - DataDir = ?config(data_dir, Config), - Suites = filelib:wildcard( - filename:join([DataDir,"scb/tests",SuiteWildCard])), - {Opts,ERPid} = setup([{suite,Suites}, - {suite_callbacks,SCBs},{label,Tag}], Config), - Res = ct_test_support:run(Opts, Config), - Events = ct_test_support:get_events(ERPid, Config), - - ct_test_support:log_events(Tag, - reformat(Events, ?eh), - ?config(priv_dir, Config)), - - TestEvents = events_to_check(Tag, EC), - ok = ct_test_support:verify_events(TestEvents, Events, Config). - -setup(Test, Config) -> - Opts0 = ct_test_support:get_opts(Config), - Level = ?config(trace_level, Config), - EvHArgs = [{cbm,ct_test_support},{trace_level,Level}], - Opts = Opts0 ++ [{event_handler,{?eh,EvHArgs}}|Test], - ERPid = ct_test_support:start_event_receiver(Config), - {Opts,ERPid}. - -reformat(Events, EH) -> - ct_test_support:reformat(Events, EH). -%reformat(Events, _EH) -> -% Events. - -%%%----------------------------------------------------------------- -%%% TEST EVENTS -%%%----------------------------------------------------------------- -events_to_check(Test) -> - %% 2 tests (ct:run_test + script_start) is default - events_to_check(Test, 2). - -events_to_check(_, 0) -> - []; -events_to_check(Test, N) -> - test_events(Test) ++ events_to_check(Test, N-1). - -test_events(one_empty_scb) -> - [ - {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{empty_scb,id,[[]]}}, - {?eh,scb,{empty_scb,init,[{'_','_','_'},[]]}}, - {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, - {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, - {?eh,scb,{empty_scb,pre_init_per_suite, - [ct_scb_empty_SUITE,'$proplist',[]]}}, - {?eh,scb,{empty_scb,post_init_per_suite, - [ct_scb_empty_SUITE,'$proplist','$proplist',[]]}}, - {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite,ok}}, - - {?eh,tc_start,{ct_scb_empty_SUITE,test_case}}, - {?eh,scb,{empty_scb,pre_init_per_testcase,[test_case,'$proplist',[]]}}, - {?eh,scb,{empty_scb,post_end_per_testcase,[test_case,'$proplist','_',[]]}}, - {?eh,tc_done,{ct_scb_empty_SUITE,test_case,ok}}, - - {?eh,tc_start,{ct_scb_empty_SUITE,end_per_suite}}, - {?eh,scb,{empty_scb,pre_end_per_suite, - [ct_scb_empty_SUITE,'$proplist',[]]}}, - {?eh,scb,{empty_scb,post_end_per_suite,[ct_scb_empty_SUITE,'$proplist','_',[]]}}, - {?eh,tc_done,{ct_scb_empty_SUITE,end_per_suite,ok}}, - {?eh,test_done,{'DEF','STOP_TIME'}}, - {?eh,scb,{empty_scb,terminate,[[]]}}, - {?eh,stop_logging,[]} - ]; - -test_events(two_empty_scb) -> - [ - {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{'_',id,[[]]}}, - {?eh,scb,{'_',init,['_',[]]}}, - {?eh,scb,{'_',id,[[]]}}, - {?eh,scb,{'_',init,['_',[]]}}, - {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, - {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, - {?eh,scb,{'_',pre_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, - {?eh,scb,{'_',pre_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, - {?eh,scb,{'_',post_init_per_suite,[ct_scb_empty_SUITE,'$proplist','$proplist',[]]}}, - {?eh,scb,{'_',post_init_per_suite,[ct_scb_empty_SUITE,'$proplist','$proplist',[]]}}, - {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite,ok}}, - - {?eh,tc_start,{ct_scb_empty_SUITE,test_case}}, - {?eh,scb,{'_',pre_init_per_testcase,[test_case,'$proplist',[]]}}, - {?eh,scb,{'_',pre_init_per_testcase,[test_case,'$proplist',[]]}}, - {?eh,scb,{'_',post_end_per_testcase,[test_case,'$proplist',ok,[]]}}, - {?eh,scb,{'_',post_end_per_testcase,[test_case,'$proplist',ok,[]]}}, - {?eh,tc_done,{ct_scb_empty_SUITE,test_case,ok}}, - - {?eh,tc_start,{ct_scb_empty_SUITE,end_per_suite}}, - {?eh,scb,{'_',pre_end_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, - {?eh,scb,{'_',pre_end_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, - {?eh,scb,{'_',post_end_per_suite,[ct_scb_empty_SUITE,'$proplist','_',[]]}}, - {?eh,scb,{'_',post_end_per_suite,[ct_scb_empty_SUITE,'$proplist','_',[]]}}, - {?eh,tc_done,{ct_scb_empty_SUITE,end_per_suite,ok}}, - {?eh,test_done,{'DEF','STOP_TIME'}}, - {?eh,scb,{'_',terminate,[[]]}}, - {?eh,scb,{'_',terminate,[[]]}}, - {?eh,stop_logging,[]} - ]; - -test_events(faulty_scb_no_init) -> - [ - {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, - {?eh,test_done,{'DEF','STOP_TIME'}}, - {?eh,stop_logging,[]} - ]; - -test_events(faulty_scb_id_no_init) -> - [ - {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{'_',id,[[]]}}, - {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, - {negative,{?eh,tc_start,'_'}, - {?eh,test_done,{'DEF','STOP_TIME'}}}, - {?eh,stop_logging,[]} - ]; - -test_events(minimal_scb) -> - [ - {?eh,start_logging,{'DEF','RUNDIR'}}, - {negative,{?eh,scb,{'_',id,['_',[]]}}, - {?eh,scb,{'_',init,['_',[]]}}}, - {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, - {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, - {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite,ok}}, - - {?eh,tc_start,{ct_scb_empty_SUITE,test_case}}, - {?eh,tc_done,{ct_scb_empty_SUITE,test_case,ok}}, - - {?eh,tc_start,{ct_scb_empty_SUITE,end_per_suite}}, - {?eh,tc_done,{ct_scb_empty_SUITE,end_per_suite,ok}}, - {?eh,test_done,{'DEF','STOP_TIME'}}, - {?eh,stop_logging,[]} - ]; - -test_events(minimal_and_maximal_scb) -> - [ - {?eh,start_logging,{'DEF','RUNDIR'}}, - {negative,{?eh,scb,{'_',id,['_',[]]}}, - {?eh,scb,{'_',init,['_',[]]}}}, - {?eh,scb,{'_',id,[[]]}}, - {?eh,scb,{'_',init,['_',[]]}}, - {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, - {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, - {?eh,scb,{'_',pre_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, - {?eh,scb,{'_',post_init_per_suite,[ct_scb_empty_SUITE,'$proplist','$proplist',[]]}}, - {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite,ok}}, - - {?eh,tc_start,{ct_scb_empty_SUITE,test_case}}, - {?eh,scb,{'_',pre_init_per_testcase,[test_case,'$proplist',[]]}}, - {?eh,scb,{'_',post_end_per_testcase,[test_case,'$proplist',ok,[]]}}, - {?eh,tc_done,{ct_scb_empty_SUITE,test_case,ok}}, - - {?eh,tc_start,{ct_scb_empty_SUITE,end_per_suite}}, - {?eh,scb,{'_',pre_end_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, - {?eh,scb,{'_',post_end_per_suite,[ct_scb_empty_SUITE,'$proplist','_',[]]}}, - {?eh,tc_done,{ct_scb_empty_SUITE,end_per_suite,ok}}, - {?eh,test_done,{'DEF','STOP_TIME'}}, - {?eh,scb,{'_',terminate,[[]]}}, - {?eh,stop_logging,[]} - ]; - -test_events(faulty_scb_undef) -> - FailReasonStr = "undef_scb:pre_init_per_suite/3 SCB call failed", - FailReason = {ct_scb_empty_SUITE,init_per_suite, - {failed,FailReasonStr}}, - [ - {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{'_',init,['_',[]]}}, - {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, - {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, - {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite, - {failed, {error,FailReasonStr}}}}, - {?eh,scb,{'_',on_tc_fail,'_'}}, - - {?eh,tc_auto_skip,{ct_scb_empty_SUITE,test_case, - {failed, FailReason}}}, - {?eh,scb,{'_',on_tc_skip,'_'}}, - - {?eh,tc_auto_skip,{ct_scb_empty_SUITE,end_per_suite, - {failed, FailReason}}}, - {?eh,scb,{'_',on_tc_skip,'_'}}, - - {?eh,test_done,{'DEF','STOP_TIME'}}, - {?eh,stop_logging,[]} - ]; - -test_events(faulty_scb_exit_in_init_scope_suite) -> - [{?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, - {?eh,tc_start,{'_',init_per_suite}}, - {?eh,scb,{empty_scb,init,['_',[]]}}, - {?eh,tc_done, - {ct_exit_in_init_scope_suite_scb_SUITE,init_per_suite, - {failed, - {error, - "Failed to start SCB, see the CT Log for details"}}}}, - {?eh,tc_auto_skip, - {ct_exit_in_init_scope_suite_scb_SUITE,test_case, - {failed, - {ct_exit_in_init_scope_suite_scb_SUITE,init_per_suite, - {failed, - "Failed to start SCB, see the CT Log for details"}}}}}, - {?eh,tc_auto_skip, - {ct_exit_in_init_scope_suite_scb_SUITE,end_per_suite, - {failed, - {ct_exit_in_init_scope_suite_scb_SUITE,init_per_suite, - {failed, - "Failed to start SCB, see the CT Log for details"}}}}}, - {?eh,test_done,{'DEF','STOP_TIME'}}, - {?eh,stop_logging,[]}]; - -test_events(faulty_scb_exit_in_init) -> - [{?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{empty_scb,init,['_',[]]}}, - {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, - {?eh,test_done,{'DEF','STOP_TIME'}}, - {?eh,stop_logging,[]}]; - -test_events(faulty_scb_exit_in_id) -> - [{?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{empty_scb,id,[[]]}}, - {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, - {negative, {?eh,tc_start,'_'}, - {?eh,test_done,{'DEF','STOP_TIME'}}}, - {?eh,stop_logging,[]}]; - -test_events(scope_per_suite_scb) -> - [ - {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, - {?eh,tc_start,{ct_scope_per_suite_scb_SUITE,init_per_suite}}, - {?eh,scb,{'_',id,[[]]}}, - {?eh,scb,{'_',init,['_',[]]}}, - {?eh,scb,{'_',post_init_per_suite,[ct_scope_per_suite_scb_SUITE,'$proplist','$proplist',[]]}}, - {?eh,tc_done,{ct_scope_per_suite_scb_SUITE,init_per_suite,ok}}, - - {?eh,tc_start,{ct_scope_per_suite_scb_SUITE,test_case}}, - {?eh,scb,{'_',pre_init_per_testcase,[test_case,'$proplist',[]]}}, - {?eh,scb,{'_',post_end_per_testcase,[test_case,'$proplist',ok,[]]}}, - {?eh,tc_done,{ct_scope_per_suite_scb_SUITE,test_case,ok}}, - - {?eh,tc_start,{ct_scope_per_suite_scb_SUITE,end_per_suite}}, - {?eh,scb,{'_',pre_end_per_suite, - [ct_scope_per_suite_scb_SUITE,'$proplist',[]]}}, - {?eh,scb,{'_',post_end_per_suite,[ct_scope_per_suite_scb_SUITE,'$proplist','_',[]]}}, - {?eh,scb,{'_',terminate,[[]]}}, - {?eh,tc_done,{ct_scope_per_suite_scb_SUITE,end_per_suite,ok}}, - {?eh,test_done,{'DEF','STOP_TIME'}}, - {?eh,stop_logging,[]} - ]; - -test_events(scope_suite_scb) -> - [ - {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, - {?eh,tc_start,{ct_scope_suite_scb_SUITE,init_per_suite}}, - {?eh,scb,{'_',id,[[]]}}, - {?eh,scb,{'_',init,['_',[]]}}, - {?eh,scb,{'_',pre_init_per_suite,[ct_scope_suite_scb_SUITE,'$proplist',[]]}}, - {?eh,scb,{'_',post_init_per_suite,[ct_scope_suite_scb_SUITE,'$proplist','$proplist',[]]}}, - {?eh,tc_done,{ct_scope_suite_scb_SUITE,init_per_suite,ok}}, - - {?eh,tc_start,{ct_scope_suite_scb_SUITE,test_case}}, - {?eh,scb,{'_',pre_init_per_testcase,[test_case,'$proplist',[]]}}, - {?eh,scb,{'_',post_end_per_testcase,[test_case,'$proplist',ok,[]]}}, - {?eh,tc_done,{ct_scope_suite_scb_SUITE,test_case,ok}}, - - {?eh,tc_start,{ct_scope_suite_scb_SUITE,end_per_suite}}, - {?eh,scb,{'_',pre_end_per_suite,[ct_scope_suite_scb_SUITE,'$proplist',[]]}}, - {?eh,scb,{'_',post_end_per_suite,[ct_scope_suite_scb_SUITE,'$proplist','_',[]]}}, - {?eh,scb,{'_',terminate,[[]]}}, - {?eh,tc_done,{ct_scope_suite_scb_SUITE,end_per_suite,ok}}, - {?eh,test_done,{'DEF','STOP_TIME'}}, - {?eh,stop_logging,[]} - ]; - -test_events(scope_per_group_scb) -> - [ - {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, - {?eh,tc_start,{ct_scope_per_group_scb_SUITE,init_per_suite}}, - {?eh,tc_done,{ct_scope_per_group_scb_SUITE,init_per_suite,ok}}, - - [{?eh,tc_start,{ct_scope_per_group_scb_SUITE,{init_per_group,group1,[]}}}, - {?eh,scb,{'_',id,[[]]}}, - {?eh,scb,{'_',init,['_',[]]}}, - {?eh,scb,{'_',post_init_per_group,[group1,'$proplist','$proplist',[]]}}, - {?eh,tc_done,{ct_scope_per_group_scb_SUITE,{init_per_group,group1,[]},ok}}, - - {?eh,tc_start,{ct_scope_per_group_scb_SUITE,test_case}}, - {?eh,scb,{'_',pre_init_per_testcase,[test_case,'$proplist',[]]}}, - {?eh,scb,{'_',post_end_per_testcase,[test_case,'$proplist',ok,[]]}}, - {?eh,tc_done,{ct_scope_per_group_scb_SUITE,test_case,ok}}, - - {?eh,tc_start,{ct_scope_per_group_scb_SUITE,{end_per_group,group1,[]}}}, - {?eh,scb,{'_',pre_end_per_group,[group1,'$proplist',[]]}}, - {?eh,scb,{'_',post_end_per_group,[group1,'$proplist','_',[]]}}, - {?eh,scb,{'_',terminate,[[]]}}, - {?eh,tc_done,{ct_scope_per_group_scb_SUITE,{end_per_group,group1,[]},ok}}], - - {?eh,tc_start,{ct_scope_per_group_scb_SUITE,end_per_suite}}, - {?eh,tc_done,{ct_scope_per_group_scb_SUITE,end_per_suite,ok}}, - {?eh,test_done,{'DEF','STOP_TIME'}}, - {?eh,stop_logging,[]} - ]; - -test_events(scope_per_suite_state_scb) -> - [ - {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, - {?eh,tc_start,{ct_scope_per_suite_state_scb_SUITE,init_per_suite}}, - {?eh,scb,{'_',id,[[test]]}}, - {?eh,scb,{'_',init,['_',[test]]}}, - {?eh,scb,{'_',post_init_per_suite,[ct_scope_per_suite_state_scb_SUITE,'$proplist','$proplist',[test]]}}, - {?eh,tc_done,{ct_scope_per_suite_state_scb_SUITE,init_per_suite,ok}}, - - {?eh,tc_start,{ct_scope_per_suite_state_scb_SUITE,test_case}}, - {?eh,scb,{'_',pre_init_per_testcase,[test_case,'$proplist',[test]]}}, - {?eh,scb,{'_',post_end_per_testcase,[test_case,'$proplist',ok,[test]]}}, - {?eh,tc_done,{ct_scope_per_suite_state_scb_SUITE,test_case,ok}}, - - {?eh,tc_start,{ct_scope_per_suite_state_scb_SUITE,end_per_suite}}, - {?eh,scb,{'_',pre_end_per_suite, - [ct_scope_per_suite_state_scb_SUITE,'$proplist',[test]]}}, - {?eh,scb,{'_',post_end_per_suite,[ct_scope_per_suite_state_scb_SUITE,'$proplist','_',[test]]}}, - {?eh,scb,{'_',terminate,[[test]]}}, - {?eh,tc_done,{ct_scope_per_suite_state_scb_SUITE,end_per_suite,ok}}, - {?eh,test_done,{'DEF','STOP_TIME'}}, - {?eh,stop_logging,[]} - ]; - -test_events(scope_suite_state_scb) -> - [ - {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, - {?eh,tc_start,{ct_scope_suite_state_scb_SUITE,init_per_suite}}, - {?eh,scb,{'_',id,[[test]]}}, - {?eh,scb,{'_',init,['_',[test]]}}, - {?eh,scb,{'_',pre_init_per_suite,[ct_scope_suite_state_scb_SUITE,'$proplist',[test]]}}, - {?eh,scb,{'_',post_init_per_suite,[ct_scope_suite_state_scb_SUITE,'$proplist','$proplist',[test]]}}, - {?eh,tc_done,{ct_scope_suite_state_scb_SUITE,init_per_suite,ok}}, - - {?eh,tc_start,{ct_scope_suite_state_scb_SUITE,test_case}}, - {?eh,scb,{'_',pre_init_per_testcase,[test_case,'$proplist',[test]]}}, - {?eh,scb,{'_',post_end_per_testcase,[test_case,'$proplist',ok,[test]]}}, - {?eh,tc_done,{ct_scope_suite_state_scb_SUITE,test_case,ok}}, - - {?eh,tc_start,{ct_scope_suite_state_scb_SUITE,end_per_suite}}, - {?eh,scb,{'_',pre_end_per_suite,[ct_scope_suite_state_scb_SUITE,'$proplist',[test]]}}, - {?eh,scb,{'_',post_end_per_suite,[ct_scope_suite_state_scb_SUITE,'$proplist','_',[test]]}}, - {?eh,scb,{'_',terminate,[[test]]}}, - {?eh,tc_done,{ct_scope_suite_state_scb_SUITE,end_per_suite,ok}}, - {?eh,test_done,{'DEF','STOP_TIME'}}, - {?eh,stop_logging,[]} - ]; - -test_events(scope_per_group_state_scb) -> - [ - {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, - {?eh,tc_start,{ct_scope_per_group_state_scb_SUITE,init_per_suite}}, - {?eh,tc_done,{ct_scope_per_group_state_scb_SUITE,init_per_suite,ok}}, - - [{?eh,tc_start,{ct_scope_per_group_state_scb_SUITE,{init_per_group,group1,[]}}}, - {?eh,scb,{'_',id,[[test]]}}, - {?eh,scb,{'_',init,['_',[test]]}}, - {?eh,scb,{'_',post_init_per_group,[group1,'$proplist','$proplist',[test]]}}, - {?eh,tc_done,{ct_scope_per_group_state_scb_SUITE,{init_per_group,group1,[]},ok}}, - - {?eh,tc_start,{ct_scope_per_group_state_scb_SUITE,test_case}}, - {?eh,scb,{'_',pre_init_per_testcase,[test_case,'$proplist',[test]]}}, - {?eh,scb,{'_',post_end_per_testcase,[test_case,'$proplist',ok,[test]]}}, - {?eh,tc_done,{ct_scope_per_group_state_scb_SUITE,test_case,ok}}, - - {?eh,tc_start,{ct_scope_per_group_state_scb_SUITE,{end_per_group,group1,[]}}}, - {?eh,scb,{'_',pre_end_per_group,[group1,'$proplist',[test]]}}, - {?eh,scb,{'_',post_end_per_group,[group1,'$proplist','_',[test]]}}, - {?eh,scb,{'_',terminate,[[test]]}}, - {?eh,tc_done,{ct_scope_per_group_state_scb_SUITE,{end_per_group,group1,[]},ok}}], - - {?eh,tc_start,{ct_scope_per_group_state_scb_SUITE,end_per_suite}}, - {?eh,tc_done,{ct_scope_per_group_state_scb_SUITE,end_per_suite,ok}}, - {?eh,test_done,{'DEF','STOP_TIME'}}, - {?eh,stop_logging,[]} - ]; - -test_events(fail_pre_suite_scb) -> - [ - {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{'_',init,['_',[]]}}, - {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, - - - {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, - {?eh,scb,{'_',pre_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, - {?eh,scb,{'_',post_init_per_suite,[ct_scb_empty_SUITE,'$proplist', - {fail,"Test failure"},[]]}}, - {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite, - {failed, {error,"Test failure"}}}}, - {?eh,scb,{'_',on_tc_fail, - [init_per_suite,{failed,"Test failure"},[]]}}, - - - {?eh,tc_auto_skip,{ct_scb_empty_SUITE,test_case, - {failed,{ct_scb_empty_SUITE,init_per_suite, - {failed,"Test failure"}}}}}, - {?eh,scb,{'_',on_tc_skip, - [test_case, {tc_auto_skip, - {failed, {ct_scb_empty_SUITE, init_per_suite, - {failed, "Test failure"}}}},[]]}}, - - - {?eh,tc_auto_skip, {ct_scb_empty_SUITE, end_per_suite, - {failed, {ct_scb_empty_SUITE, init_per_suite, - {failed, "Test failure"}}}}}, - {?eh,scb,{'_',on_tc_skip, - [end_per_suite, {tc_auto_skip, - {failed, {ct_scb_empty_SUITE, init_per_suite, - {failed, "Test failure"}}}},[]]}}, - - - {?eh,test_done,{'DEF','STOP_TIME'}}, - {?eh,scb, {'_',terminate,[[]]}}, - {?eh,stop_logging,[]} - ]; - -test_events(fail_post_suite_scb) -> - [ - {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{'_',init,['_',[]]}}, - {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, - {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, - {?eh,scb,{'_',pre_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, - {?eh,scb,{'_',post_init_per_suite,[ct_scb_empty_SUITE,'$proplist','$proplist',[]]}}, - {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite, - {failed,{error,"Test failure"}}}}, - {?eh,scb,{'_',on_tc_fail,[init_per_suite, {failed,"Test failure"}, []]}}, - - {?eh,tc_auto_skip,{ct_scb_empty_SUITE,test_case, - {failed,{ct_scb_empty_SUITE,init_per_suite, - {failed,"Test failure"}}}}}, - {?eh,scb,{'_',on_tc_skip,[test_case,{tc_auto_skip,'_'},[]]}}, - - {?eh,tc_auto_skip, {ct_scb_empty_SUITE, end_per_suite, - {failed, {ct_scb_empty_SUITE, init_per_suite, - {failed, "Test failure"}}}}}, - {?eh,scb,{'_',on_tc_skip,[end_per_suite,{tc_auto_skip,'_'},[]]}}, - - {?eh,test_done,{'DEF','STOP_TIME'}}, - {?eh,scb, {'_',terminate,[[]]}}, - {?eh,stop_logging,[]} - ]; - -test_events(skip_pre_suite_scb) -> - [ - {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{'_',init,['_',[]]}}, - {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, - {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, - {?eh,scb,{'_',pre_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, - {?eh,scb,{'_',post_init_per_suite,[ct_scb_empty_SUITE,'$proplist',{skip,"Test skip"},[]]}}, - {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite,{skipped,"Test skip"}}}, - {?eh,scb,{'_',on_tc_skip, - [init_per_suite,{tc_user_skip,{skipped,"Test skip"}},[]]}}, - - {?eh,tc_auto_skip,{ct_scb_empty_SUITE,test_case,"Test skip"}}, - {?eh,scb,{'_',on_tc_skip,[test_case,{tc_auto_skip,"Test skip"},[]]}}, - - {?eh,tc_auto_skip, {ct_scb_empty_SUITE, end_per_suite,"Test skip"}}, - {?eh,scb,{'_',on_tc_skip,[end_per_suite,{tc_auto_skip,"Test skip"},[]]}}, - - {?eh,test_done,{'DEF','STOP_TIME'}}, - {?eh,scb, {'_',terminate,[[]]}}, - {?eh,stop_logging,[]} - ]; - -test_events(skip_post_suite_scb) -> - [ - {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{'_',init,['_',[]]}}, - {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, - - {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, - {?eh,scb,{'_',pre_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, - {?eh,scb,{'_',post_init_per_suite,[ct_scb_empty_SUITE,'$proplist','$proplist',[]]}}, - {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite,{skipped,"Test skip"}}}, - {?eh,scb,{'_',on_tc_skip, - [init_per_suite,{tc_user_skip,{skipped,"Test skip"}},[]]}}, - - {?eh,tc_auto_skip,{ct_scb_empty_SUITE,test_case,"Test skip"}}, - {?eh,scb,{'_',on_tc_skip,[test_case,{tc_auto_skip,"Test skip"},[]]}}, - - {?eh,tc_auto_skip, {ct_scb_empty_SUITE, end_per_suite,"Test skip"}}, - {?eh,scb,{'_',on_tc_skip,[end_per_suite,{tc_auto_skip,"Test skip"},[]]}}, - - {?eh,test_done,{'DEF','STOP_TIME'}}, - {?eh,scb,{'_',terminate,[[]]}}, - {?eh,stop_logging,[]} - ]; - -test_events(recover_post_suite_scb) -> - Suite = ct_scb_fail_per_suite_SUITE, - [ - {?eh,start_logging,'_'}, - {?eh,scb,{'_',init,['_',[]]}}, - {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, - {?eh,tc_start,{Suite,init_per_suite}}, - {?eh,scb,{'_',pre_init_per_suite,[Suite,'$proplist','$proplist']}}, - {?eh,scb,{'_',post_init_per_suite,[Suite,contains([tc_status]), - {'EXIT',{'_','_'}},[]]}}, - {?eh,tc_done,{Suite,init_per_suite,ok}}, - - {?eh,tc_start,{Suite,test_case}}, - {?eh,scb,{'_',pre_init_per_testcase, - [test_case, not_contains([tc_status]),[]]}}, - {?eh,scb,{'_',post_end_per_testcase, - [test_case, contains([tc_status]),'_',[]]}}, - {?eh,tc_done,{Suite,test_case,ok}}, - - {?eh,tc_start,{Suite,end_per_suite}}, - {?eh,scb,{'_',pre_end_per_suite, - [Suite,not_contains([tc_status]),[]]}}, - {?eh,scb,{'_',post_end_per_suite, - [Suite,not_contains([tc_status]),'_',[]]}}, - {?eh,tc_done,{Suite,end_per_suite,ok}}, - {?eh,test_done,{'DEF','STOP_TIME'}}, - {?eh,scb,{'_',terminate,[[]]}}, - {?eh,stop_logging,[]} - ]; - -test_events(update_config_scb) -> - [ - {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{'_',init,['_',[]]}}, - {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, - - {?eh,tc_start,{ct_update_config_SUITE,init_per_suite}}, - {?eh,scb,{'_',pre_init_per_suite, - [ct_update_config_SUITE,contains([]),[]]}}, - {?eh,scb,{'_',post_init_per_suite, - [ct_update_config_SUITE, - '$proplist', - contains( - [init_per_suite, - pre_init_per_suite]), - []]}}, - {?eh,tc_done,{ct_update_config_SUITE,init_per_suite,ok}}, - - {?eh,tc_start,{ct_update_config_SUITE, {init_per_group,group1,[]}}}, - {?eh,scb,{'_',pre_init_per_group, - [group1,contains( - [post_init_per_suite, - init_per_suite, - pre_init_per_suite]), - []]}}, - {?eh,scb,{'_',post_init_per_group, - [group1, - contains( - [post_init_per_suite, - init_per_suite, - pre_init_per_suite]), - contains( - [init_per_group, - pre_init_per_group, - post_init_per_suite, - init_per_suite, - pre_init_per_suite]), - []]}}, - {?eh,tc_done,{ct_update_config_SUITE,{init_per_group,group1,[]},ok}}, - - {?eh,tc_start,{ct_update_config_SUITE,test_case}}, - {?eh,scb,{'_',pre_init_per_testcase, - [test_case,contains( - [post_init_per_group, - init_per_group, - pre_init_per_group, - post_init_per_suite, - init_per_suite, - pre_init_per_suite]), - []]}}, - {?eh,scb,{'_',post_end_per_testcase, - [test_case,contains( - [init_per_testcase, - pre_init_per_testcase, - post_init_per_group, - init_per_group, - pre_init_per_group, - post_init_per_suite, - init_per_suite, - pre_init_per_suite]), - ok,[]]}}, - {?eh,tc_done,{ct_update_config_SUITE,test_case,ok}}, - - {?eh,tc_start,{ct_update_config_SUITE, {end_per_group,group1,[]}}}, - {?eh,scb,{'_',pre_end_per_group, - [group1,contains( - [post_init_per_group, - init_per_group, - pre_init_per_group, - post_init_per_suite, - init_per_suite, - pre_init_per_suite]), - []]}}, - {?eh,scb,{'_',post_end_per_group, - [group1, - contains( - [pre_end_per_group, - post_init_per_group, - init_per_group, - pre_init_per_group, - post_init_per_suite, - init_per_suite, - pre_init_per_suite]), - ok,[]]}}, - {?eh,tc_done,{ct_update_config_SUITE,{end_per_group,group1,[]},ok}}, - - {?eh,tc_start,{ct_update_config_SUITE,end_per_suite}}, - {?eh,scb,{'_',pre_end_per_suite, - [ct_update_config_SUITE,contains( - [post_init_per_suite, - init_per_suite, - pre_init_per_suite]), - []]}}, - {?eh,scb,{'_',post_end_per_suite, - [ct_update_config_SUITE,contains( - [pre_end_per_suite, - post_init_per_suite, - init_per_suite, - pre_init_per_suite]), - '_',[]]}}, - {?eh,tc_done,{ct_update_config_SUITE,end_per_suite,ok}}, - {?eh,test_done,{'DEF','STOP_TIME'}}, - {?eh,scb,{'_',terminate,[contains( - [post_end_per_suite, - pre_end_per_suite, - post_init_per_suite, - init_per_suite, - pre_init_per_suite])]}}, - {?eh,stop_logging,[]} - ]; - -test_events(state_update_scb) -> - [ - {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{'_',init,['_',[]]}}, - {?eh,scb,{'_',init,['_',[]]}}, - {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, - {?eh,tc_start,{'_',init_per_suite}}, - - {?eh,tc_done,{'_',end_per_suite,ok}}, - {?eh,test_done,{'DEF','STOP_TIME'}}, - {?eh,scb,{'_',terminate,[contains( - [post_end_per_suite,pre_end_per_suite, - post_end_per_group,pre_end_per_group, - {not_in_order, - [post_end_per_testcase,pre_init_per_testcase, - on_tc_skip,post_end_per_testcase, - pre_init_per_testcase,on_tc_fail, - post_end_per_testcase,pre_init_per_testcase] - }, - post_init_per_group,pre_init_per_group, - post_init_per_suite,pre_init_per_suite, - init])]}}, - {?eh,scb,{'_',terminate,[contains( - [post_end_per_suite,pre_end_per_suite, - post_end_per_group,pre_end_per_group, - {not_in_order, - [post_end_per_testcase,pre_init_per_testcase, - on_tc_skip,post_end_per_testcase, - pre_init_per_testcase,on_tc_fail, - post_end_per_testcase,pre_init_per_testcase] - }, - post_init_per_group,pre_init_per_group, - post_init_per_suite,pre_init_per_suite, - init] - )]}}, - {?eh,stop_logging,[]} - ]; - -test_events(options_scb) -> - [ - {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{empty_scb,init,['_',[test]]}}, - {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, - {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, - {?eh,scb,{empty_scb,pre_init_per_suite, - [ct_scb_empty_SUITE,'$proplist',[test]]}}, - {?eh,scb,{empty_scb,post_init_per_suite, - [ct_scb_empty_SUITE,'$proplist','$proplist',[test]]}}, - {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite,ok}}, - - {?eh,tc_start,{ct_scb_empty_SUITE,test_case}}, - {?eh,scb,{empty_scb,pre_init_per_testcase,[test_case,'$proplist',[test]]}}, - {?eh,scb,{empty_scb,post_end_per_testcase,[test_case,'$proplist','_',[test]]}}, - {?eh,tc_done,{ct_scb_empty_SUITE,test_case,ok}}, - - {?eh,tc_start,{ct_scb_empty_SUITE,end_per_suite}}, - {?eh,scb,{empty_scb,pre_end_per_suite, - [ct_scb_empty_SUITE,'$proplist',[test]]}}, - {?eh,scb,{empty_scb,post_end_per_suite,[ct_scb_empty_SUITE,'$proplist','_',[test]]}}, - {?eh,tc_done,{ct_scb_empty_SUITE,end_per_suite,ok}}, - {?eh,test_done,{'DEF','STOP_TIME'}}, - {?eh,scb,{empty_scb,terminate,[[test]]}}, - {?eh,stop_logging,[]} - ]; - -test_events(same_id_scb) -> - [ - {?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{'_',id,[[]]}}, - {?eh,scb,{'_',init,[same_id_scb,[]]}}, - {?eh,scb,{'_',id,[[]]}}, - {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, - {?eh,tc_start,{ct_scb_empty_SUITE,init_per_suite}}, - {?eh,scb,{'_',pre_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, - {negative, - {?eh,scb,{'_',pre_init_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, - {?eh,scb,{'_',post_init_per_suite, - [ct_scb_empty_SUITE,'$proplist','$proplist',[]]}}}, - {negative, - {?eh,scb,{'_',post_init_per_suite, - [ct_scb_empty_SUITE,'$proplist','$proplist',[]]}}, - {?eh,tc_done,{ct_scb_empty_SUITE,init_per_suite,ok}}}, - - {?eh,tc_start,{ct_scb_empty_SUITE,test_case}}, - {?eh,scb,{'_',pre_init_per_testcase,[test_case,'$proplist',[]]}}, - {negative, - {?eh,scb,{'_',pre_init_per_testcase,[test_case,'$proplist',[]]}}, - {?eh,scb,{'_',post_end_per_testcase,[test_case,'$proplist',ok,[]]}}}, - {negative, - {?eh,scb,{'_',post_end_per_testcase,[test_case,'$proplist',ok,[]]}}, - {?eh,tc_done,{ct_scb_empty_SUITE,test_case,ok}}}, - - {?eh,tc_start,{ct_scb_empty_SUITE,end_per_suite}}, - {?eh,scb,{'_',pre_end_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, - {negative, - {?eh,scb,{'_',pre_end_per_suite,[ct_scb_empty_SUITE,'$proplist',[]]}}, - {?eh,scb,{'_',post_end_per_suite,[ct_scb_empty_SUITE,'$proplist','_',[]]}}}, - {negative, - {?eh,scb,{'_',post_end_per_suite, - [ct_scb_empty_SUITE,'$proplist','_',[]]}}, - {?eh,tc_done,{ct_scb_empty_SUITE,end_per_suite,ok}}}, - {?eh,test_done,{'DEF','STOP_TIME'}}, - {?eh,scb,{'_',terminate,[[]]}}, - {?eh,stop_logging,[]} - ]; - -test_events(fail_n_skip_with_minimal_scb) -> - [{?eh,start_logging,{'DEF','RUNDIR'}}, - {?eh,scb,{'_',init,['_',[]]}}, - {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, - {?eh,tc_start,{'_',init_per_suite}}, - - {?eh,tc_done,{'_',end_per_suite,ok}}, - {?eh,scb,{'_',terminate,[[]]}}, - {?eh,stop_logging,[]} - ]; - -test_events(ok) -> - ok. - - -%% test events help functions -contains(List) -> - fun(Proplist) when is_list(Proplist) -> - contains(List,Proplist) - end. - -contains([{not_in_order,List}|T],Rest) -> - contains_parallel(List,Rest), - contains(T,Rest); -contains([{Ele,Pos}|T] = L,[H|T2]) -> - case element(Pos,H) of - Ele -> - contains(T,T2); - _ -> - contains(L,T2) - end; -contains([Ele|T],[{Ele,_}|T2])-> - contains(T,T2); -contains([Ele|T],[Ele|T2])-> - contains(T,T2); -contains(List,[_|T]) -> - contains(List,T); -contains([],_) -> - match. - -contains_parallel([Key | T], Elems) -> - contains([Key],Elems), - contains_parallel(T,Elems); -contains_parallel([],_Elems) -> - match. - -not_contains(List) -> - fun(Proplist) when is_list(Proplist) -> - [] = [Ele || {Ele,_} <- Proplist, - Test <- List, - Test =:= Ele] - end. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/crash_id_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/crash_id_scb.erl deleted file mode 100644 index 2c256c46df..0000000000 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/crash_id_scb.erl +++ /dev/null @@ -1,34 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2010. 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(crash_id_scb). - - --include_lib("common_test/src/ct_util.hrl"). --include_lib("common_test/include/ct_event.hrl"). - - -%% Suite Callbacks --export([id/1]). - -id(Opts) -> - empty_scb:id(Opts), - exit(diediedie). - diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/crash_init_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/crash_init_scb.erl deleted file mode 100644 index c4138bbcef..0000000000 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/crash_init_scb.erl +++ /dev/null @@ -1,34 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2010. 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(crash_init_scb). - - --include_lib("common_test/src/ct_util.hrl"). --include_lib("common_test/include/ct_event.hrl"). - - -%% Suite Callbacks --export([init/2]). - -init(Id, Opts) -> - empty_scb:init(Id, Opts), - exit(diediedie). - diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_exit_in_init_scope_suite_scb_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_exit_in_init_scope_suite_scb_SUITE.erl deleted file mode 100644 index bfaeb7ca3a..0000000000 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_exit_in_init_scope_suite_scb_SUITE.erl +++ /dev/null @@ -1,50 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2010. 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(ct_exit_in_init_scope_suite_scb_SUITE). - --suite_defaults([{timetrap, {minutes, 10}}]). - -%% Note: This directive should only be used in test suites. --compile(export_all). - --include_lib("common_test/include/ct.hrl"). - -%% Test server callback functions -suite() -> - [{suite_callbacks,[crash_init_scb]}]. - -init_per_suite(Config) -> - Config. - -end_per_suite(_Config) -> - ok. - -init_per_testcase(_TestCase, Config) -> - Config. - -end_per_testcase(_TestCase, _Config) -> - ok. - -all() -> - [test_case]. - -%% Test cases starts here. -test_case(Config) when is_list(Config) -> - ok. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scb_empty_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scb_empty_SUITE.erl deleted file mode 100644 index 0eb40bce00..0000000000 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scb_empty_SUITE.erl +++ /dev/null @@ -1,47 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2010. 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(ct_scb_empty_SUITE). - --suite_defaults([{timetrap, {minutes, 10}}]). - -%% Note: This directive should only be used in test suites. --compile(export_all). - --include("ct.hrl"). - -%% Test server callback functions -init_per_suite(Config) -> - Config. - -end_per_suite(_Config) -> - ok. - -init_per_testcase(_TestCase, Config) -> - Config. - -end_per_testcase(_TestCase, _Config) -> - ok. - -all() -> - [test_case]. - -%% Test cases starts here. -test_case(Config) when is_list(Config) -> - ok. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scb_fail_one_skip_one_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scb_fail_one_skip_one_SUITE.erl deleted file mode 100644 index 593bd4a534..0000000000 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scb_fail_one_skip_one_SUITE.erl +++ /dev/null @@ -1,64 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2010. 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(ct_scb_fail_one_skip_one_SUITE). - --suite_defaults([{timetrap, {minutes, 10}}]). - -%% Note: This directive should only be used in test suites. --compile(export_all). - --include("ct.hrl"). - -%% Test server callback functions -init_per_suite(Config) -> - Config. - -end_per_suite(_Config) -> - ok. - -init_per_group(_Group,Config) -> - Config. - -end_per_group(_Group,_Config) -> - ok. - -init_per_testcase(test_case2, Config) -> - {skip,"skip it"}; -init_per_testcase(_TestCase, Config) -> - Config. - -end_per_testcase(_TestCase, _Config) -> - ok. - -groups() -> - [{group1,[parallel],[{group2,[parallel],[test_case1,test_case2,test_case3]}]}]. - -all() -> - [{group,group1}]. - -%% Test cases starts here. -test_case1(Config) -> - ok = nok. - -test_case2(Config) -> - ok. - -test_case3(Config) -> - ok. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scb_fail_per_suite_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scb_fail_per_suite_SUITE.erl deleted file mode 100644 index dfc7c37e8d..0000000000 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scb_fail_per_suite_SUITE.erl +++ /dev/null @@ -1,47 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2010. 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(ct_scb_fail_per_suite_SUITE). - --suite_defaults([{timetrap, {minutes, 10}}]). - -%% Note: This directive should only be used in test suites. --compile(export_all). - --include("ct.hrl"). - -%% Test server callback functions -init_per_suite(Config) -> - ok = nok. - -end_per_suite(_Config) -> - ok. - -init_per_testcase(_TestCase, Config) -> - Config. - -end_per_testcase(_TestCase, _Config) -> - ok. - -all() -> - [test_case]. - -%% Test cases starts here. -test_case(Config) when is_list(Config) -> - ok. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_group_scb_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_group_scb_SUITE.erl deleted file mode 100644 index 8df4a6d522..0000000000 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_group_scb_SUITE.erl +++ /dev/null @@ -1,56 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2010. 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(ct_scope_per_group_scb_SUITE). - --suite_defaults([{timetrap, {minutes, 10}}]). - -%% Note: This directive should only be used in test suites. --compile(export_all). - --include("ct.hrl"). - -%% Test server callback functions -init_per_suite(Config) -> - Config. - -end_per_suite(_Config) -> - ok. - -init_per_testcase(_TestCase, Config) -> - Config. - -end_per_testcase(_TestCase, _Config) -> - ok. - -init_per_group(GroupName, Config) -> - [{suite_callbacks,[empty_scb]}|Config]. - -end_per_group(GroupName, Config) -> - ok. - -all() -> - [{group,group1}]. - -groups() -> - [{group1,[],[test_case]}]. - -%% Test cases starts here. -test_case(Config) when is_list(Config) -> - ok. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_group_state_scb_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_group_state_scb_SUITE.erl deleted file mode 100644 index 63dd767b25..0000000000 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_group_state_scb_SUITE.erl +++ /dev/null @@ -1,56 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2010. 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(ct_scope_per_group_state_scb_SUITE). - --suite_defaults([{timetrap, {minutes, 10}}]). - -%% Note: This directive should only be used in test suites. --compile(export_all). - --include("ct.hrl"). - -%% Test server callback functions -init_per_suite(Config) -> - Config. - -end_per_suite(_Config) -> - ok. - -init_per_testcase(_TestCase, Config) -> - Config. - -end_per_testcase(_TestCase, _Config) -> - ok. - -init_per_group(_GroupName, Config) -> - [{suite_callbacks,[{empty_scb,[test]}]}|Config]. - -end_per_group(_GroupName, _Config) -> - ok. - -all() -> - [{group,group1}]. - -groups() -> - [{group1,[],[test_case]}]. - -%% Test cases starts here. -test_case(Config) when is_list(Config) -> - ok. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_suite_scb_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_suite_scb_SUITE.erl deleted file mode 100644 index 5492243b1b..0000000000 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_suite_scb_SUITE.erl +++ /dev/null @@ -1,47 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2010. 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(ct_scope_per_suite_scb_SUITE). - --suite_defaults([{timetrap, {minutes, 10}}]). - -%% Note: This directive should only be used in test suites. --compile(export_all). - --include("ct.hrl"). - -%% Test server callback functions -init_per_suite(Config) -> - [{suite_callbacks,[empty_scb]}|Config]. - -end_per_suite(_Config) -> - ok. - -init_per_testcase(_TestCase, Config) -> - Config. - -end_per_testcase(_TestCase, _Config) -> - ok. - -all() -> - [test_case]. - -%% Test cases starts here. -test_case(Config) when is_list(Config) -> - ok. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_suite_state_scb_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_suite_state_scb_SUITE.erl deleted file mode 100644 index 02a011f91b..0000000000 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_suite_state_scb_SUITE.erl +++ /dev/null @@ -1,47 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2010. 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(ct_scope_per_suite_state_scb_SUITE). - --suite_defaults([{timetrap, {minutes, 10}}]). - -%% Note: This directive should only be used in test suites. --compile(export_all). - --include("ct.hrl"). - -%% Test server callback functions -init_per_suite(Config) -> - [{suite_callbacks,[{empty_scb,[test]}]}|Config]. - -end_per_suite(_Config) -> - ok. - -init_per_testcase(_TestCase, Config) -> - Config. - -end_per_testcase(_TestCase, _Config) -> - ok. - -all() -> - [test_case]. - -%% Test cases starts here. -test_case(Config) when is_list(Config) -> - ok. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_tc_scb_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_tc_scb_SUITE.erl deleted file mode 100644 index d99e741553..0000000000 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_per_tc_scb_SUITE.erl +++ /dev/null @@ -1,110 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2010. 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(ct_scope_per_tc_scb_SUITE). - --suite_defaults([{timetrap, {minutes, 10}}]). - -%% Note: This directive should only be used in test suites. --compile(export_all). - --include("ct.hrl"). - -%% Test server callback functions -%%-------------------------------------------------------------------- -%% @doc -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Initiation before the whole suite -%% -%% Note: This function is free to add any key/value pairs to the Config -%% variable, but should NOT alter/remove any existing entries. -%% -%% @spec init_per_suite(Config) -> Config -%% @end -%%-------------------------------------------------------------------- -init_per_suite(Config) -> - Config. - -%%-------------------------------------------------------------------- -%% @doc -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Cleanup after the whole suite -%% -%% @spec end_per_suite(Config) -> _ -%% @end -%%-------------------------------------------------------------------- -end_per_suite(_Config) -> - ok. - -%%-------------------------------------------------------------------- -%% @doc -%% Case - atom() -%% Name of the test case that is about to be run. -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Initiation before each test case -%% -%% Note: This function is free to add any key/value pairs to the Config -%% variable, but should NOT alter/remove any existing entries. -%% Initiation before each test case -%% -%% @spec init_per_testcase(TestCase, Config) -> Config -%% @end -%%-------------------------------------------------------------------- -init_per_testcase(_TestCase, Config) -> - [{suite_callbacks,[empty_scb]}|Config]. - -%%-------------------------------------------------------------------- -%% @doc -%% Case - atom() -%% Name of the test case that is about to be run. -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Cleanup after each test case -%% -%% @spec end_per_testcase(TestCase, Config) -> _ -%% @end -%%-------------------------------------------------------------------- -end_per_testcase(_TestCase, _Config) -> - ok. - -%%-------------------------------------------------------------------- -%% @doc -%% TestCases - [Case] -%% Case - atom() -%% Name of a test case. -%% -%% Returns a list of all test cases in this test suite -%% -%% @spec all() -> TestCases -%% @end -%%-------------------------------------------------------------------- -all() -> - [test_case]. - -%% Test cases starts here. -%%-------------------------------------------------------------------- -test_case(Config) when is_list(Config) -> - ok. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_suite_scb_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_suite_scb_SUITE.erl deleted file mode 100644 index 7598c911b1..0000000000 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_suite_scb_SUITE.erl +++ /dev/null @@ -1,50 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2010. 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(ct_scope_suite_scb_SUITE). - --suite_defaults([{timetrap, {minutes, 10}}]). - -%% Note: This directive should only be used in test suites. --compile(export_all). - --include("ct.hrl"). - -%% Test server callback functions -suite() -> - [{suite_callbacks,[empty_scb]}]. - -init_per_suite(Config) -> - Config. - -end_per_suite(_Config) -> - ok. - -init_per_testcase(_TestCase, Config) -> - Config. - -end_per_testcase(_TestCase, _Config) -> - ok. - -all() -> - [test_case]. - -%% Test cases starts here. -test_case(Config) when is_list(Config) -> - ok. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_suite_state_scb_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_suite_state_scb_SUITE.erl deleted file mode 100644 index 869532f5cd..0000000000 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_scope_suite_state_scb_SUITE.erl +++ /dev/null @@ -1,50 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2010. 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(ct_scope_suite_state_scb_SUITE). - --suite_defaults([{timetrap, {minutes, 10}}]). - -%% Note: This directive should only be used in test suites. --compile(export_all). - --include("ct.hrl"). - -%% Test server callback functions -suite() -> - [{suite_callbacks,[{empty_scb,[test]}]}]. - -init_per_suite(Config) -> - Config. - -end_per_suite(_Config) -> - ok. - -init_per_testcase(_TestCase, Config) -> - Config. - -end_per_testcase(_TestCase, _Config) -> - ok. - -all() -> - [test_case]. - -%% Test cases starts here. -test_case(Config) when is_list(Config) -> - ok. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_update_config_SUITE.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_update_config_SUITE.erl deleted file mode 100644 index 57fea347f6..0000000000 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/ct_update_config_SUITE.erl +++ /dev/null @@ -1,56 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2010. 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(ct_update_config_SUITE). - --suite_defaults([{timetrap, {minutes, 10}}]). - -%% Note: This directive should only be used in test suites. --compile(export_all). - --include("ct.hrl"). - -%% Test server callback functions -init_per_suite(Config) -> - [{init_per_suite,now()}|Config]. - -end_per_suite(_Config) -> - ok. - -init_per_testcase(_TestCase, Config) -> - [{init_per_testcase,now()}|Config]. - -end_per_testcase(_TestCase, _Config) -> - ok. - -init_per_group(GroupName, Config) -> - [{init_per_group,now()}|Config]. - -end_per_group(GroupName, Config) -> - ok. - -all() -> - [{group,group1}]. - -groups() -> - [{group1,[],[test_case]}]. - -%% Test cases starts here. -test_case(Config) when is_list(Config) -> - ok. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/empty_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/empty_scb.erl deleted file mode 100644 index a82ca02d04..0000000000 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/empty_scb.erl +++ /dev/null @@ -1,277 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2010. 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% -%% - -%%% @doc Common Test Example Suite Callback module. -%%% -%%%

This module gives an example of a common test SCB (Suite CallBack). -%%% There are many ways to add a SCB to a test run, you can do it either in -%%% the command line using -suite_callback, in a test spec using -%%% {suite_callback,M} or in the suite it self by returning suite_callback -%%% from either suite/0, init_per_suite/1, init_per_group/2 and -%%% init_per_testcase/2. The scope of the SCB is determined by where is it -%%% started. If it is started in the command line or test spec then it will -%%% be stopped at the end of all tests. If it is started in init_per_suite, -%%% it will be stopped after end_per_suite and so on. See terminate -%%% documentation for a table describing the scoping machanics. -%%% -%%% All of callbacks except init/1 in a SCB are optional.

- --module(empty_scb). - -%% Suite Callbacks --export([id/1]). --export([init/2]). - --export([pre_init_per_suite/3]). --export([post_init_per_suite/4]). --export([pre_end_per_suite/3]). --export([post_end_per_suite/4]). - --export([pre_init_per_group/3]). --export([post_init_per_group/4]). --export([pre_end_per_group/3]). --export([post_end_per_group/4]). - --export([pre_init_per_testcase/3]). --export([post_end_per_testcase/4]). - --export([on_tc_fail/3]). --export([on_tc_skip/3]). - --export([terminate/1]). - --include_lib("common_test/src/ct_util.hrl"). --include_lib("common_test/include/ct_event.hrl"). - --type proplist() :: list({atom(),term()}). --type config() :: proplist(). --type reason() :: term(). --type skip_or_fail() :: {skip, reason()} | - {auto_skip, reason()} | - {fail, reason()}. - --record(state, { id = ?MODULE :: term()}). - -%% @doc Always called before any other callback function. Use this to initiate -%% any common state. It should return an ID for this SCB and a state. --spec init(Id :: term(), Opts :: proplist()) -> - {Id :: term(), State :: #state{}}. -init(Id, Opts) -> - gen_event:notify(?CT_EVMGR_REF, #event{ name = scb, node = node(), - data = {?MODULE, init, [Id, Opts]}}), - Opts. - -%% @doc The ID is used to uniquly identify an SCB instance, if two SCB's -%% return the same ID the seconds SCB is ignored. This function should NOT -%% have any side effects as it might be called multiple times by common test. --spec id(Opts :: proplist()) -> - Id :: term(). -id(Opts) -> - gen_event:notify(?CT_EVMGR_REF, #event{ name = scb, node = node(), - data = {?MODULE, id, [Opts]}}), - now(). - -%% @doc Called before init_per_suite is called. Note that this callback is -%% only called if the SCB is added before init_per_suite is run (eg. in a test -%% specification, suite/0 function etc). -%% You can change the config in the this function. --spec pre_init_per_suite(Suite :: atom(), - Config :: config(), - State :: #state{}) -> - {config() | skip_or_fail(), NewState :: #state{}}. -pre_init_per_suite(Suite,Config,State) -> - gen_event:notify( - ?CT_EVMGR_REF, #event{ name = scb, node = node(), - data = {?MODULE, pre_init_per_suite, - [Suite,Config,State]}}), - {Config, State}. - -%% @doc Called after init_per_suite. -%% you can change the return value in this function. --spec post_init_per_suite(Suite :: atom(), - Config :: config(), - Return :: config() | skip_or_fail(), - State :: #state{}) -> - {config() | skip_or_fail(), NewState :: #state{}}. -post_init_per_suite(Suite,Config,Return,State) -> - gen_event:notify( - ?CT_EVMGR_REF, #event{ name = scb, node = node(), - data = {?MODULE, post_init_per_suite, - [Suite,Config,Return,State]}}), - {Return, State}. - -%% @doc Called before end_per_suite. The config/state can be changed here, -%% though it will only affect the *end_per_suite function. --spec pre_end_per_suite(Suite :: atom(), - Config :: config() | skip_or_fail(), - State :: #state{}) -> - {ok | skip_or_fail(), NewState :: #state{}}. -pre_end_per_suite(Suite,Config,State) -> - gen_event:notify( - ?CT_EVMGR_REF, #event{ name = scb, node = node(), - data = {?MODULE, pre_end_per_suite, - [Suite,Config,State]}}), - {Config, State}. - -%% @doc Called after end_per_suite. Note that the config cannot be -%% changed here, only the status of the suite. --spec post_end_per_suite(Suite :: atom(), - Config :: config(), - Return :: term(), - State :: #state{}) -> - {ok | skip_or_fail(), NewState :: #state{}}. -post_end_per_suite(Suite,Config,Return,State) -> - gen_event:notify( - ?CT_EVMGR_REF, #event{ name = scb, node = node(), - data = {?MODULE, post_end_per_suite, - [Suite,Config,Return,State]}}), - {Return, State}. - -%% @doc Called before each init_per_group. -%% You can change the config in this function. --spec pre_init_per_group(Group :: atom(), - Config :: config(), - State :: #state{}) -> - {config() | skip_or_fail(), NewState :: #state{}}. -pre_init_per_group(Group,Config,State) -> - gen_event:notify( - ?CT_EVMGR_REF, #event{ name = scb, node = node(), - data = {?MODULE, pre_init_per_group, - [Group,Config,State]}}), - {Config, State}. - -%% @doc Called after each init_per_group. -%% You can change the return value in this function. --spec post_init_per_group(Group :: atom(), - Config :: config(), - Return :: config() | skip_or_fail(), - State :: #state{}) -> - {config() | skip_or_fail(), NewState :: #state{}}. -post_init_per_group(Group,Config,Return,State) -> - gen_event:notify( - ?CT_EVMGR_REF, #event{ name = scb, node = node(), - data = {?MODULE, post_init_per_group, - [Group,Config,Return,State]}}), - {Return, State}. - -%% @doc Called after each end_per_group. The config/state can be changed here, -%% though it will only affect the *end_per_group functions. --spec pre_end_per_group(Group :: atom(), - Config :: config() | skip_or_fail(), - State :: #state{}) -> - {ok | skip_or_fail(), NewState :: #state{}}. -pre_end_per_group(Group,Config,State) -> - gen_event:notify( - ?CT_EVMGR_REF, #event{ name = scb, node = node(), - data = {?MODULE, pre_end_per_group, - [Group,Config,State]}}), - {Config, State}. - -%% @doc Called after each end_per_group. Note that the config cannot be -%% changed here, only the status of the group. --spec post_end_per_group(Group :: atom(), - Config :: config(), - Return :: term(), - State :: #state{}) -> - {ok | skip_or_fail(), NewState :: #state{}}. -post_end_per_group(Group,Config,Return,State) -> - gen_event:notify( - ?CT_EVMGR_REF, #event{ name = scb, node = node(), - data = {?MODULE, post_end_per_group, - [Group,Config,Return,State]}}), - {Return, State}. - -%% @doc Called before each test case. -%% You can change the config in this function. --spec pre_init_per_testcase(TC :: atom(), - Config :: config(), - State :: #state{}) -> - {config() | skip_or_fail(), NewState :: #state{}}. -pre_init_per_testcase(TC,Config,State) -> - gen_event:notify( - ?CT_EVMGR_REF, #event{ name = scb, node = node(), - data = {?MODULE, pre_init_per_testcase, - [TC,Config,State]}}), - {Config, State}. - -%% @doc Called after each test case. Note that the config cannot be -%% changed here, only the status of the test case. --spec post_end_per_testcase(TC :: atom(), - Config :: config(), - Return :: term(), - State :: #state{}) -> - {ok | skip_or_fail(), NewState :: #state{}}. -post_end_per_testcase(TC,Config,Return,State) -> - gen_event:notify( - ?CT_EVMGR_REF, #event{ name = scb, node = node(), - data = {?MODULE, post_end_per_testcase, - [TC,Config,Return,State]}}), - {Return, State}. - -%% @doc Called after post_init_per_suite, post_end_per_suite, post_init_per_group, -%% post_end_per_group and post_end_per_tc if the suite, group or test case failed. -%% This function should be used for extra cleanup which might be needed. -%% It is not possible to modify the config or the status of the test run. --spec on_tc_fail(TC :: init_per_suite | end_per_suite | - init_per_group | end_per_group | atom(), - Reason :: term(), State :: #state{}) -> - NewState :: #state{}. -on_tc_fail(TC, Reason, State) -> - gen_event:notify( - ?CT_EVMGR_REF, #event{ name = scb, node = node(), - data = {?MODULE, on_tc_fail, - [TC,Reason,State]}}), - State. - -%% @doc Called when a test case is skipped by either user action -%% or due to an init function failing. Test case can be -%% end_per_suite, init_per_group, end_per_group and the actual test cases. --spec on_tc_skip(TC :: end_per_suite | - init_per_group | end_per_group | atom(), - {tc_auto_skip, {failed, {Mod :: atom(), Function :: atom(), Reason :: term()}}} | - {tc_user_skip, {skipped, Reason :: term()}}, - State :: #state{}) -> - NewState :: #state{}. -on_tc_skip(TC, Reason, State) -> - gen_event:notify( - ?CT_EVMGR_REF, #event{ name = scb, node = node(), - data = {?MODULE, on_tc_skip, - [TC,Reason,State]}}), - State. - -%% @doc Called when the scope of the SCB is done, this depends on -%% when the SCB was specified. This translation table describes when this -%% function is called. -%% -%% | Started in | terminate called | -%% |---------------------|-------------------------| -%% | command_line | after all tests are run | -%% | test spec | after all tests are run | -%% | suite/0 | after SUITE is done | -%% | init_per_suite/1 | after SUITE is done | -%% | init_per_group/2 | after group is done | -%% |-----------------------------------------------| -%% --spec terminate(State :: #state{}) -> - term(). -terminate(State) -> - gen_event:notify( - ?CT_EVMGR_REF, #event{ name = scb, node = node(), - data = {?MODULE, terminate, [State]}}), - ok. diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/fail_post_suite_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/fail_post_suite_scb.erl deleted file mode 100644 index 44c72f6795..0000000000 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/fail_post_suite_scb.erl +++ /dev/null @@ -1,72 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2010. 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(fail_post_suite_scb). - - --include_lib("common_test/src/ct_util.hrl"). --include_lib("common_test/include/ct_event.hrl"). - - -%% Suite Callbacks --compile(export_all). - -init(Id, Opts) -> - empty_scb:init(Id, Opts). - -pre_init_per_suite(Suite, Config, State) -> - empty_scb:pre_init_per_suite(Suite,Config,State). - -post_init_per_suite(Suite,Config,Return,State) -> - empty_scb:post_init_per_suite(Suite,Config,Return,State), - {{fail, "Test failure"}, State}. - -pre_end_per_suite(Suite,Config,State) -> - empty_scb:pre_end_per_suite(Suite,Config,State). - -post_end_per_suite(Suite,Config,Return,State) -> - empty_scb:post_end_per_suite(Suite,Config,Return,State). - -pre_init_per_group(Group,Config,State) -> - empty_scb:pre_init_per_group(Group,Config,State). - -post_init_per_group(Group,Config,Return,State) -> - empty_scb:post_init_per_group(Group,Config,Return,State). - -pre_end_per_group(Group,Config,State) -> - empty_scb:pre_end_per_group(Group,Config,State). - -post_end_per_group(Group,Config,Return,State) -> - empty_scb:post_end_per_group(Group,Config,Return,State). - -pre_init_per_testcase(TC,Config,State) -> - empty_scb:pre_init_per_testcase(TC,Config,State). - -post_end_per_testcase(TC,Config,Return,State) -> - empty_scb:post_end_per_testcase(TC,Config,Return,State). - -on_tc_fail(TC, Reason, State) -> - empty_scb:on_tc_fail(TC,Reason,State). - -on_tc_skip(TC, Reason, State) -> - empty_scb:on_tc_skip(TC,Reason,State). - -terminate(State) -> - empty_scb:terminate(State). diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/fail_pre_suite_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/fail_pre_suite_scb.erl deleted file mode 100644 index 90f10d7531..0000000000 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/fail_pre_suite_scb.erl +++ /dev/null @@ -1,72 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2010. 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(fail_pre_suite_scb). - - --include_lib("common_test/src/ct_util.hrl"). --include_lib("common_test/include/ct_event.hrl"). - - -%% Suite Callbacks --compile(export_all). - -init(Id, Opts) -> - empty_scb:init(Id, Opts). - -pre_init_per_suite(Suite, Config, State) -> - empty_scb:pre_init_per_suite(Suite,Config,State), - {{fail, "Test failure"}, State}. - -post_init_per_suite(Suite,Config,Return,State) -> - empty_scb:post_init_per_suite(Suite,Config,Return,State). - -pre_end_per_suite(Suite,Config,State) -> - empty_scb:pre_end_per_suite(Suite,Config,State). - -post_end_per_suite(Suite,Config,Return,State) -> - empty_scb:post_end_per_suite(Suite,Config,Return,State). - -pre_init_per_group(Group,Config,State) -> - empty_scb:pre_init_per_group(Group,Config,State). - -post_init_per_group(Group,Config,Return,State) -> - empty_scb:post_init_per_group(Group,Config,Return,State). - -pre_end_per_group(Group,Config,State) -> - empty_scb:pre_end_per_group(Group,Config,State). - -post_end_per_group(Group,Config,Return,State) -> - empty_scb:post_end_per_group(Group,Config,Return,State). - -pre_init_per_testcase(TC,Config,State) -> - empty_scb:pre_init_per_testcase(TC,Config,State). - -post_end_per_testcase(TC,Config,Return,State) -> - empty_scb:post_end_per_testcase(TC,Config,Return,State). - -on_tc_fail(TC, Reason, State) -> - empty_scb:on_tc_fail(TC,Reason,State). - -on_tc_skip(TC, Reason, State) -> - empty_scb:on_tc_skip(TC,Reason,State). - -terminate(State) -> - empty_scb:terminate(State). diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/id_no_init_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/id_no_init_scb.erl deleted file mode 100644 index 11fb8d739f..0000000000 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/id_no_init_scb.erl +++ /dev/null @@ -1,32 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2010. 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(id_no_init_scb). - - --include_lib("common_test/src/ct_util.hrl"). --include_lib("common_test/include/ct_event.hrl"). - - -%% Suite Callbacks --export([id/1]). - -id(Opts) -> - empty_scb:id(Opts). diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/minimal_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/minimal_scb.erl deleted file mode 100644 index b3feb1383c..0000000000 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/minimal_scb.erl +++ /dev/null @@ -1,33 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2010. 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(minimal_scb). - - --include_lib("common_test/src/ct_util.hrl"). --include_lib("common_test/include/ct_event.hrl"). - - -%% Suite Callbacks --export([init/2]). - -init(Id, Opts) -> - empty_scb:init(Id, Opts). - diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/minimal_terminate_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/minimal_terminate_scb.erl deleted file mode 100644 index 3f76d2f47d..0000000000 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/minimal_terminate_scb.erl +++ /dev/null @@ -1,38 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2010. 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(minimal_terminate_scb). - - --include_lib("common_test/src/ct_util.hrl"). --include_lib("common_test/include/ct_event.hrl"). - - -%% Suite Callbacks --export([init/2]). --export([terminate/1]). - -init(Id, Opts) -> - empty_scb:init(Id, Opts). - -terminate(State) -> - empty_scb:terminate(State). - - diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/recover_post_suite_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/recover_post_suite_scb.erl deleted file mode 100644 index 26468f0789..0000000000 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/recover_post_suite_scb.erl +++ /dev/null @@ -1,74 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2010. 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(recover_post_suite_scb). - - --include_lib("common_test/src/ct_util.hrl"). --include_lib("common_test/include/ct_event.hrl"). - - -%% Suite Callbacks --compile(export_all). - -init(Id, Opts) -> - empty_scb:init(Id, Opts). - -pre_init_per_suite(Suite, Config, State) -> - empty_scb:pre_init_per_suite(Suite,Config,State). - -post_init_per_suite(Suite,Config,{'EXIT',Reason} = Return,State) -> - empty_scb:post_init_per_suite(Suite,Config,Return,State), - {lists:keydelete(tc_status,1,Config),State}; -post_init_per_suite(Suite,Config,Return,State) -> - empty_scb:post_init_per_suite(Suite,Config,Return,State). - -pre_end_per_suite(Suite,Config,State) -> - empty_scb:pre_end_per_suite(Suite,Config,State). - -post_end_per_suite(Suite,Config,Return,State) -> - empty_scb:post_end_per_suite(Suite,Config,Return,State). - -pre_init_per_group(Group,Config,State) -> - empty_scb:pre_init_per_group(Group,Config,State). - -post_init_per_group(Group,Config,Return,State) -> - empty_scb:post_init_per_group(Group,Config,Return,State). - -pre_end_per_group(Group,Config,State) -> - empty_scb:pre_end_per_group(Group,Config,State). - -post_end_per_group(Group,Config,Return,State) -> - empty_scb:post_end_per_group(Group,Config,Return,State). - -pre_init_per_testcase(TC,Config,State) -> - empty_scb:pre_init_per_testcase(TC,Config,State). - -post_end_per_testcase(TC,Config,Return,State) -> - empty_scb:post_end_per_testcase(TC,Config,Return,State). - -on_tc_fail(TC, Reason, State) -> - empty_scb:on_tc_fail(TC,Reason,State). - -on_tc_skip(TC, Reason, State) -> - empty_scb:on_tc_skip(TC,Reason,State). - -terminate(State) -> - empty_scb:terminate(State). diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/same_id_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/same_id_scb.erl deleted file mode 100644 index 0fa708d5b6..0000000000 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/same_id_scb.erl +++ /dev/null @@ -1,75 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2010. 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(same_id_scb). - - --include_lib("common_test/src/ct_util.hrl"). --include_lib("common_test/include/ct_event.hrl"). - - -%% Suite Callbacks --compile(export_all). - -id(Opts) -> - empty_scb:id(Opts), - ?MODULE. - -init(Id, Opts) -> - empty_scb:init(Id, Opts). - -pre_init_per_suite(Suite, Config, State) -> - empty_scb:pre_init_per_suite(Suite,Config,State). - -post_init_per_suite(Suite,Config,Return,State) -> - empty_scb:post_init_per_suite(Suite,Config,Return,State). - -pre_end_per_suite(Suite,Config,State) -> - empty_scb:pre_end_per_suite(Suite,Config,State). - -post_end_per_suite(Suite,Config,Return,State) -> - empty_scb:post_end_per_suite(Suite,Config,Return,State). - -pre_init_per_group(Group,Config,State) -> - empty_scb:pre_init_per_group(Group,Config,State). - -post_init_per_group(Group,Config,Return,State) -> - empty_scb:post_init_per_group(Group,Config,Return,State). - -pre_end_per_group(Group,Config,State) -> - empty_scb:pre_end_per_group(Group,Config,State). - -post_end_per_group(Group,Config,Return,State) -> - empty_scb:post_end_per_group(Group,Config,Return,State). - -pre_init_per_testcase(TC,Config,State) -> - empty_scb:pre_init_per_testcase(TC,Config,State). - -post_end_per_testcase(TC,Config,Return,State) -> - empty_scb:post_end_per_testcase(TC,Config,Return,State). - -on_tc_fail(TC, Reason, State) -> - empty_scb:on_tc_fail(TC,Reason,State). - -on_tc_skip(TC, Reason, State) -> - empty_scb:on_tc_skip(TC,Reason,State). - -terminate(State) -> - empty_scb:terminate(State). diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/skip_post_suite_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/skip_post_suite_scb.erl deleted file mode 100644 index bb93ebee0f..0000000000 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/skip_post_suite_scb.erl +++ /dev/null @@ -1,72 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2010. 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(skip_post_suite_scb). - - --include_lib("common_test/src/ct_util.hrl"). --include_lib("common_test/include/ct_event.hrl"). - - -%% Suite Callbacks --compile(export_all). - -init(Id, Opts) -> - empty_scb:init(Id, Opts). - -pre_init_per_suite(Suite, Config, State) -> - empty_scb:pre_init_per_suite(Suite,Config,State). - -post_init_per_suite(Suite,Config,Return,State) -> - empty_scb:post_init_per_suite(Suite,Config,Return,State), - {{skip, "Test skip"}, State}. - -pre_end_per_suite(Suite,Config,State) -> - empty_scb:pre_end_per_suite(Suite,Config,State). - -post_end_per_suite(Suite,Config,Return,State) -> - empty_scb:post_end_per_suite(Suite,Config,Return,State). - -pre_init_per_group(Group,Config,State) -> - empty_scb:pre_init_per_group(Group,Config,State). - -post_init_per_group(Group,Config,Return,State) -> - empty_scb:post_init_per_group(Group,Config,Return,State). - -pre_end_per_group(Group,Config,State) -> - empty_scb:pre_end_per_group(Group,Config,State). - -post_end_per_group(Group,Config,Return,State) -> - empty_scb:post_end_per_group(Group,Config,Return,State). - -pre_init_per_testcase(TC,Config,State) -> - empty_scb:pre_init_per_testcase(TC,Config,State). - -post_end_per_testcase(TC,Config,Return,State) -> - empty_scb:post_end_per_testcase(TC,Config,Return,State). - -on_tc_fail(TC, Reason, State) -> - empty_scb:on_tc_fail(TC,Reason,State). - -on_tc_skip(TC, Reason, State) -> - empty_scb:on_tc_skip(TC,Reason,State). - -terminate(State) -> - empty_scb:terminate(State). diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/skip_pre_suite_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/skip_pre_suite_scb.erl deleted file mode 100644 index 9818964e7f..0000000000 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/skip_pre_suite_scb.erl +++ /dev/null @@ -1,73 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2010. 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(skip_pre_suite_scb). - - --include_lib("common_test/src/ct_util.hrl"). --include_lib("common_test/include/ct_event.hrl"). - - -%% Suite Callbacks --compile(export_all). - -init(Id, Opts) -> - empty_scb:init(Id, Opts). - - -pre_init_per_suite(Suite, Config, State) -> - empty_scb:pre_init_per_suite(Suite,Config,State), - {{skip, "Test skip"}, State}. - -post_init_per_suite(Suite,Config,Return,State) -> - empty_scb:post_init_per_suite(Suite,Config,Return,State). - -pre_end_per_suite(Suite,Config,State) -> - empty_scb:pre_end_per_suite(Suite,Config,State). - -post_end_per_suite(Suite,Config,Return,State) -> - empty_scb:post_end_per_suite(Suite,Config,Return,State). - -pre_init_per_group(Group,Config,State) -> - empty_scb:pre_init_per_group(Group,Config,State). - -post_init_per_group(Group,Config,Return,State) -> - empty_scb:post_init_per_group(Group,Config,Return,State). - -pre_end_per_group(Group,Config,State) -> - empty_scb:pre_end_per_group(Group,Config,State). - -post_end_per_group(Group,Config,Return,State) -> - empty_scb:post_end_per_group(Group,Config,Return,State). - -pre_init_per_testcase(TC,Config,State) -> - empty_scb:pre_init_per_testcase(TC,Config,State). - -post_end_per_testcase(TC,Config,Return,State) -> - empty_scb:post_end_per_testcase(TC,Config,Return,State). - -on_tc_fail(TC, Reason, State) -> - empty_scb:on_tc_fail(TC,Reason,State). - -on_tc_skip(TC, Reason, State) -> - empty_scb:on_tc_skip(TC,Reason,State). - -terminate(State) -> - empty_scb:terminate(State). diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/state_update_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/state_update_scb.erl deleted file mode 100644 index 13c50cf1a1..0000000000 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/state_update_scb.erl +++ /dev/null @@ -1,83 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2010. 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(state_update_scb). - - --include_lib("common_test/src/ct_util.hrl"). --include_lib("common_test/include/ct_event.hrl"). - -%% Suite Callbacks --compile(export_all). - -init(Id, Opts) -> - State = empty_scb:init(Id, Opts), - [init|State]. - -pre_init_per_suite(Suite, Config, State) -> - empty_scb:pre_init_per_suite(Suite,Config,State), - {Config, [pre_init_per_suite|State]}. - -post_init_per_suite(Suite,Config,Return,State) -> - empty_scb:post_init_per_suite(Suite,Config,Return,State), - {Config, [post_init_per_suite|State]}. - -pre_end_per_suite(Suite,Config,State) -> - empty_scb:pre_end_per_suite(Suite,Config,State), - {Config, [pre_end_per_suite|State]}. - -post_end_per_suite(Suite,Config,Return,State) -> - empty_scb:post_end_per_suite(Suite,Config,Return,State), - {Return, [post_end_per_suite|State]}. - -pre_init_per_group(Group,Config,State) -> - empty_scb:pre_init_per_group(Group,Config,State), - {Config, [pre_init_per_group|State]}. - -post_init_per_group(Group,Config,Return,State) -> - empty_scb:post_init_per_group(Group,Config,Return,State), - {Return, [post_init_per_group|State]}. - -pre_end_per_group(Group,Config,State) -> - empty_scb:pre_end_per_group(Group,Config,State), - {Config, [pre_end_per_group|State]}. - -post_end_per_group(Group,Config,Return,State) -> - empty_scb:post_end_per_group(Group,Config,Return,State), - {Return, [post_end_per_group|State]}. - -pre_init_per_testcase(TC,Config,State) -> - empty_scb:pre_init_per_testcase(TC,Config,State), - {Config, [pre_init_per_testcase|State]}. - -post_end_per_testcase(TC,Config,Return,State) -> - empty_scb:post_end_per_testcase(TC,Config,Return,State), - {Return, [post_end_per_testcase|State]}. - -on_tc_fail(TC, Reason, State) -> - empty_scb:on_tc_fail(TC,Reason,State), - [on_tc_fail|State]. - -on_tc_skip(TC, Reason, State) -> - empty_scb:on_tc_skip(TC,Reason,State), - [on_tc_skip|State]. - -terminate(State) -> - empty_scb:terminate(State). diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/undef_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/undef_scb.erl deleted file mode 100644 index 1cb64574c3..0000000000 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/undef_scb.erl +++ /dev/null @@ -1,71 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2010. 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(undef_scb). - - --include_lib("common_test/src/ct_util.hrl"). --include_lib("common_test/include/ct_event.hrl"). - - -%% Suite Callbacks --compile(export_all). - -init(Id, Opts) -> - empty_scb:init(Id, Opts). - -pre_init_per_suite(_Suite, _Config, _State) -> - lists:flaten([1,2,[3,4]]). - -post_init_per_suite(Suite,Config,Return,State) -> - empty_scb:post_init_per_suite(Suite,Config,Return,State). - -pre_end_per_suite(Suite,Config,State) -> - empty_scb:pre_end_per_suite(Suite,Config,State). - -post_end_per_suite(Suite,Config,Return,State) -> - empty_scb:post_end_per_suite(Suite,Config,Return,State). - -pre_init_per_group(Group,Config,State) -> - empty_scb:pre_init_per_group(Group,Config,State). - -post_init_per_group(Group,Config,Return,State) -> - empty_scb:post_init_per_group(Group,Config,Return,State). - -pre_end_per_group(Group,Config,State) -> - empty_scb:pre_end_per_group(Group,Config,State). - -post_end_per_group(Group,Config,Return,State) -> - empty_scb:post_end_per_group(Group,Config,Return,State). - -pre_init_per_testcase(TC,Config,State) -> - empty_scb:pre_init_per_testcase(TC,Config,State). - -post_end_per_testcase(TC,Config,Return,State) -> - empty_scb:post_end_per_testcase(TC,Config,Return,State). - -on_tc_fail(TC, Reason, State) -> - empty_scb:on_tc_fail(TC,Reason,State). - -on_tc_skip(TC, Reason, State) -> - empty_scb:on_tc_skip(TC,Reason,State). - -terminate(State) -> - empty_scb:terminate(State). diff --git a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/update_config_scb.erl b/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/update_config_scb.erl deleted file mode 100644 index 46a027403d..0000000000 --- a/lib/common_test/test/ct_suite_callback_SUITE_data/scb/tests/update_config_scb.erl +++ /dev/null @@ -1,82 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2010. 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(update_config_scb). - - --include_lib("common_test/src/ct_util.hrl"). --include_lib("common_test/include/ct_event.hrl"). - - -%% Suite Callbacks --compile(export_all). - -init(Id, Opts) -> - empty_scb:init(Id, Opts). - -pre_init_per_suite(Suite, Config, State) -> - empty_scb:pre_init_per_suite(Suite,Config,State), - {[{pre_init_per_suite,now()}|Config],State}. - -post_init_per_suite(Suite,Config,Return,State) -> - empty_scb:post_init_per_suite(Suite,Config,Return,State), - {[{post_init_per_suite,now()}|Return],State}. - -pre_end_per_suite(Suite,Config,State) -> - empty_scb:pre_end_per_suite(Suite,Config,State), - {[{pre_end_per_suite,now()}|Config],State}. - -post_end_per_suite(Suite,Config,Return,State) -> - empty_scb:post_end_per_suite(Suite,Config,Return,State), - NewConfig = [{post_end_per_suite,now()}|Config], - {NewConfig,NewConfig}. - -pre_init_per_group(Group,Config,State) -> - empty_scb:pre_init_per_group(Group,Config,State), - {[{pre_init_per_group,now()}|Config],State}. - -post_init_per_group(Group,Config,Return,State) -> - empty_scb:post_init_per_group(Group,Config,Return,State), - {[{post_init_per_group,now()}|Return],State}. - -pre_end_per_group(Group,Config,State) -> - empty_scb:pre_end_per_group(Group,Config,State), - {[{pre_end_per_group,now()}|Config],State}. - -post_end_per_group(Group,Config,Return,State) -> - empty_scb:post_end_per_group(Group,Config,Return,State), - {[{post_end_per_group,now()}|Config],State}. - -pre_init_per_testcase(TC,Config,State) -> - empty_scb:pre_init_per_testcase(TC,Config,State), - {[{pre_init_per_testcase,now()}|Config],State}. - -post_end_per_testcase(TC,Config,Return,State) -> - empty_scb:post_end_per_testcase(TC,Config,Return,State), - {[{post_end_per_testcase,now()}|Config],State}. - -on_tc_fail(TC, Reason, State) -> - empty_scb:on_tc_fail(TC,Reason,State). - -on_tc_skip(TC, Reason, State) -> - empty_scb:on_tc_skip(TC,Reason,State). - -terminate(State) -> - empty_scb:terminate(State). -- cgit v1.2.3 From 044f768b6545234461f173e8a959379630723e8f Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Wed, 9 Feb 2011 16:39:29 +0100 Subject: Rename Suite Callback to Common Test hook in documentation --- lib/common_test/doc/src/Makefile | 4 +- lib/common_test/doc/src/common_test_app.xml | 12 +- lib/common_test/doc/src/ct_hooks.xml | 556 +++++++++++++++++++++ lib/common_test/doc/src/ct_hooks_chapter.xml | 401 +++++++++++++++ lib/common_test/doc/src/ct_suite_callbacks.xml | 551 -------------------- lib/common_test/doc/src/part.xml | 2 +- lib/common_test/doc/src/ref_man.xml | 2 +- lib/common_test/doc/src/run_test_chapter.xml | 14 +- .../doc/src/suite_callbacks_chapter.xml | 394 --------------- 9 files changed, 974 insertions(+), 962 deletions(-) create mode 100644 lib/common_test/doc/src/ct_hooks.xml create mode 100644 lib/common_test/doc/src/ct_hooks_chapter.xml delete mode 100644 lib/common_test/doc/src/ct_suite_callbacks.xml delete mode 100644 lib/common_test/doc/src/suite_callbacks_chapter.xml (limited to 'lib/common_test') diff --git a/lib/common_test/doc/src/Makefile b/lib/common_test/doc/src/Makefile index a3f740852c..a914dd0c19 100644 --- a/lib/common_test/doc/src/Makefile +++ b/lib/common_test/doc/src/Makefile @@ -52,7 +52,7 @@ CT_XML_FILES = $(CT_MODULES:=.xml) XML_APPLICATION_FILES = ref_man.xml XML_REF1_FILES = ct_run.xml -XML_REF3_FILES = $(CT_XML_FILES) ct_suite_callbacks.xml +XML_REF3_FILES = $(CT_XML_FILES) ct_hooks.xml XML_REF6_FILES = common_test_app.xml XML_PART_FILES = part.xml @@ -71,7 +71,7 @@ XML_CHAPTER_FILES = \ cover_chapter.xml \ ct_master_chapter.xml \ event_handler_chapter.xml \ - suite_callbacks_chapter.xml \ + ct_hooks_chapter.xml \ dependencies_chapter.xml \ notes.xml \ notes_history.xml diff --git a/lib/common_test/doc/src/common_test_app.xml b/lib/common_test/doc/src/common_test_app.xml index a735dc85a8..b4e4b45d62 100644 --- a/lib/common_test/doc/src/common_test_app.xml +++ b/lib/common_test/doc/src/common_test_app.xml @@ -132,7 +132,7 @@ Info = {timetrap,Time} | {require,Required} | {require,Name,Required} | {userdata,UserData} | {silent_connections,Conns} | {stylesheet,CSSFile} | - {suite_callbacks, SCBs} + {ct_hooks, CTHs} Time = MilliSec | {seconds,integer()} | {minutes,integer()} | {hours,integer()} MilliSec = integer() @@ -144,9 +144,9 @@ UserData = term() Conns = [atom()] CSSFile = string() - SCBs = [SCBModule | {SCBModule, SCBInitArgs}] - SCBModule = atom() - SCBInitArgs = term() + CTHs = [CTHModule | {CTHModule, CTHInitArgs}] + CTHModule = atom() + CTHInitArgs = term() @@ -175,8 +175,8 @@ specify arbitrary test suite related information which can be read by calling ct:userdata/2.

-

The suite_callbacks tag specifies which - Suite Callbacks +

The ct_hooks tag specifies which + Common Test Hooks are to be run together with this suite.

Other tuples than the ones defined will simply be ignored.

diff --git a/lib/common_test/doc/src/ct_hooks.xml b/lib/common_test/doc/src/ct_hooks.xml new file mode 100644 index 0000000000..0d59ce3b22 --- /dev/null +++ b/lib/common_test/doc/src/ct_hooks.xml @@ -0,0 +1,556 @@ + + + + + +
+ + 20102010 + Ericsson AB. 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. + + + + Common Test Hooks + Lukas Larsson + Lukas Larsson + + + + 2010-12-02 + PA1 + ct_hooks.sgml +
+ ct_hooks + A callback interface on top of Common Test + + + +

This feature is in alpha release right now. This means that the + interface may change in the future and that there may be bugs. We + encourage you to use this feature, but be prepared + that there might be bugs and that the interface might change + inbetween releases.

+ +

The Common Test Hook (henceforth called CTH) framework allows + extensions of the default behaviour of Common Test by means of callbacks + before and after all test suite calls. It is meant for advanced users of + Common Test which want to abstract out behaviour which is common to + multiple test suites.

+ +

In brief, Common Test Hooks allows you to:

+ + + Manipulate the runtime config before each suite + configuration call + Manipulate the return of all suite configuration calls and in + extension the result of the test themselves. + + +

The following sections describe the mandatory and optional CTH + functions Common Test will call during test execution. For more details + see Common Test Hooks in + the User's Guide.

+ +

For information about how to add a CTH to your suite see + Installing a CTH + in the User's Guide.

+ +

See the + Example CTH + in the User's Guide for a minimal example of a CTH.

+ +
+ +
+ CALLBACK FUNCTIONS +

The following functions define the callback interface + for a Common Test Hook.

+
+ + + + Module:init(Id, Opts) -> State + Initiates the Common Test Hook + + Id = reference() | term() + Opts = term() + State = term() + + + +

MANDATORY

+ +

Always called before any other callback function. + Use this to initiate any common state. + It should return a state for this CTH.

+ +

Id is the return value of + id/1, or a reference + (created using + make_ref/0) + if id/1 is not implemented. +

+ +

For details about when init is called see + scope + in the User's Guide.

+ +
+
+ + + Module:pre_init_per_suite(SuiteName, Config, CTHState) -> + Result + Called before init_per_suite + + SuiteName = atom() + Config = NewConfig = [{Key,Value}] + CTHState = NewCTHState = term() + Result = {Return, NewCTHState} + Return = NewConfig | SkipOrFail + SkipOrFail = {fail, Reason} | {skip, Reason} + Key = atom() + Value = term() + Reason = term() + + + +

OPTIONAL

+ +

This function is called before + + init_per_suite if it exists. + It typically contains initialization/logging which needs to be done + before init_per_suite is called. + If {skip,Reason} or {fail,Reason} is returned, + init_per_suite and all test cases of the suite will be skipped and + Reason printed in the overview log of the suite.

+ +

SuiteName is the name of the suite to be run.

+ +

Config is the original config list of the test suite.

+ +

CTHState is the current internal state of the CTH.

+ +

Return is the result of the init_per_suite function. + If it is {skip,Reason} or {fail,Reason} + init_per_suite + will never be called, instead the initiation is considered + to be skipped/failed respectively. If a NewConfig list + is returned, + init_per_suite will be called with that NewConfig list. + See + Pre Hooks in the User's Guide for more details.

+ + +

Note that this function is only called if the CTH has been added + before init_per_suite is run, see + CTH Scoping + in the User's Guide for details.

+
+
+ + + Module:post_init_per_suite(SuiteName, Config, Return, CTHState) -> + Result + Called after init_per_suite + + SuiteName = atom() + Config = [{Key,Value}] + Return = NewReturn = Config | SkipOrFail | term() + SkipOrFail = {fail, Reason} | {skip, Reason} | term() + CTHState = NewCTHState = term() + Result = {NewReturn, NewCTHState} + Key = atom() + Value = term() + Reason = term() + + + +

OPTIONAL

+ +

This function is called after + + init_per_suite if it exists. It typically contains extra + checks to make sure that all the correct dependencies have + been started correctly.

+ +

Return is what + init_per_suite + returned, i.e. {fail,Reason}, {skip,Reason}, a Config + list or a term describing how + init_per_suite + failed.

+ +

NewReturn is the possibly modified return value of + init_per_suite + . It is here possible to recover from a failure in + init_per_suite + by returning the ConfigList with the tc_status + element removed. See + Post Hooks in the User's Guide for more details.

+ +

CTHState is the current internal state of the CTH.

+ +

Note that this function is only called if the CTH has been added + before or in init_per_suite, see + CTH Scoping + in the User's Guide for details.

+
+
+ + + Module:pre_init_per_group(GroupName, Config, CTHState) -> + Result + Called before init_per_group + + GroupName = atom() + Config = NewConfig = [{Key,Value}] + CTHState = NewCTHState = term() + Result = {NewConfig | SkipOrFail, NewCTHState} + SkipOrFail = {fail,Reason} | {skip, Reason} + Key = atom() + Value = term() + Reason = term() + + + +

OPTIONAL

+ +

This function is called before + + init_per_group if it exists. It behaves the same way as + + pre_init_per_suite, but for the + + init_per_group instead.

+
+
+ + + Module:post_init_per_group(GroupName, Config, Return, CTHState) -> + Result + Called after init_per_group + + GroupName = atom() + Config = [{Key,Value}] + Return = NewReturn = Config | SkipOrFail | term() + SkipOrFail = {fail,Reason} | {skip, Reason} + CTHState = NewCTHState = term() + Result = {NewReturn, NewCTHState} + Key = atom() + Value = term() + Reason = term() + + + +

OPTIONAL

+ +

This function is called after + + init_per_group if it exists. It behaves the same way as + + post_init_per_suite, but for the + + init_per_group instead.

+
+
+ + + Module:pre_init_per_testcase(TestcaseName, Config, CTHState) -> + Result + Called before init_per_testcase + + TestcaseName = atom() + Config = NewConfig = [{Key,Value}] + CTHState = NewCTHState = term() + Result = {NewConfig | SkipOrFail, NewCTHState} + SkipOrFail = {fail,Reason} | {skip, Reason} + Key = atom() + Value = term() + Reason = term() + + + +

OPTIONAL

+ +

This function is called before + + init_per_testcase if it exists. It behaves the same way as + + pre_init_per_suite, but for the + + init_per_testcase function instead.

+ +

Note that it is not possible to add CTH's here right now, + that feature might be added later, + but it would right now break backwards compatability.

+
+
+ + + Module:post_end_per_testcase(TestcaseName, Config, Return, CTHState) + -> Result + Called after end_per_testcase + + TestcaseName = atom() + Config = [{Key,Value}] + Return = NewReturn = Config | SkipOrFail | term() + SkipOrFail = {fail,Reason} | {skip, Reason} + CTHState = NewCTHState = term() + Result = {NewReturn, NewCTHState} + Key = atom() + Value = term() + Reason = term() + + + +

OPTIONAL

+ +

This function is called after + + end_per_testcase if it exists. It behaves the same way as + + post_init_per_suite, but for the + + end_per_testcase function instead.

+
+
+ + + Module:pre_end_per_group(GroupName, Config, CTHState) -> + Result + Called before end_per_group + + GroupName = atom() + Config = NewConfig = [{Key,Value}] + CTHState = NewCTHState = term() + Result = {NewConfig | SkipOrFail, NewCTHState} + SkipOrFail = {fail,Reason} | {skip, Reason} + Key = atom() + Value = term() + Reason = term() + + + +

OPTIONAL

+ +

This function is called before + + end_per_group if it exists. It behaves the same way as + + pre_init_per_suite, but for the + + end_per_group function instead.

+
+
+ + + Module:post_end_per_group(GroupName, Config, Return, CTHState) -> + Result + Called after end_per_group + + GroupName = atom() + Config = [{Key,Value}] + Return = NewReturn = Config | SkipOrFail | term() + SkipOrFail = {fail,Reason} | {skip, Reason} + CTHState = NewCTHState = term() + Result = {NewReturn, NewCTHState} + Key = atom() + Value = term() + Reason = term() + + + +

OPTIONAL

+ +

This function is called after + + end_per_group if it exists. It behaves the same way as + + post_init_per_suite, but for the + + end_per_group function instead.

+
+
+ + + Module:pre_end_per_suite(SuiteName, Config, CTHState) -> + Result + Called before end_per_suite + + SuiteName = atom() + Config = NewConfig = [{Key,Value}] + CTHState = NewCTHState = term() + Result = {NewConfig | SkipOrFail, NewCTHState} + SkipOrFail = {fail,Reason} | {skip, Reason} + Key = atom() + Value = term() + Reason = term() + + + +

OPTIONAL

+ +

This function is called before + + end_per_suite if it exists. It behaves the same way as + + pre_init_per_suite, but for the + + end_per_suite function instead.

+
+
+ + + Module:post_end_per_suite(SuiteName, Config, Return, CTHState) -> + Result + Called after end_per_suite + + SuiteName = atom() + Config = [{Key,Value}] + Return = NewReturn = Config | SkipOrFail | term() + SkipOrFail = {fail,Reason} | {skip, Reason} + CTHState = NewCTHState = term() + Result = {NewReturn, NewCTHState} + Key = atom() + Value = term() + Reason = term() + + + +

OPTIONAL

+ +

This function is called after + + end_per_suite if it exists. It behaves the same way as + + post_init_per_suite, but for the + + end_per_suite function instead.

+
+
+ + + Module:on_tc_fail(TestcaseName, Reason, CTHState) -> + NewCTHState + Called after the CTH scope ends + + TestcaseName = init_per_suite | end_per_suite | + init_per_group | end_per_group | atom() + Reason = term() + CTHState = NewCTHState = term() + + + +

OPTIONAL

+ +

This function is called whenever a testcase fails. + It is called after the post function has been called for + the testcase which failed. i.e. + if init_per_suite fails this function is called after + + post_init_per_suite, and if a testcase fails it is called + after + post_end_per_testcase.

+ +

The data which comes with the Reason follows the same format as the + FailReason + in the tc_done event. + See Event Handling + in the User's Guide for details.

+
+
+ + + Module:on_tc_skip(TestcaseName, Reason, CTHState) -> + NewCTHState + Called after the CTH scope ends + + TestcaseName = end_per_suite | init_per_group | + end_per_group | atom() + Reason = {tc_auto_skip | tc_user_skip, term()} + CTHState = NewCTHState = term() + + + +

OPTIONAL

+ +

This function is called whenever a testcase is skipped. + It is called after the post function has been called for the + testcase which was skipped. + i.e. if init_per_group is skipped this function is called after + post_init_per_group + , and if a testcase is skipped it is called after + post_end_per_testcase + .

+ +

The data which comes with the Reason follows the same format as + tc_auto_skip + and + tc_user_skip events. + See Event Handling + in the User's Guide for details.

+
+
+ + + Module:terminate(CTHState) + Called after the CTH scope ends + + CTHState = term() + + + +

OPTIONAL

+ +

This function is called at the end of a CTH's + scope. +

+
+
+ + + Module:id(Opts) -> Id + Called before the init function of a CTH + + Opts = term() + Id = term() + + + +

OPTIONAL

+ +

The Id is used to uniquely identify a CTH instance, + if two CTH's return the same Id the second CTH is ignored + and subsequent calls to the CTH will only be made to the first + instance. For more information see + Installing a CTH + in the User's Guide. +

+ +

This function should NOT have any side effects as it might + be called multiple times by Common Test.

+ +

If not implemented the CTH will act as if this function returned a + call to make_ref/0.

+
+
+ +
+ +
+ + diff --git a/lib/common_test/doc/src/ct_hooks_chapter.xml b/lib/common_test/doc/src/ct_hooks_chapter.xml new file mode 100644 index 0000000000..fc5ab48e1b --- /dev/null +++ b/lib/common_test/doc/src/ct_hooks_chapter.xml @@ -0,0 +1,401 @@ + + + + +
+ + 20112011 + Ericsson AB. 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. + + + + Common Test Hooks + Lukas Larsson + + + + ct_hooks_chapter.xml +
+ + +
+ General +

This feature is in alpha release right now. This means that the + interface may change in the future and that there may be bugs. We + encourage you to use this feature, but be prepared + that there might be bugs and that the interface might change + inbetween releases.

+

+ The Common Test Hook (henceforth called CTH) framework allows + extensions of the default behaviour of Common Test by means of hooks + before and after all test suite calls. CTHs allow advanced Common Test + users to abstract out behaviour which is common to multiple test suites + without littering all test suites with library calls. Some example + usages are: logging, starting and monitoring external systems, + building C files needed by the tests and much more!

+ +

In brief, Common Test Hooks allows you to:

+ + + Manipulate the runtime config before each suite + configuration call + Manipulate the return of all suite configuration calls and in + extension the result of the test themselves. + + +

The following sections describe how to use CTHs, when they are run + and how to manipulate your test results in a CTH

+ +

When executing within a CTH all timetraps are shutoff. So + if your CTH never returns, the entire test run will be stalled!

+
+ +
+ + +
+ Installing a CTH +

There are multiple ways to install a CTH in your test run. You can do it + for all tests in a run, for specific test suites and for specific groups + within a test suite. If you want a CTH to be present in all test suites + within your test run there are three different ways to accomplish that. +

+ + + Add -ct_hooks as an argument to + ct_run. + To add multiple CTHs using this method append them to each other + using the keyword and, i.e. + ct_run -ct_hooks cth1 [{debug,true}] and cth2 .... + Add the ct_hooks tag to your + + Test Specification + Add the ct_hooks tag to your call to + ct:run_test/1 + + +

You can also add CTHs within a test suite. This is done by returning + {ct_hooks,[CTH]} in the config list from + suite/0, + + init_per_suite/1 or + + init_per_group/2. CTH in this case can be either + only the module name of the CTH or a tuple with the module name and the + initial arguments to the CTH. Eg: + {ct_hooks,[my_cth_module]} or + {ct_hooks,[{my_cth_module,[{debug,true}]}]}

+ +
+ Overriding CTHs +

By default each installation of a CTH will cause a new instance of it + to be activated. This can cause problems if you want to be able to + override CTHs in test specifications while still having them in the + suite info function. The + id/1 + callback exists to address this problem. By returning the same + id in both places, Common Test knows that this CTH + has already been installed and will not try to install it again.

+
+ +
+ + +
+ CTH Scope +

Once the CTH is installed into a certain test run it will be there until + its scope is expired. The scope of a CTH depends on when it is + installed. + The init/2 is + called at the beginning of the scope and the + terminate/1 + function is called when the scope ends.

+ + + CTH Installed in + CTH scope begins before + CTH scope ends after + + + ct_run + the first test suite is to be run. + the last test suite has been run. + + + ct:run_test + the first test suite is to be run. + the last test suite has been run. + + + + Test Specification + the first test suite is to be run. + the last test suite has been run. + + + suite/0 + + + pre_init_per_suite/3 is called. + + post_end_per_suite/4 has been called for that test suite. + + + + init_per_suite/1 + + post_init_per_suite/4 is called. + + post_end_per_suite/4 has been called for that test suite. + + + + init_per_group/2 + + post_init_per_group/4 is called. + + post_end_per_group/4 has been called for that group. + + Scope of a CTH +
+ +
+ CTH Processes and Tables +

CTHs are run with the same process scoping as normal test suites + i.e. a different process will execute the init_per_suite hooks then the + init_per_group or per_testcase hooks. So if you want to spawn a + process in the CTH you cannot link with the CTH process as it will exit + after the post hook ends. Also if you for some reason need an ETS + table with your CTH, you will have to spawn a process which handles + it.

+
+ +
+ + +
+ Manipulating tests +

It is through CTHs possible to manipulate the results of tests and + configuration functions. The main purpose of doing this with CTHs is to + allow common patterns to be abstracted out from test test suites and applied to + multiple test suites without duplicating any code. All of the callback + functions for a CTH follow a common interface, this interface is + described below.

+ +

It is only possible to hook into test function which exists in the test + suite. So in order for a CTH to hook in before + init_per_suite, + the init_per_suite + function must exist in the test suite.

+ + +
+ Pre Hooks +

+ It is possible in a CTH to hook in behaviour before + init_per_suite, + init_per_group, + init_per_testcase, + end_per_group and + end_per_suite. + This is done in the CTH functions called pre_<name of function>. + All of these functions take the same three arguments: Name, + Config and CTHState. The return value of the CTH function + is always a combination of an result for the suite/group/test and an + updated CTHState. If you want the test suite to continue on + executing you should return the config list which you want the test to + use as the result. If you for some reason want to skip/fail the test, + return a tuple with skip or fail and a reason as the + result. Example: +

+ pre_init_per_suite(SuiteName, Config, CTHState) -> + case db:connect() of + {error,_Reason} -> + {{fail, "Could not connect to DB"}, CTHState}; + {ok, Handle} -> + {[{db_handle, Handle} | Config], CTHState#state{ handle = Handle }} + end. + +
+ + +
+ Post Hooks +

It is also possible in a CTH to hook in behaviour after + init_per_suite, + init_per_group, + end_per_testcase, + end_per_group and + end_per_suite. + This is done in the CTH functions called post_<name of function>. + All of these function take the same four arguments: Name, + Config, Return and CTHState. Config in this + case is the same Config as the testcase is called with. + Return is the value returned by the testcase. If the testcase + failed by crashing, Return will be + {'EXIT',{{Error,Reason},Stacktrace}}.

+ +

The return value of the CTH function is always a combination of an + result for the suite/group/test and an updated CTHState. If + you want the callback to not affect the outcome of the test you should + return the Return data as it is given to the CTH. You can also + modify the result of the test. By returning the Config list + with the tc_status element removed you can recover from a test + failure. As in all the pre hooks, it is also possible to fail/skip + the test case in the post hook. Example:

+ + post_end_per_testcase(_TC, Config, {'EXIT',{_,_}}, CTHState) -> + case db:check_consistency() of + true -> + %% DB is good, pass the test. + {proplists:delete(tc_status, Config), CTHState}; + false -> + %% DB is not good, mark as skipped instead of failing + {{skip, "DB is inconsisten!"}, CTHState} + end; +post_end_per_testcase(_TC, Config, Return, CTHState) -> + %% Do nothing if tc does not crash. + {Return, CTHState}. + + Recovering from a testcase failure using CTHs should only be done as + a last resort. If used wrongly it could become very difficult to + determine which tests pass or fail in a test run + +
+ + +
+ Skip and Fail hooks +

+ After any post hook has been executed for all installed CTHs, + on_tc_fail + or on_tc_skip + might be called if the testcase failed or was skipped + respectively. You cannot affect the outcome of the tests any further at + this point. +

+
+ +
+ + +
+ Example CTH +

The CTH below will log information about a test run into a format + parseable by file:consult/1. +

+ %%% @doc Common Test Example Common Test Hook module. +-module(example_cth). + +%% Callbacks +-export([id/1]). +-export([init/2]). + +-export([pre_init_per_suite/3]). +-export([post_init_per_suite/4]). +-export([pre_end_per_suite/3]). +-export([post_end_per_suite/4]). + +-export([pre_init_per_group/3]). +-export([post_init_per_group/4]). +-export([pre_end_per_group/3]). +-export([post_end_per_group/4]). + +-export([pre_init_per_testcase/3]). +-export([post_end_per_testcase/4]). + +-export([on_tc_fail/3]). +-export([on_tc_skip/3]). + +-export([terminate/1]). + +-record(state, { file_handle, total, suite_total, ts, tcs, data }). + +%% @doc Return a unique id for this CTH. +id(Opts) -> + proplists:get_value(filename, Opts, "/tmp/file.log"). + +%% @doc Always called before any other callback function. Use this to initiate +%% any common state. +init(Id, Opts) -> + {ok,D} = file:open(Id,[write]), + #state{ file_handle = D, total = 0, data = [] }. + +%% @doc Called before init_per_suite is called. +pre_init_per_suite(Suite,Config,State) -> + {Config, State#state{ suite_total = 0, tcs = [] }}. + +%% @doc Called after init_per_suite. +post_init_per_suite(Suite,Config,Return,State) -> + {Return, State}. + +%% @doc Called before end_per_suite. +pre_end_per_suite(Suite,Config,State) -> + {Config, State}. + +%% @doc Called after end_per_suite. +post_end_per_suite(Suite,Config,Return,State) -> + Data = {suites, Suite, State#state.suite_total, lists:reverse(State#state.tcs)}, + {Return, State#state{ data = [Data | State#state.data] , + total = State#state.total + State#state.suite_total } }. + +%% @doc Called before each init_per_group. +pre_init_per_group(Group,Config,State) -> + {Config, State}. + +%% @doc Called after each init_per_group. +post_init_per_group(Group,Config,Return,State) -> + {Return, State}. + +%% @doc Called after each end_per_group. +pre_end_per_group(Group,Config,State) -> + {Config, State}. + +%% @doc Called after each end_per_group. +post_end_per_group(Group,Config,Return,State) -> + {Return, State}. + +%% @doc Called before each test case. +pre_init_per_testcase(TC,Config,State) -> + {Config, State#state{ ts = now(), total = State#state.suite_total + 1 } }. + +%% @doc Called after each test case. +post_end_per_testcase(TC,Config,Return,State) -> + TCInfo = {testcase, TC, Return, timer:now_diff(now(), State#state.ts)}, + {Return, State#state{ ts = undefined, tcs = [TCInfo | State#state.tcs] } }. + +%% @doc Called after post_init_per_suite, post_end_per_suite, post_init_per_group, +%% post_end_per_group and post_end_per_testcase if the suite, group or test case failed. +on_tc_fail(TC, Reason, State) -> + State. + +%% @doc Called when a test case is skipped by either user action +%% or due to an init function failing. +on_tc_skip(TC, Reason, State) -> + State. + +%% @doc Called when the scope of the CTH is done +terminate(State) -> + io:format(State#state.file_handle, "~p.~n", + [{test_run, State#state.total, State#state.data}]), + file:close(State#state.file_handle), + ok. +
+ +
+ + + + diff --git a/lib/common_test/doc/src/ct_suite_callbacks.xml b/lib/common_test/doc/src/ct_suite_callbacks.xml deleted file mode 100644 index cea5804825..0000000000 --- a/lib/common_test/doc/src/ct_suite_callbacks.xml +++ /dev/null @@ -1,551 +0,0 @@ - - - - - -
- - 20102010 - Ericsson AB. 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. - - - - Suite Callbacks - Lukas Larsson - Lukas Larsson - - - - 2010-12-02 - PA1 - suite_callback.sgml -
- ct_suite_callback - A callback interface on top of Common Test - - - -

This feature is in alpha release right now. This means that the - interface may change in the future and that there may be bugs. We - encourage you to use this feature, but be prepared - that there might be bugs and that the interface might change - inbetween releases.

- -

The Suite Callback (henceforth called SCB) framework allows - extensions of the default behaviour of Common Test by means of callbacks - before and after all test suite calls. It is meant for advanced users of - Common Test which want to abstract out behaviour which is common to - multiple test suites.

- -

In brief, Suite Callbacks allows you to:

- - - Manipulate the runtime config before each suite - configuration calls - Manipulate the return of all suite configuration calls and in - extension the result of the test themselves. - - -

The following sections describe the mandatory and optional SCB - functions Common Test will call during test execution. For more details - see Suite Callbacks in - the User's Guide.

- -

For information about how to add a SCB to your suite see - Installing an SCB - in the User's Guide.

- -

See the - Example SCB - in the User's Guide for a minimal example of an SCB.

- -
- -
- CALLBACK FUNCTIONS -

The following functions define the callback interface - for a suite callback.

-
- - - - Module:init(Id, Opts) -> State - Initiates the Suite Callback - - Id = reference() | term() - Opts = term() - State = term() - - - -

MANDATORY

- -

Always called before any other callback function. - Use this to initiate any common state. - It should return a state for this SCB.

- -

Id is the return value of - id/1, or a reference - if id/1 is not implemented. -

- -

For details about when init is called see - scope - in the User's Guide.

- -
-
- - - Module:pre_init_per_suite(SuiteName, Config, SCBState) -> - Result - Called before init_per_suite - - SuiteName = atom() - Config = NewConfig = [{Key,Value}] - SCBState = NewSCBState = term() - Result = {Return, NewSCBState} - Return = NewConfig | SkipOrFail - SkipOrFail = {fail, Reason} | {skip, Reason} - Key = atom() - Value = term() - Reason = term() - - - -

OPTIONAL

- -

This function is called before - - init_per_suite if it exists. - It typically contains initialization/logging which needs to be done - before init_per_suite is called. - If {skip,Reason} or {fail,Reason} is returned, - init_per_suite and all test cases of the suite will be skipped and - Reason printed in the overview log of the suite.

- -

SuiteName is the name of the suite to be run.

- -

Config is the original config list of the test suite.

- -

SCBState is the current internal state of the SCB.

- -

Return is the result of the init_per_suite function. - If it is {skip,Reason} or {fail,Reason} - init_per_suite - will never be called, instead the initiation is considered - to be skipped/failed respectively. If a NewConfig list - is returned, - init_per_suite will be called with that NewConfig list. - See - Manipulating tests in the User's Guide for more details.

- - -

Note that this function is only called if the SCB has been added - before init_per_suite is run, see - SCB Scoping - in the User's Guide for details.

-
-
- - - Module:post_init_per_suite(SuiteName, Config, Return, SCBState) -> - Result - Called after init_per_suite - - SuiteName = atom() - Config = [{Key,Value}] - Return = NewReturn = Config | SkipOrFail | term() - SkipOrFail = {fail, Reason} | {skip, Reason} | term() - SCBState = NewSCBState = term() - Result = {NewReturn, NewSCBState} - Key = atom() - Value = term() - Reason = term() - - - -

OPTIONAL

- -

Return is what - init_per_suite - returned, i.e. {fail,Reason}, {skip,Reason}, a Config - list or a term describing how - init_per_suite - failed.

- -

NewReturn is the possibly modified return value of - init_per_suite - . It is here possible to recover from a failure in - init_per_suite - by returning the ConfigList with the tc_status - element removed.

- -

SCBState is the current internal state of the SCB.

- -

This function is called after - - init_per_suite if it exists.

- -

Note that this function is only called if the SCB has been added - before or in init_per_suite, see - SCB Scoping - in the User's Guide for details.

-
-
- - - Module:pre_init_per_group(GroupName, Config, SCBState) -> - Result - Called before init_per_group - - GroupName = atom() - Config = NewConfig = [{Key,Value}] - SCBState = NewSCBState = term() - Result = {NewConfig | SkipOrFail, NewSCBState} - SkipOrFail = {fail,Reason} | {skip, Reason} - Key = atom() - Value = term() - Reason = term() - - - -

OPTIONAL

- -

This function is called before - - init_per_group if it exists. It behaves the same way as - - pre_init_per_suite, but for the - - init_per_group instead.

-
-
- - - Module:post_init_per_group(GroupName, Config, Return, SCBState) -> - Result - Called after init_per_group - - GroupName = atom() - Config = [{Key,Value}] - Return = NewReturn = Config | SkipOrFail | term() - SkipOrFail = {fail,Reason} | {skip, Reason} - SCBState = NewSCBState = term() - Result = {NewReturn, NewSCBState} - Key = atom() - Value = term() - Reason = term() - - - -

OPTIONAL

- -

This function is called after - - init_per_group if it exists. It behaves the same way as - - post_init_per_suite, but for the - - init_per_group instead.

-
-
- - - Module:pre_init_per_testcase(TestcaseName, Config, SCBState) -> - Result - Called before init_per_testcase - - TestcaseName = atom() - Config = NewConfig = [{Key,Value}] - SCBState = NewSCBState = term() - Result = {NewConfig | SkipOrFail, NewSCBState} - SkipOrFail = {fail,Reason} | {skip, Reason} - Key = atom() - Value = term() - Reason = term() - - - -

OPTIONAL

- -

This function is called before - - init_per_testcase if it exists. It behaves the same way as - - pre_init_per_suite, but for the - - init_per_testcase function instead.

- -

Note that it is not possible to add SCB's here right now, - that feature might be added later, - but it would right now break backwards compatability.

-
-
- - - Module:post_end_per_testcase(TestcaseName, Config, Return, SCBState) - -> Result - Called after end_per_testcase - - TestcaseName = atom() - Config = [{Key,Value}] - Return = NewReturn = Config | SkipOrFail | term() - SkipOrFail = {fail,Reason} | {skip, Reason} - SCBState = NewSCBState = term() - Result = {NewReturn, NewSCBState} - Key = atom() - Value = term() - Reason = term() - - - -

OPTIONAL

- -

This function is called after - - end_per_testcase if it exists. It behaves the same way as - - post_init_per_suite, but for the - - end_per_testcase function instead.

-
-
- - - Module:pre_end_per_group(GroupName, Config, SCBState) -> - Result - Called before end_per_group - - GroupName = atom() - Config = NewConfig = [{Key,Value}] - SCBState = NewSCBState = term() - Result = {NewConfig | SkipOrFail, NewSCBState} - SkipOrFail = {fail,Reason} | {skip, Reason} - Key = atom() - Value = term() - Reason = term() - - - -

OPTIONAL

- -

This function is called before - - end_per_group if it exists. It behaves the same way as - - pre_init_per_suite, but for the - - end_per_group function instead.

-
-
- - - Module:post_end_per_group(GroupName, Config, Return, SCBState) -> - Result - Called after end_per_group - - GroupName = atom() - Config = [{Key,Value}] - Return = NewReturn = Config | SkipOrFail | term() - SkipOrFail = {fail,Reason} | {skip, Reason} - SCBState = NewSCBState = term() - Result = {NewReturn, NewSCBState} - Key = atom() - Value = term() - Reason = term() - - - -

OPTIONAL

- -

This function is called after - - end_per_group if it exists. It behaves the same way as - - post_init_per_suite, but for the - - end_per_group function instead.

-
-
- - - Module:pre_end_per_suite(SuiteName, Config, SCBState) -> - Result - Called before end_per_suite - - SuiteName = atom() - Config = NewConfig = [{Key,Value}] - SCBState = NewSCBState = term() - Result = {NewConfig | SkipOrFail, NewSCBState} - SkipOrFail = {fail,Reason} | {skip, Reason} - Key = atom() - Value = term() - Reason = term() - - - -

OPTIONAL

- -

This function is called before - - end_per_suite if it exists. It behaves the same way as - - pre_init_per_suite, but for the - - end_per_suite function instead.

-
-
- - - Module:post_end_per_suite(SuiteName, Config, Return, SCBState) -> - Result - Called after end_per_suite - - SuiteName = atom() - Config = [{Key,Value}] - Return = NewReturn = Config | SkipOrFail | term() - SkipOrFail = {fail,Reason} | {skip, Reason} - SCBState = NewSCBState = term() - Result = {NewReturn, NewSCBState} - Key = atom() - Value = term() - Reason = term() - - - -

OPTIONAL

- -

This function is called after - - end_per_suite if it exists. It behaves the same way as - - post_init_per_suite, but for the - - end_per_suite function instead.

-
-
- - - Module:on_tc_fail(TestcaseName, Reason, SCBState) -> - NewSCBState - Called after the SCB scope ends - - TestcaseName = init_per_suite | end_per_suite | - init_per_group | end_per_group | atom() - Reason = term() - SCBState = NewSCBState = term() - - - -

OPTIONAL

- -

This function is called whenever a testcase fails. - It is called after the post function has been called for - the testcase which failed. i.e. - if init_per_suite fails this function is called after - - post_init_per_suite, and if a testcase fails it is called - after - post_end_per_testcase.

- -

The data which comes with the Reason follows the same format as the - FailReason - in the tc_done event. - See Event Handling - in the User's Guide for details.

-
-
- - - Module:on_tc_skip(TestcaseName, Reason, SCBState) -> - NewSCBState - Called after the SCB scope ends - - TestcaseName = end_per_suite | init_per_group | - end_per_group | atom() - Reason = {tc_auto_skip | tc_user_skip, term()} - SCBState = NewSCBState = term() - - - -

OPTIONAL

- -

This function is called whenever a testcase is skipped. - It is called after the post function has been called for the - testcase which was skipped. - i.e. if init_per_group is skipped this function is called after - post_init_per_group - , and if a testcase is skipped it is called after - post_end_per_testcase - .

- -

The data which comes with the Reason follows the same format as - tc_auto_skip - and - tc_user_skip events. - See Event Handling - in the User's Guide for details.

-
-
- - - Module:terminate(SCBState) - Called after the SCB scope ends - - SCBState = term() - - - -

OPTIONAL

- -

This function is called at the end of an SCB's - scope. -

-
-
- - - Module:id(Opts) -> Id - Called before the init function of an SCB - - Opts = term() - Id = term() - - - -

OPTIONAL

- -

The Id is used to uniquely identify an SCB instance, - if two SCB's return the same Id the second SCB is ignored - and subsequent calls to the SCB will only be made to the first - instance. For more information see - Installing an SCB - in the User's Guide. -

- -

This function should NOT have any side effects as it might - be called multiple times by Common Test.

- -

If not implemented the SCB will act as if this function returned a - call to make_ref/0.

-
-
- -
- -
- - diff --git a/lib/common_test/doc/src/part.xml b/lib/common_test/doc/src/part.xml index 1a09ec1da2..41371b60be 100644 --- a/lib/common_test/doc/src/part.xml +++ b/lib/common_test/doc/src/part.xml @@ -75,7 +75,7 @@ - + diff --git a/lib/common_test/doc/src/ref_man.xml b/lib/common_test/doc/src/ref_man.xml index 100c0fe5d7..631e3871c2 100644 --- a/lib/common_test/doc/src/ref_man.xml +++ b/lib/common_test/doc/src/ref_man.xml @@ -76,7 +76,7 @@ - + diff --git a/lib/common_test/doc/src/run_test_chapter.xml b/lib/common_test/doc/src/run_test_chapter.xml index 81e752680b..7b485bdc35 100644 --- a/lib/common_test/doc/src/run_test_chapter.xml +++ b/lib/common_test/doc/src/run_test_chapter.xml @@ -148,8 +148,8 @@ event handlers. ]]>, to install event handlers including start arguments. - ]]>, to install - Suite Callbacks including start arguments. + ]]>, to install + Common Test Hooks including start arguments. , specifies include directories (see above). , disables the automatic test suite compilation feature (see above). ]]>, extends timetrap @@ -444,8 +444,8 @@ {event_handler, EventHandlers, InitArgs}. {event_handler, NodeRefs, EventHandlers, InitArgs}. - {suite_callbacks, SCBModules}. - {suite_callbacks, NodeRefs, SCBModules}. + {ct_hooks, CTHModules}. + {ct_hooks, NodeRefs, CTHModules}.

Test terms:

@@ -484,9 +484,9 @@
       LogDir        = string()
       EventHandlers = atom() | [atom()]
       InitArgs      = [term()]
-      SCBModules    = [SCBModule | {SCBModule, SCBInitArgs}]
-      SCBModule     = atom()
-      SCBInitArgs   = term()
+      CTHModules    = [CTHModule | {CTHModule, CTHInitArgs}]
+      CTHModule     = atom()
+      CTHInitArgs   = term()
       DirRef        = DirAlias | Dir
       Suites        = atom() | [atom()] | all
       Suite         = atom()
diff --git a/lib/common_test/doc/src/suite_callbacks_chapter.xml b/lib/common_test/doc/src/suite_callbacks_chapter.xml
deleted file mode 100644
index 89f78898d4..0000000000
--- a/lib/common_test/doc/src/suite_callbacks_chapter.xml
+++ /dev/null
@@ -1,394 +0,0 @@
-
-
-
-
-  
- - 20112011 - Ericsson AB. 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. - - - - Suite Callbacks - Lukas Larsson - - - - suite_callbacks_chapter.xml -
- - -
- General -

This feature is in alpha release right now. This means that the - interface may change in the future and that there may be bugs. We - encourage you to use this feature, but be prepared - that there might be bugs and that the interface might change - inbetween releases.

-

- The Suite Callback (henceforth called SCB) framework allows - extensions of the default behaviour of Common Test by means of callbacks - before and after all test suite calls. SCBs allow advanced Common Test - users to abstract out behaviour which is common to multiple test suites - without littering all test suites with library calls. Some example - usages are: logging, starting and monitoring external systems, - building C files needed by the tests and much more!

- -

In brief, Suite Callbacks allows you to:

- - - Manipulate the runtime config before each suite - configuration calls - Manipulate the return of all suite configuration calls and in - extension the result of the test themselves. - - -

The following sections describe how to use SCBs, when they are run - and how to manipulate your test results in an SCB

- -

When executing within an SCB all timetraps are shutoff. So - if your SCB never returns, the entire test run will be stalled!

-
- -
- - -
- Installing an SCB -

There are multiple ways to install an SCB in your test run. You can do it - for all tests in a run, for specific test suites and for specific groups - within a test suite. If you want an SCB to be present in all test suites - within your testrun there are three different ways to accomplish that.

- - - Add -suite_callbacks as an argument to - ct_run. - To add multiple SCBs using this method append them to each other - using the keyword and, i.e. - ct_run -suite_callbacks scb1 [{debug,true}] and scb2 .... - Add the suite_callbacks tag to your - - Test Specification - Add the suite_callbacks tag to your call to - ct:run_test/1 - - -

You can also add SCBs within a test suite. This is done by returning - {suite_callbacks,[SCB]} in the config list from - suite/0, - - init_per_suite/1 or - - init_per_group/2. SCB in this case can be either - only the module name of the SCB or a tuple with the module name and the - initial arguments to the SCB. Eg: - {suite_callbacks,[my_scb_module]} or - {suite_callbacks,[{my_scb_module,[{debug,true}]}]}

- -
- Overriding SCBs -

By default each installation of an SCB will cause a new instance of it - to be activated. This can cause problems if you want to be able to - override SCBs in testspecifications while still having them in the - suite info function. The - id/1 - callback exists to address this problem. By returning the same - id in both places, Common Test knows that this SCB - has already been installed and will not try to install it again.

-
- -
- - -
- SCB Scope -

Once the SCB is installed into a certain test run it will be there until - it's scope is expired. The scope of an SCB depends on when it is - installed. - The init/2 is - called at the beginning of the scope and the - terminate/1 - function is called when the scope ends.

- - - SCB Installed in - SCB scope begins before - SCB scope ends after - - - ct_run - the first test suite is to be run. - the last test suite has been run. - - - ct:run_test - the first test suite is to be run. - the last test suite has been run. - - - - Test Specification - the first test suite is to be run. - the last test suite has been run. - - - suite/0 - - - pre_init_per_suite/3 is called. - - post_end_per_suite/4 has been called for that test suite. - - - - init_per_suite/1 - - post_init_per_suite/4 is called. - - post_end_per_suite/4 has been called for that test suite. - - - - init_per_group/2 - - post_init_per_group/4 is called. - - post_end_per_group/4 has been called for that group. - - Scope of an SCB -
- -
- CTH Processes and Tables -

CTHs are run with the same process scoping as normal test suites - i.e. a different process will execute the init_per_suite hooks then the - init_per_group or per_testcase hooks. So if you want to spawn a - process in the CTH you cannot link with the CTH process as it will exit - after the post hook ends. Also if you for some reason need an ETS - table with your CTH, you will have to spawn a process which handles - it.

-
- -
- - -
- Manipulating tests -

It is through SCB's possible to manipulate the results of tests and - configuration functions. The main purpose of doing this with SCBs is to - allow common patterns to be abstracted out from test test suites and applied to - multiple test suites without duplicating any code. All of the callback - functions for an SCB follow a common interface, this interface is - described below.

- - -
- Pre test manipulation -

- It is possible in an SCB to hook in behaviour before - init_per_suite, - init_per_group, - init_per_testcase, - end_per_group and - end_per_suite. - This is done in the SCB functions called pre_<name of function>. - All of these function take the same three arguments: Name, - Config and SCBState. The return value of the SCB function - is always a combination of an result for the suite/group/test and an - updated SCBState. If you want the test suite to continue on - executing you should return the config list which you want the test to - use as the result. If you for some reason want to skip/fail the test, - return a tuple with skip or fail and a reason as the - result. Example: -

- pre_init_per_suite(SuiteName, Config, SCBState) -> - case db:connect() of - {error,_Reason} -> - {{fail, "Could not connect to DB"}, SCBState}; - {ok, Handle} -> - {[{db_handle, Handle} | Config], SCBState#state{ handle = Handle }} - end. - -
- - -
- Post test manipulation -

It is also possible in an SCB to hook in behaviour after - init_per_suite, - init_per_group, - end_per_testcase, - end_per_group and - end_per_suite. - This is done in the SCB functions called post_<name of function>. - All of these function take the same four arguments: Name, - Config, Return and SCBState. Config in this - case is the same Config as the testcase is called with. - Return is the value returned by the testcase. If the testcase - failed by crashing, Return will be - {'EXIT',{{Error,Reason},Stacktrace}}.

- -

The return value of the SCB function is always a combination of an - result for the suite/group/test and an updated SCBState. If - you want the callback to not affect the outcome of the test you should - return the Return data as it is given to the SCB. You can also - modify the result of the test. By returning the Config list - with the tc_status element removed you can recover from a test - failure. As in all the pre hooks, it is also possible to fail/skip - the test case in the post hook. Example:

- - post_end_per_testcase(_TC, Config, {'EXIT',{_,_}}, SCBState) -> - case db:check_consistency() of - true -> - %% DB is good, pass the test. - {proplists:delete(tc_status, Config), SCBState}; - false -> - %% DB is not good, mark as skipped instead of failing - {{skip, "DB is inconsisten!"}, SCBState} - end; -post_end_per_testcase(_TC, Config, Return, SCBState) -> - %% Do nothing if tc does not crash. - {Return, SCBState}. - - Recovering from a testcase failure using SCBs should only be done as - a last resort. If used wrongly it could become very difficult to - determine which tests pass or fail in a test run - -
- - -
- Skip and Fail -

- After any post hook has been executed for all installed SCBs, - on_tc_fail - or on_tc_skip - might be called if the testcase failed or was skipped - respectively. You cannot affect the outcome of the tests any further at - this point. -

-
- -
- - -
- Example SCB -

The SCB below will log information about a test run into a format - parseable by file:consult/1. -

- %%% @doc Common Test Example Suite Callback module. --module(example_scb). - -%% Suite Callbacks --export([id/1]). --export([init/2]). - --export([pre_init_per_suite/3]). --export([post_init_per_suite/4]). --export([pre_end_per_suite/3]). --export([post_end_per_suite/4]). - --export([pre_init_per_group/3]). --export([post_init_per_group/4]). --export([pre_end_per_group/3]). --export([post_end_per_group/4]). - --export([pre_init_per_testcase/3]). --export([post_end_per_testcase/4]). - --export([on_tc_fail/3]). --export([on_tc_skip/3]). - --export([terminate/1]). - --record(state, { file_handle, total, suite_total, ts, tcs, data }). - -%% @doc Return a unique id for this SCB. -id(Opts) -> - proplists:get_value(filename, Opts, "/tmp/file.log"). - -%% @doc Always called before any other callback function. Use this to initiate -%% any common state. -init(Id, Opts) -> - {ok,D} = file:open(Id,[write]), - #state{ file_handle = D, total = 0, data = [] }. - -%% @doc Called before init_per_suite is called. -pre_init_per_suite(Suite,Config,State) -> - {Config, State#state{ suite_total = 0, tcs = [] }}. - -%% @doc Called after init_per_suite. -post_init_per_suite(Suite,Config,Return,State) -> - {Return, State}. - -%% @doc Called before end_per_suite. -pre_end_per_suite(Suite,Config,State) -> - {Config, State}. - -%% @doc Called after end_per_suite. -post_end_per_suite(Suite,Config,Return,State) -> - Data = {suites, Suite, State#state.suite_total, lists:reverse(State#state.tcs)}, - {Return, State#state{ data = [Data | State#state.data] , - total = State#state.total + State#state.suite_total } }. - -%% @doc Called before each init_per_group. -pre_init_per_group(Group,Config,State) -> - {Config, State}. - -%% @doc Called after each init_per_group. -post_init_per_group(Group,Config,Return,State) -> - {Return, State}. - -%% @doc Called after each end_per_group. -pre_end_per_group(Group,Config,State) -> - {Config, State}. - -%% @doc Called after each end_per_group. -post_end_per_group(Group,Config,Return,State) -> - {Return, State}. - -%% @doc Called before each test case. -pre_init_per_testcase(TC,Config,State) -> - {Config, State#state{ ts = now(), total = State#state.suite_total + 1 } }. - -%% @doc Called after each test case. -post_end_per_testcase(TC,Config,Return,State) -> - TCInfo = {testcase, TC, Return, timer:now_diff(now(), State#state.ts)}, - {Return, State#state{ ts = undefined, tcs = [TCInfo | State#state.tcs] } }. - -%% @doc Called after post_init_per_suite, post_end_per_suite, post_init_per_group, -%% post_end_per_group and post_end_per_testcase if the suite, group or test case failed. -on_tc_fail(TC, Reason, State) -> - State. - -%% @doc Called when a test case is skipped by either user action -%% or due to an init function failing. -on_tc_skip(TC, Reason, State) -> - State. - -%% @doc Called when the scope of the SCB is done -terminate(State) -> - io:format(State#state.file_handle, "~p.~n", - [{test_run, State#state.total, State#state.data}]), - file:close(State#state.file_handle), - ok. -
- -
- - - - -- cgit v1.2.3 From 8b9b6e1436e255b8cd40ed8ab44bc0c7a90ef798 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Tue, 15 Feb 2011 13:37:19 +0100 Subject: Cleanup code to fix dialyzer warning --- lib/common_test/src/ct_hooks.erl | 2 +- lib/common_test/src/ct_run.erl | 12 +----------- lib/common_test/src/ct_testspec.erl | 2 -- 3 files changed, 2 insertions(+), 14 deletions(-) (limited to 'lib/common_test') diff --git a/lib/common_test/src/ct_hooks.erl b/lib/common_test/src/ct_hooks.erl index 8e80ce8f37..77b7566d9e 100644 --- a/lib/common_test/src/ct_hooks.erl +++ b/lib/common_test/src/ct_hooks.erl @@ -94,7 +94,7 @@ init_tc(_Mod, TC, Config) -> {skip, Reason :: term()} | {auto_skip, Reason :: term()} | {fail, Reason :: term()} | - ok. + ok | '$ct_no_change'. end_tc(ct_framework, _Func, _Args, Result, _Return) -> Result; diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl index 36fccf65f3..f50a46a241 100644 --- a/lib/common_test/src/ct_run.erl +++ b/lib/common_test/src/ct_run.erl @@ -1072,15 +1072,7 @@ refresh_logs(LogDir) -> which(logdir, undefined) -> "."; which(logdir, Dir) -> - Dir; -which(multiply_timetraps, undefined) -> - 1; -which(multiply_timetraps, MT) -> - MT; -which(scale_timetraps, undefined) -> - false; -which(scale_timetraps, ST) -> - ST. + Dir. choose_val(undefined, V1) -> V1; @@ -2068,8 +2060,6 @@ get_start_opt(Key, IfExists, IfNotExists, Args) -> Val; {value,{Key,_Val}} -> IfExists; - _ when is_function(IfNotExists) -> - IfNotExists(); _ -> IfNotExists end. diff --git a/lib/common_test/src/ct_testspec.erl b/lib/common_test/src/ct_testspec.erl index db1d4c5fb0..2b6abefb72 100644 --- a/lib/common_test/src/ct_testspec.erl +++ b/lib/common_test/src/ct_testspec.erl @@ -394,8 +394,6 @@ filter_init_terms([Term|Ts], NewTerms, Spec)-> filter_init_terms([], NewTerms, Spec)-> {lists:reverse(NewTerms), Spec}. -add_option([], _, List, _)-> - List; add_option({Key, Value}, Node, List, WarnIfExists) when is_list(Value)-> OldOptions = case lists:keyfind(Node, 1, List) of {Node, Options}-> -- cgit v1.2.3 From d87708bf18d29c0a66f6654368b4553067e62394 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 17 Feb 2011 16:57:56 +0100 Subject: Update example cth spec to reflect the implementation --- lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lib/common_test') diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl index 7654a7ee2f..5d07cd3dea 100644 --- a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl @@ -64,14 +64,15 @@ -type reason() :: term(). -type skip_or_fail() :: {skip, reason()} | {auto_skip, reason()} | - {fail, reason()}. + {fail, reason()} | + {'EXIT',reason()}. -record(state, { id = ?MODULE :: term()}). %% @doc Always called before any other callback function. Use this to initiate %% any common state. It should return an state for this CTH. -spec init(Id :: term(), Opts :: proplist()) -> - {Id :: term(), State :: #state{}}. + State :: #state{}. init(Id, Opts) -> gen_event:notify(?CT_EVMGR_REF, #event{ name = cth, node = node(), data = {?MODULE, init, [Id, Opts]}}), -- cgit v1.2.3